[Wl530g-svncheckins] r255 - in trunk/Marvell/Src/uClinux-dist/user.asus: . busybox-1.2.1 busybox-1.2.1/applets busybox-1.2.1/archival busybox-1.2.1/archival/libunarchive busybox-1.2.1/console-tools busybox-1.2.1/coreutils busybox-1.2.1/coreutils/libcoreutils busybox-1.2.1/debianutils busybox-1.2.1/docs busybox-1.2.1/docs/busybox.net busybox-1.2.1/docs/busybox.net/images busybox-1.2.1/e2fsprogs busybox-1.2.1/e2fsprogs/blkid busybox-1.2.1/e2fsprogs/e2p busybox-1.2.1/e2fsprogs/ext2fs busybox-1.2.1/e2fsprogs/uuid busybox-1.2.1/editors busybox-1.2.1/examples busybox-1.2.1/examples/bootfloppy busybox-1.2.1/examples/bootfloppy/etc busybox-1.2.1/examples/bootfloppy/etc/init.d busybox-1.2.1/examples/udhcp busybox-1.2.1/findutils busybox-1.2.1/include busybox-1.2.1/include/config busybox-1.2.1/include/config/bb busybox-1.2.1/include/config/config busybox-1.2.1/include/config/config/ash busybox-1.2.1/include/config/config/ash/builtin busybox-1.2.1/include/config/config/ash/expand busybox-1.2.1/inc! lude/config/config/ash/job busybox-1.2.1/include/config/config/ash/math busybox-1.2.1/include/config/config/ash/optimize busybox-1.2.1/include/config/config/ash/optimize/for busybox-1.2.1/include/config/config/ash/random busybox-1.2.1/include/config/config/ash/read busybox-1.2.1/include/config/config/busybox busybox-1.2.1/include/config/config/busybox/exec busybox-1.2.1/include/config/config/debug busybox-1.2.1/include/config/config/devfsd busybox-1.2.1/include/config/config/feature busybox-1.2.1/include/config/config/feature/aix busybox-1.2.1/include/config/config/feature/ar busybox-1.2.1/include/config/config/feature/ar/long busybox-1.2.1/include/config/config/feature/awk busybox-1.2.1/include/config/config/feature/buffers busybox-1.2.1/include/config/config/feature/buffers/go busybox-1.2.1/include/config/config/feature/buffers/go/in busybox-1.2.1/include/config/config/feature/buffers/go/on busybox-1.2.1/include/config/config/feature/check busybox-1.2.1/include/config/con! fig/feature/check/tainted busybox-1.2.1/include/config/config/! feature/

jcollake at mail.berlios.de jcollake at mail.berlios.de
Sun Sep 17 22:23:05 CEST 2006


Author: jcollake
Date: 2006-09-17 22:11:48 +0200 (Sun, 17 Sep 2006)
New Revision: 255

Added:
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.config
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.config.cmd
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.config_mine
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.depend
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.indent.pro
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/AUTHORS
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/INSTALL
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/LICENSE
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/README
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/Rules.mak
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/TODO
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/applets.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/busybox.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/busybox.mkll
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/install.sh
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/version.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/ar.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/bunzip2.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/cpio.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/dpkg.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/dpkg_deb.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/gunzip.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/gzip.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/archive_xread_all.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/archive_xread_all_eof.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/check_header_gzip.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_align.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_extract_all.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_extract_to_buffer.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_extract_to_stdout.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_skip.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/decompress_bunzip2.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/decompress_uncompress.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/decompress_unlzma.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/decompress_unzip.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/filter_accept_all.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/filter_accept_list.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/filter_accept_list_reassign.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/filter_accept_reject_list.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/find_list_entry.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_ar.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_cpio.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_tar.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_tar_bz2.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_tar_gz.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_tar_lzma.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/header_list.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/header_skip.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/header_verbose_list.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/init_handle.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/open_transformer.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/seek_by_char.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/seek_by_jump.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/unpack_ar_archive.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/rpm.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/rpm2cpio.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/tar.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/uncompress.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/unlzma.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/unzip.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/changelog
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/chvt.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/clear.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/deallocvt.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/dumpkmap.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/loadfont.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/loadkmap.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/openvt.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/reset.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/setconsole.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/setkeycodes.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/setlogcons.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/basename.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cal.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cat.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/catv.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/chgrp.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/chmod.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/chown.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/chroot.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cksum.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cmp.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/comm.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cp.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cut.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/date.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/dd.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/df.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/diff.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/dirname.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/dos2unix.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/du.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/echo.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/env.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/expr.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/false.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/fold.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/head.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/hostid.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/id.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/install.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/length.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/coreutils.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/cp_mv_stat.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/getopt_mk_fifo_nod.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/ln.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/logname.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/ls.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/md5_sha1_sum.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/mkdir.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/mkfifo.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/mknod.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/mv.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/nice.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/nohup.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/od.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/printenv.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/printf.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/pwd.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/realpath.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/rm.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/rmdir.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/seq.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/sleep.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/sort.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/stat.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/stty.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/sum.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/sync.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/tail.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/tee.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/test.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/touch.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/tr.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/true.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/tty.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/uname.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/uniq.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/usleep.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/uudecode.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/uuencode.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/watch.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/wc.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/who.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/whoami.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/yes.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/mktemp.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/pipe_progress.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/readlink.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/run_parts.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/start_stop_daemon.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/which.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/autodocifier.pl
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/FAQ.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/about.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/busybox-growth.ps
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/copyright.txt
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/developer.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/download.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/footer.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/header.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/back.png
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/busybox.jpeg
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/busybox.png
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/busybox1.png
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/busybox2.jpg
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/busybox3.jpg
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/dir.png
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/donate.png
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/fm.mini.png
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/gfx_by_gimp.png
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/ltbutton2.png
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/osuosl.png
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/sdsmall.png
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/text.png
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/valid-html401.png
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/vh40.gif
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/written.in.vi.png
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/index.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/license.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/links.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/lists.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/news.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/oldnews.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/products.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/screenshot.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/shame.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/sponsors.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/subversion.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/tinyutils.html
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox_footer.pod
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox_header.pod
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/contributing.txt
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/new-applet-HOWTO.txt
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/style-guide.txt
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/README
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/blkid.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/blkidP.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/blkid_getsize.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/cache.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/dev.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/devname.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/devno.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/list.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/probe.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/probe.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/read.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/resolve.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/save.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/tag.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/version.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/chattr.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2fsbb.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2fsck.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2fsck.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/e2p.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/feature.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/fgetsetflags.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/fgetsetversion.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/hashstr.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/iod.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/ls.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/mntopts.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/ostype.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/parse_num.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/pe.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/pf.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/ps.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/uuid.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/alloc.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/alloc_sb.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/alloc_stats.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/alloc_tables.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/badblocks.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bb_compat.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bb_inode.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bitmaps.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bitops.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bitops.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/block.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bmap.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bmove.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/brel.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/brel_ma.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/check_desc.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/closefs.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/cmp_bitmaps.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dblist.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dblist_dir.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dir_iterate.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dirblock.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dirhash.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dupfs.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/e2image.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/expanddir.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_err.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_ext_attr.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_io.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_types.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2fsP.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs_inline.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext_attr.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/fileio.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/finddev.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/flushb.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/freefs.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/gen_bitmap.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/get_pathname.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/getsectsize.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/getsize.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/icount.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/imager.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ind_block.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/initialize.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/inline.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/inode.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/inode_io.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/io_manager.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/irel.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/irel_ma.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ismounted.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/jfs_dat.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/kernel-jbd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/kernel-list.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/link.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/lookup.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/mkdir.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/mkjournal.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/namei.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/newdir.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/openfs.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/read_bb.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/read_bb_file.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/res_gdt.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/rs_bitmap.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/rw_bitmaps.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/sparse.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/swapfs.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/test_io.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/unix_io.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/unlink.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/valid_blk.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/version.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/write_bb_file.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/fsck.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/fsck.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/lsattr.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/mke2fs.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/tune2fs.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/util.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/util.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/compare.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/gen_uuid.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/pack.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/parse.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/unpack.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/unparse.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/uuid.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/uuidP.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/uuid_time.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/awk.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/ed.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/patch.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/sed.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/vi.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/bootfloppy.txt
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/display.txt
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/fstab
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/init.d/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/init.d/rcS
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/inittab
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/profile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/mkdevs.sh
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/mkrootfs.sh
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/mksyslinux.sh
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/quickstart.txt
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/syslinux.cfg
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/busybox.spec
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/depmod.pl
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/devfsd.conf
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/dnsd.conf
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/inetd.conf
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/inittab
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/mk2knr.pl
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.bound
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.deconfig
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.nak
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.renew
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.script
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/simple.script
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/udhcpd.conf
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/undeb
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/unrpm
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/zcip.script
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/find.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/grep.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/xargs.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/applets.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/bb_config.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/busybox.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/bb/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/bb/bt.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/bb/ver.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ar.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/alias.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/builtin/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/builtin/echo.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/builtin/test.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/cmdcmd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/expand/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/expand/prmt.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/getopts.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/job/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/job/control.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/mail.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/math/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/math/support.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/math/support_64.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/optimize/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/optimize/for/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/optimize/for/size.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/random/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/random/support.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/read/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/read/nchars.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/read/timeout.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/busybox/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/busybox/exec/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/busybox/exec/path.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/debug.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/debug/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/debug/tftp.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/devfsd/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/devfsd/verbose.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/e2label.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/aix/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/aix/label.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ar/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ar/long/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ar/long/filenames.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/autowidth.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/awk/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/awk/math.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/buffers/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/buffers/go/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/buffers/go/in/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/buffers/go/in/bss.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/buffers/go/on/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/buffers/go/on/stack.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/check/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/check/tainted/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/check/tainted/module.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/clean/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/clean/up.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/editing.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/editing/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/editing/vi.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/history.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/savehistory.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/tab/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/tab/completion.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/username/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/username/completion.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/deb/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/deb/tar/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/deb/tar/bz2.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/deb/tar/gz.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/devfs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/devpts.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/du/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/du/default/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/du/default/blocksize_1k.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/extra/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/extra/quiet.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/echo.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/ping.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/ping6.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/sleep.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/tail.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fbset/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fbset/fancy.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fbset/readmode.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fdisk/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fdisk/advanced.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fdisk/writable.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/exec.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/inum.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/mmin.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/mtime.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/newer.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/perm.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/print0.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/type.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/xdev.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/gunzip/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/gunzip/uncompress.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/get/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/get/identity.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/drive/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/drive/reset.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/getset/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/getset/dma.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/scan/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/scan/hwif.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/tristate/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/tristate/hwif.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/unregister/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/unregister/hwif.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/auth/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/auth/md5.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/basic/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/basic/auth.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/cgi.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/config/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/config/with/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/config/with/mime/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/config/with/mime/types.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/config/with/script/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/config/with/script/interpr.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/encode/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/encode/url/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/encode/url/str.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/reload/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/reload/config/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/reload/config/sighup.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/set/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/set/remote/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/set/remote/port/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/set/remote/port/to/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/set/remote/port/to/env.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/setuid.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/without/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/without/inetd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/human/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/human/readable.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hwclock/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hwclock/adjtime/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hwclock/adjtime/fhs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/broadcast/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/broadcast/plus.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/hw.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/memstart/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/memstart/ioaddr/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/memstart/ioaddr/irq.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/slip.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/status.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/ip.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/ipv4.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/ipv6.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/mapping.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/rpc.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/chargen.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/daytime.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/discard.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/echo.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/time.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/init/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/init/coredumps.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/init/sctty.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/ksymoops/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/ksymoops/symbols.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/load/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/load/map.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/load/map/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/load/map/full.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/loadinkmem.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/version/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/version/checking.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/installer.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/address.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/link.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/route.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/tunnel.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipc/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipc/syslog.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipc/syslog/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipc/syslog/buffer/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipc/syslog/buffer/size.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipcalc/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipcalc/fancy.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipv6.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/brackets.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/flagcs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/flags.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/marks.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/regexp.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/logread/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/logread/reduced/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/logread/reduced/locking.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/color.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/color/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/color/is/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/color/is/default.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/filetypes.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/followlinks.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/recursive.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/sortfiles.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/timestamps.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/username.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/lsmod/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/lsmod/pretty_2_6/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/lsmod/pretty_2_6/output.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/lzma/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/lzma/fast.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/makedevs/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/makedevs/leaf.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/makedevs/table.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/md5/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/md5/sha1/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/md5/sha1/sum/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/md5/sha1/sum/check.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/minix2.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/mount/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/mount/loop.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/mtab/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/mtab/support.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/osf/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/osf/label.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/query/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/query/module/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/query/module/interface.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/readlink/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/readlink/follow.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/remote/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/remote/log.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/rotate/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/rotate/logfile.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/securetty.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sgi/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sgi/label.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sh/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sh/extra/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sh/extra/quiet.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sh/fancy/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sh/fancy/prompt.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sh/standalone/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sh/standalone/shell.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/shadowpasswds.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sort/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sort/big.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/stat/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/stat/format.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/suid.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/suid/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/suid/config.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/suid/config/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/suid/config/quiet.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sun/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sun/label.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/bzip2.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/compress.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/create.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/from.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/gnu/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/gnu/extensions.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/gzip.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/long/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/long/options.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/lzma.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/oldgnu/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/oldgnu/compatibility.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tee/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tee/use/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tee/use/block/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tee/use/block/io.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/telnet/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/telnet/autologin.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/telnet/ttype.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/telnetd/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/telnetd/inetd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/test_64.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tftp/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tftp/blocksize.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tftp/get.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tftp/put.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/top/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/top/cpu/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/top/cpu/usage/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/top/cpu/usage/percentage.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/traceroute/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/traceroute/source/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/traceroute/source/route.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/traceroute/use/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/traceroute/use/icmp.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/traceroute/verbose.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/udhcp/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/udhcp/debug.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/udhcp/syslog.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/unarchive/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/unarchive/tape.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/use/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/use/inittab.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/use/termios.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/utmp.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/verbose/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/verbose/usage.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/colon.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/dot/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/dot/cmd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/optimize/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/optimize/cursor.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/readonly.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/search.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/set.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/setopts.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/use/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/use/signals.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/win/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/win/resize.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/yankmark.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wget/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wget/authentication.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wget/ip6/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wget/ip6/literal.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wget/statusbar.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wtmp.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/confirmation.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/quotes.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/termopt.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/zero/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/zero/term.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature_2_4/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature_2_4/modules.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature_2_6/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature_2_6/modules.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/findfs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/gunzip.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/init.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/install/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/install/no/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/install/no/usr.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/killall.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/lfs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/locale/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/locale/support.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/login.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/md5/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/md5/size/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/md5/size/vs/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/md5/size/vs/speed.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/md5sum.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/nc/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/nc/gaping/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/nc/gaping/security/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/nc/gaping/security/hole.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ps.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/route.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/selinux.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/sha1sum.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/syslogd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/tar.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/use/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/use/bb/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/use/bb/pwd/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/use/bb/pwd/grp.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/use/bb/shadow.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/alias.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/builtin/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/builtin/echo.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/builtin/test.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/cmdcmd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/job/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/job/control.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug/crond/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug/crond/option.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug/init.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug/yank/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug/yank/susv2.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/deluser.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/devfsd/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/devfsd/fg/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/devfsd/fg/np.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/devfsd/modload.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/devfsd/verbose.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/e2label.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/expr/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/expr/math/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/expr/math/support_64.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/fdflush.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/autowidth.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/check/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/check/tainted/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/check/tainted/module.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/clean/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/clean/up.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/command/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/command/editing.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/compress/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/compress/usage.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/crond/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/crond/call/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/crond/call/sendmail.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/date/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/date/isofmt.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/dd/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/dd/ibs/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/dd/ibs/obs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/dd/signal/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/dd/signal/handling.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/deb/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/deb/tar/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/deb/tar/lzma.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/diff/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/diff/binary.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/diff/dir.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/diff/minimal.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/env/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/env/long/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/env/long/options.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/fancy/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/fancy/head.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/fancy/tail.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ftpgetput/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ftpgetput/long/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ftpgetput/long/options.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/grep/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/grep/context.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/grep/egrep/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/grep/egrep/alias.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/grep/fgrep/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/grep/fgrep/alias.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hdparm/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hdparm/get/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hdparm/get/identity.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hdparm/hdio/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hdparm/hdio/scan/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hdparm/hdio/scan/hwif.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hwclock/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hwclock/long/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hwclock/long/options.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ifupdown/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ifupdown/ipv4.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ifupdown/ipv6.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/initrd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/install/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/install/long/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/install/long/options.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/installer.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ipcalc/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ipcalc/fancy.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ipcalc/long/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ipcalc/long/options.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ls/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ls/recursive.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ls/sortfiles.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ls/timestamps.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/md5/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/md5/sha1/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/md5/sha1/sum/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/md5/sha1/sum/check.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mdev/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mdev/conf.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mdev/exec.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mkdir/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mkdir/long/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mkdir/long/options.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mkswap/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mkswap/v0.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/modprobe/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/modprobe/multiple/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/modprobe/multiple/options.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mount/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mount/loop.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mount/nfs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mtab/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mtab/support.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mv/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mv/long/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mv/long/options.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/pidof/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/pidof/omit.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/pidof/single.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/preserve/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/preserve/hardlinks.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ps/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ps/wide.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/readlink/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/readlink/follow.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/setconsole/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/setconsole/long/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/setconsole/long/options.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/sh/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/sh/extra/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/sh/extra/quiet.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/sh/standalone/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/sh/standalone/shell.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/shadowpasswds.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/sort/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/sort/big.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/start/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/start/stop/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/start/stop/daemon/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/start/stop/daemon/fancy.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/start/stop/daemon/long/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/start/stop/daemon/long/options.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/suid.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/suid/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/suid/config.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/bzip2.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/compress.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/create.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/from.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/gzip.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/long/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/long/options.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/lzma.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tftp/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tftp/get.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tftp/put.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tr/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tr/classes.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tr/equiv.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/udhcp/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/udhcp/debug.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/udhcp/syslog.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/umount/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/umount/all.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/vi/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/vi/win/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/vi/win/resize.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature_2_4/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature_2_4/modules.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature_2_6/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature_2_6/modules.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/findfs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/freeramdisk.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ftpget.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ftpput.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/getopt/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/getopt/long.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/init.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/locale/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/locale/support.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/md5sum.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/selinux.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/sha1sum.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/show/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/show/usage.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/swaponoff.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/du/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/du/default/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/du/default/blocksize_1k.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/auth/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/auth/md5.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/basic/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/basic/auth.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/encode/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/encode/url/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/encode/url/str.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/setuid.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/without/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/without/inetd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/human/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/human/readable.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/start/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/start/stop/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/start/stop/daemon/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/start/stop/daemon/fancy.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/addgroup.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/adduser.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/adjtimex.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/app/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/app/dumpleases.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/app/udhcpc.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/app/udhcpd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ar.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/arping.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ash.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/awk.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/basename.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/bb/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/bb/sysctl.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/bbconfig.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/bunzip2.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cal.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cat.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/catv.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chattr.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chgrp.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chmod.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chown.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chroot.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chvt.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cksum.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/clear.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cmp.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/comm.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cp.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cpio.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/crond.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/crontab.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cut.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/date.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dc.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/deallocvt.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/delgroup.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/deluser.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/devfsd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/devfsd/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/devfsd/fg/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/devfsd/fg/np.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/df.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/diff.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dirname.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dmesg.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dnsd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dos2unix.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dpkg.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dpkg/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dpkg/deb.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/du.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dumpkmap.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/e2fsck.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/e2label.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/echo.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ed.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/eject.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/env.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ether/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ether/wake.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/expr.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fakeidentd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/false.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fbset.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fdflush.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fdformat.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fdisk.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/command/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/command/editing.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/date/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/date/isofmt.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/dd/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/dd/ibs/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/dd/ibs/obs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/du/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/du/default/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/du/default/blocksize_1k.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/fancy/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/fancy/echo.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/fancy/head.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/exec.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/inum.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/mmin.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/mtime.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/newer.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/perm.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/print0.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/type.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/grep/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/grep/context.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/grep/egrep/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/grep/egrep/alias.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/grep/fgrep/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/grep/fgrep/alias.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/get/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/get/identity.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/drive/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/drive/reset.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/getset/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/getset/dma.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/scan/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/scan/hwif.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/tristate/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/tristate/hwif.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/unregister/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/unregister/hwif.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/auth/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/auth/md5.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/basic/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/basic/auth.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/cgi.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/encode/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/encode/url/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/encode/url/str.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/setuid.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/without/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/without/inetd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/human/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/human/readable.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/initrd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/ipcalc/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/ipcalc/fancy.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/ls/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/ls/sortfiles.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/mdev/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/mdev/exec.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/mtab/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/mtab/support.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/ash.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/hush.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/lash.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/msh.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/start/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/start/stop/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/start/stop/daemon/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/start/stop/daemon/fancy.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/stat/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/stat/format.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/tftp/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/tftp/blocksize.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/top/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/top/cpu/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/top/cpu/usage/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/top/cpu/usage/percentage.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/find.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/findfs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fold.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/free.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/freeramdisk.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fsck.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fsck/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fsck/minix.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ftpget.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ftpput.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fuser.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/getopt.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/getty.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/grep.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/gunzip.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/gzip.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/halt.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hdparm.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/head.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hexdump.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hostid.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hostname.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/httpd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hush.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hwclock.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/id.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ifconfig.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ifupdown.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/inetd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/init.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/insmod.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/install.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ip.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ipaddr.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ipcalc.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ipcrm.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ipcs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/iplink.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/iproute.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/iptunnel.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/kill.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/killall.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/klogd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/lash.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/last.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/length.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/less.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ln.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/loadfont.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/loadkmap.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/logger.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/login.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/logname.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/logread.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/losetup.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ls.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/lsattr.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/lsmod.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/makedevs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/md5sum.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mdev.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mesg.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkdir.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mke2fs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkfifo.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkfs/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkfs/minix.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mknod.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkswap.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mktemp.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/modprobe.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/more.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mount.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mountpoint.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/msh.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mt.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mv.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nameif.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nc.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/netstat.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nice.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nohup.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nslookup.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/od.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/openvt.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/passwd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/patch.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pidof.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ping.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ping6.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pipe/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pipe/progress.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pivot/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pivot/root.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/printenv.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/printf.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ps.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pwd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rdate.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/readlink.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/readprofile.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/realpath.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/renice.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/reset.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rm.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rmdir.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rmmod.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/route.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rpm.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rpm2cpio.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/run/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/run/parts.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/runlevel.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rx.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sed.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/seq.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setarch.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setconsole.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setkeycodes.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setlogcons.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setsid.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sha1sum.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sleep.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sort.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/start/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/start/stop/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/start/stop/daemon.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/stat.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/strings.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/stty.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/su.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sulogin.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sum.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/swaponoff.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/switch/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/switch/root.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sync.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/syslogd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tail.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tar.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tee.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/telnet.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/telnetd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/test.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tftp.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/time.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/top.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/touch.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tr.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/traceroute.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/true.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tty.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tune2fs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/umount.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uname.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uncompress.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uniq.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/unix2dos.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/unlzma.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/unzip.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uptime.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/usleep.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uudecode.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uuencode.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/vconfig.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/vi.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/vlock.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/watch.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/watchdog.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/wc.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/wget.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/which.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/who.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/whoami.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/xargs.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/yes.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/zcip.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/dump.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/grp_.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/inet_common.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/libbb.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/platform.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/pwd_.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/shadow_.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/unarchive.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/usage.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/xregex.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/halt.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/init.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/init_shared.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/init_shared.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/mesg.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/install_firmware.sh
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/README
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/ask_confirmation.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_askpass.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_asprintf.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_do_delay.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_pwd.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xbind.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xchdir.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xdaemon.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xlisten.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xsocket.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/change_identity.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/chomp.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/compare_string_array.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/concat_path_file.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/concat_subpath_file.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/conftest.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/copy_file.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/copyfd.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/correct_password.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/crc32.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/create_icmp6_socket.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/create_icmp_socket.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/daemon.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/default_error_retval.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/device_open.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/dump.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/error_msg.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/error_msg_and_die.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/fclose_nonstdin.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/fflush_stdout_and_exit.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/fgets_str.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/find_mount_point.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/find_pid_by_name.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/find_root_device.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/full_read.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/full_write.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/get_console.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/get_last_path_component.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/get_line_from_file.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/get_terminal_width_height.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/getopt_ulflags.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/herror_msg.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/herror_msg_and_die.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/human_readable.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/inet_common.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/inode_hash.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/isdirectory.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/kernel_version.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/last_char_is.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/llist.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/login.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/loop.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/make_directory.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/md5.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/messages.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/mode_string.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/mtab.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/mtab_file.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/obscure.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/opendir.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/parse_mode.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/parse_number.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/perror_msg.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/perror_msg_and_die.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/perror_nomsg.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/perror_nomsg_and_die.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/print_file.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/printf.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/process_escape_sequence.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/procps.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/pw_encrypt.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/pwd2spwd.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/qmodule.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/read_package_field.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/recursive_action.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/remove_file.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/restricted_shell.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/run_parts.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/run_shell.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/safe_read.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/safe_strncpy.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/safe_strtol.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/safe_write.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/setup_environment.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/sha1.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/simplify_path.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/skip_whitespace.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/speed_table.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/trim.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/u_signal_names.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/vdprintf.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/verror_msg.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/vfork_daemon_rexec.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/vherror_msg.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/vperror_msg.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/warn_ignoring_args.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/wfopen.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/wfopen_input.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xconnect.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xfuncs.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgetcwd.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgethostbyname.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgethostbyname2.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgetlarg.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgetularg.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xreadlink.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xregcomp.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xstat.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libc.aold
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/pwd_grp.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/pwd_grp_internal.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/addgroup.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/adduser.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/deluser.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/getty.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/login.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/passwd.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/su.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/sulogin.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/vlock.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/adjtimex.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/bbconfig.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/crond.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/crontab.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/dc.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/devfsd.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/eject.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/hdparm.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/last.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/less.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/makedevs.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/mountpoint.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/mt.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/runlevel.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/rx.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/setsid.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/strings.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/time.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/watchdog.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/insmod.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/lsmod.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/modprobe.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/rmmod.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/arping.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/dnsd.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ether-wake.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/fakeidentd.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ftpgetput.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/hostname.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/httpd.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ifconfig.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ifupdown.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/inetd.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/interface.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ip.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ipaddr.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ipcalc.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/iplink.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/iproute.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/iptunnel.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ip_common.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ip_parse_common_args.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ipaddress.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/iplink.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/iproute.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/iptunnel.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/libnetlink.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/libnetlink.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/linux/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/linux/pkt_sched.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_addr.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_map.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_map.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_proto.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_types.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/rt_names.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/rt_names.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/rtm_map.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/rtm_map.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/utils.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/utils.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/nameif.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/nc.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/netstat.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/nslookup.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ping.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ping6.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/route.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/telnet.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/telnetd.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/tftp.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/traceroute.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/arpping.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/arpping.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/clientpacket.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/clientpacket.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/clientsocket.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/clientsocket.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/common.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/common.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dhcpc.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dhcpc.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dhcpd.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dhcpd.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dumpleases.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/files.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/files.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/frontend.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/leases.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/leases.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/libbb_udhcp.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/options.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/options.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/packet.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/packet.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/pidfile.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/pidfile.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/script.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/serverpacket.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/serverpacket.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/signalpipe.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/signalpipe.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/socket.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/socket.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/static_leases.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/static_leases.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/vconfig.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/wget.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/zcip.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/free.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/fuser.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/kill.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/pidof.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/ps.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/renice.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/sysctl.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/top.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/uptime.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/bb_mkdep
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/bb_mkdep.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/bloat-o-meter
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/checkhelp.awk
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/Kconfig-language.txt
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/conf.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/confdata.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/expr.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/expr.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lex.zconf.c_shipped
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lkc.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lkc_proto.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/BIG.FAT.WARNING
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/checklist.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/colors.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/dialog.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/inputbox.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/menubox.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/msgbox.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/textbox.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/util.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/yesno.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/mconf.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/menu.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/mkconfigs
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/symbol.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/util.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/zconf.l
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/zconf.tab.c_shipped
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/zconf.tab.h_shipped
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/zconf.y
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/objsizes
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/showasm
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/usage.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/usage_compressed
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/ash.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/cmdedit.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/cmdedit.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/hush.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/lash.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/msh.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/klogd.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/logger.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/logread.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/syslogd.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/[
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/[[
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/awk
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/basename
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/busybox
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cal
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cat
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/chmod
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/clear
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cmp
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cp
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/crontab
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cut
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/date
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/dd
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/df
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/diff
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/dmesg
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/dos2unix
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/du
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/echo
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/env
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/expr
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/false
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/find
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/fold
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/free
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ftpget
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ftpput
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/grep
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/head
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/hexdump
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/hostid
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/kill
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/killall
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/length
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ln
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/logger
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/logname
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ls
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mesg
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mkdir
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mktemp
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/more
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mount
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/msh
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mv
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/nc
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/netstat
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/nslookup
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/pidof
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ping
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/printf
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ps
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/pwd
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/realpath
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/rm
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/rmdir
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sed
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/seq
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sleep
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sort
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/strings
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sum
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sync
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tail
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tar
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tee
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/test
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tftp
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/time
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/top
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/touch
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tr
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/traceroute
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/true
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/umount
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/uname
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/uniq
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/unix2dos
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/uptime
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/usleep
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/wc
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/wget
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/which
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/who
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/whoami
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/xargs
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/yes
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/chroot
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/crond
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/halt
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/klogd
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/logread
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/lsmod
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/pivot_root
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/poweroff
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/rdate
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/reboot
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/start-stop-daemon
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/switch_root
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/sysctl
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/syslogd
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/README
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/TODO
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/all_sourcecode.tests
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/basename/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/basename/basename-does-not-remove-identical-extension
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/basename/basename-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/bunzip2/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/bunzip2/bunzip2-reads-from-standard-input
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/bunzip2/bunzip2-removes-compressed-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/bunzip2/bzcat-does-not-remove-compressed-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/busybox.tests
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cat/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cat/cat-prints-a-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cat/cat-prints-a-file-and-standard-input
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cmp/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cmp/cmp-detects-difference
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-a-files-to-dir
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-a-preserves-links
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-copies-empty-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-copies-large-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-copies-small-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-d-files-to-dir
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-dir-create-dir
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-dir-existing-dir
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-does-not-copy-unreadable-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-files-to-dir
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-follows-links
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-preserves-hard-links
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-preserves-links
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-preserves-source-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-a-character
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-a-closed-range
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-a-field
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-an-open-range
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-an-unclosed-range
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/date-R-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/date-format-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/date-u-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/date-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/dd-accepts-if
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/dd-accepts-of
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/dd-copies-from-standard-input-to-standard-output
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/dd-prints-count-to-standard-error
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-absolute-path
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-empty-path
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-multiple-slashes
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-relative-path
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-root
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-single-component
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-h-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-k-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-l-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-m-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-s-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/echo-does-not-print-newline
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/echo-prints-argument
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/echo-prints-arguments
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/echo-prints-newline
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/expr/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/expr/expr-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/false/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/false/false-is-silent
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/false/false-returns-failure
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/find/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/find/find-supports-minus-xdev
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/grep.tests
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gunzip/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gunzip/gunzip-reads-from-standard-input
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gzip/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gzip/gzip-accepts-multiple-files
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gzip/gzip-accepts-single-minus
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gzip/gzip-removes-original-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/head/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/head/head-n-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/head/head-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostid/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostid/hostid-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/hostname-d-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/hostname-i-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/hostname-s-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/hostname-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/id-g-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/id-u-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/id-un-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/id-ur-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-creates-hard-links
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-creates-soft-links
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-force-creates-hard-links
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-force-creates-soft-links
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-preserves-hard-links
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-preserves-soft-links
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/ls-1-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/ls-h-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/ls-l-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/ls-s-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/md5sum/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/md5sum/md5sum-verifies-non-binary-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mkdir/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mkdir/mkdir-makes-a-directory
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mkdir/mkdir-makes-parent-directories
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mount.testroot
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/msh/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/msh/msh-supports-underscores-in-variable-names
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-files-to-dir
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-follows-links
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-empty-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-hardlinks
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-large-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-small-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-symlinks
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-unreadable-files
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-preserves-hard-links
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-preserves-links
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-refuses-mv-dir-to-subdir
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-removes-source-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/pidof.tests
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/pwd/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/pwd/pwd-prints-working-directory
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/readlink.tests
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/rm/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/rm/rm-removes-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/rmdir/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/rmdir/rmdir-removes-parent-directories
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/runtest
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/sed.tests
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/seq.tests
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/sort.tests
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/strings/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/strings/strings-works-like-GNU
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tail/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tail/tail-n-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tail/tail-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-archives-multiple-files
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-complains-about-missing-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-demands-at-least-one-ctx
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-demands-at-most-one-ctx
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-extracts-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-extracts-from-standard-input
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-extracts-multiple-files
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-extracts-to-standard-output
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-cz-options
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-empty-include-and-non-empty-exclude-list
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-exclude-and-extract-lists
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-multiple-X-options
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-nested-exclude
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tee/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tee/tee-appends-input
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tee/tee-tees-input
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/testing.sh
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/touch/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/touch/touch-creates-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/touch/touch-does-not-create-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/touch/touch-touches-files-after-non-existent-file
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tr/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tr/tr-d-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tr/tr-non-gnu
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tr/tr-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/true/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/true/true-is-silent
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/true/true-returns-success
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/umlwrapper.sh
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/uniq.tests
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/unzip.tests
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/uptime/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/uptime/uptime-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/uuencode/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/uuencode/uuencode-sets-standard-input-mode-correctly
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-counts-all
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-counts-characters
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-counts-lines
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-counts-words
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-prints-longest-line-length
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/wget--O-overrides--P
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/wget-handles-empty-path
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/wget-retrieves-google-index
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/wget-supports--P
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/which/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/which/which-uses-default-path
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/xargs/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/xargs/xargs-works
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/Config.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/Makefile
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/Makefile.in
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/dmesg.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/fbset.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/fdformat.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/fdisk.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/freeramdisk.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/fsck_minix.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/getopt.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/hexdump.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/hwclock.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/ipcrm.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/ipcs.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/losetup.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/mdev.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/mkfs_minix.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/mkswap.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/more.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/mount.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/nfsmount.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/nfsmount.h
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/pivot_root.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/rdate.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/readprofile.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/setarch.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/swaponoff.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/switch_root.c
   trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/umount.c
Log:
busybox 1.2.1 arm-no-mmu ready


Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.config
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.config	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.config	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,635 @@
+#
+# Automatically generated make config: don't edit
+#
+HAVE_DOT_CONFIG=y
+
+#
+# Busybox Settings
+#
+
+#
+# General Configuration
+#
+CONFIG_NITPICK=y
+CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
+# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
+# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
+CONFIG_SHOW_USAGE=y
+# CONFIG_FEATURE_VERBOSE_USAGE is not set
+CONFIG_FEATURE_COMPRESS_USAGE=y
+# CONFIG_FEATURE_INSTALLER is not set
+# CONFIG_LOCALE_SUPPORT is not set
+CONFIG_GETOPT_LONG=y
+# CONFIG_FEATURE_DEVPTS is not set
+# CONFIG_FEATURE_CLEAN_UP is not set
+CONFIG_FEATURE_SUID=y
+# CONFIG_FEATURE_SUID_CONFIG is not set
+# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set
+# CONFIG_SELINUX is not set
+CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe"
+
+#
+# Build Options
+#
+CONFIG_STATIC=y
+# CONFIG_BUILD_LIBBUSYBOX is not set
+# CONFIG_FEATURE_FULL_LIBBUSYBOX is not set
+# CONFIG_FEATURE_SHARED_BUSYBOX is not set
+# CONFIG_LFS is not set
+USING_CROSS_COMPILER=y
+CROSS_COMPILER_PREFIX="arm-elf-"
+CONFIG_BUILD_AT_ONCE=y
+
+#
+# Debugging Options
+#
+# CONFIG_DEBUG is not set
+# CONFIG_DEBUG_PESSIMIZE is not set
+# CONFIG_NO_DEBUG_LIB is not set
+# CONFIG_DMALLOC is not set
+# CONFIG_EFENCE is not set
+CONFIG_DEBUG_YANK_SUSv2=y
+
+#
+# Installation Options
+#
+CONFIG_INSTALL_NO_USR=y
+CONFIG_INSTALL_APPLET_SYMLINKS=y
+# CONFIG_INSTALL_APPLET_HARDLINKS is not set
+# CONFIG_INSTALL_APPLET_DONT is not set
+PREFIX="./_install"
+
+#
+# Busybox Library Tuning
+#
+CONFIG_MD5_SIZE_VS_SPEED=3
+
+#
+# Applets
+#
+
+#
+# Archival Utilities
+#
+# CONFIG_AR is not set
+# CONFIG_FEATURE_AR_LONG_FILENAMES is not set
+# CONFIG_BUNZIP2 is not set
+# CONFIG_CPIO is not set
+# CONFIG_DPKG is not set
+# CONFIG_DPKG_DEB is not set
+# CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set
+# CONFIG_GUNZIP is not set
+# CONFIG_FEATURE_GUNZIP_UNCOMPRESS is not set
+# CONFIG_GZIP is not set
+# CONFIG_RPM2CPIO is not set
+# CONFIG_RPM is not set
+CONFIG_TAR=y
+# CONFIG_FEATURE_TAR_CREATE is not set
+CONFIG_FEATURE_TAR_BZIP2=y
+# CONFIG_FEATURE_TAR_LZMA is not set
+# CONFIG_FEATURE_TAR_FROM is not set
+CONFIG_FEATURE_TAR_GZIP=y
+# CONFIG_FEATURE_TAR_COMPRESS is not set
+# CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set
+# CONFIG_FEATURE_TAR_GNU_EXTENSIONS is not set
+# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set
+# CONFIG_UNCOMPRESS is not set
+# CONFIG_UNLZMA is not set
+# CONFIG_FEATURE_LZMA_FAST is not set
+# CONFIG_UNZIP is not set
+
+#
+# Common options for cpio and tar
+#
+# CONFIG_FEATURE_UNARCHIVE_TAPE is not set
+# CONFIG_FEATURE_DEB_TAR_GZ is not set
+# CONFIG_FEATURE_DEB_TAR_BZ2 is not set
+# CONFIG_FEATURE_DEB_TAR_LZMA is not set
+
+#
+# Coreutils
+#
+CONFIG_BASENAME=y
+# CONFIG_CAL is not set
+CONFIG_CAT=y
+# CONFIG_CATV is not set
+# CONFIG_CHGRP is not set
+CONFIG_CHMOD=y
+# CONFIG_CHOWN is not set
+CONFIG_CHROOT=y
+# CONFIG_CKSUM is not set
+# CONFIG_CMP is not set
+# CONFIG_COMM is not set
+CONFIG_CP=y
+CONFIG_CUT=y
+CONFIG_DATE=y
+# CONFIG_FEATURE_DATE_ISOFMT is not set
+CONFIG_DD=y
+# CONFIG_FEATURE_DD_SIGNAL_HANDLING is not set
+# CONFIG_FEATURE_DD_IBS_OBS is not set
+CONFIG_DF=y
+# CONFIG_DIFF is not set
+# CONFIG_FEATURE_DIFF_BINARY is not set
+# CONFIG_FEATURE_DIFF_DIR is not set
+# CONFIG_FEATURE_DIFF_MINIMAL is not set
+# CONFIG_DIRNAME is not set
+# CONFIG_DOS2UNIX is not set
+# CONFIG_UNIX2DOS is not set
+CONFIG_DU=y
+# CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K is not set
+CONFIG_ECHO=y
+# CONFIG_FEATURE_FANCY_ECHO is not set
+CONFIG_ENV=y
+# CONFIG_FEATURE_ENV_LONG_OPTIONS is not set
+CONFIG_EXPR=y
+# CONFIG_EXPR_MATH_SUPPORT_64 is not set
+CONFIG_FALSE=y
+CONFIG_FOLD=y
+CONFIG_HEAD=y
+# CONFIG_FEATURE_FANCY_HEAD is not set
+# CONFIG_HOSTID is not set
+# CONFIG_ID is not set
+# CONFIG_INSTALL is not set
+# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set
+# CONFIG_LENGTH is not set
+CONFIG_LN=y
+# CONFIG_LOGNAME is not set
+CONFIG_LS=y
+# CONFIG_FEATURE_LS_FILETYPES is not set
+CONFIG_FEATURE_LS_FOLLOWLINKS=y
+# CONFIG_FEATURE_LS_RECURSIVE is not set
+CONFIG_FEATURE_LS_SORTFILES=y
+CONFIG_FEATURE_LS_TIMESTAMPS=y
+# CONFIG_FEATURE_LS_USERNAME is not set
+CONFIG_FEATURE_LS_COLOR=y
+CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y
+# CONFIG_MD5SUM is not set
+CONFIG_MKDIR=y
+# CONFIG_FEATURE_MKDIR_LONG_OPTIONS is not set
+CONFIG_MKFIFO=y
+# CONFIG_MKNOD is not set
+CONFIG_MV=y
+# CONFIG_FEATURE_MV_LONG_OPTIONS is not set
+# CONFIG_NICE is not set
+# CONFIG_NOHUP is not set
+# CONFIG_OD is not set
+# CONFIG_PRINTENV is not set
+# CONFIG_PRINTF is not set
+CONFIG_PWD=y
+# CONFIG_REALPATH is not set
+CONFIG_RM=y
+CONFIG_RMDIR=y
+CONFIG_SEQ=y
+# CONFIG_SHA1SUM is not set
+CONFIG_SLEEP=y
+# CONFIG_FEATURE_FANCY_SLEEP is not set
+CONFIG_SORT=y
+# CONFIG_FEATURE_SORT_BIG is not set
+# CONFIG_STAT is not set
+# CONFIG_FEATURE_STAT_FORMAT is not set
+# CONFIG_STTY is not set
+# CONFIG_SUM is not set
+# CONFIG_SYNC is not set
+CONFIG_TAIL=y
+# CONFIG_FEATURE_FANCY_TAIL is not set
+CONFIG_TEE=y
+# CONFIG_FEATURE_TEE_USE_BLOCK_IO is not set
+CONFIG_TEST=y
+# CONFIG_FEATURE_TEST_64 is not set
+CONFIG_TOUCH=y
+CONFIG_TR=y
+# CONFIG_FEATURE_TR_CLASSES is not set
+# CONFIG_FEATURE_TR_EQUIV is not set
+CONFIG_TRUE=y
+# CONFIG_TTY is not set
+CONFIG_UNAME=y
+CONFIG_UNIQ=y
+CONFIG_USLEEP=y
+# CONFIG_UUDECODE is not set
+# CONFIG_UUENCODE is not set
+# CONFIG_WATCH is not set
+CONFIG_WC=y
+# CONFIG_WHO is not set
+# CONFIG_WHOAMI is not set
+CONFIG_YES=y
+
+#
+# Common options for cp and mv
+#
+# CONFIG_FEATURE_PRESERVE_HARDLINKS is not set
+
+#
+# Common options for ls, more and telnet
+#
+CONFIG_FEATURE_AUTOWIDTH=y
+
+#
+# Common options for df, du, ls
+#
+# CONFIG_FEATURE_HUMAN_READABLE is not set
+# CONFIG_FEATURE_MD5_SHA1_SUM_CHECK is not set
+
+#
+# Console Utilities
+#
+# CONFIG_CHVT is not set
+CONFIG_CLEAR=y
+# CONFIG_DEALLOCVT is not set
+# CONFIG_DUMPKMAP is not set
+# CONFIG_LOADFONT is not set
+# CONFIG_LOADKMAP is not set
+# CONFIG_OPENVT is not set
+# CONFIG_RESET is not set
+# CONFIG_SETCONSOLE is not set
+# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set
+# CONFIG_SETKEYCODES is not set
+# CONFIG_SETLOGCONS is not set
+
+#
+# Debian Utilities
+#
+CONFIG_MKTEMP=y
+# CONFIG_PIPE_PROGRESS is not set
+# CONFIG_READLINK is not set
+# CONFIG_FEATURE_READLINK_FOLLOW is not set
+# CONFIG_RUN_PARTS is not set
+# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set
+# CONFIG_START_STOP_DAEMON is not set
+# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set
+# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set
+CONFIG_WHICH=y
+
+#
+# Editors
+#
+CONFIG_AWK=y
+# CONFIG_FEATURE_AWK_MATH is not set
+# CONFIG_ED is not set
+# CONFIG_PATCH is not set
+CONFIG_SED=y
+# CONFIG_VI is not set
+# CONFIG_FEATURE_VI_COLON is not set
+# CONFIG_FEATURE_VI_YANKMARK is not set
+# CONFIG_FEATURE_VI_SEARCH is not set
+# CONFIG_FEATURE_VI_USE_SIGNALS is not set
+# CONFIG_FEATURE_VI_DOT_CMD is not set
+# CONFIG_FEATURE_VI_READONLY is not set
+# CONFIG_FEATURE_VI_SETOPTS is not set
+# CONFIG_FEATURE_VI_SET is not set
+# CONFIG_FEATURE_VI_WIN_RESIZE is not set
+# CONFIG_FEATURE_VI_OPTIMIZE_CURSOR is not set
+
+#
+# Finding Utilities
+#
+CONFIG_FIND=y
+# CONFIG_FEATURE_FIND_PRINT0 is not set
+# CONFIG_FEATURE_FIND_MTIME is not set
+# CONFIG_FEATURE_FIND_MMIN is not set
+# CONFIG_FEATURE_FIND_PERM is not set
+# CONFIG_FEATURE_FIND_TYPE is not set
+# CONFIG_FEATURE_FIND_XDEV is not set
+# CONFIG_FEATURE_FIND_NEWER is not set
+# CONFIG_FEATURE_FIND_INUM is not set
+CONFIG_FEATURE_FIND_EXEC=y
+CONFIG_GREP=y
+# CONFIG_FEATURE_GREP_EGREP_ALIAS is not set
+# CONFIG_FEATURE_GREP_FGREP_ALIAS is not set
+# CONFIG_FEATURE_GREP_CONTEXT is not set
+# CONFIG_XARGS is not set
+# CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION is not set
+# CONFIG_FEATURE_XARGS_SUPPORT_QUOTES is not set
+# CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT is not set
+# CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM is not set
+
+#
+# Init Utilities
+#
+# CONFIG_INIT is not set
+# CONFIG_DEBUG_INIT is not set
+# CONFIG_FEATURE_USE_INITTAB is not set
+# CONFIG_FEATURE_INIT_SCTTY is not set
+# CONFIG_FEATURE_EXTRA_QUIET is not set
+# CONFIG_FEATURE_INIT_COREDUMPS is not set
+# CONFIG_FEATURE_INITRD is not set
+# CONFIG_HALT is not set
+# CONFIG_MESG is not set
+
+#
+# Login/Password Management Utilities
+#
+# CONFIG_FEATURE_SHADOWPASSWDS is not set
+# CONFIG_USE_BB_SHADOW is not set
+# CONFIG_USE_BB_PWD_GRP is not set
+# CONFIG_ADDGROUP is not set
+# CONFIG_DELGROUP is not set
+# CONFIG_ADDUSER is not set
+# CONFIG_DELUSER is not set
+# CONFIG_GETTY is not set
+# CONFIG_FEATURE_UTMP is not set
+# CONFIG_FEATURE_WTMP is not set
+# CONFIG_LOGIN is not set
+# CONFIG_FEATURE_SECURETTY is not set
+# CONFIG_PASSWD is not set
+# CONFIG_SU is not set
+# CONFIG_SULOGIN is not set
+# CONFIG_VLOCK is not set
+
+#
+# Linux Ext2 FS Progs
+#
+# CONFIG_CHATTR is not set
+# CONFIG_E2FSCK is not set
+# CONFIG_FSCK is not set
+# CONFIG_LSATTR is not set
+# CONFIG_MKE2FS is not set
+# CONFIG_TUNE2FS is not set
+# CONFIG_E2LABEL is not set
+# CONFIG_FINDFS is not set
+
+#
+# Linux Module Utilities
+#
+CONFIG_INSMOD=y
+# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
+# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
+CONFIG_FEATURE_INSMOD_LOADINKMEM=y
+# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
+# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
+# CONFIG_RMMOD is not set
+CONFIG_LSMOD=y
+# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set
+CONFIG_MODPROBE=y
+# CONFIG_FEATURE_MODPROBE_MULTIPLE_OPTIONS is not set
+
+#
+# Options common to multiple modutils
+#
+# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
+CONFIG_FEATURE_2_4_MODULES=y
+# CONFIG_FEATURE_2_6_MODULES is not set
+CONFIG_FEATURE_QUERY_MODULE_INTERFACE=y
+
+#
+# Linux System Utilities
+#
+CONFIG_DMESG=y
+# CONFIG_FBSET is not set
+# CONFIG_FEATURE_FBSET_FANCY is not set
+# CONFIG_FEATURE_FBSET_READMODE is not set
+# CONFIG_FDFLUSH is not set
+# CONFIG_FDFORMAT is not set
+# CONFIG_FDISK is not set
+# FDISK_SUPPORT_LARGE_DISKS is not set
+# CONFIG_FEATURE_FDISK_WRITABLE is not set
+# CONFIG_FEATURE_AIX_LABEL is not set
+# CONFIG_FEATURE_SGI_LABEL is not set
+# CONFIG_FEATURE_SUN_LABEL is not set
+# CONFIG_FEATURE_OSF_LABEL is not set
+# CONFIG_FEATURE_FDISK_ADVANCED is not set
+# CONFIG_FREERAMDISK is not set
+# CONFIG_FSCK_MINIX is not set
+# CONFIG_MKFS_MINIX is not set
+# CONFIG_FEATURE_MINIX2 is not set
+# CONFIG_GETOPT is not set
+# CONFIG_HEXDUMP is not set
+# CONFIG_HWCLOCK is not set
+# CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS is not set
+# CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set
+# CONFIG_IPCRM is not set
+# CONFIG_IPCS is not set
+# CONFIG_LOSETUP is not set
+# CONFIG_MDEV is not set
+# CONFIG_FEATURE_MDEV_CONF is not set
+# CONFIG_FEATURE_MDEV_EXEC is not set
+# CONFIG_MKSWAP is not set
+# CONFIG_FEATURE_MKSWAP_V0 is not set
+CONFIG_MORE=y
+# CONFIG_FEATURE_USE_TERMIOS is not set
+CONFIG_MOUNT=y
+CONFIG_FEATURE_MOUNT_NFS=y
+CONFIG_PIVOT_ROOT=y
+CONFIG_RDATE=y
+# CONFIG_READPROFILE is not set
+# CONFIG_SETARCH is not set
+# CONFIG_SWAPONOFF is not set
+# CONFIG_SWITCH_ROOT is not set
+CONFIG_UMOUNT=y
+# CONFIG_FEATURE_UMOUNT_ALL is not set
+
+#
+# Common options for mount/umount
+#
+CONFIG_FEATURE_MOUNT_LOOP=y
+# CONFIG_FEATURE_MTAB_SUPPORT is not set
+
+#
+# Miscellaneous Utilities
+#
+# CONFIG_ADJTIMEX is not set
+# CONFIG_BBCONFIG is not set
+CONFIG_CROND=y
+# CONFIG_DEBUG_CROND_OPTION is not set
+# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set
+CONFIG_CRONTAB=y
+# CONFIG_DC is not set
+# CONFIG_DEVFSD is not set
+# CONFIG_DEVFSD_MODLOAD is not set
+# CONFIG_DEVFSD_FG_NP is not set
+# CONFIG_DEVFSD_VERBOSE is not set
+# CONFIG_FEATURE_DEVFS is not set
+# CONFIG_EJECT is not set
+# CONFIG_LAST is not set
+# CONFIG_LESS is not set
+# CONFIG_FEATURE_LESS_BRACKETS is not set
+# CONFIG_FEATURE_LESS_FLAGS is not set
+# CONFIG_FEATURE_LESS_FLAGCS is not set
+# CONFIG_FEATURE_LESS_MARKS is not set
+# CONFIG_FEATURE_LESS_REGEXP is not set
+# CONFIG_HDPARM is not set
+# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set
+# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set
+# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set
+# CONFIG_MAKEDEVS is not set
+# CONFIG_FEATURE_MAKEDEVS_LEAF is not set
+# CONFIG_FEATURE_MAKEDEVS_TABLE is not set
+# CONFIG_MOUNTPOINT is not set
+# CONFIG_MT is not set
+# CONFIG_RUNLEVEL is not set
+# CONFIG_RX is not set
+CONFIG_STRINGS=y
+# CONFIG_SETSID is not set
+# CONFIG_TASKSET is not set
+CONFIG_TIME=y
+# CONFIG_WATCHDOG is not set
+
+#
+# Networking Utilities
+#
+# CONFIG_FEATURE_IPV6 is not set
+CONFIG_ARPING=y
+# CONFIG_DNSD is not set
+# CONFIG_ETHER_WAKE is not set
+# CONFIG_FAKEIDENTD is not set
+CONFIG_FTPGET=y
+CONFIG_FTPPUT=y
+# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set
+# CONFIG_HOSTNAME is not set
+# CONFIG_HTTPD is not set
+# CONFIG_FEATURE_HTTPD_WITHOUT_INETD is not set
+# CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP is not set
+# CONFIG_FEATURE_HTTPD_SETUID is not set
+# CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set
+# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set
+# CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES is not set
+# CONFIG_FEATURE_HTTPD_CGI is not set
+# CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set
+# CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set
+# CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set
+CONFIG_IFCONFIG=y
+CONFIG_FEATURE_IFCONFIG_STATUS=y
+# CONFIG_FEATURE_IFCONFIG_SLIP is not set
+# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set
+# CONFIG_FEATURE_IFCONFIG_HW is not set
+# CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS is not set
+# CONFIG_IFUPDOWN is not set
+# CONFIG_FEATURE_IFUPDOWN_IP is not set
+# CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN is not set
+# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set
+# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set
+# CONFIG_FEATURE_IFUPDOWN_IPX is not set
+# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set
+# CONFIG_INETD is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set
+# CONFIG_FEATURE_INETD_RPC is not set
+# CONFIG_IP is not set
+# CONFIG_FEATURE_IP_ADDRESS is not set
+# CONFIG_FEATURE_IP_LINK is not set
+# CONFIG_FEATURE_IP_ROUTE is not set
+# CONFIG_FEATURE_IP_TUNNEL is not set
+# CONFIG_FEATURE_IP_SHORT_FORMS is not set
+# CONFIG_IPADDR is not set
+# CONFIG_IPLINK is not set
+# CONFIG_IPROUTE is not set
+# CONFIG_IPTUNNEL is not set
+# CONFIG_IPCALC is not set
+# CONFIG_FEATURE_IPCALC_FANCY is not set
+# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set
+# CONFIG_NAMEIF is not set
+CONFIG_NC=y
+# CONFIG_NC_GAPING_SECURITY_HOLE is not set
+CONFIG_NETSTAT=y
+CONFIG_NSLOOKUP=y
+CONFIG_PING=y
+# CONFIG_FEATURE_FANCY_PING is not set
+# CONFIG_PING6 is not set
+# CONFIG_FEATURE_FANCY_PING6 is not set
+# CONFIG_ROUTE is not set
+# CONFIG_TELNET is not set
+# CONFIG_FEATURE_TELNET_TTYPE is not set
+# CONFIG_FEATURE_TELNET_AUTOLOGIN is not set
+# CONFIG_TELNETD is not set
+# CONFIG_FEATURE_TELNETD_INETD is not set
+CONFIG_TFTP=y
+CONFIG_FEATURE_TFTP_GET=y
+CONFIG_FEATURE_TFTP_PUT=y
+# CONFIG_FEATURE_TFTP_BLOCKSIZE is not set
+# CONFIG_DEBUG_TFTP is not set
+CONFIG_TRACEROUTE=y
+# CONFIG_FEATURE_TRACEROUTE_VERBOSE is not set
+# CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE is not set
+# CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set
+
+#
+# udhcp Server/Client
+#
+# CONFIG_APP_UDHCPD is not set
+# CONFIG_APP_UDHCPC is not set
+# CONFIG_APP_DUMPLEASES is not set
+# CONFIG_FEATURE_UDHCP_SYSLOG is not set
+# CONFIG_FEATURE_UDHCP_DEBUG is not set
+# CONFIG_VCONFIG is not set
+CONFIG_WGET=y
+# CONFIG_FEATURE_WGET_STATUSBAR is not set
+# CONFIG_FEATURE_WGET_AUTHENTICATION is not set
+# CONFIG_FEATURE_WGET_IP6_LITERAL is not set
+# CONFIG_FEATURE_WGET_LONG_OPTIONS is not set
+# CONFIG_ZCIP is not set
+
+#
+# Process Utilities
+#
+CONFIG_FREE=y
+# CONFIG_FUSER is not set
+CONFIG_KILL=y
+CONFIG_KILLALL=y
+# CONFIG_PIDOF is not set
+# CONFIG_FEATURE_PIDOF_SINGLE is not set
+# CONFIG_FEATURE_PIDOF_OMIT is not set
+CONFIG_PS=y
+# CONFIG_FEATURE_PS_WIDE is not set
+# CONFIG_RENICE is not set
+CONFIG_BB_SYSCTL=y
+CONFIG_TOP=y
+CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y
+CONFIG_UPTIME=y
+
+#
+# Shells
+#
+# CONFIG_FEATURE_SH_IS_ASH is not set
+# CONFIG_FEATURE_SH_IS_HUSH is not set
+# CONFIG_FEATURE_SH_IS_LASH is not set
+CONFIG_FEATURE_SH_IS_MSH=y
+# CONFIG_FEATURE_SH_IS_NONE is not set
+# CONFIG_ASH is not set
+# CONFIG_ASH_JOB_CONTROL is not set
+# CONFIG_ASH_READ_NCHARS is not set
+# CONFIG_ASH_READ_TIMEOUT is not set
+# CONFIG_ASH_ALIAS is not set
+# CONFIG_ASH_MATH_SUPPORT is not set
+# CONFIG_ASH_MATH_SUPPORT_64 is not set
+# CONFIG_ASH_GETOPTS is not set
+# CONFIG_ASH_BUILTIN_ECHO is not set
+# CONFIG_ASH_BUILTIN_TEST is not set
+# CONFIG_ASH_CMDCMD is not set
+# CONFIG_ASH_MAIL is not set
+# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_ASH_RANDOM_SUPPORT is not set
+# CONFIG_ASH_EXPAND_PRMT is not set
+# CONFIG_HUSH is not set
+# CONFIG_LASH is not set
+CONFIG_MSH=y
+
+#
+# Bourne Shell Options
+#
+# CONFIG_FEATURE_SH_EXTRA_QUIET is not set
+# CONFIG_FEATURE_SH_STANDALONE_SHELL is not set
+CONFIG_FEATURE_COMMAND_EDITING=y
+# CONFIG_FEATURE_COMMAND_EDITING_VI is not set
+CONFIG_FEATURE_COMMAND_HISTORY=15
+# CONFIG_FEATURE_COMMAND_SAVEHISTORY is not set
+CONFIG_FEATURE_COMMAND_TAB_COMPLETION=y
+# CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION is not set
+CONFIG_FEATURE_SH_FANCY_PROMPT=y
+
+#
+# System Logging Utilities
+#
+CONFIG_SYSLOGD=y
+# CONFIG_FEATURE_ROTATE_LOGFILE is not set
+CONFIG_FEATURE_REMOTE_LOG=y
+CONFIG_FEATURE_IPC_SYSLOG=y
+CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=16
+CONFIG_LOGREAD=y
+# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set
+CONFIG_KLOGD=y
+CONFIG_LOGGER=y

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.config.cmd
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.config.cmd	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.config.cmd	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,24 @@
+deps_config := \
+	sysklogd/Config.in \
+	shell/Config.in \
+	procps/Config.in \
+	networking/udhcp/Config.in \
+	networking/Config.in \
+	miscutils/Config.in \
+	util-linux/Config.in \
+	modutils/Config.in \
+	e2fsprogs/Config.in \
+	loginutils/Config.in \
+	init/Config.in \
+	findutils/Config.in \
+	editors/Config.in \
+	debianutils/Config.in \
+	console-tools/Config.in \
+	coreutils/Config.in \
+	archival/Config.in \
+	libbb/Config.in \
+	/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/Config.in
+
+.config include/config.h: $(deps_config)
+
+$(deps_config):

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.config_mine
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.config_mine	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.config_mine	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,635 @@
+#
+# Automatically generated make config: don't edit
+#
+HAVE_DOT_CONFIG=y
+
+#
+# Busybox Settings
+#
+
+#
+# General Configuration
+#
+CONFIG_NITPICK=y
+CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
+# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
+# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
+CONFIG_SHOW_USAGE=y
+# CONFIG_FEATURE_VERBOSE_USAGE is not set
+CONFIG_FEATURE_COMPRESS_USAGE=y
+# CONFIG_FEATURE_INSTALLER is not set
+# CONFIG_LOCALE_SUPPORT is not set
+CONFIG_GETOPT_LONG=y
+# CONFIG_FEATURE_DEVPTS is not set
+# CONFIG_FEATURE_CLEAN_UP is not set
+CONFIG_FEATURE_SUID=y
+# CONFIG_FEATURE_SUID_CONFIG is not set
+# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set
+# CONFIG_SELINUX is not set
+CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe"
+
+#
+# Build Options
+#
+CONFIG_STATIC=y
+# CONFIG_BUILD_LIBBUSYBOX is not set
+# CONFIG_FEATURE_FULL_LIBBUSYBOX is not set
+# CONFIG_FEATURE_SHARED_BUSYBOX is not set
+# CONFIG_LFS is not set
+USING_CROSS_COMPILER=y
+CROSS_COMPILER_PREFIX="arm-elf-"
+CONFIG_BUILD_AT_ONCE=y
+
+#
+# Debugging Options
+#
+# CONFIG_DEBUG is not set
+# CONFIG_DEBUG_PESSIMIZE is not set
+# CONFIG_NO_DEBUG_LIB is not set
+# CONFIG_DMALLOC is not set
+# CONFIG_EFENCE is not set
+CONFIG_DEBUG_YANK_SUSv2=y
+
+#
+# Installation Options
+#
+CONFIG_INSTALL_NO_USR=y
+CONFIG_INSTALL_APPLET_SYMLINKS=y
+# CONFIG_INSTALL_APPLET_HARDLINKS is not set
+# CONFIG_INSTALL_APPLET_DONT is not set
+PREFIX="./_install"
+
+#
+# Busybox Library Tuning
+#
+CONFIG_MD5_SIZE_VS_SPEED=3
+
+#
+# Applets
+#
+
+#
+# Archival Utilities
+#
+# CONFIG_AR is not set
+# CONFIG_FEATURE_AR_LONG_FILENAMES is not set
+# CONFIG_BUNZIP2 is not set
+# CONFIG_CPIO is not set
+# CONFIG_DPKG is not set
+# CONFIG_DPKG_DEB is not set
+# CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set
+# CONFIG_GUNZIP is not set
+# CONFIG_FEATURE_GUNZIP_UNCOMPRESS is not set
+# CONFIG_GZIP is not set
+# CONFIG_RPM2CPIO is not set
+# CONFIG_RPM is not set
+CONFIG_TAR=y
+# CONFIG_FEATURE_TAR_CREATE is not set
+CONFIG_FEATURE_TAR_BZIP2=y
+# CONFIG_FEATURE_TAR_LZMA is not set
+# CONFIG_FEATURE_TAR_FROM is not set
+CONFIG_FEATURE_TAR_GZIP=y
+# CONFIG_FEATURE_TAR_COMPRESS is not set
+# CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set
+# CONFIG_FEATURE_TAR_GNU_EXTENSIONS is not set
+# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set
+# CONFIG_UNCOMPRESS is not set
+# CONFIG_UNLZMA is not set
+# CONFIG_FEATURE_LZMA_FAST is not set
+# CONFIG_UNZIP is not set
+
+#
+# Common options for cpio and tar
+#
+# CONFIG_FEATURE_UNARCHIVE_TAPE is not set
+# CONFIG_FEATURE_DEB_TAR_GZ is not set
+# CONFIG_FEATURE_DEB_TAR_BZ2 is not set
+# CONFIG_FEATURE_DEB_TAR_LZMA is not set
+
+#
+# Coreutils
+#
+CONFIG_BASENAME=y
+# CONFIG_CAL is not set
+CONFIG_CAT=y
+# CONFIG_CATV is not set
+# CONFIG_CHGRP is not set
+CONFIG_CHMOD=y
+# CONFIG_CHOWN is not set
+CONFIG_CHROOT=y
+# CONFIG_CKSUM is not set
+# CONFIG_CMP is not set
+# CONFIG_COMM is not set
+CONFIG_CP=y
+CONFIG_CUT=y
+CONFIG_DATE=y
+# CONFIG_FEATURE_DATE_ISOFMT is not set
+CONFIG_DD=y
+# CONFIG_FEATURE_DD_SIGNAL_HANDLING is not set
+# CONFIG_FEATURE_DD_IBS_OBS is not set
+CONFIG_DF=y
+# CONFIG_DIFF is not set
+# CONFIG_FEATURE_DIFF_BINARY is not set
+# CONFIG_FEATURE_DIFF_DIR is not set
+# CONFIG_FEATURE_DIFF_MINIMAL is not set
+# CONFIG_DIRNAME is not set
+# CONFIG_DOS2UNIX is not set
+# CONFIG_UNIX2DOS is not set
+CONFIG_DU=y
+# CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K is not set
+CONFIG_ECHO=y
+# CONFIG_FEATURE_FANCY_ECHO is not set
+CONFIG_ENV=y
+# CONFIG_FEATURE_ENV_LONG_OPTIONS is not set
+CONFIG_EXPR=y
+# CONFIG_EXPR_MATH_SUPPORT_64 is not set
+CONFIG_FALSE=y
+CONFIG_FOLD=y
+CONFIG_HEAD=y
+# CONFIG_FEATURE_FANCY_HEAD is not set
+# CONFIG_HOSTID is not set
+# CONFIG_ID is not set
+# CONFIG_INSTALL is not set
+# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set
+# CONFIG_LENGTH is not set
+CONFIG_LN=y
+# CONFIG_LOGNAME is not set
+CONFIG_LS=y
+# CONFIG_FEATURE_LS_FILETYPES is not set
+CONFIG_FEATURE_LS_FOLLOWLINKS=y
+# CONFIG_FEATURE_LS_RECURSIVE is not set
+CONFIG_FEATURE_LS_SORTFILES=y
+CONFIG_FEATURE_LS_TIMESTAMPS=y
+# CONFIG_FEATURE_LS_USERNAME is not set
+CONFIG_FEATURE_LS_COLOR=y
+CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y
+# CONFIG_MD5SUM is not set
+CONFIG_MKDIR=y
+# CONFIG_FEATURE_MKDIR_LONG_OPTIONS is not set
+CONFIG_MKFIFO=y
+# CONFIG_MKNOD is not set
+CONFIG_MV=y
+# CONFIG_FEATURE_MV_LONG_OPTIONS is not set
+# CONFIG_NICE is not set
+# CONFIG_NOHUP is not set
+# CONFIG_OD is not set
+# CONFIG_PRINTENV is not set
+# CONFIG_PRINTF is not set
+CONFIG_PWD=y
+# CONFIG_REALPATH is not set
+CONFIG_RM=y
+CONFIG_RMDIR=y
+CONFIG_SEQ=y
+# CONFIG_SHA1SUM is not set
+CONFIG_SLEEP=y
+# CONFIG_FEATURE_FANCY_SLEEP is not set
+CONFIG_SORT=y
+# CONFIG_FEATURE_SORT_BIG is not set
+# CONFIG_STAT is not set
+# CONFIG_FEATURE_STAT_FORMAT is not set
+# CONFIG_STTY is not set
+# CONFIG_SUM is not set
+# CONFIG_SYNC is not set
+CONFIG_TAIL=y
+# CONFIG_FEATURE_FANCY_TAIL is not set
+CONFIG_TEE=y
+# CONFIG_FEATURE_TEE_USE_BLOCK_IO is not set
+CONFIG_TEST=y
+# CONFIG_FEATURE_TEST_64 is not set
+CONFIG_TOUCH=y
+CONFIG_TR=y
+# CONFIG_FEATURE_TR_CLASSES is not set
+# CONFIG_FEATURE_TR_EQUIV is not set
+CONFIG_TRUE=y
+# CONFIG_TTY is not set
+CONFIG_UNAME=y
+CONFIG_UNIQ=y
+CONFIG_USLEEP=y
+# CONFIG_UUDECODE is not set
+# CONFIG_UUENCODE is not set
+# CONFIG_WATCH is not set
+CONFIG_WC=y
+# CONFIG_WHO is not set
+# CONFIG_WHOAMI is not set
+CONFIG_YES=y
+
+#
+# Common options for cp and mv
+#
+# CONFIG_FEATURE_PRESERVE_HARDLINKS is not set
+
+#
+# Common options for ls, more and telnet
+#
+CONFIG_FEATURE_AUTOWIDTH=y
+
+#
+# Common options for df, du, ls
+#
+# CONFIG_FEATURE_HUMAN_READABLE is not set
+# CONFIG_FEATURE_MD5_SHA1_SUM_CHECK is not set
+
+#
+# Console Utilities
+#
+# CONFIG_CHVT is not set
+CONFIG_CLEAR=y
+# CONFIG_DEALLOCVT is not set
+# CONFIG_DUMPKMAP is not set
+# CONFIG_LOADFONT is not set
+# CONFIG_LOADKMAP is not set
+# CONFIG_OPENVT is not set
+# CONFIG_RESET is not set
+# CONFIG_SETCONSOLE is not set
+# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set
+# CONFIG_SETKEYCODES is not set
+# CONFIG_SETLOGCONS is not set
+
+#
+# Debian Utilities
+#
+CONFIG_MKTEMP=y
+# CONFIG_PIPE_PROGRESS is not set
+# CONFIG_READLINK is not set
+# CONFIG_FEATURE_READLINK_FOLLOW is not set
+# CONFIG_RUN_PARTS is not set
+# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set
+# CONFIG_START_STOP_DAEMON is not set
+# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set
+# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set
+CONFIG_WHICH=y
+
+#
+# Editors
+#
+CONFIG_AWK=y
+# CONFIG_FEATURE_AWK_MATH is not set
+# CONFIG_ED is not set
+# CONFIG_PATCH is not set
+CONFIG_SED=y
+# CONFIG_VI is not set
+# CONFIG_FEATURE_VI_COLON is not set
+# CONFIG_FEATURE_VI_YANKMARK is not set
+# CONFIG_FEATURE_VI_SEARCH is not set
+# CONFIG_FEATURE_VI_USE_SIGNALS is not set
+# CONFIG_FEATURE_VI_DOT_CMD is not set
+# CONFIG_FEATURE_VI_READONLY is not set
+# CONFIG_FEATURE_VI_SETOPTS is not set
+# CONFIG_FEATURE_VI_SET is not set
+# CONFIG_FEATURE_VI_WIN_RESIZE is not set
+# CONFIG_FEATURE_VI_OPTIMIZE_CURSOR is not set
+
+#
+# Finding Utilities
+#
+CONFIG_FIND=y
+# CONFIG_FEATURE_FIND_PRINT0 is not set
+# CONFIG_FEATURE_FIND_MTIME is not set
+# CONFIG_FEATURE_FIND_MMIN is not set
+# CONFIG_FEATURE_FIND_PERM is not set
+# CONFIG_FEATURE_FIND_TYPE is not set
+# CONFIG_FEATURE_FIND_XDEV is not set
+# CONFIG_FEATURE_FIND_NEWER is not set
+# CONFIG_FEATURE_FIND_INUM is not set
+CONFIG_FEATURE_FIND_EXEC=y
+CONFIG_GREP=y
+# CONFIG_FEATURE_GREP_EGREP_ALIAS is not set
+# CONFIG_FEATURE_GREP_FGREP_ALIAS is not set
+# CONFIG_FEATURE_GREP_CONTEXT is not set
+# CONFIG_XARGS is not set
+# CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION is not set
+# CONFIG_FEATURE_XARGS_SUPPORT_QUOTES is not set
+# CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT is not set
+# CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM is not set
+
+#
+# Init Utilities
+#
+# CONFIG_INIT is not set
+# CONFIG_DEBUG_INIT is not set
+# CONFIG_FEATURE_USE_INITTAB is not set
+# CONFIG_FEATURE_INIT_SCTTY is not set
+# CONFIG_FEATURE_EXTRA_QUIET is not set
+# CONFIG_FEATURE_INIT_COREDUMPS is not set
+# CONFIG_FEATURE_INITRD is not set
+# CONFIG_HALT is not set
+# CONFIG_MESG is not set
+
+#
+# Login/Password Management Utilities
+#
+# CONFIG_FEATURE_SHADOWPASSWDS is not set
+# CONFIG_USE_BB_SHADOW is not set
+# CONFIG_USE_BB_PWD_GRP is not set
+# CONFIG_ADDGROUP is not set
+# CONFIG_DELGROUP is not set
+# CONFIG_ADDUSER is not set
+# CONFIG_DELUSER is not set
+# CONFIG_GETTY is not set
+# CONFIG_FEATURE_UTMP is not set
+# CONFIG_FEATURE_WTMP is not set
+# CONFIG_LOGIN is not set
+# CONFIG_FEATURE_SECURETTY is not set
+# CONFIG_PASSWD is not set
+# CONFIG_SU is not set
+# CONFIG_SULOGIN is not set
+# CONFIG_VLOCK is not set
+
+#
+# Linux Ext2 FS Progs
+#
+# CONFIG_CHATTR is not set
+# CONFIG_E2FSCK is not set
+# CONFIG_FSCK is not set
+# CONFIG_LSATTR is not set
+# CONFIG_MKE2FS is not set
+# CONFIG_TUNE2FS is not set
+# CONFIG_E2LABEL is not set
+# CONFIG_FINDFS is not set
+
+#
+# Linux Module Utilities
+#
+CONFIG_INSMOD=y
+# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
+# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
+CONFIG_FEATURE_INSMOD_LOADINKMEM=y
+# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
+# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
+# CONFIG_RMMOD is not set
+CONFIG_LSMOD=y
+# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set
+CONFIG_MODPROBE=y
+# CONFIG_FEATURE_MODPROBE_MULTIPLE_OPTIONS is not set
+
+#
+# Options common to multiple modutils
+#
+# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
+CONFIG_FEATURE_2_4_MODULES=y
+# CONFIG_FEATURE_2_6_MODULES is not set
+CONFIG_FEATURE_QUERY_MODULE_INTERFACE=y
+
+#
+# Linux System Utilities
+#
+CONFIG_DMESG=y
+# CONFIG_FBSET is not set
+# CONFIG_FEATURE_FBSET_FANCY is not set
+# CONFIG_FEATURE_FBSET_READMODE is not set
+# CONFIG_FDFLUSH is not set
+# CONFIG_FDFORMAT is not set
+# CONFIG_FDISK is not set
+# FDISK_SUPPORT_LARGE_DISKS is not set
+# CONFIG_FEATURE_FDISK_WRITABLE is not set
+# CONFIG_FEATURE_AIX_LABEL is not set
+# CONFIG_FEATURE_SGI_LABEL is not set
+# CONFIG_FEATURE_SUN_LABEL is not set
+# CONFIG_FEATURE_OSF_LABEL is not set
+# CONFIG_FEATURE_FDISK_ADVANCED is not set
+# CONFIG_FREERAMDISK is not set
+# CONFIG_FSCK_MINIX is not set
+# CONFIG_MKFS_MINIX is not set
+# CONFIG_FEATURE_MINIX2 is not set
+# CONFIG_GETOPT is not set
+# CONFIG_HEXDUMP is not set
+# CONFIG_HWCLOCK is not set
+# CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS is not set
+# CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set
+# CONFIG_IPCRM is not set
+# CONFIG_IPCS is not set
+# CONFIG_LOSETUP is not set
+# CONFIG_MDEV is not set
+# CONFIG_FEATURE_MDEV_CONF is not set
+# CONFIG_FEATURE_MDEV_EXEC is not set
+# CONFIG_MKSWAP is not set
+# CONFIG_FEATURE_MKSWAP_V0 is not set
+CONFIG_MORE=y
+# CONFIG_FEATURE_USE_TERMIOS is not set
+CONFIG_MOUNT=y
+CONFIG_FEATURE_MOUNT_NFS=y
+CONFIG_PIVOT_ROOT=y
+CONFIG_RDATE=y
+# CONFIG_READPROFILE is not set
+# CONFIG_SETARCH is not set
+# CONFIG_SWAPONOFF is not set
+# CONFIG_SWITCH_ROOT is not set
+CONFIG_UMOUNT=y
+# CONFIG_FEATURE_UMOUNT_ALL is not set
+
+#
+# Common options for mount/umount
+#
+CONFIG_FEATURE_MOUNT_LOOP=y
+# CONFIG_FEATURE_MTAB_SUPPORT is not set
+
+#
+# Miscellaneous Utilities
+#
+# CONFIG_ADJTIMEX is not set
+# CONFIG_BBCONFIG is not set
+CONFIG_CROND=y
+# CONFIG_DEBUG_CROND_OPTION is not set
+# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set
+CONFIG_CRONTAB=y
+# CONFIG_DC is not set
+# CONFIG_DEVFSD is not set
+# CONFIG_DEVFSD_MODLOAD is not set
+# CONFIG_DEVFSD_FG_NP is not set
+# CONFIG_DEVFSD_VERBOSE is not set
+# CONFIG_FEATURE_DEVFS is not set
+# CONFIG_EJECT is not set
+# CONFIG_LAST is not set
+# CONFIG_LESS is not set
+# CONFIG_FEATURE_LESS_BRACKETS is not set
+# CONFIG_FEATURE_LESS_FLAGS is not set
+# CONFIG_FEATURE_LESS_FLAGCS is not set
+# CONFIG_FEATURE_LESS_MARKS is not set
+# CONFIG_FEATURE_LESS_REGEXP is not set
+# CONFIG_HDPARM is not set
+# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set
+# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set
+# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set
+# CONFIG_MAKEDEVS is not set
+# CONFIG_FEATURE_MAKEDEVS_LEAF is not set
+# CONFIG_FEATURE_MAKEDEVS_TABLE is not set
+# CONFIG_MOUNTPOINT is not set
+# CONFIG_MT is not set
+# CONFIG_RUNLEVEL is not set
+# CONFIG_RX is not set
+CONFIG_STRINGS=y
+# CONFIG_SETSID is not set
+# CONFIG_TASKSET is not set
+CONFIG_TIME=y
+# CONFIG_WATCHDOG is not set
+
+#
+# Networking Utilities
+#
+# CONFIG_FEATURE_IPV6 is not set
+CONFIG_ARPING=y
+# CONFIG_DNSD is not set
+# CONFIG_ETHER_WAKE is not set
+# CONFIG_FAKEIDENTD is not set
+CONFIG_FTPGET=y
+CONFIG_FTPPUT=y
+# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set
+# CONFIG_HOSTNAME is not set
+# CONFIG_HTTPD is not set
+# CONFIG_FEATURE_HTTPD_WITHOUT_INETD is not set
+# CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP is not set
+# CONFIG_FEATURE_HTTPD_SETUID is not set
+# CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set
+# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set
+# CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES is not set
+# CONFIG_FEATURE_HTTPD_CGI is not set
+# CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set
+# CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set
+# CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set
+CONFIG_IFCONFIG=y
+CONFIG_FEATURE_IFCONFIG_STATUS=y
+# CONFIG_FEATURE_IFCONFIG_SLIP is not set
+# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set
+# CONFIG_FEATURE_IFCONFIG_HW is not set
+# CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS is not set
+# CONFIG_IFUPDOWN is not set
+# CONFIG_FEATURE_IFUPDOWN_IP is not set
+# CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN is not set
+# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set
+# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set
+# CONFIG_FEATURE_IFUPDOWN_IPX is not set
+# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set
+# CONFIG_INETD is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set
+# CONFIG_FEATURE_INETD_RPC is not set
+# CONFIG_IP is not set
+# CONFIG_FEATURE_IP_ADDRESS is not set
+# CONFIG_FEATURE_IP_LINK is not set
+# CONFIG_FEATURE_IP_ROUTE is not set
+# CONFIG_FEATURE_IP_TUNNEL is not set
+# CONFIG_FEATURE_IP_SHORT_FORMS is not set
+# CONFIG_IPADDR is not set
+# CONFIG_IPLINK is not set
+# CONFIG_IPROUTE is not set
+# CONFIG_IPTUNNEL is not set
+# CONFIG_IPCALC is not set
+# CONFIG_FEATURE_IPCALC_FANCY is not set
+# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set
+# CONFIG_NAMEIF is not set
+CONFIG_NC=y
+# CONFIG_NC_GAPING_SECURITY_HOLE is not set
+CONFIG_NETSTAT=y
+CONFIG_NSLOOKUP=y
+CONFIG_PING=y
+# CONFIG_FEATURE_FANCY_PING is not set
+# CONFIG_PING6 is not set
+# CONFIG_FEATURE_FANCY_PING6 is not set
+# CONFIG_ROUTE is not set
+# CONFIG_TELNET is not set
+# CONFIG_FEATURE_TELNET_TTYPE is not set
+# CONFIG_FEATURE_TELNET_AUTOLOGIN is not set
+# CONFIG_TELNETD is not set
+# CONFIG_FEATURE_TELNETD_INETD is not set
+CONFIG_TFTP=y
+CONFIG_FEATURE_TFTP_GET=y
+CONFIG_FEATURE_TFTP_PUT=y
+# CONFIG_FEATURE_TFTP_BLOCKSIZE is not set
+# CONFIG_DEBUG_TFTP is not set
+CONFIG_TRACEROUTE=y
+# CONFIG_FEATURE_TRACEROUTE_VERBOSE is not set
+# CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE is not set
+# CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set
+
+#
+# udhcp Server/Client
+#
+# CONFIG_APP_UDHCPD is not set
+# CONFIG_APP_UDHCPC is not set
+# CONFIG_APP_DUMPLEASES is not set
+# CONFIG_FEATURE_UDHCP_SYSLOG is not set
+# CONFIG_FEATURE_UDHCP_DEBUG is not set
+# CONFIG_VCONFIG is not set
+CONFIG_WGET=y
+# CONFIG_FEATURE_WGET_STATUSBAR is not set
+# CONFIG_FEATURE_WGET_AUTHENTICATION is not set
+# CONFIG_FEATURE_WGET_IP6_LITERAL is not set
+# CONFIG_FEATURE_WGET_LONG_OPTIONS is not set
+# CONFIG_ZCIP is not set
+
+#
+# Process Utilities
+#
+CONFIG_FREE=y
+# CONFIG_FUSER is not set
+CONFIG_KILL=y
+CONFIG_KILLALL=y
+# CONFIG_PIDOF is not set
+# CONFIG_FEATURE_PIDOF_SINGLE is not set
+# CONFIG_FEATURE_PIDOF_OMIT is not set
+CONFIG_PS=y
+# CONFIG_FEATURE_PS_WIDE is not set
+# CONFIG_RENICE is not set
+CONFIG_BB_SYSCTL=y
+CONFIG_TOP=y
+CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y
+CONFIG_UPTIME=y
+
+#
+# Shells
+#
+# CONFIG_FEATURE_SH_IS_ASH is not set
+# CONFIG_FEATURE_SH_IS_HUSH is not set
+# CONFIG_FEATURE_SH_IS_LASH is not set
+CONFIG_FEATURE_SH_IS_MSH=y
+# CONFIG_FEATURE_SH_IS_NONE is not set
+# CONFIG_ASH is not set
+# CONFIG_ASH_JOB_CONTROL is not set
+# CONFIG_ASH_READ_NCHARS is not set
+# CONFIG_ASH_READ_TIMEOUT is not set
+# CONFIG_ASH_ALIAS is not set
+# CONFIG_ASH_MATH_SUPPORT is not set
+# CONFIG_ASH_MATH_SUPPORT_64 is not set
+# CONFIG_ASH_GETOPTS is not set
+# CONFIG_ASH_BUILTIN_ECHO is not set
+# CONFIG_ASH_BUILTIN_TEST is not set
+# CONFIG_ASH_CMDCMD is not set
+# CONFIG_ASH_MAIL is not set
+# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_ASH_RANDOM_SUPPORT is not set
+# CONFIG_ASH_EXPAND_PRMT is not set
+# CONFIG_HUSH is not set
+# CONFIG_LASH is not set
+CONFIG_MSH=y
+
+#
+# Bourne Shell Options
+#
+# CONFIG_FEATURE_SH_EXTRA_QUIET is not set
+# CONFIG_FEATURE_SH_STANDALONE_SHELL is not set
+CONFIG_FEATURE_COMMAND_EDITING=y
+# CONFIG_FEATURE_COMMAND_EDITING_VI is not set
+CONFIG_FEATURE_COMMAND_HISTORY=15
+# CONFIG_FEATURE_COMMAND_SAVEHISTORY is not set
+CONFIG_FEATURE_COMMAND_TAB_COMPLETION=y
+# CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION is not set
+CONFIG_FEATURE_SH_FANCY_PROMPT=y
+
+#
+# System Logging Utilities
+#
+CONFIG_SYSLOGD=y
+# CONFIG_FEATURE_ROTATE_LOGFILE is not set
+CONFIG_FEATURE_REMOTE_LOG=y
+CONFIG_FEATURE_IPC_SYSLOG=y
+CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=16
+CONFIG_LOGREAD=y
+# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set
+CONFIG_KLOGD=y
+CONFIG_LOGGER=y

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.depend
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.depend	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.depend	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2173 @@
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/ipcs.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/dmesg.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/rdate.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/fdisk.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/fdisk/advanced.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/osf/label.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/sun/label.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/sgi/label.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/aix/label.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/fdisk/writable.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/fdformat.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/getopt.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/swaponoff.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/mkswap.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/mkswap/v0.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/more.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/use/termios.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/mount.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/mtab/support.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/mtab/support.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/mount/loop.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/mount/nfs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/mkfs_minix.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/minix2.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/fbset.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/fbset/readmode.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/fbset/fancy.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/switch_root.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/pivot_root.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/freeramdisk.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/freeramdisk.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/fdflush.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/nfsmount.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/nfsmount.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/mount/nfs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/ipcrm.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/hexdump.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/dump.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/umount.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/mtab/support.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/mount/loop.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/umount/all.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/setarch.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/hwclock.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/hwclock/adjtime/fhs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/hwclock/long/options.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/fsck_minix.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/minix2.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/mdev.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/xregex.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/mdev/exec.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/mdev/conf.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/losetup.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/util-linux/readprofile.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/editors/patch.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/editors/vi.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/vi/optimize/cursor.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/vi/win/resize.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/vi/win/resize.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/vi/set.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/vi/setopts.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/vi/readonly.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/vi/dot/cmd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/vi/use/signals.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/vi/search.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/vi/yankmark.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/vi/colon.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/locale/support.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/bb/bt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/bb/ver.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/editors/awk.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/xregex.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/awk/math.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/editors/ed.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/editors/sed.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/xregex.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/applets/version.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/bb/bt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/bb/ver.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/applets/applets.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/usage_compressed.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/grp_.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/pwd_.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/applets.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/usage.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/suid/config/quiet.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/suid/config.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/suid/config.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/suid.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/suid.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/compress/usage.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/show/usage.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/applets/busybox.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/autowidth.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/locale/support.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/installer.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/installer.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/procps/free.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/procps/pidof.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/pidof/omit.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/pidof/single.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/procps/sysctl.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/procps/ps.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/ps/wide.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/selinux.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/procps/top.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/top/cpu/usage/percentage.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/top/cpu/usage/percentage.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/use/termios.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/procps/uptime.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/procps/fuser.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/procps/renice.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/procps/kill.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/killall.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/init/init.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/init/init_shared.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/syslogd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/swaponoff.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/initrd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/init/coredumps.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/extra/quiet.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/init/sctty.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/use/inittab.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/debug/init.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/selinux.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/init/halt.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/initrd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/init.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/init/init_shared.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/init/init_shared.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/init.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/init/mesg.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/findutils/find.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/find/exec.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/find/inum.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/find/newer.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/find/xdev.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/find/type.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/find/perm.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/find/mmin.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/find/mtime.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/find/print0.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/findutils/xargs.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/xargs/support/zero/term.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/xargs/support/termopt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/xargs/support/quotes.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/xargs/support/confirmation.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/findutils/grep.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/xregex.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/grep/context.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/grep/fgrep/alias.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/grep/egrep/alias.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libpwdgrp/pwd_grp_internal.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/shadow_.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/grp_.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/pwd_.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libpwdgrp/pwd_grp.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libpwdgrp/pwd_grp_internal.c \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/shadow_.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/loginutils/sulogin.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/shadowpasswds.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/selinux.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/loginutils/vlock.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/loginutils/passwd.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/shadowpasswds.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/loginutils/deluser.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/deluser.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/shadowpasswds.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/loginutils/addgroup.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/shadowpasswds.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/loginutils/adduser.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/shadowpasswds.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/loginutils/su.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/utmp.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/selinux.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/loginutils/login.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/securetty.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/wtmp.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/utmp.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/selinux.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/loginutils/getty.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/syslogd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/wtmp.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/utmp.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/applets.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/pwd_.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/use/bb/pwd/grp.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/platform.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/shadow_.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/grp_.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/pwd_.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/top/cpu/usage/percentage.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/devfs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/shadowpasswds.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/selinux.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/buffers/go/in/bss.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/buffers/go/on/stack.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/inet_common.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/platform.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/shadow_.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/use/bb/shadow.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/usage.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ipc/syslog.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/remote/log.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/rotate/logfile.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/ps/wide.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/pidof/omit.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/pidof/single.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tftp/blocksize.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tftp/put.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tftp/get.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/telnetd/inetd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/telnet/autologin.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/fancy/ping6.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/fancy/ping.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/nc/gaping/security/hole.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ipcalc/fancy.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ifconfig/hw.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ifconfig/memstart/ioaddr/irq.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ifconfig/slip.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ifconfig/status.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/httpd/auth/md5.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/httpd/basic/auth.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/httpd/setuid.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/httpd/without/inetd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ipv6.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/makedevs/table.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/makedevs/leaf.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/hdparm/hdio/getset/dma.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/hdparm/hdio/tristate/hwif.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/hdparm/hdio/drive/reset.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/hdparm/hdio/unregister/hwif.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/hdparm/hdio/scan/hwif.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/hdparm/get/identity.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/devfsd/fg/np.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/mtab/support.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/mount/loop.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/mdev/exec.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/insmod/load/map.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/xargs/support/zero/term.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/xargs/support/termopt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/xargs/support/confirmation.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/grep/context.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/grep/egrep/alias.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/find/exec.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/find/inum.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/find/newer.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/find/type.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/find/perm.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/find/mmin.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/find/mtime.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/find/print0.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/start/stop/daemon/fancy.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/readlink/follow.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/md5/sha1/sum/check.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/skip/feature/human/readable.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/human/readable.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/autowidth.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/fancy/tail.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/stat/format.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/sort/big.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/fancy/sleep.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ls/color.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ls/timestamps.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ls/sortfiles.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ls/recursive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ls/followlinks.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ls/filetypes.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/fancy/head.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/fancy/echo.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/skip/feature/du/default/blocksize_1k.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/du/default/blocksize_1k.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/dd/ibs/obs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/date/isofmt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tar/compress.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tar/gzip.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tar/lzma.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tar/bzip2.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tar/create.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/selinux.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/grp_.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/use/bb/pwd/grp.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/applets.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/logger.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/klogd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/logread.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/syslogd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/msh.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/lash.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/hush.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ash.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/sh/is/msh.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/sh/is/lash.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/sh/is/hush.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/sh/is/ash.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/uptime.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/top.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/bb/sysctl.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/renice.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ps.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/pidof.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/killall.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/kill.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/fuser.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/free.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/zcip.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/wget.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/vconfig.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/app/dumpleases.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/app/udhcpc.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/app/udhcpd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/traceroute.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/tftp.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/telnetd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/telnet.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/route.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ping6.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ping.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/nslookup.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/netstat.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/nc.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/nameif.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ipcalc.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/iptunnel.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/iproute.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/iplink.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ipaddr.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ip.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/inetd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ifupdown.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ifconfig.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/httpd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/hostname.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ftpput.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ftpget.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/fakeidentd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ether/wake.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/dnsd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/arping.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/watchdog.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/time.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/setsid.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/strings.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/rx.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/runlevel.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/mt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/mountpoint.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/makedevs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/hdparm.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/less.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/last.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/eject.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/devfsd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/dc.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/crontab.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/crond.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/bbconfig.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/adjtimex.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/umount.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/switch/root.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/swaponoff.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/setarch.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/readprofile.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/rdate.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/pivot/root.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/mount.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/more.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/mkswap.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/mdev.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/losetup.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ipcs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ipcrm.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/hwclock.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/hexdump.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/getopt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/mkfs/minix.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/fsck/minix.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/freeramdisk.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/fdisk.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/fdformat.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/fdflush.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/fbset.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/dmesg.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/modprobe.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/lsmod.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/rmmod.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/insmod.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/findfs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/e2label.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/tune2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/mke2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/lsattr.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/fsck.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/e2fsck.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/chattr.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/vlock.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/sulogin.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/su.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/passwd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/login.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/getty.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/deluser.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/adduser.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/delgroup.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/addgroup.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/mesg.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/halt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/initrd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/init.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/xargs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/grep/fgrep/alias.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/grep/egrep/alias.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/grep.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/find.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/vi.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/sed.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/patch.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ed.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/awk.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/which.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/start/stop/daemon.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/run/parts.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/readlink.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/pipe/progress.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/mktemp.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/setlogcons.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/setkeycodes.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/setconsole.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/reset.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/openvt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/loadkmap.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/loadfont.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/dumpkmap.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/deallocvt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/clear.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/chvt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/yes.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/whoami.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/who.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/wc.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/watch.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/uuencode.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/uudecode.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/usleep.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/uniq.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/uname.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/tty.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/true.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/tr.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/touch.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/test.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/tee.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/tail.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/sync.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/sum.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/stty.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/stat.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/sort.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/sleep.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/sha1sum.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/seq.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/rmdir.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/rm.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/realpath.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/pwd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/printf.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/printenv.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/od.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/nohup.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/nice.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/mv.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/mknod.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/mkfifo.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/mkdir.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/md5sum.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ls.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/logname.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ln.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/length.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/install.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/id.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/hostid.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/head.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/fold.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/false.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/expr.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/env.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/echo.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/du.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/unix2dos.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/dos2unix.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/dirname.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/diff.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/df.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/dd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/date.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/cut.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/cp.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/comm.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/cmp.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/cksum.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/chroot.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/chown.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/chmod.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/chgrp.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/catv.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/cat.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/cal.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/basename.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/unzip.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/unlzma.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/uncompress.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/tar.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/rpm.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/rpm2cpio.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/gzip.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/gunzip.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/dpkg/deb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/dpkg.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/cpio.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/bunzip2.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/ar.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/install/no/usr.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/verbose/usage.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/makedevs.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/makedevs/table.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/makedevs/leaf.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/time.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/watchdog.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/last.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/crond.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/crond/call/sendmail.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/debug/crond/option.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/adjtimex.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/less.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/xregex.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/less/regexp.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/less/marks.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/less/flagcs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/less/flags.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/less/brackets.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/bbconfig.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/hdparm.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/hdparm/hdio/getset/dma.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/hdparm/hdio/getset/dma.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/hdparm/hdio/tristate/hwif.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/hdparm/hdio/tristate/hwif.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/hdparm/hdio/drive/reset.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/hdparm/hdio/drive/reset.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/hdparm/hdio/unregister/hwif.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/hdparm/hdio/unregister/hwif.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/hdparm/hdio/scan/hwif.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/hdparm/hdio/scan/hwif.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/hdparm/hdio/scan/hwif.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/hdparm/get/identity.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/hdparm/get/identity.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/hdparm/get/identity.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/devfsd.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/xregex.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/devfsd/verbose.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/devfsd/verbose.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/devfsd/fg/np.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/devfsd/modload.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/debug.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/debug.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/mountpoint.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/mt.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/dc.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/crontab.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/rx.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/strings.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/eject.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/mtab/support.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/setsid.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/miscutils/runlevel.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2fsbb.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/lsattr.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2fsbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/lfs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2fsck.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2fsck.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/util.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/util.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkid.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2fsbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/lfs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2fsck.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/uuid.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_ext_attr.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/fsck.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/kernel-jbd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/kernel-list.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkid.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/chattr.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2fsbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/lfs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/tune2fs.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/uuid.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/kernel-jbd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/util.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkid.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2fsbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/grp_.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/pwd_.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/findfs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/findfs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/e2label.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/e2label.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/fsck.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/fsck.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkid.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2fsbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/devfs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/mke2fs.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/uuid.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/util.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2fsbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/make_directory.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/bb_xdaemon.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/error_msg.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/safe_read.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/printf.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/get_last_path_component.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/find_root_device.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/chomp.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/procps.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/top/cpu/usage/percentage.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/get_line_from_file.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/inet_common.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/inet_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ipv6.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/xgetlarg.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/crc32.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/create_icmp6_socket.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ipv6.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/mode_string.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/compare_string_array.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/pwd2spwd.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/shadow_.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/correct_password.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/shadowpasswds.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/bb_do_delay.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/perror_nomsg_and_die.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/create_icmp_socket.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/xgethostbyname2.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ipv6.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/setup_environment.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/xregcomp.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/xregex.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/md5.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/md5/size/vs/speed.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/llist.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/bb_xlisten.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/process_escape_sequence.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/bb_asprintf.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/run_shell.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/selinux.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/vdprintf.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/opendir.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/fgets_str.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/safe_strncpy.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/vfork_daemon_rexec.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/xgethostbyname.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/login.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/get_terminal_width_height.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/obscure.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/recursive_action.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/qmodule.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/speed_table.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/loop.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/herror_msg_and_die.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/trim.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/perror_msg_and_die.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/device_open.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/xconnect.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/xreadlink.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/mtab_file.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/mtab/support.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/skip_whitespace.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/bb_xsocket.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/u_signal_names.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/verror_msg.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/sha1.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/wfopen.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/restricted_shell.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/error_msg_and_die.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/xgetularg.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/xstat.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/getopt_ulflags.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ps.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/tar.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ar.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/clean/up.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/getopt/long.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/xgetcwd.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/bb_askpass.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/copy_file.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/preserve/hardlinks.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/run_parts.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/dump.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/dump.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/default_error_retval.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/find_mount_point.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/concat_subpath_file.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/concat_path_file.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/bb_xchdir.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/human_readable.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/read_package_field.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/last_char_is.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/print_file.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/change_identity.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/vherror_msg.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/find_pid_by_name.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/isdirectory.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/inode_hash.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/get_console.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/vperror_msg.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/messages.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/bb/bt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/bb/ver.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/xfuncs.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/debug.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/busybox/exec/path.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/simplify_path.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/herror_msg.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/bb_xbind.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/full_write.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/parse_number.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/parse_mode.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/perror_msg.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/safe_write.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/mtab.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/mtab/support.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/copyfd.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/ask_confirmation.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/kernel_version.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/safe_strtol.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/remove_file.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/pw_encrypt.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/full_read.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/bb_pwd.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/grp_.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/pwd_.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/libbb/daemon.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/md5_sha1_sum.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/md5/sha1/sum/check.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/sha1sum.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/sha1sum.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/md5sum.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/md5sum.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/printf.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/uname.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/sleep.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/fancy/sleep.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/wc.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/locale/support.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/basename.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/nice.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/mv.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/libcoreutils/coreutils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/mv/long/options.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/dd.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/dd/ibs/obs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/dd/signal/handling.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/df.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/human/readable.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/uudecode.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/mknod.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/libcoreutils/coreutils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/diff.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/diff/minimal.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/diff/dir.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/diff/binary.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/ln.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/mkfifo.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/libcoreutils/coreutils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/dos2unix.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/tee.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tee/use/block/io.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/date.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/date/isofmt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/date/isofmt.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/rm.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/expr.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/expr/math/support_64.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/true.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/test.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/test_64.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/cksum.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/fold.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/debug/yank/susv2.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/tr.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/tr/equiv.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/tr/classes.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/sort.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/sort/big.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/seq.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/nohup.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/pwd.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/chmod.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/realpath.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/yes.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/head.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/fancy/head.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/debug/yank/susv2.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/od.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/dump.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/cp.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/libcoreutils/coreutils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/stty.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/sum.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/install.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/libcoreutils/coreutils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/install/long/options.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/uuencode.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/stat.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/stat/format.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/stat/format.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/uniq.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/chown.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/echo.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/fancy/echo.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/length.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/env.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/env/long/options.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/tail.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/fancy/tail.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/debug/yank/susv2.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/false.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/hostid.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/catv.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/usleep.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/who.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/chroot.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/cal.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/locale/support.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/chgrp.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/printenv.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/mkdir.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/mkdir/long/options.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/watch.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/cat.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/du.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/human/readable.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/du/default/blocksize_1k.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/sync.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/rmdir.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/ls.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/human/readable.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/autowidth.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ls/color/is/default.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ls/color.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ls/username.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/ls/timestamps.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ls/timestamps.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/ls/sortfiles.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/ls/sortfiles.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ls/sortfiles.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/ls/recursive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ls/recursive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ls/followlinks.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ls/filetypes.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/selinux.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/locale/support.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/cmp.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/dirname.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/tty.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/touch.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/logname.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/whoami.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/cut.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/comm.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/id.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/pwd_.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/selinux.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/shell/cmdedit.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/command/savehistory.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/command/editing/vi.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ash.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/shell/hush.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/shell/cmdedit.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/sh/fancy/prompt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/command/editing.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/sh/standalone/shell.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/sh/extra/quiet.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/clean/up.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/bb/ver.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/shell/lash.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/shell/cmdedit.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/sh/fancy/prompt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/command/editing.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/command/editing.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/sh/standalone/shell.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/sh/extra/quiet.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/clean/up.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/locale/support.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/shell/msh.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/shell/cmdedit.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/sh/fancy/prompt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/command/editing.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/sh/standalone/shell.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/sh/extra/quiet.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/busybox/exec/path.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/shell/cmdedit.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/shell/cmdedit.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/pwd_.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/sh/fancy/prompt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/command/username/completion.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/command/tab/completion.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/command/savehistory.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/command/history.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/command/editing/vi.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/command/editing.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/command/editing.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ash.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/clean/up.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/locale/support.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/shell/ash.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/shell/cmdedit.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/pwd_.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/sh/fancy/prompt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/command/tab/completion.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/command/savehistory.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/command/editing/vi.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/command/editing.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/sh/standalone/shell.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/sh/extra/quiet.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ash/expand/prmt.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ash/random/support.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ash/optimize/for/size.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ash/mail.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/ash/cmdcmd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ash/cmdcmd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/ash/builtin/test.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ash/builtin/test.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/ash/builtin/echo.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ash/builtin/echo.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ash/getopts.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ash/math/support_64.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ash/math/support.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/ash/alias.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ash/alias.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ash/read/timeout.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ash/read/nchars.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/ash/job/control.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/ash/job/control.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/busybox/exec/path.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/locale/support.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/debianutils/pipe_progress.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/debianutils/which.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/debianutils/start_stop_daemon.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/pwd_.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/start/stop/daemon/long/options.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/skip/feature/start/stop/daemon/fancy.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/start/stop/daemon/fancy.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/start/stop/daemon/fancy.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/debianutils/readlink.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/readlink/follow.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/debianutils/mktemp.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/debianutils/run_parts.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/console-tools/setkeycodes.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/console-tools/dumpkmap.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/console-tools/setconsole.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/setconsole/long/options.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/console-tools/setlogcons.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/console-tools/reset.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/console-tools/loadfont.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/console-tools/chvt.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/console-tools/clear.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/console-tools/loadkmap.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/console-tools/openvt.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/console-tools/deallocvt.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/modutils/lsmod.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/query/module/interface.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/check/tainted/module.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/lsmod/pretty_2_6/output.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/modutils/rmmod.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/query/module/interface.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature_2_6/modules.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature_2_4/modules.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/modutils/modprobe.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature_2_6/modules.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature_2_4/modules.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/modprobe/multiple/options.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/modutils/insmod.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature_2_6/modules.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature_2_4/modules.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/check/tainted/module.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/check/tainted/module.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/insmod/load/map/full.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/insmod/load/map.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/insmod/loadinkmem.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/insmod/ksymoops/symbols.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/insmod/version/checking.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/sysklogd/logger.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/syslogd.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/sysklogd/klogd.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/sysklogd/syslogd.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ipc/syslog/buffer/size.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ipc/syslog.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/remote/log.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/rotate/logfile.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/bb/ver.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/sysklogd/logread.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/logread/reduced/locking.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/uncompress.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/rpm.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/dpkg_deb.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/deb/tar/bz2.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/deb/tar/gz.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/ar.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/unzip.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/unlzma.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/gzip.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/gunzip.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/gunzip.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/gunzip/uncompress.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/dpkg.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/deb/tar/bz2.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/deb/tar/gz.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/tar.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/tar/long/options.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tar/long/options.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/tar/compress.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tar/compress.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/tar/gzip.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tar/gzip.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/tar/from.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tar/from.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/tar/lzma.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tar/lzma.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/tar/bzip2.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tar/bzip2.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/tar/create.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tar/create.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/bunzip2.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/cpio.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/rpm2cpio.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/iptunnel.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ip_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/utils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/fakeidentd.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/nameif.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/interface.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/inet_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ipv6.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/ipaddr.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ip_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/utils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/wget.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/wget/ip6/literal.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/wget/authentication.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/wget/statusbar.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/ip.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ip_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/utils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ip/tunnel.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ip/route.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ip/link.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ip/address.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/nslookup.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/tftp.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/debug/tftp.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/tftp/blocksize.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tftp/blocksize.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/tftp/put.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tftp/put.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/tftp/get.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tftp/get.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/dnsd.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/ifupdown.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ifupdown/mapping.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/ifupdown/ipv6.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ifupdown/ipv6.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/ifupdown/ipv4.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ifupdown/ipv4.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ifupdown/ip.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/ether-wake.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/route.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/inet_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ipv6.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/telnetd.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/telnetd/inetd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ipv6.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/login.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/devpts.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/nc.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/nc/gaping/security/hole.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/inetd.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/inetd/rpc.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/chargen.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/daytime.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/time.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/discard.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/echo.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ipv6.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/zcip.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/traceroute.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/inet_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/traceroute/use/icmp.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/traceroute/source/route.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/traceroute/verbose.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/hostname.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/arping.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/netstat.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/inet_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/pwd_.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/route.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ipv6.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/ftpgetput.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/ftpgetput/long/options.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/ftpput.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/ftpget.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/ping6.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/fancy/ping6.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/fancy/ping.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/httpd.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/skip/feature/httpd/encode/url/str.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/httpd/encode/url/str.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/httpd/encode/url/str.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/httpd/set/remote/port/to/env.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/httpd/config/with/script/interpr.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/httpd/cgi.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/httpd/cgi.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/httpd/config/with/mime/types.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/skip/feature/httpd/auth/md5.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/httpd/auth/md5.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/httpd/auth/md5.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/skip/feature/httpd/basic/auth.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/httpd/basic/auth.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/httpd/basic/auth.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/skip/feature/httpd/setuid.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/httpd/setuid.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/httpd/setuid.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/httpd/reload/config/sighup.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/skip/feature/httpd/without/inetd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/httpd/without/inetd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/httpd/without/inetd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/lfs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/ifconfig.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/inet_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ifconfig/broadcast/plus.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ifconfig/hw.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ifconfig/memstart/ioaddr/irq.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ifconfig/slip.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ifconfig/status.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ipv6.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/iplink.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ip_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/utils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/iproute.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ip_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/utils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/telnet.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/telnet/autologin.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/telnet/ttype.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/autowidth.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/ipcalc.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/ipcalc/long/options.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/use/feature/ipcalc/fancy.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/ipcalc/fancy.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ipcalc/fancy.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/vconfig.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/ping.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/fancy/ping6.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/fancy/ping.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/usage.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/applets.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/usage.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/mconf.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lkc.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lxdialog/dialog.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/menu.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lkc.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/symbol.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lkc.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/util.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lkc.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lkc.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lkc_proto.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/expr.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/expr.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lkc.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/confdata.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lkc.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/conf.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lkc.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/clientpacket.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpc.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/options.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/clientpacket.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpd.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/options.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/packet.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/arpping.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/arpping.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpd.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/script.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpc.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/options.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpd.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/pidfile.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/pidfile.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/packet.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/packet.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/options.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpd.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/clientpacket.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/packet.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/leases.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/static_leases.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/leases.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/files.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/arpping.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/options.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpd.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpc.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/signalpipe.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/socket.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/clientsocket.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpc.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/options.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/clientpacket.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/bb/ver.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpd.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/serverpacket.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/signalpipe.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/socket.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/static_leases.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/files.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/arpping.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/options.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/udhcp/debug.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/static_leases.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/static_leases.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/udhcp/debug.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpc.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/libbb_udhcp.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpd.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/libbb_udhcp.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/leases.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/static_leases.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpd.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/signalpipe.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/signalpipe.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/serverpacket.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/serverpacket.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/static_leases.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/options.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpd.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/libbb_udhcp.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/packet.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/install/no/usr.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/files.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/static_leases.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/files.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/options.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/udhcp/debug.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dumpleases.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/libbb_udhcp.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/leases.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpd.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/serverpacket.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/packet.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/clientsocket.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/clientsocket.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/pidfile.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/udhcp/syslog.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/udhcp/syslog.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/bb/ver.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/socket.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/socket.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/options.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/files.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/options.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/dhcpd.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/common.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/udhcp/libbb_udhcp.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/udhcp/debug.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/iptunnel.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/rt_names.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ip_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/utils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/rtm_map.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/rt_names.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/utils.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/utils.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/utils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/inet_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ll_addr.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/rt_names.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/utils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ll_map.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ll_map.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/libnetlink.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/utils.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/rtm_map.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ll_map.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/libnetlink.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/rt_names.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/rt_names.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ipaddress.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/rt_names.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ip_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/utils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ip_common.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/iplink.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/rt_names.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ip_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/utils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/iproute.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/rt_names.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ip_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/utils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ip_parse_common_args.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ip_common.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/utils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ll_proto.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/rt_names.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/utils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/ll_types.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/rt_names.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/libnetlink.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/networking/libiproute/libnetlink.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/data_extract_to_buffer.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/data_skip.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/get_header_cpio.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/unpack_ar_archive.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/data_extract_to_stdout.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/get_header_ar.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/ar/long/filenames.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/decompress_bunzip2.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/init_handle.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/check_header_gzip.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/get_header_tar_lzma.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/open_transformer.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/header_list.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/data_align.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/header_verbose_list.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/archive_xread_all.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/get_header_tar.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tar/gnu/extensions.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/tar/oldgnu/compatibility.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/filter_accept_list.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/decompress_uncompress.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/get_header_tar_bz2.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/seek_by_jump.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/unarchive/tape.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/seek_by_char.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/header_skip.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/filter_accept_reject_list.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/archive_xread_all_eof.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/decompress_unzip.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/decompress_unlzma.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/lzma/fast.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/clean/up.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/filter_accept_list_reassign.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/enable/feature/deb/tar/lzma.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/deb/tar/bz2.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/feature/deb/tar/gz.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/data_extract_all.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/find_list_entry.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/filter_accept_all.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/archival/libunarchive/get_header_tar_gz.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/unarchive.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/libcoreutils/cp_mv_stat.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/libcoreutils/coreutils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/libcoreutils/getopt_mk_fifo_nod.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/coreutils/libcoreutils/coreutils.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/libbb.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/read_bb_file.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/bitmaps.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/test_io.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/bmove.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fsP.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/getsize.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/lfs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/alloc_tables.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/expanddir.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/bmap.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/bitops.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_err.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_io.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_types.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/dupfs.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fsP.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/kernel-jbd.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/badblocks.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fsP.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/getsectsize.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/lfs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/inode_io.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/bb_compat.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fsP.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/valid_blk.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/newdir.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/namei.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/openfs.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/e2image.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/inode.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/e2image.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fsP.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/bitops.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/initialize.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/icount.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/bb_inode.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/rw_bitmaps.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/e2image.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/freefs.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fsP.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/inline.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/dirhash.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/flushb.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/version.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/res_gdt.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/get_pathname.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/dirblock.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext_attr.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_ext_attr.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/block.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/write_bb_file.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/unlink.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/io_manager.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/brel_ma.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/brel.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/mkjournal.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/kernel-jbd.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2fsck.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ismounted.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/irel_ma.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/irel.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs_inline.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/bitops.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/check_desc.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/dblist_dir.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fsP.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_types.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/rs_bitmap.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/dir_iterate.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fsP.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/closefs.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fsP.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/cmp_bitmaps.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fsP.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/swapfs.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_ext_attr.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/imager.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/gen_bitmap.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/mkdir.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/fileio.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/alloc_stats.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/lookup.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/unix_io.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/lfs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/alloc_sb.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_io.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/lfs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/read_bb.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/finddev.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/dblist.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fsP.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ind_block.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/alloc.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/link.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/sparse.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2fsP.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/gen_uuid.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/uuidP.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/pack.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/uuidP.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/uuid_time.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/uuidP.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/unpack.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/uuidP.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/compare.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/uuidP.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/parse.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/uuidP.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/uuidP.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/uuid.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/unparse.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/uuidP.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/ostype.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/ls.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/fgetsetflags.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/ps.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/fgetsetversion.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/mntopts.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/pe.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/pf.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/uuid.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_types.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/parse_num.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/busybox.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/feature.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/iod.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/hashstr.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/e2p/e2p.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/devname.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkidP.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/dev.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkidP.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/save.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkidP.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkid_getsize.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkidP.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/resolve.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/probe.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkidP.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/cache.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkidP.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/version.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkid.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/probe.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/probe.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkidP.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/uuid.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkidP.h: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/list.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkid.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/include/config/config/lfs.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/devno.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkidP.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/read.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkidP.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/uuid/uuid.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/tag.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/e2fsprogs/blkid/blkidP.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lxdialog/inputbox.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lxdialog/dialog.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lxdialog/msgbox.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lxdialog/dialog.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lxdialog/checklist.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lxdialog/dialog.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lxdialog/menubox.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lxdialog/dialog.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lxdialog/textbox.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lxdialog/dialog.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lxdialog/util.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lxdialog/colors.h \
+   /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lxdialog/dialog.h
+
+/home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lxdialog/yesno.o: /home/db90h/llf/trunk/Marvell/Src/uClinux-dist/user/busybox-1.2.1/scripts/config/lxdialog/dialog.h

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.indent.pro
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.indent.pro	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/.indent.pro	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,33 @@
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--break-before-boolean-operator
+--no-blank-lines-after-commas
+--braces-on-if-line
+--braces-on-struct-decl-line
+--comment-indentation25
+--declaration-comment-column25
+--no-comment-delimiters-on-blank-lines
+--cuddle-else
+--continuation-indentation4
+--case-indentation0
+--else-endif-column33
+--space-after-cast
+--line-comments-indentation0
+--declaration-indentation1
+--dont-format-first-column-comments
+--dont-format-comments
+--honour-newlines
+--indent-level4
+/* changed from 0 to 4 */
+--parameter-indentation4
+--line-length78 /* changed from 75 */
+--continue-at-parentheses
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--dont-star-comments
+--leave-optional-blank-lines
+--dont-space-special-semicolon
+--tab-size4
+/* additions by Mark */
+--case-brace-indentation0
+--leave-preprocessor-space

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/AUTHORS
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/AUTHORS	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/AUTHORS	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,173 @@
+List of the authors of code contained in BusyBox.
+
+If you have code in BusyBox, you should be listed here.  If you should be
+listed, or the description of what you have done needs more detail, or is
+incorrect, _please_ let me know.
+
+ -Erik
+
+-----------
+
+Peter Willis <psyphreak at phreaker.net>
+    eject
+
+Emanuele Aina <emanuele.aina at tiscali.it>
+    run-parts
+
+Erik Andersen <andersen at codepoet.org>
+    Tons of new stuff, major rewrite of most of the
+    core apps, tons of new apps as noted in header files.
+    Lots of tedious effort writing these boring docs that
+    nobody is going to actually read.
+
+Laurence Anderson <l.d.anderson at warwick.ac.uk>
+    rpm2cpio, unzip, get_header_cpio, read_gz interface, rpm
+
+Jeff Angielski <jeff at theptrgroup.com>
+    ftpput, ftpget
+
+Enrik Berkhan <Enrik.Berkhan at inka.de>
+    setconsole
+
+Jim Bauer <jfbauer at nfr.com>
+    modprobe shell dependency
+
+Edward Betts <edward at debian.org>
+    expr, hostid, logname, whoami
+
+John Beppu <beppu at codepoet.org>
+    du, nslookup, sort
+
+David Brownell <dbrownell at users.sourceforge.net>
+    zcip
+
+Brian Candler <B.Candler at pobox.com>
+    tiny-ls(ls)
+
+Randolph Chung <tausq at debian.org>
+    fbset, ping, hostname
+
+Dave Cinege <dcinege at psychosis.com>
+    more(v2), makedevs, dutmp, modularization, auto links file,
+    various fixes, Linux Router Project maintenance
+
+Jordan Crouse <jordan at cosmicpenguin.net>
+    ipcalc
+
+Magnus Damm <damm at opensource.se>
+    tftp client
+    insmod powerpc support
+
+Larry Doolittle <ldoolitt at recycle.lbl.gov>
+    pristine source directory compilation, lots of patches and fixes.
+
+Glenn Engel <glenne at engel.org>
+    httpd
+
+Gennady Feldman <gfeldman at gena01.com>
+    Sysklogd (single threaded syslogd, IPC Circular buffer support,
+    logread), various fixes.
+
+Robert Griebl <sandman at handhelds.org>
+    modprobe, hwclock, suid/sgid handling, tinylogin integration
+    many bugfixes and enhancements
+
+Karl M. Hegbloom <karlheg at debian.org>
+    cp_mv.c, the test suite, various fixes to utility.c, &c.
+
+Daniel Jacobowitz <dan at debian.org>
+    mktemp.c
+
+Matt Kraai <kraai at alumni.cmu.edu>
+    documentation, bugfixes, test suite
+
+Rob Landley <rob at landley.net>
+    Became busybox maintainer in 2006.
+
+    sed (major rewrite in 2003, and I now maintain the thing)
+    bunzip2 (complete from-scratch rewrite, then mjn3 optimized the result)
+    sort (more or less from scratch rewrite in 2004, I now maintain it)
+    mount (rewrite in 2005, I maintain the new one)
+
+Stephan Linz <linz at li-pro.net>
+    ipcalc, Red Hat equivalence
+
+John Lombardo <john at deltanet.com>
+    tr
+
+Glenn McGrath <bug1 at iinet.net.au>
+    Common unarchiving code and unarchiving applets, ifupdown, ftpgetput,
+    nameif, sed, patch, fold, install, uudecode.
+    Various bugfixes, review and apply numerous patches.
+
+Manuel Novoa III <mjn3 at codepoet.org>
+    cat, head, mkfifo, mknod, rmdir, sleep, tee, tty, uniq, usleep, wc, yes,
+    mesg, vconfig, nice, renice,
+    make_directory, parse_mode, dirname, mode_string,
+    get_last_path_component, simplify_path, and a number trivial libbb routines
+
+    also bug fixes, partial rewrites, and size optimizations in
+    ash, basename, cal, cmp, cp, df, du, echo, env, ln, logname, md5sum, mkdir,
+    mv, realpath, rm, sort, tail, touch, uname, watch, arith, human_readable,
+    interface, dutmp, ifconfig, route
+
+Vladimir Oleynik <dzo at simtreas.ru>
+    cmdedit; bb_mkdep, xargs(current), httpd(current);
+    ports: ash, crond, fdisk (initial, unmaintained now), inetd, stty, traceroute, 
+    top;
+    locale, various fixes
+    and irreconcilable critic of everything not perfect.
+
+Bruce Perens <bruce at pixar.com>
+    Original author of BusyBox in 1995, 1996. Some of his code can
+    still be found hiding here and there...
+
+Rodney Radford <rradford at mindspring.com>
+    ipcs, ipcrm
+
+Tim Riker <Tim at Rikers.org>
+    bug fixes, member of fan club
+
+Kent Robotti <robotti at metconnect.com>
+    reset, tons and tons of bug reports and patches.
+
+Chip Rosenthal <chip at unicom.com>, <crosenth at covad.com>
+    wget - Contributed by permission of Covad Communications
+
+Pavel Roskin <proski at gnu.org>
+    Lots of bugs fixes and patches.
+
+Gyepi Sam <gyepi at praxis-sw.com>
+    Remote logging feature for syslogd
+
+Rob Sullivan <cogito.ergo.cogito at gmail.com>
+    comm
+
+Linus Torvalds
+    mkswap, fsck.minix, mkfs.minix
+
+Mark Whitley <markw at codepoet.org>
+    grep, sed, cut, xargs(previous),
+    style-guide, new-applet-HOWTO, bug fixes, etc.
+
+Charles P. Wright <cpwright at villagenet.com>
+    gzip, mini-netcat(nc)
+
+Enrique Zanardi <ezanardi at ull.es>
+    tarcat (since removed), loadkmap, various fixes, Debian maintenance
+
+Tito Ragusa <farmatito at tiscali.it>
+    devfsd and size optimizations in strings, openvt, chvt, deallocvt, hdparm,
+    fdformat, lsattr, chattr, id and eject.
+
+Paul Fox <pgf at foxharp.boston.ma.us>
+    vi editing mode for ash, various other patches/fixes
+
+Roberto A. Foglietta <me at roberto.foglietta.name>
+    port: dnsd
+
+Bernhard Fischer <rep.nop at aon.at>
+    misc
+
+Mike Frysinger <vapier at gentoo.org>
+    initial e2fsprogs, printenv, setarch, sum, misc

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,475 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+mainmenu "BusyBox Configuration"
+
+config HAVE_DOT_CONFIG
+	bool
+	default y
+
+menu "Busybox Settings"
+
+menu "General Configuration"
+
+config CONFIG_NITPICK
+	bool "See lots more (probably unnecessary) configuration options."
+	default n
+	help
+	  Some BusyBox applets have more configuration options than anyone
+	  will ever care about.  To avoid drowining people in complexity, most
+	  of the applet features that can be set to a sane default value are
+	  hidden, unless you hit the above switch.
+
+	  This is better than to telling people to edit the busybox source
+	  code, but not by much.
+
+	  See http://en.wikipedia.org/wiki/Fibber_McGee_and_Molly#The_Closet
+
+	  You have been warned.
+
+choice
+	prompt "Buffer allocation policy"
+	default CONFIG_FEATURE_BUFFERS_USE_MALLOC
+	depends on CONFIG_NITPICK
+	help
+	  There are 3 ways BusyBox can handle buffer allocations:
+	  - Use malloc. This costs code size for the call to xmalloc.
+	  - Put them on stack. For some very small machines with limited stack
+	    space, this can be deadly.  For most folks, this works just fine.
+	  - Put them in BSS. This works beautifully for computers with a real
+	    MMU (and OS support), but wastes runtime RAM for uCLinux. This
+	    behavior was the only one available for BusyBox versions 0.48 and
+	    earlier.
+
+config CONFIG_FEATURE_BUFFERS_USE_MALLOC
+	bool "Allocate with Malloc"
+
+config CONFIG_FEATURE_BUFFERS_GO_ON_STACK
+	bool "Allocate on the Stack"
+
+config CONFIG_FEATURE_BUFFERS_GO_IN_BSS
+	bool "Allocate in the .bss section"
+
+endchoice
+
+config CONFIG_SHOW_USAGE
+	bool "Show terse applet usage messages"
+	default y
+	help
+	  All BusyBox applets will show help messages when invoked with
+	  wrong arguments. You can turn off printing these terse usage
+	  messages if you say no here.
+	  This will save you up to 7k.
+
+config CONFIG_FEATURE_VERBOSE_USAGE
+	bool "Show verbose applet usage messages"
+	default n
+	select CONFIG_SHOW_USAGE
+	help
+	  All BusyBox applets will show more verbose help messages when
+	  busybox is invoked with --help.  This will add a lot of text to the
+	  busybox binary.  In the default configuration, this will add about
+	  13k, but it can add much more depending on your configuration.
+
+config CONFIG_FEATURE_COMPRESS_USAGE
+	bool "Store applet usage messages in compressed form"
+	default y
+	depends on CONFIG_SHOW_USAGE && CONFIG_NITPICK
+	help
+	  Store usage messages in compressed form, uncompress them on-the-fly
+	  when <applet> --help is called.
+
+	  If you have a really tiny busybox with few applets enabled (and
+	  bunzip2 isn't one of them), the overhead of the decompressor might
+	  be noticeable.  Also, if you run executables directly from ROM
+	  and have very little memory, this might not be a win.  Otherwise,
+	  you probably want this.
+
+config CONFIG_FEATURE_INSTALLER
+	bool "Support --install [-s] to install applet links at runtime"
+	default n
+	help
+	  Enable 'busybox --install [-s]' support.  This will allow you to use
+	  busybox at runtime to create hard links or symlinks for all the
+	  applets that are compiled into busybox.  This feature requires the
+	  /proc filesystem.
+
+config CONFIG_LOCALE_SUPPORT
+	bool "Enable locale support (system needs locale for this to work)"
+	default n
+	help
+	  Enable this if your system has locale support and you would like
+	  busybox to support locale settings.
+
+config CONFIG_GETOPT_LONG
+	bool
+	default y
+#	bool "Enable support for --long-options"
+#	default n
+#	help
+#	  Enable this if you want busybox applets to use the gnu --long-option
+#	  style, in addition to single character -a -b -c style options.
+
+config CONFIG_FEATURE_DEVPTS
+	bool "Use the devpts filesystem for Unix98 PTYs"
+	default y
+	help
+	  Enable if you want BusyBox to use Unix98 PTY support. If enabled,
+	  busybox will use /dev/ptmx for the master side of the pseudoterminal
+	  and /dev/pts/<number> for the slave side.  Otherwise, BSD style
+	  /dev/ttyp<number> will be used. To use this option, you should have
+	  devpts mounted.
+
+config CONFIG_FEATURE_CLEAN_UP
+	bool "Clean up all memory before exiting (usually not needed)"
+	default n
+	depends on CONFIG_NITPICK
+	help
+	  As a size optimization, busybox normally exits without explicitly
+	  freeing dynamically allocated memory or closing files.  This saves
+	  space since the OS will clean up for us, but it can confuse debuggers
+	  like valgrind, which report tons of memory and resource leaks.
+
+	  Don't enable this unless you have a really good reason to clean
+	  things up manually.
+
+config CONFIG_FEATURE_SUID
+	bool "Support for SUID/SGID handling"
+	default n
+	help
+	  With this option you can install the busybox binary belonging
+	  to root with the suid bit set, and it'll and it'll automatically drop
+	  priviledges for applets that don't need root access.
+
+	  If you're really paranoid and don't want to do this, build two
+	  busybox binaries with different applets in them (and the appropriate
+	  symlinks pointing to each binary), and only set the suid bit on the
+	  one that needs it.  The applets currently marked to need the suid bit
+	  are login, passwd, su, ping, traceroute, crontab, dnsd, ipcrm, ipcs,
+	  and vlock.
+
+config CONFIG_FEATURE_SUID_CONFIG
+	bool "Runtime SUID/SGID configuration via /etc/busybox.conf"
+	default n if CONFIG_FEATURE_SUID
+	depends on CONFIG_FEATURE_SUID
+	help
+	  Allow the SUID / SGID state of an applet to be determined at runtime
+	  by checking /etc/busybox.conf.  (This is sort of a poor man's sudo.)
+	  The format of this file is as follows:
+
+	  <applet> = [Ssx-][Ssx-][x-] (<username>|<uid>).(<groupname>|<gid>)
+
+	  An example might help:
+
+	  [SUID]
+	  su = ssx root.0 # applet su can be run by anyone and runs with euid=0/egid=0
+	  su = ssx        # exactly the same
+
+	  mount = sx- root.disk # applet mount can be run by root and members of group disk
+	                        # and runs with euid=0
+
+	  cp = --- # disable applet cp for everyone
+
+	  The file has to be owned by user root, group root and has to be
+	  writeable only by root:
+	  	(chown 0.0 /etc/busybox.conf; chmod 600 /etc/busybox.conf)
+	  The busybox executable has to be owned by user root, group
+	  root and has to be setuid root for this to work:
+	  	(chown 0.0 /bin/busybox; chmod 4755 /bin/busybox)
+
+	  Robert 'sandman' Griebl has more information here:
+	  <url: http://www.softforge.de/bb/suid.html >.
+
+config CONFIG_FEATURE_SUID_CONFIG_QUIET
+	bool "Suppress warning message if /etc/busybox.conf is not readable"
+	default y
+	depends on CONFIG_FEATURE_SUID_CONFIG
+	help
+	  /etc/busybox.conf should be readable by the user needing the SUID, check
+	  this option to avoid users to be notified about missing permissions.
+
+config CONFIG_SELINUX
+	bool "Support NSA Security Enhanced Linux"
+	default n
+	help
+	  Enable support for SELinux in applets ls, ps, and id.  Also provide
+	  the option of compiling in SELinux applets.
+
+	  If you do not have a complete SELinux userland installed, this stuff
+	  will not compile. Go visit
+		http://www.nsa.gov/selinux/index.html
+	  to download the necessary stuff to allow busybox to compile with
+	  this option enabled. Specifially, libselinux 1.28 or better is
+	  directly required by busybox. If the installation is located in a
+	  non-standard directory, provide it by invoking make as follows:
+		CFLAGS=-I<libselinux-include-path> \
+		LDFLAGS=-L<libselinux-lib-path> \
+		make
+
+	  Most people will leave this set to 'N'.
+
+config CONFIG_BUSYBOX_EXEC_PATH
+	string "Path to BusyBox executable"
+	default "/proc/self/exe"
+	help
+	  When Busybox applets need to run other busybox applets, BusyBox
+	  sometimes needs to exec() itself.  When the /proc filesystem is
+	  mounted, /proc/self/exe always points to the currently running
+	  executable.  If you haven't got /proc, set this to wherever you
+	  want to run BusyBox from.
+
+endmenu
+
+menu 'Build Options'
+
+config CONFIG_STATIC
+	bool "Build BusyBox as a static binary (no shared libs)"
+	default n
+	help
+	  If you want to build a static BusyBox binary, which does not
+	  use or require any shared libraries, then enable this option.
+	  This can cause BusyBox to be considerably larger, so you should
+	  leave this option false unless you have a good reason (i.e.
+	  your target platform does not support shared libraries, or
+	  you are building an initrd which doesn't need anything but
+	  BusyBox, etc).
+
+	  Most people will leave this set to 'N'.
+
+config CONFIG_BUILD_LIBBUSYBOX
+	bool "Build shared libbusybox"
+	default n
+	help
+	  Build a shared library libbusybox.so which contains all
+	  libraries used inside busybox.
+
+	  This is an experimental feature intended to support the upcoming
+	  "make standalone" mode.  Enabling it against the one big busybox
+	  binary serves no purpose (and increases the size).  You should
+	  almost certainly say "no" to this right now.
+
+config CONFIG_FEATURE_FULL_LIBBUSYBOX
+	bool "Feature-complete libbusybox"
+	default n if !CONFIG_FEATURE_SHARED_BUSYBOX
+	depends on CONFIG_BUILD_LIBBUSYBOX
+	help
+	  Build a libbusybox with the complete feature-set, disregarding
+	  the actually selected config.
+
+	  Normally, libbusybox will only contain the features which are
+	  used by busybox itself. If you plan to write a separate
+	  standalone application which uses libbusybox say 'Y'.
+
+	  Note: libbusybox is GPL, not LGPL, and exports no stable API that
+	  might act as a copyright barrier.  We can and will modify the
+	  exported function set between releases (even minor version number
+	  changes), and happily break out-of-tree features.
+
+	  Say 'N' if in doubt.
+
+config CONFIG_FEATURE_SHARED_BUSYBOX
+	bool "Use shared libbusybox for busybox"
+	default y if CONFIG_BUILD_LIBBUSYBOX
+	depends on !CONFIG_STATIC && CONFIG_BUILD_LIBBUSYBOX
+	help
+	  Use libbusybox.so also for busybox itself.
+	  You need to have a working dynamic linker to use this variant.
+
+config CONFIG_LFS
+	bool "Build with Large File Support (for accessing files > 2 GB)"
+	default n
+	select FDISK_SUPPORT_LARGE_DISKS
+	help
+	  If you want to build BusyBox with large file support, then enable
+	  this option.  This will have no effect if your kernel or your C
+	  library lacks large file support for large files.  Some of the
+	  programs that can benefit from large file support include dd, gzip,
+	  cp, mount, tar, and many others.  If you want to access files larger
+	  than 2 Gigabytes, enable this option.  Otherwise, leave it set to 'N'.
+
+config USING_CROSS_COMPILER
+	bool "Do you want to build BusyBox with a Cross Compiler?"
+	default n
+	help
+	  Do you want to build BusyBox with a Cross Compiler?  If so,
+	  then enable this option.  Otherwise leave it set to 'N'.
+
+config CROSS_COMPILER_PREFIX
+	string "Cross Compiler prefix"
+	default "/usr/i386-linux-uclibc/bin/i386-uclibc-"
+	depends on USING_CROSS_COMPILER
+	help
+	  If you want to build BusyBox with a cross compiler, then you
+	  will need to set this to the cross-compiler prefix.  For example,
+	  if my cross-compiler is /usr/i386-linux-uclibc/bin/i386-uclibc-gcc
+	  then I would enter '/usr/i386-linux-uclibc/bin/i386-uclibc-' here,
+	  which will ensure the correct compiler is used.
+
+config CONFIG_BUILD_AT_ONCE
+	bool "Compile all sources at once"
+	default n
+	help
+	  Normally each source-file is compiled with one invocation of
+	  the compiler.
+	  If you set this option, all sources are compiled at once.
+	  This gives the compiler more opportunities to optimize which can
+	  result in smaller and/or faster binaries.
+
+	  Setting this option will consume alot of memory, e.g. if you
+	  enable all applets with all features, gcc uses more than 300MB
+	  RAM during compilation of busybox.
+
+	  This option is most likely only beneficial for newer compilers
+	  such as gcc-4.1 and above.
+
+	  Say 'N' unless you know what you are doing.
+
+endmenu
+
+menu 'Debugging Options'
+
+config CONFIG_DEBUG
+	bool "Build BusyBox with extra Debugging symbols"
+	default n
+	help
+	  Say Y here if you wish to examine BusyBox internals while applets are
+	  running.  This increases the size of the binary considerably, and
+	  should only be used when doing development.  If you are doing
+	  development and want to debug BusyBox, answer Y.
+
+	  Most people should answer N.
+
+config CONFIG_DEBUG_PESSIMIZE
+	bool "Disable compiler optimizations."
+	default n
+	depends on CONFIG_DEBUG
+	help
+	  The compiler's optimization of source code can eliminate and reorder
+	  code, resulting in an executable that's hard to understand when
+	  stepping through it with a debugger.  This switches it off, resulting
+	  in a much bigger executable that more closely matches the source
+	  code.
+
+choice
+	prompt "Additional debugging library"
+	default CONFIG_NO_DEBUG_LIB
+	depends on CONFIG_DEBUG
+	help
+	  Using an additional debugging library will make BusyBox become
+	  considerable larger and will cause it to run more slowly.  You
+	  should always leave this option disabled for production use.
+
+	  dmalloc support:
+	  ----------------
+	  This enables compiling with dmalloc ( http://dmalloc.com/ )
+	  which is an excellent public domain mem leak and malloc problem
+	  detector.  To enable dmalloc, before running busybox you will
+	  want to properly set your environment, for example:
+	    export DMALLOC_OPTIONS=debug=0x34f47d83,inter=100,log=logfile
+	  The 'debug=' value is generated using the following command
+	    dmalloc -p log-stats -p log-non-free -p log-bad-space -p log-elapsed-time \
+	       -p check-fence -p check-heap -p check-lists -p check-blank \
+	       -p check-funcs -p realloc-copy -p allow-free-null
+
+	  Electric-fence support:
+	  -----------------------
+	  This enables compiling with Electric-fence support.  Electric
+	  fence is another very useful malloc debugging library which uses
+	  your computer's virtual memory hardware to detect illegal memory
+	  accesses.  This support will make BusyBox be considerable larger
+	  and run slower, so you should leave this option disabled unless
+	  you are hunting a hard to find memory problem.
+
+
+config CONFIG_NO_DEBUG_LIB
+	bool "None"
+
+config CONFIG_DMALLOC
+	bool "Dmalloc"
+
+config CONFIG_EFENCE
+	bool "Electric-fence"
+
+endchoice
+
+config CONFIG_DEBUG_YANK_SUSv2
+	bool "Disable obsolete features removed before SUSv3?"
+	default y
+	help
+	  This option will disable backwards compatibility with SuSv2,
+	  specifically, old-style numeric options ('command -1 <file>')
+	  will not be supported in head, tail, and fold.  (Note: should
+	  yank from renice too.)
+
+endmenu
+
+menu 'Installation Options'
+
+config CONFIG_INSTALL_NO_USR
+	bool "Don't use /usr"
+	default n
+	help
+	  Disable use of /usr. Don't activate this option if you don't know
+	  that you really want this behaviour.
+
+choice
+       prompt "Applets links"
+       default CONFIG_INSTALL_APPLET_SYMLINKS
+       help
+         Choose how you install applets links.
+
+config CONFIG_INSTALL_APPLET_SYMLINKS
+       bool "as soft-links"
+       help
+         Install applets as soft-links to the busybox binary. This needs some
+         free inodes on the filesystem, but might help with filesystem
+         generators that can't cope with hard-links.
+
+config CONFIG_INSTALL_APPLET_HARDLINKS
+       bool "as hard-links"
+       help
+         Install applets as hard-links to the busybox binary. This might count
+         on a filesystem with few inodes.
+
+config CONFIG_INSTALL_APPLET_DONT
+       bool
+       prompt "not installed"
+       depends on CONFIG_FEATURE_INSTALLER || CONFIG_FEATURE_SH_STANDALONE_SHELL
+       help
+         Do not install applets links. Usefull when using the -install feature
+         or a standalone shell for rescue pruposes.
+
+endchoice
+
+config PREFIX
+	string "BusyBox installation prefix"
+	default "./_install"
+	help
+	  Define your directory to install BusyBox files/subdirs in.
+
+endmenu
+
+source libbb/Config.in
+
+endmenu
+
+comment "Applets"
+
+source archival/Config.in
+source coreutils/Config.in
+source console-tools/Config.in
+source debianutils/Config.in
+source editors/Config.in
+source findutils/Config.in
+source init/Config.in
+source loginutils/Config.in
+source e2fsprogs/Config.in
+source modutils/Config.in
+source util-linux/Config.in
+source miscutils/Config.in
+source networking/Config.in
+source procps/Config.in
+source shell/Config.in
+source sysklogd/Config.in

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/INSTALL
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/INSTALL	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/INSTALL	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,123 @@
+Building:
+=========
+
+The BusyBox build process is similar to the Linux kernel build:
+
+  make menuconfig     # This creates a file called ".config"
+  make                # This creates the "busybox" executable
+  make install        # or make PREFIX=/path/from/root install
+
+The full list of configuration and install options is available by typing:
+
+  make help
+
+Quick Start:
+============
+
+The easy way to try out BusyBox for the first time, without having to install
+it, is to enable all features and then use "standalone shell" mode with a
+blank command $PATH.
+
+To enable all features, use "make defconfig", which produces the largest
+general-purpose configuration.  (It's allyesconfig minus debugging options,
+optional packaging choices, and a few special-purpose features requiring
+extra configuration to use.)
+
+  make defconfig
+  make
+  PATH= ./busybox ash
+
+Standalone shell mode causes busybox's built-in command shell to run
+any built-in busybox applets directly, without looking for external
+programs by that name.  Supplying an empty command path (as above) means
+the only commands busybox can find are the built-in ones.
+
+(Note that the standalone shell currently requires /proc/self/exe to
+launch new applets.)
+
+Configuring Busybox:
+====================
+
+Busybox is optimized for size, but enabling the full set of functionality
+still results in a fairly large executable -- more than 1 megabyte when
+statically linked.  To save space, busybox can be configured with only the
+set of applets needed for each environment.  The minimal configuration, with
+all applets disabled, produces a 4k executable.  (It's useless, but very small.)
+
+The manual configurator "make menuconfig" modifies the existing configuration.
+(For systems without ncurses, try "make config" instead.) The two most
+interesting starting configurations are "make allnoconfig" (to start with
+everything disabled and add just what you need), and "make defconfig" (to
+start with everything enabled and remove what you don't need).  If menuconfig
+is run without an existing configuration, make defconfig will run first to
+create a known starting point.
+
+Other starting configurations (mostly used for testing purposes) include
+"make allbareconfig" (enables all applets but disables all optional features),
+"make allyesconfig" (enables absolutely everything including debug features),
+and "make randconfig" (produce a random configuration).
+
+Configuring BusyBox produces a file ".config", which can be saved for future
+use.  Run "make oldconfig" to bring a .config file from an older version of
+busybox up to date.
+
+Installing Busybox:
+===================
+
+Busybox is a single executable that can behave like many different commands,
+and BusyBox uses the name it was invoked under to determine the desired
+behavior.  (Try "mv busybox ls" and then "./ls -l".)
+
+Installing busybox consists of creating symlinks (or hardlinks) to the busybox
+binary for each applet enabled in busybox, and making sure these symlinks are
+in the shell's command $PATH.  Running "make install" creates these symlinks,
+or "make install-hardlinks" creates hardlinks instead (useful on systems with
+a limited number of inodes).  This install process uses the file
+"busybox.links" (created by make), which contains the list of enabled applets
+and the path at which to install them.
+
+Installing links to busybox is not always necessary.  The special applet name
+"busybox" (or with any optional suffix, such as "busybox-static") uses the
+first argument to determine which applet to behave as, for example
+"./busybox cat LICENSE".  (Running the busybox applet with no arguments gives
+a list of all enabled applets.) The standalone shell can also call busybox
+applets without links to busybox under other names in the filesystem.  You can
+also configure a standaone install capability into the busybox base applet,
+and then install such links at runtime with one of "busybox --install" (for
+hardlinks) or "busybox --install -s" (for symlinks).
+
+If you enabled the busybox shared library feature (libbusybox.so) and want
+to run tests without installing, set your LD_LIBRARY_PATH accordingly when
+running the executable:
+
+  LD_LIBRARY_PATH=`pwd` ./busybox
+
+Building out-of-tree:
+=====================
+
+By default, the BusyBox build puts its temporary files in the source tree.
+Building from a read-only source tree, or building multiple configurations from
+the same source directory, requires the ability to put the temporary files
+somewhere else.
+
+To build out of tree, cd to an empty directory and configure busybox from there:
+
+  make -f /path/to/source/Makefile defconfig
+  make
+  make install
+
+Alternately, use the O=$BUILDPATH option (with an absolute path) during the
+configuration step, as in:
+
+  make O=/some/empty/directory allyesconfig
+  cd /some/empty/directory
+  make
+  make PREFIX=. install
+
+More Information:
+=================
+
+Se also the busybox FAQ, under the questions "How can I get started using
+BusyBox" and "How do I build a BusyBox-based system?"  The BusyBox FAQ is
+available from http://www.busybox.net/FAQ.html or as the file
+docs/busybox.net/FAQ.html in this tarball.

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/LICENSE
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/LICENSE	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/LICENSE	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,524 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under GPLv2, see the file LICENSE in this tarball for details.
+#
+
+# You shouldn't have to edit anything in this file for configuration
+# purposes, try "make help" or read http://busybox.net/FAQ.html.
+
+.PHONY: dummy subdirs release distclean clean config oldconfig menuconfig \
+        tags check test depend dep buildtree hosttools _all checkhelp \
+        sizes bloatcheck baseline objsizes
+
+noconfig_targets := menuconfig config oldconfig randconfig hosttools \
+	defconfig allyesconfig allnoconfig allbareconfig \
+	clean distclean help \
+	release tags
+
+nocheck_targets := clean distclean help release tags
+
+# the toplevel sourcedir
+ifndef top_srcdir
+top_srcdir=$(CURDIR)
+endif
+# toplevel directory of the object-tree
+ifndef top_builddir
+top_builddir=$(CURDIR)
+endif
+
+export srctree=$(top_srcdir)
+vpath %/Config.in $(srctree)
+
+DIRS:=applets archival archival/libunarchive coreutils console-tools \
+	debianutils editors findutils init miscutils modutils networking \
+	networking/libiproute networking/udhcp procps loginutils shell \
+	sysklogd util-linux e2fsprogs libpwdgrp coreutils/libcoreutils libbb
+
+SRC_DIRS:=$(patsubst %,$(top_srcdir)/%,$(DIRS))
+
+# That's our default target when none is given on the command line
+_all:
+
+CONFIG_CONFIG_IN = $(top_srcdir)/Config.in
+
+ifeq ($(BUILD_SRC),)
+ifdef O
+  ifeq ("$(origin O)", "command line")
+    BUILD_OUTPUT := $(O)
+    top_builddir := $(O)
+  endif
+else
+# If no alternate output-dir was specified, we build in cwd
+# We are using BUILD_OUTPUT nevertheless to make sure that we create
+# Rules.mak and the toplevel Makefile, in case they don't exist.
+  BUILD_OUTPUT := $(top_builddir)
+endif
+
+# see if we are in verbose mode
+BUILD_VERBOSE :=
+ifdef V
+  ifeq ("$(origin V)", "command line")
+    BUILD_VERBOSE := $(V)
+  endif
+endif
+ifdef VERBOSE
+  ifeq ("$(origin VERBOSE)", "command line")
+    BUILD_VERBOSE := $(VERBOSE)
+  endif
+endif
+
+ifneq ($(strip $(BUILD_VERBOSE)),)
+  export BUILD_VERBOSE
+  CHECK_VERBOSE := -v
+# ARFLAGS+=v
+endif
+
+ifneq ($(strip $(HAVE_DOT_CONFIG)),y)
+# pull in settings early
+-include $(top_srcdir)/Rules.mak
+endif
+
+# All object directories.
+OBJ_DIRS := $(DIRS)
+all_tree := $(patsubst %,$(top_builddir)/%,$(OBJ_DIRS) scripts scripts/config include)
+all_tree: $(all_tree)
+$(all_tree):
+	@mkdir -p "$@"
+
+ifneq ($(BUILD_OUTPUT),)
+# Invoke a second make in the output directory, passing relevant variables
+# Check that the output directory actually exists
+saved-output := $(BUILD_OUTPUT)
+BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd)
+$(if $(wildcard $(BUILD_OUTPUT)),, \
+     $(error output directory "$(saved-output)" does not exist))
+
+.PHONY: $(MAKECMDGOALS)
+
+$(filter-out _all,$(MAKECMDGOALS)) _all: $(BUILD_OUTPUT)/Rules.mak $(BUILD_OUTPUT)/Makefile all_tree
+	$(Q)$(MAKE) -C $(BUILD_OUTPUT) \
+	top_srcdir=$(top_srcdir) \
+	top_builddir=$(top_builddir) \
+	BUILD_SRC=$(top_srcdir) \
+	-f $(CURDIR)/Makefile $@
+
+$(BUILD_OUTPUT)/Rules.mak:
+	@echo > $@
+	@echo top_srcdir=$(top_srcdir) >> $@
+	@echo top_builddir=$(BUILD_OUTPUT) >> $@
+	@echo include $(top_srcdir)/Rules.mak >> $@
+
+$(BUILD_OUTPUT)/Makefile:
+	@echo > $@
+	@echo top_srcdir=$(top_srcdir) >> $@
+	@echo top_builddir=$(BUILD_OUTPUT) >> $@
+	@echo BUILD_SRC='$$(top_srcdir)' >> $@
+	@echo include '$$(BUILD_SRC)'/Makefile >> $@
+
+# Leave processing to above invocation of make
+skip-makefile := 1
+endif # ifneq ($(BUILD_OUTPUT),)
+endif # ifeq ($(BUILD_SRC),)
+
+ifeq ($(skip-makefile),)
+
+# We only need a copy of the Makefile for the config targets and reuse
+# the rest from the source directory, i.e. we do not cp ALL_MAKEFILES.
+scripts/config/Makefile: $(top_srcdir)/scripts/config/Makefile
+	cp $< $@
+
+_all: all
+
+help:
+	@echo 'Cleaning:'
+	@echo '  clean			- delete temporary files created by build'
+	@echo '  distclean		- delete all non-source files (including .config)'
+	@echo
+	@echo 'Build:'
+	@echo '  all			- Executable and documentation'
+	@echo '  busybox		- the swiss-army executable'
+	@echo '  doc			- docs/BusyBox.{txt,html,1}'
+	@echo '  html			- create html-based cross-reference'
+	@echo
+	@echo 'Configuration:'
+	@echo '  allnoconfig		- disable all symbols in .config'
+	@echo '  allyesconfig		- enable all symbols in .config (see defconfig)'
+	@echo '  allbareconfig		- enable all applets without any sub-features'
+	@echo '  config		- text based configurator (of last resort)'
+	@echo '  defconfig		- set .config to largest generic configuration'
+	@echo '  menuconfig		- interactive curses-based configurator'
+	@echo '  oldconfig		- resolve any unresolved symbols in .config'
+	@echo '  hosttools  		- build sed for the host.'
+	@echo '  			  You can use these commands if the commands on the host'
+	@echo '  			  is unusable. Afterwards use it like:'
+	@echo '			  make SED="$(top_builddir)/sed"'
+	@echo
+	@echo 'Installation:'
+	@echo '  install		- install busybox into $(PREFIX)'
+	@echo '  uninstall'
+	@echo
+	@echo 'Development:'
+	@echo '  baseline		- create busybox_old for bloatcheck.'
+	@echo '  bloatcheck		- show size difference between old and new versions'
+	@echo '  check			- run the test suite for all applets'
+	@echo '  checkhelp		- check for missing help-entries in Config.in'
+	@echo '  randconfig		- generate a random configuration'
+	@echo '  release		- create a distribution tarball'
+	@echo '  sizes			- show size of all enabled busybox symbols'
+	@echo '  objsizes		- show size of each .o object built'
+	@echo
+
+
+include $(top_srcdir)/Rules.mak
+
+ifneq ($(strip $(HAVE_DOT_CONFIG)),y)
+
+# Default target if none was requested explicitly
+all: menuconfig
+
+# warn if no configuration exists and we are asked to build a non-config target
+.config:
+	@echo ""
+	@echo "No $(top_builddir)/$@ found!"
+	@echo "Please refer to 'make  help', section Configuration."
+	@echo ""
+	@exit 1
+
+# configuration
+# ---------------------------------------------------------------------------
+
+scripts/config/conf: scripts/config/Makefile
+	$(Q)$(MAKE) -C scripts/config conf
+	- at if [ ! -f .config ] ; then \
+		touch .config; \
+	fi
+
+scripts/config/mconf: scripts/config/Makefile
+	$(Q)$(MAKE) -C scripts/config ncurses conf mconf
+	- at if [ ! -f .config ] ; then \
+		touch .config; \
+	fi
+
+menuconfig: scripts/config/mconf
+	@[ -f .config ] || $(MAKE) $(MAKEFLAGS) defconfig
+	@./scripts/config/mconf $(CONFIG_CONFIG_IN)
+
+config: scripts/config/conf
+	@./scripts/config/conf $(CONFIG_CONFIG_IN)
+
+oldconfig: scripts/config/conf
+	@./scripts/config/conf -o $(CONFIG_CONFIG_IN)
+
+randconfig: scripts/config/conf
+	@./scripts/config/conf -r $(CONFIG_CONFIG_IN)
+
+allyesconfig: scripts/config/conf
+	@./scripts/config/conf -y $(CONFIG_CONFIG_IN) > /dev/null
+	@$(SED) -i -r -e "s/^(USING_CROSS_COMPILER)=.*/# \1 is not set/" .config
+	@./scripts/config/conf -o $(CONFIG_CONFIG_IN) > /dev/null
+
+allnoconfig: scripts/config/conf
+	@./scripts/config/conf -n $(CONFIG_CONFIG_IN) > /dev/null
+
+# defconfig is allyesconfig minus any features that are specialized enough
+# or cause enough behavior change that the user really should switch them on
+# manually if that's what they want.  Sort of "maximum sane config".
+
+defconfig: scripts/config/conf
+	@./scripts/config/conf -y $(CONFIG_CONFIG_IN) > /dev/null
+	@$(SED) -i -r -e "s/^(USING_CROSS_COMPILER|CONFIG_(DEBUG.*|STATIC|SELINUX|BUILD_(AT_ONCE|LIBBUSYBOX)|FEATURE_(DEVFS|FULL_LIBBUSYBOX|SHARED_BUSYBOX|MTAB_SUPPORT|CLEAN_UP|UDHCP_DEBUG)|INSTALL_NO_USR))=.*/# \1 is not set/" .config
+	@./scripts/config/conf -o $(CONFIG_CONFIG_IN) > /dev/null
+
+
+allbareconfig: scripts/config/conf
+	@./scripts/config/conf -y $(CONFIG_CONFIG_IN) > /dev/null
+	@$(SED) -i -r -e "s/^(USING_CROSS_COMPILER|CONFIG_(DEBUG|STATIC|SELINUX|DEVFSD|NC_GAPING_SECURITY_HOLE|BUILD_AT_ONCE)).*/# \1 is not set/" .config
+	@$(SED) -i -e "/FEATURE/s/=.*//;/^[^#]/s/.*FEATURE.*/# \0 is not set/;" .config
+	@echo "CONFIG_FEATURE_BUFFERS_GO_ON_STACK=y" >> .config
+	@yes n | ./scripts/config/conf -o $(CONFIG_CONFIG_IN) > /dev/null
+
+hosttools:
+	$(Q)cp .config .config.bak || noold=yea
+	$(Q)$(MAKE) CC="$(HOSTCC)" CFLAGS="$(HOSTCFLAGS) $(INCS)" allnoconfig
+	$(Q)mv .config .config.in
+	$(Q)(grep -v CONFIG_SED .config.in ; \
+	 echo "CONFIG_SED=y" ; ) > .config
+	$(Q)$(MAKE) CC="$(HOSTCC)" CFLAGS="$(HOSTCFLAGS) $(INCS)" oldconfig include/bb_config.h
+	$(Q)$(MAKE) CC="$(HOSTCC)" CFLAGS="$(HOSTCFLAGS) $(INCS)" busybox
+	$(Q)[ -f .config.bak ] && mv .config.bak .config || rm .config
+	mv busybox sed
+	@echo "Now do: $(MAKE) SED=$(top_builddir)/sed <target>"
+
+else # ifneq ($(strip $(HAVE_DOT_CONFIG)),y)
+
+all: busybox busybox.links doc
+
+# In this section, we need .config
+-include $(top_builddir)/.config.cmd
+include $(patsubst %,%/Makefile.in, $(SRC_DIRS))
+
+endif # ifneq ($(strip $(HAVE_DOT_CONFIG)),y)
+
+-include $(top_builddir)/.config
+-include $(top_builddir)/.depend
+
+
+ifeq ($(strip $(CONFIG_BUILD_AT_ONCE)),y)
+libraries-y:=
+# Which parts of the internal libs are requested?
+# Per default we only want what was actually selected.
+# -a denotes all while -y denotes the selected ones.
+ifeq ($(strip $(CONFIG_FEATURE_FULL_LIBBUSYBOX)),y)
+LIBRARY_DEFINE:=$(LIBRARY_DEFINE-a)
+LIBRARY_SRC   :=$(LIBRARY_SRC-a)
+else # CONFIG_FEATURE_FULL_LIBBUSYBOX
+LIBRARY_DEFINE:=$(LIBRARY_DEFINE-y)
+LIBRARY_SRC   :=$(LIBRARY_SRC-y)
+endif # CONFIG_FEATURE_FULL_LIBBUSYBOX
+APPLET_SRC:=$(APPLET_SRC-y)
+APPLETS_DEFINE:=$(APPLETS_DEFINE-y)
+else  # CONFIG_BUILD_AT_ONCE
+# no --combine, build archives out of the individual .o
+# This was the old way the binary was built.
+libbusybox-obj:=archival/libunarchive/libunarchive.a \
+	networking/libiproute/libiproute.a \
+	libpwdgrp/libpwdgrp.a \
+	coreutils/libcoreutils/libcoreutils.a \
+	libbb/libbb.a
+libbusybox-obj:=$(patsubst %,$(top_builddir)/%,$(libbusybox-obj))
+
+ifeq ($(strip $(CONFIG_FEATURE_SHARED_BUSYBOX)),y)
+# linking against libbusybox, so don't build the .a already contained in the .so
+libraries-y:=$(filter-out $(libbusybox-obj),$(libraries-y))
+endif # CONFIG_FEATURE_SHARED_BUSYBOX
+endif # CONFIG_BUILD_AT_ONCE
+
+
+ifeq ($(strip $(CONFIG_BUILD_LIBBUSYBOX)),y)
+LD_LIBBUSYBOX:=libbusybox.so
+LIBBUSYBOX_SONAME:=$(LD_LIBBUSYBOX).$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL_VERSION)
+DO_INSTALL_LIBS:=$(LD_LIBBUSYBOX) \
+	$(LD_LIBBUSYBOX).$(MAJOR_VERSION) \
+	$(LD_LIBBUSYBOX).$(MAJOR_VERSION).$(MINOR_VERSION)
+endif # CONFIG_BUILD_LIBBUSYBOX
+
+ifeq ($(strip $(CONFIG_BUILD_AT_ONCE)),y)
+ifneq ($(strip $(CONFIG_FEATURE_SHARED_BUSYBOX)),y)
+# --combine but not linking against libbusybox, so compile all
+BUSYBOX_SRC   := $(LIBRARY_SRC)
+BUSYBOX_DEFINE:= $(LIBRARY_DEFINE)
+endif # !CONFIG_FEATURE_SHARED_BUSYBOX
+$(LIBBUSYBOX_SONAME): $(LIBRARY_SRC)
+else # CONFIG_BUILD_AT_ONCE
+$(LIBBUSYBOX_SONAME): $(libbusybox-obj)
+endif # CONFIG_BUILD_AT_ONCE
+
+ifeq ($(strip $(CONFIG_FEATURE_SHARED_BUSYBOX)),y)
+LDBUSYBOX:=-L$(top_builddir) -lbusybox
+endif
+
+ifeq ($(strip $(CONFIG_BUILD_LIBBUSYBOX)),y)
+$(LIBBUSYBOX_SONAME):
+ifndef MAJOR_VERSION
+	$(error MAJOR_VERSION needed for $@ is not defined)
+endif
+	$(do_link.so) \
+	-Wl,-soname=$(LD_LIBBUSYBOX).$(MAJOR_VERSION) \
+	-Wl,-z,combreloc
+	@rm -f $(DO_INSTALL_LIBS)
+	@for i in $(DO_INSTALL_LIBS); do ln -s $(@) $$i ; done
+	$(do_strip)
+
+endif # ifeq ($(strip $(CONFIG_BUILD_LIBBUSYBOX)),y)
+
+busybox_unstripped: .depend $(LIBBUSYBOX_SONAME) $(BUSYBOX_SRC) $(APPLET_SRC) $(libraries-y)
+	$(do_link)
+
+busybox: busybox_unstripped
+	$(Q)cp busybox_unstripped busybox
+	$(do_strip)
+
+%.bflt: %_unstripped
+	$(do_elf2flt)
+
+busybox.links: $(top_srcdir)/applets/busybox.mkll include/bb_config.h $(top_srcdir)/include/applets.h
+	$(Q)-$(SHELL) $^ >$@
+
+install: $(top_srcdir)/applets/install.sh busybox busybox.links
+	$(Q)DO_INSTALL_LIBS="$(strip $(LIBBUSYBOX_SONAME) $(DO_INSTALL_LIBS))" \
+		$(SHELL) $< $(PREFIX) $(INSTALL_OPTS)
+ifeq ($(strip $(CONFIG_FEATURE_SUID)),y)
+	@echo
+	@echo
+	@echo --------------------------------------------------
+	@echo You will probably need to make your busybox binary
+	@echo setuid root to ensure all configured applets will
+	@echo work properly.
+	@echo --------------------------------------------------
+	@echo
+endif
+
+uninstall: busybox.links
+	rm -f $(PREFIX)/bin/busybox
+	for i in `cat busybox.links` ; do rm -f $(PREFIX)$$i; done
+ifneq ($(strip $(DO_INSTALL_LIBS)),n)
+	for i in $(LIBBUSYBOX_SONAME) $(DO_INSTALL_LIBS); do \
+		rm -f $(PREFIX)$$i; \
+	done
+endif
+
+check test: busybox
+	bindir=$(top_builddir) srcdir=$(top_srcdir)/testsuite SED="$(SED)" \
+	$(SHELL) $(top_srcdir)/testsuite/runtest $(CHECK_VERBOSE)
+
+checkhelp:
+	$(Q)$(top_srcdir)/scripts/checkhelp.awk \
+		$(wildcard $(patsubst %,%/Config.in,$(SRC_DIRS) ./))
+
+sizes: busybox_unstripped
+	$(NM) --size-sort $(<)
+
+bloatcheck: busybox_old busybox_unstripped
+	@$(top_srcdir)/scripts/bloat-o-meter busybox_old busybox_unstripped
+
+baseline: busybox_unstripped
+	@mv busybox_unstripped busybox_old
+
+objsizes: busybox_unstripped
+	$(SHELL) $(top_srcdir)/scripts/objsizes
+
+# Documentation Targets
+doc: docs/busybox.pod docs/BusyBox.txt docs/BusyBox.1 docs/BusyBox.html
+
+docs/busybox.pod : $(top_srcdir)/docs/busybox_header.pod $(top_srcdir)/include/usage.h $(top_srcdir)/docs/busybox_footer.pod $(top_srcdir)/docs/autodocifier.pl
+	$(disp_doc)
+	$(Q)-mkdir -p docs
+	$(Q)-( cat $(top_srcdir)/docs/busybox_header.pod ; \
+	    $(top_srcdir)/docs/autodocifier.pl $(top_srcdir)/include/usage.h ; \
+	    cat $(top_srcdir)/docs/busybox_footer.pod ; ) > docs/busybox.pod
+
+docs/BusyBox.txt: docs/busybox.pod
+	$(disp_doc)
+	$(Q)-mkdir -p docs
+	$(Q)-pod2text $< > $@
+
+docs/BusyBox.1: docs/busybox.pod
+	$(disp_doc)
+	$(Q)-mkdir -p docs
+	$(Q)-pod2man --center=BusyBox --release="version $(VERSION)" \
+		$< > $@
+
+docs/BusyBox.html: docs/busybox.net/BusyBox.html
+	$(disp_doc)
+	$(Q)-mkdir -p docs
+	$(Q)-rm -f docs/BusyBox.html
+	$(Q)-cp docs/busybox.net/BusyBox.html docs/BusyBox.html
+
+docs/busybox.net/BusyBox.html: docs/busybox.pod
+	$(Q)-mkdir -p docs/busybox.net
+	$(Q)-pod2html --noindex $< > \
+	    docs/busybox.net/BusyBox.html
+	$(Q)-rm -f pod2htm*
+
+# The nifty new dependency stuff
+scripts/bb_mkdep: $(top_srcdir)/scripts/bb_mkdep.c
+	$(do_link.h)
+
+DEP_INCLUDES := include/bb_config.h
+
+ifeq ($(strip $(CONFIG_BBCONFIG)),y)
+DEP_INCLUDES += include/bbconfigopts.h
+
+include/bbconfigopts.h: .config $(top_srcdir)/scripts/config/mkconfigs
+	$(disp_gen)
+	$(Q)$(top_srcdir)/scripts/config/mkconfigs > $@
+endif
+
+ifeq ($(strip $(CONFIG_FEATURE_COMPRESS_USAGE)),y)
+USAGE_BIN:=scripts/usage
+$(USAGE_BIN): $(top_srcdir)/scripts/usage.c .config \
+		$(top_srcdir)/include/usage.h
+	$(do_link.h)
+
+DEP_INCLUDES += include/usage_compressed.h
+
+include/usage_compressed.h: .config $(USAGE_BIN) \
+		$(top_srcdir)/scripts/usage_compressed
+	$(Q)SED="$(SED)" $(SHELL) $(top_srcdir)/scripts/usage_compressed \
+	"$(top_builddir)/scripts" > $@
+endif # CONFIG_FEATURE_COMPRESS_USAGE
+
+# workaround alleged bug in make-3.80, make-3.81
+.NOTPARALLEL: .depend
+
+depend dep: .depend
+.depend: scripts/bb_mkdep $(USAGE_BIN) $(DEP_INCLUDES)
+	$(disp_gen)
+	$(Q)rm -f .depend
+	$(Q)mkdir -p include/config
+	$(Q)scripts/bb_mkdep -I $(top_srcdir)/include $(top_srcdir) > $@.tmp
+	$(Q)mv $@.tmp $@
+
+include/bb_config.h: .config
+	@if [ ! -x $(top_builddir)/scripts/config/conf ] ; then \
+	    $(MAKE) -C scripts/config conf; \
+	fi;
+	@$(top_builddir)/scripts/config/conf -o $(CONFIG_CONFIG_IN)
+
+clean:
+	- $(MAKE) -C scripts/config $@
+	- rm -f docs/busybox.dvi docs/busybox.ps \
+	    docs/busybox.pod docs/busybox.net/busybox.html \
+	    docs/busybox pod2htm* *.gdb *.elf *~ core .*config.log \
+	    docs/BusyBox.txt docs/BusyBox.1 docs/BusyBox.html \
+	    docs/busybox.net/BusyBox.html busybox.links \
+	    libbusybox.so* \
+	    .config.old busybox busybox_unstripped \
+	    include/usage_compressed.h scripts/usage
+	- rm -r -f _install testsuite/links
+	- find . -name .\*.flags -o -name \*.o  -o -name \*.om -o -name \*.syn \
+	    -o -name \*.os -o -name \*.osm -o -name \*.a | xargs rm -f
+
+distclean: clean
+	rm -f scripts/bb_mkdep scripts/usage
+	rm -r -f include/config include/config.h $(DEP_INCLUDES)
+	find . -name .depend'*' -print0 | xargs -0 rm -f
+	rm -f .hdepend
+	rm -f .config .config.old .config.cmd
+
+release: distclean #doc
+	cd ..; \
+	rm -r -f $(PROG)-$(VERSION); \
+	cp -a busybox $(PROG)-$(VERSION); \
+	\
+	find $(PROG)-$(VERSION)/ -type d \
+		-name .svn \
+		-print \
+		-exec rm -r -f {} \; ; \
+	\
+	find $(PROG)-$(VERSION)/ -type f \
+		-name .\#* \
+		-print \
+		-exec rm -f {} \; ; \
+	\
+	tar -cvzf $(PROG)-$(VERSION).tar.gz $(PROG)-$(VERSION)/;
+
+tags:
+	ctags -R .
+
+# documentation, cross-reference
+# Modern distributions already ship synopsis packages (e.g. debian)
+# If you have an old distribution go to http://synopsis.fresco.org/
+syn_tgt := $(wildcard $(patsubst %,%/*.c,$(SRC_DIRS)))
+syn     := $(patsubst %.c, %.syn, $(syn_tgt))
+
+%.syn: %.c
+	synopsis -p C -l Comments.SSDFilter,Comments.Previous $(INCS) -Wp,verbose,debug,preprocess,cppflags="'$(CFLAGS) $(EXTRA_CFLAGS) $(LDFLAGS) $(PROG_CFLAGS) $(PROG_LDFLAGS) $(CFLAGS_COMBINE) $(APPLETS_DEFINE) $(BUSYBOX_DEFINE)'" -o $@ $<
+html: $(syn)
+	synopsis -f HTML -Wf,title="'BusyBox Documentation'" -o $@ $^
+
+
+endif # ifeq ($(skip-makefile),)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/README
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/README	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/README	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,198 @@
+Please see the LICENSE file for details on copying and usage.
+Please refer to the INSTALL file for instructions on how to build.
+
+What is busybox:
+
+  BusyBox combines tiny versions of many common UNIX utilities into a single
+  small executable.  It provides minimalist replacements for most of the
+  utilities you usually find in bzip2, coreutils, dhcp, diffutils, e2fsprogs,
+  file, findutils, gawk, grep, inetutils, less, modutils, net-tools, procps,
+  sed, shadow, sysklogd, sysvinit, tar, util-linux, and vim.  The utilities
+  in BusyBox often have fewer options than their full-featured cousins;
+  however, the options that are included provide the expected functionality
+  and behave very much like their larger counterparts.
+
+  BusyBox has been written with size-optimization and limited resources in
+  mind, both to produce small binaries and to reduce run-time memory usage.
+  Busybox is also extremely modular so you can easily include or exclude
+  commands (or features) at compile time.  This makes it easy to customize
+  embedded systems; to create a working system, just add /dev, /etc, and a
+  Linux kernel.  Busybox (usually together with uClibc) has also been used as
+  a component of "thin client" desktop systems, live-CD distributions, rescue
+  disks, installers, and so on.
+
+  BusyBox provides a fairly complete POSIX environment for any small system,
+  both embedded environments and more full featured systems concerned about
+  space.  Busybox is slowly working towards implementing the full Single Unix
+  Specification V3 (http://www.opengroup.org/onlinepubs/009695399/), but isn't
+  there yet (and for size reasons will probably support at most UTF-8 for
+  internationalization).  We are also interested in passing the Linux Test
+  Project (http://ltp.sourceforge.net).
+
+----------------
+
+Using busybox:
+
+  BusyBox is extremely configurable.  This allows you to include only the
+  components and options you need, thereby reducing binary size.  Run 'make
+  config' or 'make menuconfig' to select the functionality that you wish to
+  enable.  (See 'make help' for more commands.)
+
+  The behavior of busybox is determined by the name it's called under: as
+  "cp" it behaves like cp, as "sed" it behaves like sed, and so on.  Called
+  as "busybox" it takes the second argument as the name of the applet to
+  run (I.E. "./busybox ls -l /proc").
+
+  The "standalone shell" mode is an easy way to try out busybox; this is a
+  command shell that calls the builtin applets without needing them to be
+  installed in the path.  (Note that this requires /proc to be mounted, if
+  testing from a boot floppy or in a chroot environment.)
+
+  The build automatically generates a file "busybox.links", which is used by
+  'make install' to create symlinks to the BusyBox binary for all compiled in
+  commands.  This uses the PREFIX environment variable to specify where to
+  install, and installs hardlinks or symlinks depending on the configuration
+  preferences.  (You can also manually run the install script at
+  "applets/install.sh").
+
+----------------
+
+Downloading the current source code:
+
+  Source for the latest released version, as well as daily snapshots, can always
+  be downloaded from
+
+    http://busybox.net/downloads/
+
+  You can browse the up to the minute source code and change history online.
+
+    http://www.busybox.net/cgi-bin/viewcvs.cgi/trunk/busybox/
+
+  Anonymous SVN access is available.  For instructions, check out:
+
+    http://busybox.net/subversion.html
+
+  For those that are actively contributing and would like to check files in,
+  see:
+
+    http://busybox.net/developer.html
+
+  The developers also have a bug and patch tracking system
+  (http://bugs.busybox.net) although posting a bug/patch to the mailing list
+  is generally a faster way of getting it fixed, and the complete archive of
+  what happened is the subversion changelog.
+
+----------------
+
+getting help:
+
+  when you find you need help, you can check out the busybox mailing list
+  archives at http://busybox.net/lists/busybox/ or even join
+  the mailing list if you are interested.
+
+----------------
+
+bugs:
+
+  if you find bugs, please submit a detailed bug report to the busybox mailing
+  list at busybox at busybox.net.  a well-written bug report should include a
+  transcript of a shell session that demonstrates the bad behavior and enables
+  anyone else to duplicate the bug on their own machine. the following is such
+  an example:
+
+    to: busybox at busybox.net
+    from: diligent at testing.linux.org
+    subject: /bin/date doesn't work
+
+    package: busybox
+    version: 1.00
+
+    when i execute busybox 'date' it produces unexpected results.
+    with gnu date i get the following output:
+
+	$ date
+	fri oct  8 14:19:41 mdt 2004
+
+    but when i use busybox date i get this instead:
+
+	$ date
+	illegal instruction
+
+    i am using debian unstable, kernel version 2.4.25-vrs2 on a netwinder,
+    and the latest uclibc from cvs.  thanks for the wonderful program!
+
+	-diligent
+
+  note the careful description and use of examples showing not only what
+  busybox does, but also a counter example showing what an equivalent app
+  does (or pointing to the text of a relevant standard).  Bug reports lacking
+  such detail may never be fixed...  Thanks for understanding.
+
+----------------
+
+Portability:
+
+  Busybox is developed and tested on Linux 2.4 and 2.6 kernels, compiled
+  with gcc (the unit-at-a-time optimizations in version 3.4 and later are
+  worth upgrading to get, but older versions should work), and linked against
+  uClibc (0.9.27 or greater) or glibc (2.2 or greater).  In such an
+  environment, the full set of busybox features should work, and if
+  anything doesn't we want to know about it so we can fix it.
+
+  There are many other environments out there, in which busybox may build
+  and run just fine.  We just don't test them.  Since busybox consists of a
+  large number of more or less independent applets, portability is a question
+  of which features work where.  Some busybox applets (such as cat and rm) are
+  highly portable and likely to work just about anywhere, while others (such as
+  insmod and losetup) require recent Linux kernels with recent C libraries.
+
+  Earlier versions of Linux and glibc may or may not work, for any given
+  configuration.  Linux 2.2 or earlier should mostly work (there's still
+  some support code in things like mount.c) but this is no longer regularly
+  tested, and inherently won't support certain features (such as long files
+  and --bind mounts).  The same is true for glibc 2.0 and 2.1: expect a higher
+  testing and debugging burden using such old infrastructure.  (The busybox
+  developers are not very interested in supporting these older versions, but
+  will probably accept small self-contained patches to fix simple problems.)
+
+  Some environments are not recommended.  Early versions of uClibc were buggy
+  and missing many features: upgrade.  Linking against libc5 or dietlibc is
+  not supported and not interesting to the busybox developers.  (The first is
+  obsolete and has no known size or feature advantages over uClibc, the second
+  has known bugs that its developers have actively refused to fix.)  Ancient
+  Linux kernels (2.0.x and earlier) are similarly uninteresting.
+
+  In theory it's possible to use Busybox under other operating systems (such as
+  MacOS X, Solaris, Cygwin, or the BSD Fork Du Jour).  This generally involves
+  a different kernel and a different C library at the same time.  While it
+  should be possible to port the majority of the code to work in one of
+  these environments, don't be suprised if it doesn't work out of the box.  If
+  you're into that sort of thing, start small (selecting just a few applets)
+  and work your way up.
+
+  Shaun Jackman has recently (2005) ported busybox to a combination of newlib
+  and libgloss, and some of his patches have been integrated.  This platform
+  may join glibc/uclibc and Linux as a supported combination with the 1.1
+  release, but is not supported in 1.0.
+
+Supported hardware:
+
+  BusyBox in general will build on any architecture supported by gcc.  We
+  support both 32 and 64 bit platforms, and both big and little endian
+  systems.
+
+  Under 2.4 Linux kernels, kernel module loading was implemented in a
+  platform-specific manner.  Busybox's insmod utility has been reported to
+  work under ARM, CRIS, H8/300, x86, ia64, x86_64, m68k, MIPS, PowerPC, S390,
+  SH3/4/5, Sparc, v850e, and x86_64.  Anything else probably won't work.
+
+  The module loading mechanism for the 2.6 kernel is much more generic, and
+  we believe 2.6.x kernel module loading support should work on all
+  architectures supported by the kernel.
+
+----------------
+
+Please feed suggestions, bug reports, insults, and bribes back to the busybox
+maintainer:
+	Rob Landley
+	<rob at landley.net>

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/Rules.mak
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/Rules.mak	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/Rules.mak	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,430 @@
+# Rules.make for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under GPLv2, see the file LICENSE in this tarball for details.
+#
+
+# Pull in the user's busybox configuration
+ifeq ($(filter $(noconfig_targets),$(MAKECMDGOALS)),)
+-include $(top_builddir)/.config
+endif
+
+#--------------------------------------------------------
+PROG      := busybox
+MAJOR_VERSION   :=1
+MINOR_VERSION   :=2
+SUBLEVEL_VERSION:=1
+EXTRAVERSION    :=
+VERSION   :=$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL_VERSION)$(EXTRAVERSION)
+BUILDTIME := $(shell TZ=UTC date -u "+%Y.%m.%d-%H:%M%z")
+
+
+#--------------------------------------------------------
+# With a modern GNU make(1) (highly recommended, that's what all the
+# developers use), all of the following configuration values can be
+# overridden at the command line.  For example:
+#   make CROSS=powerpc-linux- top_srcdir="$HOME/busybox" PREFIX=/mnt/app
+#--------------------------------------------------------
+
+# If you are running a cross compiler, you will want to set 'CROSS'
+# to something more interesting...  Target architecture is determined
+# by asking the CC compiler what arch it compiles things for, so unless
+# your compiler is broken, you should not need to specify TARGET_ARCH
+CROSS          =$(strip $(subst ",, $(strip $(CROSS_COMPILER_PREFIX))))
+# be gentle to vi coloring.. "))
+CC             = $(CROSS)gcc
+AR             = $(CROSS)ar
+AS             = $(CROSS)as
+LD             = $(CROSS)ld
+NM             = $(CROSS)nm
+#jmc: since we aren't generating an intermediate ELF
+#STRIP          = $(CROSS)strip
+STRIP          = echo
+ELF2FLT        = $(CROSS)elf2flt
+CPP            = $(CC) -E
+SED           ?= sed
+BZIP2         ?= bzip2
+
+# What OS are you compiling busybox for?  This allows you to include
+# OS specific things, syscall overrides, etc.
+TARGET_OS=linux
+
+# Ensure consistent sort order, 'gcc -print-search-dirs' behavior, etc.
+LC_ALL:= C
+
+# This must bind late because srcdir is reset for every source subdirectory.
+INCS:=-I$(top_builddir)/include -I$(top_srcdir)/include
+CFLAGS=$(INCS) -I$(srcdir) -D_GNU_SOURCE
+CFLAGS+=$(CHECKED_CFLAGS)
+ARFLAGS=cru
+
+# custom CFLAGS for FLT
+CFLAGS+=-Wl,-elf2flt="-s 16384" 
+# gcc centric. Perhaps fiddle with findstring gcc,$(CC) for the rest
+# get the CC MAJOR/MINOR version
+CC_MAJOR:=$(shell printf "%02d" $(shell echo __GNUC__ | $(CC) -E -xc - | tail -n 1))
+CC_MINOR:=$(shell printf "%02d" $(shell echo __GNUC_MINOR__ | $(CC) -E -xc - | tail -n 1))
+
+#--------------------------------------------------------
+export VERSION BUILDTIME HOSTCC HOSTCFLAGS CROSS CC AR AS LD NM STRIP CPP
+ifeq ($(strip $(TARGET_ARCH)),)
+TARGET_ARCH:=$(shell $(CC) -dumpmachine | $(SED) -e s'/-.*//' \
+		-e 's/i.86/i386/' \
+		-e 's/sparc.*/sparc/' \
+		-e 's/arm.*/arm/g' \
+		-e 's/m68k.*/m68k/' \
+		-e 's/ppc/powerpc/g' \
+		-e 's/v850.*/v850/g' \
+		-e 's/sh[234]/sh/' \
+		-e 's/mips-.*/mips/' \
+		-e 's/mipsel-.*/mipsel/' \
+		-e 's/cris.*/cris/' \
+		)
+endif
+
+# A nifty macro to make testing gcc features easier, but note that everything
+# that uses this _must_ use := or it will be re-evaluated everytime it is
+# referenced.
+ifeq ($(strip $(BUILD_VERBOSE)),2)
+VERBOSE_CHECK_CC=echo CC=\"$(1)\" check_cc $(2) >&2;
+endif
+check_cc=$(shell \
+	$(VERBOSE_CHECK_CC) \
+	if [ "x$(1)" != "x" ] && [ "x$(2)" != "x" ]; then \
+		echo "int i;" > ./conftest.c; \
+		if $(1) $(2) -c -o conftest.o conftest.c > /dev/null 2>&1; \
+		then echo "$(2)"; else echo "$(3)"; fi ; \
+		rm -f conftest.c conftest.o; \
+	fi)
+
+ifneq ($(filter $(nocheck_targets),$(MAKECMDGOALS)),)
+check_cc:=
+endif
+
+# A not very robust macro to check for available ld flags
+ifeq ($(strip $(BUILD_VERBOSE)),2)
+VERBOSE_CHECK_LD=echo LD=\"$(1)\" check_ld $(2) >&2;
+endif
+check_ld=$(shell \
+	$(VERBOSE_CHECK_LD) \
+	if [ "x$(1)" != "x" ] && [ "x$(2)" != "x" ]; then \
+		$(1) -o /dev/null -b binary /dev/null > /dev/null 2>&1 && \
+		echo "-Wl,$(2)" ; \
+	fi)
+
+ifneq ($(filter $(nocheck_targets),$(MAKECMDGOALS)),)
+check_ld:=
+endif
+
+# A not very robust macro to check for available strip flags
+ifeq ($(strip $(BUILD_VERBOSE)),2)
+VERBOSE_CHECK_STRIP=echo STRIPCMD=\"$(1)\" check_strip $(2) >&2;
+endif
+check_strip=$(shell \
+	$(VERBOSE_CHECK_STRIP) \
+	if [ "x$(1)" != "x" ] && [ "x$(2)" != "x" ]; then \
+		echo "int i;" > ./conftest.c ; \
+		$(CC) -c -o conftest.o conftest.c > /dev/null 2>&1 ; \
+		$(1) $(2) conftest.o > /dev/null 2>&1 && \
+		echo "$(1) $(2)" || echo "$(3)"; \
+		rm -f conftest.c conftest.o > /dev/null 2>&1 ; \
+	fi)
+
+ifneq ($(filter $(nocheck_targets),$(MAKECMDGOALS)),)
+check_strip:=
+endif
+
+
+# Select the compiler needed to build binaries for your development system
+HOSTCC     = gcc
+HOSTCFLAGS:=$(call check_cc,$(HOSTCC),-Wall,)
+HOSTCFLAGS+=$(call check_cc,$(HOSTCC),-Wstrict-prototypes,)
+HOSTCFLAGS+=$(call check_cc,$(HOSTCC),-O2,)
+HOSTCFLAGS+=$(call check_cc,$(HOSTCC),-fomit-frame-pointer,)
+
+LD_WHOLE_ARCHIVE:=$(shell echo "int i;" > conftest.c ; \
+	$(CC) -c -o conftest.o conftest.c ; \
+	echo "int main(void){return 0;}" > conftest_main.c ; \
+	$(CC) -c -o conftest_main.o conftest_main.c ; \
+	$(AR) $(ARFLAGS) conftest.a conftest.o ; \
+	$(CC) -Wl,--whole-archive conftest.a -Wl,--no-whole-archive \
+	 conftest_main.o -o conftest > /dev/null 2>&1 \
+	 && echo "-Wl,--whole-archive" ; \
+	rm conftest_main.o conftest_main.c conftest.o conftest.c \
+	 conftest.a conftest > /dev/null 2>&1 ; )
+ifneq ($(findstring whole-archive,$(LD_WHOLE_ARCHIVE)),)
+LD_NO_WHOLE_ARCHIVE:= -Wl,--no-whole-archive
+endif
+
+LD_START_GROUP:=$(shell echo "int bar(void){return 0;}" > conftest.c ; \
+	$(CC) -c -o conftest.o conftest.c ; \
+	echo "int main(void){return bar();}" > conftest_main.c ; \
+	$(CC) -c -o conftest_main.o conftest_main.c ; \
+	$(AR) $(ARFLAGS) conftest.a conftest.o ; \
+	$(CC) -Wl,--start-group conftest.a conftest_main.o -Wl,--end-group \
+	 -o conftest > /dev/null 2>&1 && echo "-Wl,--start-group" ; \
+	rm conftest_main.o conftest_main.c conftest.o conftest.c \
+	 conftest.a conftest > /dev/null 2>&1 ; )
+ifneq ($(findstring start-group,$(LD_START_GROUP)),)
+LD_END_GROUP:= -Wl,--end-group
+endif
+
+CHECKED_LDFLAGS := $(call check_ld,$(LD),--warn-common,)
+
+# Pin CHECKED_CFLAGS with := so it's only evaluated once.
+CHECKED_CFLAGS:=$(call check_cc,$(CC),-Wall,)
+CHECKED_CFLAGS+=$(call check_cc,$(CC),-Wstrict-prototypes,)
+CHECKED_CFLAGS+=$(call check_cc,$(CC),-Wshadow,)
+CHECKED_CFLAGS+=$(call check_cc,$(CC),-funsigned-char,)
+CHECKED_CFLAGS+=$(call check_cc,$(CC),-mmax-stack-frame=256,)
+CHECKED_CFLAGS+=$(call check_cc,$(CC),-fno-builtin-strlen)
+
+# Preemptively pin this too.
+PROG_CFLAGS:=
+
+
+#--------------------------------------------------------
+# Arch specific compiler optimization stuff should go here.
+# Unless you want to override the defaults, do not set anything
+# for OPTIMIZATION...
+
+# use '-Os' optimization if available, else use -O2
+OPTIMIZATION:=$(call check_cc,$(CC),-Os,-O2)
+
+ifeq ($(CONFIG_BUILD_AT_ONCE),y)
+# gcc 2.95 exits with 0 for "unrecognized option"
+ifeq ($(strip $(shell [ $(CC_MAJOR) -ge 3 ] ; echo $$?)),0)
+	CFLAGS_COMBINE:=$(call check_cc,$(CC),--combine,)
+endif
+OPTIMIZATION+=$(call check_cc,$(CC),-funit-at-a-time,)
+OPTIMIZATION+=$(call check_cc,$(CC),-fgcse-after-reload,)
+ifneq ($(CONFIG_BUILD_LIBBUSYBOX),y)
+# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25795
+# This prevents us from using -fwhole-program when we build the lib
+PROG_CFLAGS+=$(call check_cc,$(CC),-fwhole-program,)
+endif # CONFIG_BUILD_LIBBUSYBOX
+endif # CONFIG_BUILD_AT_ONCE
+
+LIB_LDFLAGS:=$(call check_ld,$(LD),--enable-new-dtags,)
+#LIB_LDFLAGS+=$(call check_ld,$(LD),--reduce-memory-overheads,)
+#LIB_LDFLAGS+=$(call check_ld,$(LD),--as-needed,)
+#LIB_LDFLAGS+=$(call check_ld,$(LD),--warn-shared-textrel,)
+
+
+# Some nice architecture specific optimizations
+ifeq ($(strip $(TARGET_ARCH)),arm)
+	OPTIMIZATION+=-fstrict-aliasing
+endif
+ifeq ($(strip $(TARGET_ARCH)),i386)
+	OPTIMIZATION+=$(call check_cc,$(CC),-march=i386,)
+# gcc-4.0 and older seem to benefit from these
+#ifneq ($(strip $(shell [ $(CC_MAJOR) -ge 4 -a $(CC_MINOR) -ge 1 ] ; echo $$?)),0)
+	OPTIMIZATION+=$(call check_cc,$(CC),-mpreferred-stack-boundary=2,)
+	OPTIMIZATION+=$(call check_cc,$(CC),-falign-functions=1 -falign-jumps=1 -falign-loops=1,\
+		-malign-functions=0 -malign-jumps=0 -malign-loops=0)
+#endif # gcc-4.0 and older
+
+# gcc-4.1 and beyond seem to benefit from these
+ifeq ($(strip $(shell [ $(CC_MAJOR) -ge 4 -a $(CC_MINOR) -ge 1 ] ; echo $$?)),0)
+	# turn off flags which hurt -Os
+	OPTIMIZATION+=$(call check_cc,$(CC),-fno-tree-loop-optimize,)
+	OPTIMIZATION+=$(call check_cc,$(CC),-fno-tree-dominator-opts,)
+	OPTIMIZATION+=$(call check_cc,$(CC),-fno-strength-reduce,)
+
+	OPTIMIZATION+=$(call check_cc,$(CC),-fno-branch-count-reg,)
+endif # gcc-4.1 and beyond
+endif
+OPTIMIZATION+=$(call check_cc,$(CC),-fomit-frame-pointer,)
+OPTIMIZATION+=$(call check_cc,$(CC),-ffunction-sections -fdata-sections,)
+
+#
+#--------------------------------------------------------
+# If you're going to do a lot of builds with a non-vanilla configuration,
+# it makes sense to adjust parameters above, so you can type "make"
+# by itself, instead of following it by the same half-dozen overrides
+# every time.  The stuff below, on the other hand, is probably less
+# prone to casual user adjustment.
+#
+
+ifeq ($(strip $(CONFIG_LFS)),y)
+    # For large file summit support
+    CFLAGS+=-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+endif
+ifeq ($(strip $(CONFIG_DMALLOC)),y)
+    # For testing mem leaks with dmalloc
+    CFLAGS+=-DDMALLOC
+    LIBRARIES:=-ldmalloc
+else
+    ifeq ($(strip $(CONFIG_EFENCE)),y)
+	LIBRARIES:=-lefence
+    endif
+endif
+
+# Debugging info
+
+ifeq ($(strip $(CONFIG_DEBUG)),y)
+    CFLAGS +=-g
+else
+    CFLAGS +=-DNDEBUG
+    CHECKED_LDFLAGS += $(call check_ld,$(LD),--sort-common,)
+    CHECKED_LDFLAGS += $(call check_ld,--gc-sections,)
+endif
+
+ifneq ($(strip $(CONFIG_DEBUG_PESSIMIZE)),y)
+    CFLAGS += $(OPTIMIZATION)
+endif
+
+# warn a bit more verbosely for non-release versions
+ifneq ($(EXTRAVERSION),)
+    CHECKED_CFLAGS+=$(call check_cc,$(CC),-Wstrict-prototypes,)
+    CHECKED_CFLAGS+=$(call check_cc,$(CC),-Wmissing-prototypes,)
+    CHECKED_CFLAGS+=$(call check_cc,$(CC),-Wmissing-declarations,)
+    CHECKED_CFLAGS+=$(call check_cc,$(CC),-Wunused,)
+    CHECKED_CFLAGS+=$(call check_cc,$(CC),-Winit-self,)
+    CHECKED_CFLAGS+=$(call check_cc,$(CC),-Wshadow,)
+    CHECKED_CFLAGS+=$(call check_cc,$(CC),-Wcast-align,)
+endif
+STRIPCMD:=$(call check_strip,$(STRIP),-s --remove-section=.note --remove-section=.comment,$(STRIP))
+ifeq ($(strip $(CONFIG_STATIC)),y)
+    PROG_CFLAGS += $(call check_cc,$(CC),-static,)
+endif
+CFLAGS_SHARED := $(call check_cc,$(CC),-shared,)
+LIB_CFLAGS+=$(CFLAGS_SHARED)
+
+ifeq ($(strip $(CONFIG_BUILD_LIBBUSYBOX)),y)
+    CFLAGS_PIC:= $(call check_cc,$(CC),-fPIC,)
+    LIB_CFLAGS+=$(CFLAGS_PIC)
+endif
+
+ifeq ($(strip $(CONFIG_SELINUX)),y)
+    LIBRARIES += -lselinux
+endif
+
+ifeq ($(strip $(PREFIX)),)
+    PREFIX:=`pwd`/_install
+endif
+
+ifneq ($(strip $(CONFIG_GETOPT_LONG)),y)
+    CFLAGS += -D__need_getopt
+endif
+
+# Additional complications due to support for pristine source dir.
+# Include files in the build directory should take precedence over
+# the copy in top_srcdir, both during the compilation phase and the
+# shell script that finds the list of object files.
+# Work in progress by <ldoolitt at recycle.lbl.gov>.
+
+
+OBJECTS:=$(APPLET_SOURCES:.c=.o) busybox.o usage.o applets.o
+CFLAGS  += $(CHECKED_CFLAGS) $(CROSS_CFLAGS)
+LDFLAGS += $(CHECKED_LDFLAGS)
+
+ifdef BB_INIT_SCRIPT
+    CFLAGS += -DINIT_SCRIPT='"$(BB_INIT_SCRIPT)"'
+endif
+
+# Put user-supplied flags at the end, where they
+# have a chance of winning.
+-include $(top_builddir)/.config.mak
+
+#------------------------------------------------------------
+# Installation options
+ifeq ($(strip $(CONFIG_INSTALL_APPLET_HARDLINKS)),y)
+INSTALL_OPTS=--hardlinks
+endif
+ifeq ($(strip $(CONFIG_INSTALL_APPLET_SYMLINKS)),y)
+INSTALL_OPTS=--symlinks
+endif
+ifeq ($(strip $(CONFIG_INSTALL_APPLET_DONT)),y)
+INSTALL_OPTS=
+endif
+
+#------------------------------------------------------------
+# Make the output nice and tight
+MAKEFLAGS += --no-print-directory
+export MAKE_IS_SILENT=n
+ifneq ($(findstring s,$(MAKEFLAGS)),)
+export MAKE_IS_SILENT=y
+SECHO := @-false
+DISP  := sil
+Q     := @
+else
+ifneq ($(BUILD_VERBOSE),)
+SECHO := @-false
+DISP  := ver
+Q     := 
+else
+SECHO := @echo
+DISP  := pur
+Q     := @
+endif
+endif
+
+show_objs = $(subst $(top_builddir)/,,$(subst ../,,$@))
+pur_disp_compile.c = echo "  "CC $(show_objs)
+pur_disp_compile.h = echo "  "HOSTCC $(show_objs)
+pur_disp_strip     = echo "  "STRIP $(show_objs)
+pur_disp_link      = echo "  "LINK $(show_objs)
+pur_disp_link.h    = echo "  "HOSTLINK $(show_objs)
+pur_disp_ar        = echo "  "AR $(ARFLAGS) $(show_objs)
+pur_disp_elf2flt   = echo "  "ELF2FLT $(ELF2FLTFLAGS) $(show_objs)
+sil_disp_compile.c = true
+sil_disp_compile.h = true
+sil_disp_strip     = true
+sil_disp_link      = true
+sil_disp_link.h    = true
+sil_disp_ar        = true
+sil_disp_elf2flt   = true
+ver_disp_compile.c = echo $(cmd_compile.c)
+ver_disp_compile.h = echo $(cmd_compile.h)
+ver_disp_strip     = echo $(cmd_strip)
+ver_disp_link      = echo $(cmd_link)
+ver_disp_link.h    = echo $(cmd_link.h)
+ver_disp_ar        = echo $(cmd_ar)
+ver_disp_elf2flt   = echo $(cmd_elf2flt)
+disp_compile.c     = $($(DISP)_disp_compile.c)
+disp_compile.h     = $($(DISP)_disp_compile.h)
+disp_strip         = $($(DISP)_disp_strip)
+disp_link          = $($(DISP)_disp_link)
+disp_link.h        = $($(DISP)_disp_link.h)
+disp_ar            = $($(DISP)_disp_ar)
+disp_gen           = $(SECHO) "  "GEN $@ ; true
+disp_doc           = $(SECHO) "  "DOC $(subst docs/,,$@) ; true
+disp_elf2flt       = $($(DISP)_disp_elf2flt)
+cmd_compile.c      = $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
+cmd_compile.h      = $(HOSTCC) $(HOSTCFLAGS) $(INCS) -c -o $@ $<
+cmd_strip          = $(STRIPCMD) $@
+cmd_link           = $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(LDFLAGS) \
+			$(PROG_CFLAGS) $(PROG_LDFLAGS) $(CFLAGS_COMBINE) \
+			-o $@ $(LD_START_GROUP)  \
+			$(APPLETS_DEFINE) $(APPLET_SRC) \
+			$(BUSYBOX_DEFINE) $(BUSYBOX_SRC) $(libraries-y) \
+			$(LDBUSYBOX) $(LIBRARIES) \
+			$(LD_END_GROUP)
+cmd_link.so        = $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(LDFLAGS) \
+			$(LIB_CFLAGS) $(CFLAGS_COMBINE) $(LIB_LDFLAGS) \
+			-o $(@) $(LD_START_GROUP) $(LD_WHOLE_ARCHIVE) \
+			$(LIBRARY_DEFINE) $(^) \
+			$(LD_NO_WHOLE_ARCHIVE) $(LD_END_GROUP)
+cmd_link.h         = $(HOSTCC) $(HOSTCFLAGS) $(INCS) $< -o $@
+cmd_ar             = $(AR) $(ARFLAGS) $@ $^
+cmd_elf2flt        = $(ELF2FLT) $(ELF2FLTFLAGS) $< -o $@
+compile.c          = @$(disp_compile.c) ; $(cmd_compile.c)
+compile.h          = @$(disp_compile.h) ; $(cmd_compile.h)
+do_strip           = @$(disp_strip)     ; $(cmd_strip)
+do_link            = @$(disp_link)      ; $(cmd_link)
+do_link.so         = @$(disp_link)      ; $(cmd_link.so)
+do_link.h          = @$(disp_link.h)    ; $(cmd_link.h)
+do_ar              = @$(disp_ar)        ; $(cmd_ar)
+do_elf2flt         = @$(disp_elf2flt)   ; $(cmd_elf2flt)
+
+uppercase = $(shell echo $1 | $(SED) -e "y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/")
+%.a:
+	@if test -z "$($(call uppercase,$*)_DIR)" ; then \
+		echo "Invalid target $@" ; \
+		exit 1 ; \
+	fi
+	$(Q)$(MAKE) $($(call uppercase,$*)_DIR)$@
+
+.PHONY: dummy

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/TODO
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/TODO	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/TODO	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,306 @@
+Busybox TODO
+
+Stuff that needs to be done.  This is organized by who plans to get around to
+doing it eventually, but that doesn't mean they "own" the item.  If you want to
+do one of these bounce an email off the person it's listed under to see if they
+have any suggestions how they plan to go about it, and to minimize conflicts
+between your work and theirs.  But otherwise, all of these are fair game.
+
+Rob Landley <rob at landley.net>:
+  Add BB_NOMMU to platform.h and migrate __uClinux__ tests to that.
+    #if defined __UCLIBC__ && !defined __ARCH_USE_MMU__
+  Add a libbb/platform.c
+    Implement fdprintf() for platforms that haven't got one.
+    Implement bb_realpath() that can handle NULL on non-glibc.
+    Cleanup bb_asprintf()
+
+  Migrate calloc() and bb_calloc() occurrences to bb_xzalloc().
+  Remove obsolete _() wrapper crud for internationalization we don't do.
+  Figure out where we need utf8 support, and add it.
+
+  sh
+    The command shell situation is a big mess.  We have three or four different
+    shells that don't really share any code, and the "standalone shell" doesn't
+    work all that well (especially not in a chroot environment), due to apps not
+    being reentrant.  I'm writing a new shell (bbsh) to unify the various
+    shells and configurably add the minimal set of bash features people
+    actually use.  The hardest part is it has to configure down as small as
+    lash while providing lash's features.  The rest is easy in comparison.
+  bzip2
+    Compression-side support.
+  init
+    General cleanup (should use ENABLE_FEATURE_INIT_SYSLOG and ENABLE_FEATURE_INIT_DEBUG).
+  depmod
+    busybox lacks a way to update module deps when running from firmware without the
+    use of the depmod.pl (perl is to bloated for most embedded setups) and or orig
+    modutils. The orig depmod is rather pointless to have to add to a firmware image 
+    in when we already have a insmod/rmmod and friends.
+  Unify base64 handling.
+    There's base64 encoding and decoding going on in:
+      networking/wget.c:base64enc()
+      coreutils/uudecode.c:read_base64()
+      coreutils/uuencode.c:tbl_base64[]
+      networking/httpd.c:decodeBase64()
+    And probably elsewhere.  That needs to be unified into libbb functions.
+  Do a SUSv3 audit
+    Look at the full Single Unix Specification version 3 (available online at
+    "http://www.opengroup.org/onlinepubs/009695399/nfindex.html") and
+    figure out which of our apps are compliant, and what we're missing that
+    we might actually care about.
+
+    Even better would be some kind of automated compliance test harness that
+    exercises each command line option and the various corner cases.
+  Internationalization
+    How much internationalization should we do?
+
+    The low hanging fruit is UTF-8 character set support.  We should do this.
+    (Vodz pointed out the shell's cmdedit as needing work here.  What else?)
+
+    We also have lots of hardwired english text messages.  Consolidating this
+    into some kind of message table not only makes translation easier, but
+    also allows us to consolidate redundant (or close) strings.
+
+    We probably don't want to be bloated with locale support.  (Not unless we
+    can cleanly export it from our underlying C library without having to
+    concern ourselves with it directly.  Perhaps a few specific things like a
+    config option for "date" are low hanging fruit here?)
+
+    What level should things happen at?  How much do we care about
+    internationalizing the text console when X11 and xterms are so much better
+    at it?  (There's some infrastructure here we don't implement: The
+    "unicode_start" and "unicode_stop" shell scripts need "vt-is-UTF8" and a
+    --unicode option to loadkeys.  That implies a real loadkeys/dumpkeys
+    implementation to replace loadkmap/dumpkmap.  Plus messing with console font
+    loading.  Is it worth it, or do we just say "use X"?)
+
+  Individual compilation of applets.
+    It would be nice if busybox had the option to compile to individual applets,
+    for people who want an alternate implementation less bloated than the gnu
+    utils (or simply with less political baggage), but without it being one big
+    executable.
+
+    Turning libbb into a real dll is another possibility, especially if libbb
+    could export some of the other library interfaces we've already more or less
+    got the code for (like zlib).
+  buildroot - Make a "dogfood" option
+    Busybox 1.1 will be capable of replacing most gnu packages for real world
+    use, such as developing software or in a live CD.  It needs wider testing.
+
+    Busybox should now be able to replace bzip2, coreutils, e2fsprogs, file,
+    findutils, gawk, grep, inetutils, less, modutils, net-tools, patch, procps,
+    sed, shadow, sysklogd, sysvinit, tar, util-linux, and vim.  The resulting
+    system should be self-hosting (I.E. able to rebuild itself from source
+    code).  This means it would need (at least) binutils, gcc, and make, or
+    equivalents.
+
+    It would be a good "eating our own dogfood" test if buildroot had the option
+    of using a "make allyesconfig" busybox instead of the all of the above
+    packages.  Anything that's wrong with the resulting system, we can fix.  (It
+    would be nice to be able to upgrade busybox to be able to replace bash and
+    diffutils as well, but we're not there yet.)
+
+    One example of an existing system that does this already is Firmware Linux:
+      http://www.landley.net/code/firmware
+  initramfs
+    Busybox should have a sample initramfs build script.  This depends on
+    bbsh, mdev, and switch_root.
+  mkdep
+    Write a mkdep that doesn't segfault if there's a directory it doesn't
+    have permission to read, isn't based on manually editing the output of
+    lexx and yacc, doesn't make such a mess under include/config, etc.
+  Group globals into unions of structures.
+    Go through and turn all the global and static variables into structures,
+    and have all those structures be in a big union shared between processes,
+    so busybox uses less bss.  (This is a big win on nommu machines.)  See
+    sed.c and mdev.c for examples.
+  Go through bugs.busybox.net and close out all of that somehow.
+    This one's open to everybody, but I'll wind up doing it...
+
+
+Bernhard Fischer <rep.nop at anon.at>:
+  Makefile stuff:
+    make -j is broken, -j1 is forced atm
+  New debug options:
+    -Wlarger-than-127
+  Collate BUFSIZ IOBUF_SIZE MY_BUF_SIZE PIPE_PROGRESS_SIZE BUFSIZE PIPESIZE
+    Use bb_common_bufsiz1?
+
+As yet unclaimed:
+
+----
+find
+  doesn't understand (), lots of susv3 stuff.
+----
+diff
+  Make sure we handle empty files properly:
+    From the patch man page:
+
+   you can remove a file by sending out a context diff that compares
+   the file to be deleted with an empty file dated the Epoch.  The
+   file will be removed unless patch is conforming to POSIX and the
+   -E or --remove-empty-files option is not given.
+---
+patch
+  Should have simple fuzz factor support to apply patches at an offset which
+  shouldn't take up too much space.
+
+  And while we're at it, a new patch filename quoting format is apparently
+  coming soon:  http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
+---
+man
+  It would be nice to have a man command.  Not one that handles troff or
+  anything, just one that can handle preformatted ascii man pages, possibly
+  compressed.  This could probably be a script in the extras directory that
+  calls cat/zcat/bzcat | less
+
+  (How doclifter might work into this is anybody's guess.)
+---
+ar
+  Write support?
+---
+crond
+  turn FEATURE_DEBUG_OPT into ENABLE_FEATURE_CROND_DEBUG_OPT
+
+Architectural issues:
+
+bb_close() with fsync()
+  We should have a bb_close() in place of normal close, with a CONFIG_ option
+  to not just check the return value of close() for an error, but fsync().
+  Close can't reliably report anything useful because if write() accepted the
+  data then it either went out to the network or it's in cache or a pipe
+  buffer.  Either way, there's no guarantee it'll make it to its final
+  destination before close() gets called, so there's no guarantee that any
+  error will be reported.
+
+  You need to call fsync() if you care about errors that occur after write(),
+  but that can have a big performance impact.  So make it a config option.
+---
+Unify archivers
+  Lots of archivers have the same general infrastructure.  The directory
+  traversal code should be factored out, and the guts of each archiver could
+  be some setup code and a series of callbacks for "add this file",
+  "add this directory", "add this symlink" and so on.
+
+  This could clean up tar and zip, and make it cheaper to add cpio and ar
+  write support, and possibly even cheaply add things like mkisofs or
+  mksquashfs someday, if they become relevant.
+---
+Text buffer support.
+  Several existing applets (sort, vi, less...) read
+  a whole file into memory and act on it.  There might be an opportunity
+  for shared code in there that could be moved into libbb...
+---
+Memory Allocation
+  We have a CONFIG_BUFFER mechanism that lets us select whether to do memory
+  allocation on the stack or the heap.  Unfortunately, we're not using it much.
+  We need to audit our memory allocations and turn a lot of malloc/free calls
+  into RESERVE_CONFIG_BUFFER/RELEASE_CONFIG_BUFFER.
+  For a start, see e.g. make EXTRA_CFLAGS=-Wlarger-than-64
+
+  And while we're at it, many of the CONFIG_FEATURE_CLEAN_UP #ifdefs will be
+  optimized out by the compiler in the stack allocation case (since there's no
+  free for an alloca()), and this means that various cleanup loops that just
+  call free might also be optimized out by the compiler if written right, so
+  we can yank those #ifdefs too, and generally clean up the code.
+---
+Switch CONFIG_SYMBOLS to ENABLE_SYMBOLS
+
+  In busybox 1.0 and earlier, configuration was done by CONFIG_SYMBOLS
+  that were either defined or undefined to indicate whether the symbol was
+  selected in the .config file.  They were used with #ifdefs, ala:
+
+    #ifdef CONFIG_SYMBOL
+      if (other_test) {
+        do_code();
+      }
+    #endif
+
+  In 1.1, we have new ENABLE_SYMBOLS which are always defined (as 0 or 1),
+  meaning you can still use them for preprocessor tests by replacing
+  "#ifdef CONFIG_SYMBOL" with "#if ENABLE_SYMBOL".  But more importantly, we
+  can use them as a true or false test in normal C code:
+
+    if (ENABLE_SYMBOL && other_test) {
+      do_code();
+    }
+
+  (Optimizing away if() statements that resolve to a constant value
+  is known as "dead code elimination", an optimization so old and simple that
+  Turbo Pascal for DOS did it twenty years ago.  Even modern mini-compilers
+  like the Tiny C Compiler (tcc) and the Small Device C Compiler (SDCC)
+  perform dead code elimination.)
+
+  Right now, busybox.h is #including both "config.h" (defining the
+  CONFIG_SYMBOLS) and "bb_config.h" (defining the ENABLE_SYMBOLS).  At some
+  point in the future, it would be nice to wean ourselves off of the
+  CONFIG versions.  (Among other things, some defective build environments
+  leak the Linux kernel's CONFIG_SYMBOLS into the system's standard #include
+  files.  We've experienced collisions before.)
+---
+FEATURE_CLEAN_UP
+  This is more an unresolved issue than a to-do item.  More thought is needed.
+
+  Normally we rely on exit() to free memory, close files, and unmap segments
+  for us.  This makes most calls to free(), close(), and unmap() optional in
+  busybox applets that don't intend to run for very long, and optional stuff
+  can be omitted to save size.
+
+  The idea was raised that we could simulate fork/exit with setjmp/longjmp
+  for _really_ brainless embedded systems, or speed up the standalone shell
+  by not forking.  Doing so would require a reliable FEATURE_CLEAN_UP.
+  Unfortunately, this isn't as easy as it sounds.
+
+  The problem is, lots of things exit(), sometimes unexpectedly (xmalloc())
+  and sometimes reliably (bb_perror_msg_and_die() or show_usage()).  This
+  jumps out of the normal flow control and bypasses any cleanup code we
+  put at the end of our applets.
+
+  It's possible to add hooks to libbb functions like xmalloc() and bb_xopen()
+  to add their entries to a linked list, which could be traversed and
+  freed/closed automatically.  (This would need to be able to free just the
+  entries after a checkpoint to be usable for a forkless standalone shell.
+  You don't want to free the shell's own resources.)
+
+  Right now, FEATURE_CLEAN_UP is more or less a debugging aid, to make things
+  like valgrind happy.  It's also documentation of _what_ we're trusting
+  exit() to clean up for us.  But new infrastructure to auto-free stuff would
+  render the existing FEATURE_CLEAN_UP code redundant.
+
+  For right now, exit() handles it just fine.
+
+
+
+Minor stuff:
+  watchdog.c could autodetect the timer duration via:
+    if(!ioctl (fd, WDIOC_GETTIMEOUT, &tmo)) timer_duration = 1 + (tmo / 2);
+  Unfortunately, that needs linux/watchdog.h and that contains unfiltered
+  kernel types on some distros, which breaks the build.
+---
+  use bb_error_msg where appropriate: See
+  egrep "(printf.*\([[:space:]]*(stderr|2)|[^_]write.*\([[:space:]]*(stderr|2))"
+---
+  use bb_perror_msg where appropriate: See
+  egrep "[^_]perror"
+---
+  Remove superfluous fmt occurances: e.g.
+  fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
+  -> fprintf(stderr, "unalias: %s not found\n", *argptr);
+---
+  possible code duplication ingroup() and is_a_group_member()
+---
+  unify itoa: netstat.c, hush.c, lash.c, msh.c
+  Put one single, robust version into e.g. safe_strtol.c
+---
+
+
+Code cleanup:
+
+Replace deprecated functions.
+
+bzero() -> memset()
+---
+sigblock(), siggetmask(), sigsetmask(), sigmask() -> sigprocmask et al
+---
+vdprintf() -> similar sized functionality
+---
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/applets
+APPLETS_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include $(srcdir)/Makefile.in
+all: $(libraries-y)
+-include $(top_builddir).depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,26 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+APPLETS_AR:=applets.a
+ifndef $(APPLETS_DIR)
+APPLETS_DIR:=$(top_builddir)/applets/
+endif
+srcdir=$(top_srcdir)/applets
+
+APPLET_SRC:= $(patsubst %,$(srcdir)/%,applets.c busybox.c version.c)
+APPLET_OBJ:= $(patsubst $(srcdir)/%.c,$(APPLETS_DIR)%.o, $(APPLET_SRC))
+
+APPLET_SRC-y+=$(APPLET_SRC)
+APPLET_SRC-a+=$(APPLET_SRC)
+
+libraries-y+=$(APPLETS_DIR)$(APPLETS_AR)
+
+$(APPLETS_DIR)$(APPLETS_AR): $(APPLET_OBJ)
+	$(do_ar)
+
+$(APPLET_OBJ): $(top_builddir)/.config 
+$(APPLET_OBJ): $(APPLETS_DIR)%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/applets.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/applets.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/applets.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,486 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) tons of folks.  Tracking down who wrote what
+ * isn't something I'm going to worry about...  If you wrote something
+ * here, please feel free to acknowledge your work.
+ *
+ * Based in part on code from sash, Copyright (c) 1999 by David I. Bell
+ * Permission has been granted to redistribute this code under the GPL.
+ *
+ * Licensed under GPLv2 or later, see file License in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+
+#if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE
+static const char usage_messages[] =
+#define MAKE_USAGE
+#include "usage.h"
+#include "applets.h"
+;
+#undef MAKE_USAGE
+#else
+#define usage_messages 0
+#endif /* ENABLE_SHOW_USAGE */
+
+#undef APPLET
+#undef APPLET_NOUSAGE
+#undef PROTOTYPES
+#include "applets.h"
+
+static struct BB_applet *applet_using;
+
+/* The -1 arises because of the {0,NULL,0,-1} entry above. */
+const size_t NUM_APPLETS = (sizeof (applets) / sizeof (struct BB_applet) - 1);
+
+
+#ifdef CONFIG_FEATURE_SUID_CONFIG
+
+#include <ctype.h>
+#include "pwd_.h"
+#include "grp_.h"
+
+#define CONFIG_FILE "/etc/busybox.conf"
+
+/* applets [] is const, so we have to define this "override" structure */
+static struct BB_suid_config
+{
+  struct BB_applet *m_applet;
+
+  uid_t m_uid;
+  gid_t m_gid;
+  mode_t m_mode;
+
+  struct BB_suid_config *m_next;
+} *suid_config;
+
+static int suid_cfg_readable;
+
+/* check if u is member of group g */
+static int ingroup (uid_t u, gid_t g)
+{
+  struct group *grp = getgrgid (g);
+
+  if (grp) {
+	char **mem;
+
+	for (mem = grp->gr_mem; *mem; mem++) {
+	  struct passwd *pwd = getpwnam (*mem);
+
+	  if (pwd && (pwd->pw_uid == u))
+		return 1;
+	}
+  }
+  return 0;
+}
+
+/* This should probably be a libbb routine.  In that case,
+ * I'd probably rename it to something like bb_trimmed_slice.
+ */
+static char *get_trimmed_slice(char *s, char *e)
+{
+	/* First, consider the value at e to be nul and back up until we
+	 * reach a non-space char.  Set the char after that (possibly at
+	 * the original e) to nul. */
+	while (e-- > s) {
+		if (!isspace(*e)) {
+			break;
+		}
+	}
+	e[1] = 0;
+
+	/* Next, advance past all leading space and return a ptr to the
+	 * first non-space char; possibly the terminating nul. */
+	return skip_whitespace(s);
+}
+
+
+#define parse_error(x)  { err=x; goto pe_label; }
+
+/* Don't depend on the tools to combine strings. */
+static const char config_file[] = CONFIG_FILE;
+
+/* There are 4 chars + 1 nul for each of user/group/other. */
+static const char mode_chars[] = "Ssx-\0Ssx-\0Ttx-";
+
+/* We don't supply a value for the nul, so an index adjustment is
+ * necessary below.  Also, we use unsigned short here to save some
+ * space even though these are really mode_t values. */
+static const unsigned short mode_mask[] = {
+	/*  SST         sst                 xxx   --- */
+	S_ISUID,    S_ISUID|S_IXUSR,    S_IXUSR,    0,	/* user */
+	S_ISGID,    S_ISGID|S_IXGRP,    S_IXGRP,    0,	/* group */
+	0,          S_IXOTH,            S_IXOTH,    0	/* other */
+};
+
+static void parse_config_file(void)
+{
+	struct BB_suid_config *sct_head;
+	struct BB_suid_config *sct;
+	struct BB_applet *applet;
+	FILE *f;
+	char *err;
+	char *s;
+	char *e;
+	int i, lc, section;
+	char buffer[256];
+	struct stat st;
+
+	assert(!suid_config);		/* Should be set to NULL by bss init. */
+
+	if ((stat(config_file, &st) != 0)			/* No config file? */
+		|| !S_ISREG(st.st_mode)					/* Not a regular file? */
+		|| (st.st_uid != 0)						/* Not owned by root? */
+		|| (st.st_mode & (S_IWGRP | S_IWOTH))	/* Writable by non-root? */
+		|| !(f = fopen(config_file, "r"))		/* Can not open? */
+		) {
+		return;
+	}
+
+	suid_cfg_readable = 1;
+	sct_head = NULL;
+	section = lc = 0;
+
+	do {
+		s = buffer;
+
+		if (!fgets(s, sizeof(buffer), f)) { /* Are we done? */
+			if (ferror(f)) {   /* Make sure it wasn't a read error. */
+				parse_error("reading");
+			}
+			fclose(f);
+			suid_config = sct_head;	/* Success, so set the pointer. */
+			return;
+		}
+
+		lc++;					/* Got a (partial) line. */
+
+		/* If a line is too long for our buffer, we consider it an error.
+		 * The following test does mistreat one corner case though.
+		 * If the final line of the file does not end with a newline and
+		 * yet exactly fills the buffer, it will be treated as too long
+		 * even though there isn't really a problem.  But it isn't really
+		 * worth adding code to deal with such an unlikely situation, and
+		 * we do err on the side of caution.  Besides, the line would be
+		 * too long if it did end with a newline. */
+		if (!strchr(s, '\n') && !feof(f)) {
+			parse_error("line too long");
+		}
+
+		/* Trim leading and trailing whitespace, ignoring comments, and
+		 * check if the resulting string is empty. */
+		if (!*(s = get_trimmed_slice(s, strchrnul(s, '#')))) {
+			continue;
+		}
+
+		/* Check for a section header. */
+
+		if (*s == '[') {
+			/* Unlike the old code, we ignore leading and trailing
+			 * whitespace for the section name.  We also require that
+			 * there are no stray characters after the closing bracket. */
+			if (!(e = strchr(s, ']'))	/* Missing right bracket? */
+				|| e[1]					/* Trailing characters? */
+				|| !*(s = get_trimmed_slice(s+1, e)) /* Missing name? */
+				) {
+				parse_error("section header");
+			}
+			/* Right now we only have one section so just check it.
+			 * If more sections are added in the future, please don't
+			 * resort to cascading ifs with multiple strcasecmp calls.
+			 * That kind of bloated code is all too common.  A loop
+			 * and a string table would be a better choice unless the
+			 * number of sections is very small. */
+			if (strcasecmp(s, "SUID") == 0) {
+				section = 1;
+				continue;
+			}
+			section = -1;	/* Unknown section so set to skip. */
+			continue;
+		}
+
+		/* Process sections. */
+
+		if (section == 1) {		/* SUID */
+			/* Since we trimmed leading and trailing space above, we're
+			 * now looking for strings of the form
+			 *    <key>[::space::]*=[::space::]*<value>
+			 * where both key and value could contain inner whitespace. */
+
+			/* First get the key (an applet name in our case). */
+			if (!!(e = strchr(s, '='))) {
+				s = get_trimmed_slice(s, e);
+			}
+			if (!e || !*s) {	/* Missing '=' or empty key. */
+				parse_error("keyword");
+			}
+
+			/* Ok, we have an applet name.  Process the rhs if this
+			 * applet is currently built in and ignore it otherwise.
+			 * Note: This can hide config file bugs which only pop
+			 * up when the busybox configuration is changed. */
+			if ((applet = find_applet_by_name(s))) {
+				/* Note: We currently don't check for duplicates!
+				 * The last config line for each applet will be the
+				 * one used since we insert at the head of the list.
+				 * I suppose this could be considered a feature. */
+				sct = xmalloc(sizeof(struct BB_suid_config));
+				sct->m_applet = applet;
+				sct->m_mode = 0;
+				sct->m_next = sct_head;
+				sct_head = sct;
+
+				/* Get the specified mode. */
+
+				e = skip_whitespace(e+1);
+
+				for (i=0 ; i < 3 ; i++) {
+					const char *q;
+					if (!*(q = strchrnul(mode_chars + 5*i, *e++))) {
+						parse_error("mode");
+					}
+					/* Adjust by -i to account for nul. */
+					sct->m_mode |= mode_mask[(q - mode_chars) - i];
+				}
+
+				/* Now get the the user/group info. */
+
+				s = skip_whitespace(e);
+
+				/* Note: We require whitespace between the mode and the
+				 * user/group info. */
+				if ((s == e) || !(e = strchr(s, '.'))) {
+					parse_error("<uid>.<gid>");
+				}
+				*e++ = 0;
+
+				/* We can't use get_ug_id here since it would exit()
+				 * if a uid or gid was not found.  Oh well... */
+				{
+					char *e2;
+
+					sct->m_uid = strtoul(s, &e2, 10);
+					if (*e2 || (s == e2)) {
+						struct passwd *pwd;
+						if (!(pwd = getpwnam(s))) {
+							parse_error("user");
+						}
+						sct->m_uid = pwd->pw_uid;
+					}
+
+					sct->m_gid = strtoul(e, &e2, 10);
+					if (*e2 || (e == e2)) {
+						struct group *grp;
+						if (!(grp = getgrnam(e))) {
+							parse_error("group");
+						}
+						sct->m_gid = grp->gr_gid;
+					}
+				}
+			}
+			continue;
+		}
+
+		/* Unknown sections are ignored. */
+
+		/* Encountering configuration lines prior to seeing a
+		 * section header is treated as an error.  This is how
+		 * the old code worked, but it may not be desirable.
+		 * We may want to simply ignore such lines in case they
+		 * are used in some future version of busybox. */
+		if (!section) {
+			parse_error("keyword outside section");
+		}
+
+	} while (1);
+
+ pe_label:
+	fprintf(stderr, "Parse error in %s, line %d: %s\n",
+			config_file, lc, err);
+
+	fclose(f);
+	/* Release any allocated memory before returning. */
+	while (sct_head) {
+		sct = sct_head->m_next;
+		free(sct_head);
+		sct_head = sct;
+	}
+	return;
+}
+
+#else
+#define parse_config_file()
+#endif /* CONFIG_FEATURE_SUID_CONFIG */
+
+#ifdef CONFIG_FEATURE_SUID
+static void check_suid (struct BB_applet *applet)
+{
+  uid_t ruid = getuid ();               /* real [ug]id */
+  uid_t rgid = getgid ();
+
+#ifdef CONFIG_FEATURE_SUID_CONFIG
+  if (suid_cfg_readable) {
+	struct BB_suid_config *sct;
+
+	for (sct = suid_config; sct; sct = sct->m_next) {
+	  if (sct->m_applet == applet)
+		break;
+	}
+	if (sct) {
+	  mode_t m = sct->m_mode;
+
+	  if (sct->m_uid == ruid)       /* same uid */
+		m >>= 6;
+	  else if ((sct->m_gid == rgid) || ingroup (ruid, sct->m_gid))  /* same group / in group */
+		m >>= 3;
+
+	  if (!(m & S_IXOTH))           /* is x bit not set ? */
+		bb_error_msg_and_die ("You have no permission to run this applet!");
+
+	  if ((sct->m_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {     /* *both* have to be set for sgid */
+		if (setegid (sct->m_gid))
+		  bb_error_msg_and_die
+			("BusyBox binary has insufficient rights to set proper GID for applet!");
+	  } else
+		setgid (rgid);                  /* no sgid -> drop */
+
+	  if (sct->m_mode & S_ISUID) {
+		if (seteuid (sct->m_uid))
+		  bb_error_msg_and_die
+			("BusyBox binary has insufficient rights to set proper UID for applet!");
+	  } else
+		setuid (ruid);                  /* no suid -> drop */
+	} else {
+		/* default: drop all privileges */
+	  setgid (rgid);
+	  setuid (ruid);
+	}
+	return;
+  } else {
+#ifndef CONFIG_FEATURE_SUID_CONFIG_QUIET
+	static int onetime = 0;
+
+	if (!onetime) {
+	  onetime = 1;
+	  fprintf (stderr, "Using fallback suid method\n");
+	}
+#endif
+  }
+#endif
+
+  if (applet->need_suid == _BB_SUID_ALWAYS) {
+	if (geteuid () != 0)
+	  bb_error_msg_and_die ("This applet requires root privileges!");
+  } else if (applet->need_suid == _BB_SUID_NEVER) {
+	setgid (rgid);                          /* drop all privileges */
+	setuid (ruid);
+  }
+}
+#else
+#define check_suid(x)
+#endif /* CONFIG_FEATURE_SUID */
+
+
+
+#if ENABLE_FEATURE_COMPRESS_USAGE
+
+#include "usage_compressed.h"
+#include "unarchive.h"
+
+static const char *unpack_usage_messages(void)
+{
+	int input[2], output[2], pid;
+	char *buf;
+
+	if(pipe(input) < 0 || pipe(output) < 0)
+		exit(1);
+
+	pid = fork();
+	switch (pid) {
+	case -1: /* error */
+		exit(1);
+	case 0: /* child */
+		close(input[1]);
+		close(output[0]);
+		uncompressStream(input[0], output[1]);
+		exit(0);
+	}
+	/* parent */
+
+	close(input[0]);
+	close(output[1]);
+	pid = fork();
+	switch (pid) {
+	case -1: /* error */
+		exit(1);
+	case 0: /* child */
+		bb_full_write(input[1], packed_usage, sizeof(packed_usage));
+		exit(0);
+	}
+	/* parent */
+	close(input[1]);
+
+	buf = xmalloc(SIZEOF_usage_messages);
+	bb_full_read(output[0], buf, SIZEOF_usage_messages);
+	return buf;
+}
+
+#else
+#define unpack_usage_messages() usage_messages
+#endif /* ENABLE_FEATURE_COMPRESS_USAGE */
+
+void bb_show_usage (void)
+{
+	if (ENABLE_SHOW_USAGE) {
+		const char *format_string;
+		const char *usage_string = unpack_usage_messages();
+		int i;
+
+		for (i = applet_using - applets; i > 0;)
+			if (!*usage_string++) --i;
+
+		format_string = "%s\n\nUsage: %s %s\n\n";
+		if (*usage_string == '\b')
+			format_string = "%s\n\nNo help available.\n\n";
+		fprintf (stderr, format_string, bb_msg_full_version,
+			applet_using->name, usage_string);
+	}
+
+  exit (bb_default_error_retval);
+}
+
+static int applet_name_compare (const void *x, const void *y)
+{
+  const char *name = x;
+  const struct BB_applet *applet = y;
+
+  return strcmp (name, applet->name);
+}
+
+extern const size_t NUM_APPLETS;
+
+struct BB_applet *find_applet_by_name (const char *name)
+{
+  return bsearch (name, applets, NUM_APPLETS, sizeof (struct BB_applet),
+				  applet_name_compare);
+}
+
+void run_applet_by_name (const char *name, int argc, char **argv)
+{
+	if(ENABLE_FEATURE_SUID_CONFIG) parse_config_file ();
+
+	if(!strncmp(name, "busybox", 7)) busybox_main(argc, argv);
+	/* Do a binary search to find the applet entry given the name. */
+	applet_using = find_applet_by_name(name);
+	if(applet_using) {
+		bb_applet_name = applet_using->name;
+		if(argc==2 && !strcmp(argv[1], "--help")) bb_show_usage ();
+		if(ENABLE_FEATURE_SUID) check_suid (applet_using);
+		exit ((*(applet_using->main)) (argc, argv));
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/busybox.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/busybox.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/busybox.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,154 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * BusyBox' main applet dispatcher.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+#include "busybox.h"
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#if ENABLE_LOCALE_SUPPORT
+#include <locale.h>
+#else
+#define setlocale(x,y)
+#endif
+
+const char *bb_applet_name ATTRIBUTE_EXTERNALLY_VISIBLE;
+
+#ifdef CONFIG_FEATURE_INSTALLER
+/*
+ * directory table
+ *		this should be consistent w/ the enum, busybox.h::Location,
+ *		or else...
+ */
+static const char usr_bin [] ="/usr/bin";
+static const char usr_sbin[] ="/usr/sbin";
+
+static const char* const install_dir[] = {
+	&usr_bin [8], /* "", equivalent to "/" for concat_path_file() */
+	&usr_bin [4], /* "/bin" */
+	&usr_sbin[4], /* "/sbin" */
+	usr_bin,
+	usr_sbin
+};
+
+/* abstract link() */
+typedef int (*__link_f)(const char *, const char *);
+
+/* create (sym)links for each applet */
+static void install_links(const char *busybox, int use_symbolic_links)
+{
+	__link_f Link = link;
+
+	char *fpc;
+	int i;
+	int rc;
+
+	if (use_symbolic_links)
+		Link = symlink;
+
+	for (i = 0; applets[i].name != NULL; i++) {
+		fpc = concat_path_file(
+			install_dir[applets[i].location], applets[i].name);
+		rc = Link(busybox, fpc);
+		if (rc!=0 && errno!=EEXIST) {
+			bb_perror_msg("%s", fpc);
+		}
+		free(fpc);
+	}
+}
+
+#else
+#define install_links(x,y)
+#endif /* CONFIG_FEATURE_INSTALLER */
+
+int main(int argc, char **argv)
+{
+	const char *s;
+
+	bb_applet_name=argv[0];
+	if (*bb_applet_name == '-') bb_applet_name++;
+	for (s = bb_applet_name; *s ;)
+		if (*(s++) == '/') bb_applet_name = s;
+
+	/* Set locale for everybody except `init' */
+	if(ENABLE_LOCALE_SUPPORT && getpid() != 1)
+		setlocale(LC_ALL, "");
+
+	run_applet_by_name(bb_applet_name, argc, argv);
+	bb_error_msg_and_die("applet not found");
+}
+
+int busybox_main(int argc, char **argv)
+{
+	/*
+	 * This style of argument parsing doesn't scale well
+	 * in the event that busybox starts wanting more --options.
+	 * If someone has a cleaner approach, by all means implement it.
+	 */
+	if (ENABLE_FEATURE_INSTALLER && argc > 1 && !strcmp(argv[1], "--install")) {
+		int use_symbolic_links = 0;
+		int rc = 0;
+		char *busybox;
+
+		/* to use symlinks, or not to use symlinks... */
+		if (argc > 2) {
+			if ((strcmp(argv[2], "-s") == 0)) {
+				use_symbolic_links = 1;
+			}
+		}
+
+		/* link */
+		busybox = xreadlink("/proc/self/exe");
+		if (busybox) {
+			install_links(busybox, use_symbolic_links);
+			free(busybox);
+		} else {
+			rc = 1;
+		}
+		return rc;
+	}
+
+	/* Deal with --help.  (Also print help when called with no arguments) */
+
+	if (argc==1 || !strcmp(argv[1],"--help") ) {
+		if (argc>2) {
+			run_applet_by_name(bb_applet_name=argv[2], 2, argv);
+		} else {
+			const struct BB_applet *a;
+			int col, output_width;
+
+			if (ENABLE_FEATURE_AUTOWIDTH) {
+				/* Obtain the terminal width.  */
+				get_terminal_width_height(0, &output_width, NULL);
+				/* leading tab and room to wrap */
+				output_width -= 20;
+			} else output_width = 60;
+
+			printf("%s\n\n"
+			       "Usage: busybox [function] [arguments]...\n"
+			       "   or: [function] [arguments]...\n\n"
+			       "\tBusyBox is a multi-call binary that combines many common Unix\n"
+			       "\tutilities into a single executable.  Most people will create a\n"
+			       "\tlink to busybox for each function they wish to use and BusyBox\n"
+			       "\twill act like whatever it was invoked as!\n"
+			       "\nCurrently defined functions:\n", bb_msg_full_version);
+
+			col=0;
+			for(a = applets; a->name;) {
+				col += printf("%s%s", (col ? ", " : "\t"), (a++)->name);
+				if (col > output_width && a->name) {
+					printf(",\n");
+					col = 0;
+				}
+			}
+			printf("\n\n");
+			exit(0);
+		}
+	} else run_applet_by_name(argv[1], argc-1, argv+1);
+
+	bb_error_msg_and_die("applet not found");
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/busybox.mkll
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/busybox.mkll	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/busybox.mkll	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,24 @@
+#!/bin/sh
+# Make busybox links list file.
+
+# input $1: full path to Config.h
+# input $2: full path to applets.h
+# output (stdout): list of pathnames that should be linked to busybox
+
+# Maintainer: Larry Doolittle <ldoolitt at recycle.lbl.gov>
+
+export LC_ALL=POSIX
+export LC_CTYPE=POSIX
+
+CONFIG_H=${1:-include/bb_config.h}
+APPLETS_H=${2:-include/applets.h}
+$HOSTCC -E -DMAKE_LINKS -include $CONFIG_H $APPLETS_H |
+  awk '/^[ \t]*LINK/{
+	dir=substr($2,8)
+	gsub("_","/",dir)
+	if(dir=="/ROOT") dir=""
+	file=$3
+	gsub("\"","",file)
+	if (file=="busybox") next
+	print tolower(dir) "/" file
+  }'


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/busybox.mkll
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/install.sh
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/install.sh	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/install.sh	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,94 @@
+#!/bin/sh
+
+export LC_ALL=POSIX
+export LC_CTYPE=POSIX
+
+prefix=${1}
+if [ -z "$prefix" ]; then
+	echo "usage: applets/install.sh DESTINATION [--symlinks/--hardlinks]"
+	exit 1;
+fi
+h=`sort busybox.links | uniq`
+cleanup="0"
+noclobber="0"
+case "$2" in
+	--hardlinks) linkopts="-f";;
+	--symlinks)  linkopts="-fs";;
+	--cleanup)   cleanup="1";;
+	--noclobber) noclobber="1";;
+	"")          h="";;
+	*)           echo "Unknown install option: $2"; exit 1;;
+esac
+
+if [ -n "$DO_INSTALL_LIBS" ] && [ "$DO_INSTALL_LIBS" != "n" ]; then
+	# get the target dir for the libs
+	# assume it starts with lib
+	libdir=$($CC -print-file-name=libc.so | \
+		 sed -n 's%^.*\(/lib[^\/]*\)/libc.so%\1%p')
+	if test -z "$libdir"; then
+		libdir=/lib
+	fi
+
+	mkdir -p $prefix/$libdir || exit 1
+	for i in $DO_INSTALL_LIBS; do
+		rm -f $prefix/$libdir/$i || exit 1
+		if [ -f $i ]; then
+			cp -a $i $prefix/$libdir/ || exit 1
+			chmod 0644 $prefix/$libdir/$i || exit 1
+		fi
+	done
+fi
+
+if [ "$cleanup" = "1" ] && [ -e "$prefix/bin/busybox" ]; then
+	inode=`ls -i "$prefix/bin/busybox" | awk '{print $1}'`
+	sub_shell_it=`
+	cd "$prefix"
+	for d in usr/sbin usr/bin sbin bin ; do
+		pd=$PWD
+		if [ -d "$d" ]; then
+			cd $d
+			ls -iL . | grep "^ *$inode" | awk '{print $2}' | env -i xargs rm -f
+		fi
+		cd "$pd"
+	done
+	`
+fi
+
+rm -f $prefix/bin/busybox || exit 1
+mkdir -p $prefix/bin || exit 1
+install -m 755 busybox $prefix/bin/busybox || exit 1
+
+for i in $h ; do
+	appdir=`dirname $i`
+	mkdir -p $prefix/$appdir || exit 1
+	if [ "$2" = "--hardlinks" ]; then
+		bb_path="$prefix/bin/busybox"
+	else
+		case "$appdir" in
+		/)
+			bb_path="bin/busybox"
+		;;
+		/bin)
+			bb_path="busybox"
+		;;
+		/sbin)
+			bb_path="../bin/busybox"
+		;;
+		/usr/bin|/usr/sbin)
+			bb_path="../../bin/busybox"
+		;;
+		*)
+		echo "Unknown installation directory: $appdir"
+		exit 1
+		;;
+		esac
+	fi
+	if [ "$noclobber" = "0" ] || [ ! -e "$prefix$i" ]; then
+		echo "  $prefix$i -> $bb_path"
+		ln $linkopts $bb_path $prefix$i || exit 1
+	else
+		echo "  $prefix$i already exists"
+	fi
+done
+
+exit 0


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/install.sh
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/version.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/version.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/applets/version.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,17 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Version stuff.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+
+#ifndef BB_EXTRA_VERSION
+#define BANNER "BusyBox v" BB_VER " (" BB_BT ")"
+#else
+#define BANNER "BusyBox v" BB_VER " (" BB_EXTRA_VERSION ")"
+#endif
+
+const char BB_BANNER[]=BANNER;
+const char * const bb_msg_full_version = BANNER " multi-call binary";

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,300 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Archival Utilities"
+
+config CONFIG_AR
+	bool "ar"
+	default n
+	help
+	  ar is an archival utility program used to create, modify, and
+	  extract contents from archives.  An archive is a single file holding
+	  a collection of other files in a structure that makes it possible to
+	  retrieve the original individual files (called archive members).
+	  The original files' contents, mode (permissions), timestamp, owner,
+	  and group are preserved in the archive, and can be restored on
+	  extraction.
+
+	  The stored filename is limited to 15 characters. (for more information
+	  see long filename support).
+	  ar has 60 bytes of overheads for every stored file.
+
+	  This implementation of ar can extract archives, it cannot create or
+	  modify them.
+	  On an x86 system, the ar applet adds about 1K.
+
+	  Unless you have a specific application which requires ar, you should
+	  probably say N here.
+
+config CONFIG_FEATURE_AR_LONG_FILENAMES
+	bool "Enable support for long filenames (not need for debs)"
+	default n
+	depends on CONFIG_AR
+	help
+	  By default the ar format can only store the first 15 characters of the
+	  filename, this option removes that limitation.
+	  It supports the GNU ar long filename method which moves multiple long
+	  filenames into a the data section of a new ar entry.
+
+config CONFIG_BUNZIP2
+	bool "bunzip2"
+	default n
+	help
+	  bunzip2 is a compression utility using the Burrows-Wheeler block
+	  sorting text compression algorithm, and Huffman coding.  Compression
+	  is generally considerably better than that achieved by more
+	  conventional LZ77/LZ78-based compressors, and approaches the
+	  performance of the PPM family of statistical compressors.
+
+	  The BusyBox bunzip2 applet is limited to de-compression only.
+	  On an x86 system, this applet adds about 11K.
+
+	  Unless you have a specific application which requires bunzip2, you
+	  should probably say N here.
+
+config CONFIG_CPIO
+	bool "cpio"
+	default n
+	help
+	  cpio is an archival utility program used to create, modify, and extract
+	  contents from archives.
+	  cpio has 110 bytes of overheads for every stored file.
+
+	  This implementation of cpio can extract cpio archives created in the
+	  "newc" or "crc" format, it cannot create or modify them.
+
+	  Unless you have a specific application which requires cpio, you should
+	  probably say N here.
+
+config CONFIG_DPKG
+	bool "dpkg"
+	default n
+	help
+	  dpkg is a medium-level tool to install, build, remove and manage Debian packages.
+
+	  This implementation of dpkg has a number of limitations, you should use the
+	  official dpkg if possible.
+
+config CONFIG_DPKG_DEB
+	bool "dpkg_deb"
+	default n
+	help
+	  dpkg-deb packs, unpacks and provides information about Debian archives.
+
+	  This implementation of dpkg-deb cannot pack archives.
+
+	  Unless you have a specific application which requires dpkg-deb, you should
+	  probably say N here.
+
+config CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY
+	bool "extract only (-x)"
+	default n
+	depends on CONFIG_DPKG_DEB
+	help
+	  This reduces dpkg-deb to the equivalent of "ar -p <deb> data.tar.gz | tar -zx".
+	  However it saves space as none of the extra dpkg-deb, ar or tar options are
+	  needed, they are linked to internally.
+
+config CONFIG_GUNZIP
+	bool "gunzip"
+	default n
+	help
+	  gunzip is used to decompress archives created by gzip.
+	  You can use the `-t' option to test the integrity of
+	  an archive, without decompressing it.
+
+config CONFIG_FEATURE_GUNZIP_UNCOMPRESS
+	bool "Uncompress support"
+	default n
+	depends on CONFIG_GUNZIP
+	help
+	  Enable if you want gunzip to have the ability to decompress
+	  archives created by the program compress (not much
+	  used anymore).
+
+config CONFIG_GZIP
+	bool "gzip"
+	default n
+	help
+	  gzip is used to compress files.
+	  It's probably the most widely used UNIX compression program.
+
+config CONFIG_RPM2CPIO
+	bool "rpm2cpio"
+	default n
+	help
+	  Converts an RPM file into a CPIO archive.
+
+config CONFIG_RPM
+	bool "rpm"
+	default n
+	help
+	  Mini RPM applet - queries and extracts
+
+config CONFIG_TAR
+	bool "tar"
+	default n
+	help
+	  tar is an archiving program. It's commonly used with gzip to
+	  create compressed archives. It's probably the most widely used
+	  UNIX archive program.
+
+config CONFIG_FEATURE_TAR_CREATE
+	bool "Enable archive creation"
+	default y
+	depends on CONFIG_TAR
+	help
+	  If you enable this option you'll be able to create
+	  tar archives using the `-c' option.
+
+config CONFIG_FEATURE_TAR_BZIP2
+	bool "Enable -j option to handle .tar.bz2 files"
+	default n
+	depends on CONFIG_TAR
+	help
+	  If you enable this option you'll be able to extract
+	  archives compressed with bzip2.
+
+config CONFIG_FEATURE_TAR_LZMA
+	bool "Enable -a option to handle .tar.lzma files"
+	default n
+	depends on CONFIG_TAR
+	help
+	  If you enable this option you'll be able to extract
+	  archives compressed with lzma.
+
+config CONFIG_FEATURE_TAR_FROM
+	bool "Enable -X (exclude from) and -T (include from) options)"
+	default n
+	depends on CONFIG_TAR
+	help
+	  If you enable this option you'll be able to specify
+	  a list of files to include or exclude from an archive.
+
+config CONFIG_FEATURE_TAR_GZIP
+	bool "Enable -z option"
+	default y
+	depends on CONFIG_TAR
+	help
+	  If you enable this option tar will be able to call gzip,
+	  when creating or extracting tar gziped archives.
+
+config CONFIG_FEATURE_TAR_COMPRESS
+	bool "Enable -Z option"
+	default n
+	depends on CONFIG_TAR
+	help
+	  If you enable this option tar will be able to call uncompress,
+	  when extracting .tar.Z archives.
+
+config CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY
+	bool "Enable support for old tar header format"
+	default N
+	depends on CONFIG_TAR
+	help
+	  This option is required to unpack archives created in
+	  the old GNU format; help to kill this old format by
+	  repacking your ancient archives with the new format.
+
+config CONFIG_FEATURE_TAR_GNU_EXTENSIONS
+	bool "Enable support for some GNU tar extensions"
+	default y
+	depends on CONFIG_TAR
+	help
+	  With this option busybox supports GNU long filenames and
+	  linknames.
+
+config CONFIG_FEATURE_TAR_LONG_OPTIONS
+	bool "Enable long options"
+	default n
+	depends on CONFIG_TAR && CONFIG_GETOPT_LONG
+	help
+		Enable use of long options, increases size by about 400 Bytes
+
+config CONFIG_UNCOMPRESS
+	bool "uncompress"
+	default n
+	help
+	  uncompress is used to decompress archives created by compress.
+	  Not much used anymore, replaced by gzip/gunzip.
+
+config CONFIG_UNLZMA
+	bool "unlzma"
+	default n
+	help
+	  unlzma is a compression utility using the Lempel-Ziv-Markov chain
+	  compression algorithm, and range coding.  Compression
+	  is generally considerably better than that achieved by the bzip2
+	  compressors.
+
+	  The BusyBox unlzma applet is limited to de-compression only.
+	  On an x86 system, this applet adds about 4K.
+
+	  Unless you have a specific application which requires unlzma, you
+	  should probably say N here.
+
+config CONFIG_FEATURE_LZMA_FAST
+	bool "Optimze unlzma for speed"
+	default n
+	depends on CONFIG_UNLZMA
+	help
+	  This option reduces decompression time by about 33% at the cost of
+	  a 2K bigger binary.
+
+config CONFIG_UNZIP
+	bool "unzip"
+	default n
+	help
+	  unzip will list or extract files from a ZIP archive,
+	  commonly found on DOS/WIN systems. The default behavior
+	  (with no options) is to extract the archive into the
+	  current directory. Use the `-d' option to extract to a
+	  directory of your choice.
+
+comment "Common options for cpio and tar"
+	depends on CONFIG_CPIO || CONFIG_TAR
+
+config CONFIG_FEATURE_UNARCHIVE_TAPE
+	bool "Enable tape drive support"
+	default n
+	depends on CONFIG_CPIO || CONFIG_TAR
+	help
+	  I don't think this is needed anymore.
+
+comment "Common options for dpkg and dpkg_deb"
+	depends on CONFIG_DPKG || CONFIG_DPKG_DEB
+
+config CONFIG_FEATURE_DEB_TAR_GZ
+	bool "gzip debian packages (normal)"
+	default y if CONFIG_DPKG || CONFIG_DPKG_DEB
+	depends on CONFIG_DPKG || CONFIG_DPKG_DEB
+	help
+	  This is the default compression method inside the debian ar file.
+
+	  If you want compatibility with standard .deb's you should say yes here.
+
+config CONFIG_FEATURE_DEB_TAR_BZ2
+	bool "bzip2 debian packages"
+	default n
+	depends on CONFIG_DPKG || CONFIG_DPKG_DEB
+	help
+	  This allows dpkg and dpkg-deb to extract deb's that are compressed internally
+	  with bzip2 instead of gzip.
+
+	  You only want this if you are creating your own custom debian packages that
+	  use an internal control.tar.bz2 or data.tar.bz2.
+
+config CONFIG_FEATURE_DEB_TAR_LZMA
+	bool "lzma debian packages"
+	default n
+	depends on CONFIG_DPKG || CONFIG_DPKG_DEB
+	help
+	  This allows dpkg and dpkg-deb to extract deb's that are compressed
+          internally with lzma instead of gzip.
+
+	  You only want this if you are creating your own custom debian
+          packages that use an internal control.tar.lzma or data.tar.lzma.
+
+endmenu

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+ARCHIVAL_DIR:=./
+srcdir=$(top_srcdir)/archival
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include $(srcdir)/Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,42 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ARCHIVAL_AR:=archival.a
+ifndef $(ARCHIVAL_DIR)
+ARCHIVAL_DIR:=$(top_builddir)/archival/
+endif
+srcdir=$(top_srcdir)/archival
+
+ARCHIVAL-y:=
+ARCHIVAL-$(CONFIG_APT_GET)	+=
+ARCHIVAL-$(CONFIG_AR)		+= ar.o
+ARCHIVAL-$(CONFIG_BUNZIP2)	+= bunzip2.o
+ARCHIVAL-$(CONFIG_UNLZMA)	+= unlzma.o
+ARCHIVAL-$(CONFIG_CPIO)		+= cpio.o
+ARCHIVAL-$(CONFIG_DPKG)		+= dpkg.o
+ARCHIVAL-$(CONFIG_DPKG_DEB)	+= dpkg_deb.o
+ARCHIVAL-$(CONFIG_GUNZIP)	+= gunzip.o
+ARCHIVAL-$(CONFIG_GZIP)		+= gzip.o
+ARCHIVAL-$(CONFIG_RPM2CPIO)	+= rpm2cpio.o
+ARCHIVAL-$(CONFIG_RPM)		+= rpm.o
+ARCHIVAL-$(CONFIG_TAR)		+= tar.o
+ARCHIVAL-$(CONFIG_UNCOMPRESS)	+= uncompress.o
+ARCHIVAL-$(CONFIG_UNZIP)	+= unzip.o
+
+ifneq ($(strip $(ARCHIVAL-y)),)
+libraries-y+=$(ARCHIVAL_DIR)$(ARCHIVAL_AR)
+endif
+
+ARCHIVAL_SRC-y:=$(patsubst %.o,$(srcdir)/%.c,$(ARCHIVAL-y))
+ARCHIVAL_SRC-a:=$(wildcard $(srcdir)/*.c)
+APPLET_SRC-y+=$(ARCHIVAL_SRC-y)
+APPLET_SRC-a+=$(ARCHIVAL_SRC-a)
+
+$(ARCHIVAL_DIR)$(ARCHIVAL_AR): $(patsubst %,$(ARCHIVAL_DIR)%, $(ARCHIVAL-y))
+	$(do_ar)
+
+$(ARCHIVAL_DIR)%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/ar.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/ar.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/ar.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,112 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini ar implementation for busybox
+ *
+ * Copyright (C) 2000 by Glenn McGrath
+ * Written by Glenn McGrath <bug1 at iinet.net.au> 1 June 2000
+ *
+ * Based in part on BusyBox tar, Debian dpkg-deb and GNU ar.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * There is no single standard to adhere to so ar may not portable
+ * between different systems
+ * http://www.unix-systems.org/single_unix_specification_v2/xcu/ar.html
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <utime.h>
+#include <unistd.h>
+
+#include "unarchive.h"
+#include "busybox.h"
+
+static void header_verbose_list_ar(const file_header_t *file_header)
+{
+	const char *mode = bb_mode_string(file_header->mode);
+	char *mtime;
+
+	mtime = ctime(&file_header->mtime);
+	mtime[16] = ' ';
+	memmove(&mtime[17], &mtime[20], 4);
+	mtime[21] = '\0';
+	printf("%s %d/%d%7d %s %s\n", &mode[1], file_header->uid, file_header->gid, (int) file_header->size, &mtime[4], file_header->name);
+}
+
+#define AR_CTX_PRINT		0x01
+#define AR_CTX_LIST		0x02
+#define AR_CTX_EXTRACT		0x04
+#define AR_OPT_PRESERVE_DATE	0x08
+#define AR_OPT_VERBOSE		0x10
+#define AR_OPT_CREATE		0x20
+#define AR_OPT_INSERT		0x40
+
+int ar_main(int argc, char **argv)
+{
+	archive_handle_t *archive_handle;
+	unsigned long opt;
+	static const char msg_unsupported_err[] =
+			"Archive %s not supported.  Install binutils 'ar'.";
+	char magic[8];
+
+	archive_handle = init_handle();
+
+	/* Prepend '-' to the first argument if required */
+	bb_opt_complementally = "--:p:t:x:-1:?:p--tx:t--px:x--pt";
+	opt = bb_getopt_ulflags(argc, argv, "ptxovcr");
+
+	if (opt & AR_CTX_PRINT) {
+		archive_handle->action_data = data_extract_to_stdout;
+	}
+	if (opt & AR_CTX_LIST) {
+		archive_handle->action_header = header_list;
+	}
+	if (opt & AR_CTX_EXTRACT) {
+		archive_handle->action_data = data_extract_all;
+	}
+	if (opt & AR_OPT_PRESERVE_DATE) {
+		archive_handle->flags |= ARCHIVE_PRESERVE_DATE;
+	}
+	if (opt & AR_OPT_VERBOSE) {
+		archive_handle->action_header = header_verbose_list_ar;
+	}
+	if (opt & AR_OPT_CREATE) {
+		bb_error_msg_and_die(msg_unsupported_err, "creation");
+	}
+	if (opt & AR_OPT_INSERT) {
+		bb_error_msg_and_die(msg_unsupported_err, "insertion");
+	}
+
+	archive_handle->src_fd = bb_xopen(argv[optind++], O_RDONLY);
+
+	while (optind < argc) {
+		archive_handle->filter = filter_accept_list;
+		llist_add_to(&(archive_handle->accept), argv[optind++]);
+	}
+
+	archive_xread_all(archive_handle, magic, 7);
+	if (strncmp(magic, "!<arch>", 7) != 0) {
+		bb_error_msg_and_die("Invalid ar magic");
+	}
+	archive_handle->offset += 7;
+
+	while (get_header_ar(archive_handle) == EXIT_SUCCESS);
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/bunzip2.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/bunzip2.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/bunzip2.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,67 @@
+/*
+ *  Modified for busybox by Glenn McGrath <bug1 at iinet.net.au>
+ *  Added support output to stdout by Thomas Lundquist <thomasez at zelow.no>
+ *
+ *  Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "busybox.h"
+#include "unarchive.h"
+
+#define BUNZIP2_OPT_STDOUT	1
+#define BUNZIP2_OPT_FORCE	2
+
+int bunzip2_main(int argc, char **argv)
+{
+	char *filename;
+	unsigned long opt;
+	int status, src_fd, dst_fd;
+
+	opt = bb_getopt_ulflags(argc, argv, "cf");
+
+	/* Set input filename and number */
+	filename = argv[optind];
+	if ((filename) && (filename[0] != '-') && (filename[1] != '\0')) {
+		/* Open input file */
+		src_fd = bb_xopen(filename, O_RDONLY);
+	} else {
+		src_fd = STDIN_FILENO;
+		filename = 0;
+	}
+
+	/* if called as bzcat force the stdout flag */
+	if ((opt & BUNZIP2_OPT_STDOUT) || bb_applet_name[2] == 'c')
+		filename = 0;
+
+	/* Check that the input is sane.  */
+	if (isatty(src_fd) && (opt & BUNZIP2_OPT_FORCE) == 0) {
+		bb_error_msg_and_die("Compressed data not read from terminal.  Use -f to force it.");
+	}
+
+	if (filename) {
+		struct stat stat_buf;
+		char *extension=filename+strlen(filename)-4;
+		if (strcmp(extension, ".bz2") != 0) {
+			bb_error_msg_and_die("Invalid extension");
+		}
+		xstat(filename, &stat_buf);
+		*extension=0;
+		dst_fd = bb_xopen3(filename, O_WRONLY | O_CREAT, stat_buf.st_mode);
+	} else dst_fd = STDOUT_FILENO;
+	status = uncompressStream(src_fd, dst_fd);
+	if(filename) {
+		if (!status) filename[strlen(filename)]='.';
+		if (unlink(filename) < 0) {
+			bb_error_msg_and_die("Couldn't remove %s", filename);
+		}
+	}
+
+	return status;
+}
+/* vi:set ts=4: */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/cpio.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/cpio.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/cpio.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,98 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini cpio implementation for busybox
+ *
+ * Copyright (C) 2001 by Glenn McGrath
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Limitations:
+ *		Doesn't check CRC's
+ *		Only supports new ASCII and CRC formats
+ *
+ */
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "unarchive.h"
+#include "busybox.h"
+
+#define CPIO_OPT_EXTRACT			0x01
+#define CPIO_OPT_TEST				0x02
+#define CPIO_OPT_UNCONDITIONAL		0x04
+#define CPIO_OPT_VERBOSE			0x08
+#define CPIO_OPT_FILE				0x10
+#define CPIO_OPT_CREATE_LEADING_DIR	0x20
+#define CPIO_OPT_PRESERVE_MTIME		0x40
+
+int cpio_main(int argc, char **argv)
+{
+	archive_handle_t *archive_handle;
+	char *cpio_filename = NULL;
+	unsigned long opt;
+
+	/* Initialise */
+	archive_handle = init_handle();
+	archive_handle->src_fd = STDIN_FILENO;
+	archive_handle->seek = seek_by_char;
+	archive_handle->flags = ARCHIVE_EXTRACT_NEWER | ARCHIVE_PRESERVE_DATE;
+
+	opt = bb_getopt_ulflags(argc, argv, "ituvF:dm", &cpio_filename);
+
+	/* One of either extract or test options must be given */
+	if ((opt & (CPIO_OPT_TEST | CPIO_OPT_EXTRACT)) == 0) {
+		bb_show_usage();
+	}
+
+	if (opt & CPIO_OPT_TEST) {
+		/* if both extract and test options are given, ignore extract option */
+		if (opt & CPIO_OPT_EXTRACT) {
+			opt &= ~CPIO_OPT_EXTRACT;
+		}
+		archive_handle->action_header = header_list;
+	}
+	if (opt & CPIO_OPT_EXTRACT) {
+		archive_handle->action_data = data_extract_all;
+	}
+	if (opt & CPIO_OPT_UNCONDITIONAL) {
+		archive_handle->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;
+		archive_handle->flags &= ~ARCHIVE_EXTRACT_NEWER;
+	}
+	if (opt & CPIO_OPT_VERBOSE) {
+		if (archive_handle->action_header == header_list) {
+			archive_handle->action_header = header_verbose_list;
+		} else {
+			archive_handle->action_header = header_list;
+		}
+	}
+	if (cpio_filename) { /* CPIO_OPT_FILE */
+		archive_handle->src_fd = bb_xopen(cpio_filename, O_RDONLY);
+		archive_handle->seek = seek_by_jump;
+	}
+	if (opt & CPIO_OPT_CREATE_LEADING_DIR) {
+		archive_handle->flags |= ARCHIVE_CREATE_LEADING_DIRS;
+	}
+
+	while (optind < argc) {
+		archive_handle->filter = filter_accept_list;
+		llist_add_to(&(archive_handle->accept), argv[optind]);
+		optind++;
+	}
+
+	while (get_header_cpio(archive_handle) == EXIT_SUCCESS);
+
+	return(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/dpkg.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/dpkg.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/dpkg.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1731 @@
+/*
+ *  Mini dpkg implementation for busybox.
+ *  This is not meant as a replacement for dpkg
+ *
+ *  Written By Glenn McGrath with the help of others
+ *  Copyright (C) 2001 by Glenn McGrath
+ *
+ *  Started life as a busybox implementation of udpkg
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/*
+ * Known difference between busybox dpkg and the official dpkg that i don't
+ * consider important, its worth keeping a note of differences anyway, just to
+ * make it easier to maintain.
+ *  - The first value for the Confflile: field isnt placed on a new line.
+ *  - When installing a package the Status: field is placed at the end of the
+ *      section, rather than just after the Package: field.
+ *
+ * Bugs that need to be fixed
+ *  - (unknown, please let me know when you find any)
+ *
+ */
+
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "unarchive.h"
+#include "busybox.h"
+
+/* NOTE: If you vary HASH_PRIME sizes be aware,
+ * 1) Tweaking these will have a big effect on how much memory this program uses.
+ * 2) For computational efficiency these hash tables should be at least 20%
+ *    larger than the maximum number of elements stored in it.
+ * 3) All _HASH_PRIME's must be a prime number or chaos is assured, if your looking
+ *    for a prime, try http://www.utm.edu/research/primes/lists/small/10000.txt
+ * 4) If you go bigger than 15 bits you may get into trouble (untested) as its
+ *    sometimes cast to an unsigned int, if you go to 16 bit you will overlap
+ *    int's and chaos is assured, 16381 is the max prime for 14 bit field
+ */
+
+/* NAME_HASH_PRIME, Stores package names and versions,
+ * I estimate it should be at least 50% bigger than PACKAGE_HASH_PRIME,
+ * as there a lot of duplicate version numbers */
+#define NAME_HASH_PRIME 16381
+static char *name_hashtable[NAME_HASH_PRIME + 1];
+
+/* PACKAGE_HASH_PRIME, Maximum number of unique packages,
+ * It must not be smaller than STATUS_HASH_PRIME,
+ * Currently only packages from status_hashtable are stored in here, but in
+ * future this may be used to store packages not only from a status file,
+ * but an available_hashtable, and even multiple packages files.
+ * Package can be stored more than once if they have different versions.
+ * e.g. The same package may have different versions in the status file
+ *      and available file */
+#define PACKAGE_HASH_PRIME 10007
+typedef struct edge_s {
+	unsigned int operator:3;
+	unsigned int type:4;
+	unsigned int name:14;
+	unsigned int version:14;
+} edge_t;
+
+typedef struct common_node_s {
+	unsigned int name:14;
+	unsigned int version:14;
+	unsigned int num_of_edges:14;
+	edge_t **edge;
+} common_node_t;
+static common_node_t *package_hashtable[PACKAGE_HASH_PRIME + 1];
+
+/* Currently it doesnt store packages that have state-status of not-installed
+ * So it only really has to be the size of the maximum number of packages
+ * likely to be installed at any one time, so there is a bit of leeway here */
+#define STATUS_HASH_PRIME 8191
+typedef struct status_node_s {
+	unsigned int package:14;	/* has to fit PACKAGE_HASH_PRIME */
+	unsigned int status:14;		/* has to fit STATUS_HASH_PRIME */
+} status_node_t;
+static status_node_t *status_hashtable[STATUS_HASH_PRIME + 1];
+
+/* Even numbers are for 'extras', like ored dependencies or null */
+enum edge_type_e {
+	EDGE_NULL = 0,
+	EDGE_PRE_DEPENDS = 1,
+	EDGE_OR_PRE_DEPENDS = 2,
+	EDGE_DEPENDS = 3,
+	EDGE_OR_DEPENDS = 4,
+	EDGE_REPLACES = 5,
+	EDGE_PROVIDES = 7,
+	EDGE_CONFLICTS = 9,
+	EDGE_SUGGESTS = 11,
+	EDGE_RECOMMENDS = 13,
+	EDGE_ENHANCES = 15
+};
+enum operator_e {
+	VER_NULL = 0,
+	VER_EQUAL = 1,
+	VER_LESS = 2,
+	VER_LESS_EQUAL = 3,
+	VER_MORE = 4,
+	VER_MORE_EQUAL = 5,
+	VER_ANY = 6
+};
+
+enum dpkg_opt_e {
+	dpkg_opt_purge = 1,
+	dpkg_opt_remove = 2,
+	dpkg_opt_unpack = 4,
+	dpkg_opt_configure = 8,
+	dpkg_opt_install = 16,
+	dpkg_opt_package_name = 32,
+	dpkg_opt_filename = 64,
+	dpkg_opt_list_installed = 128,
+	dpkg_opt_force_ignore_depends = 256
+};
+
+typedef struct deb_file_s {
+	char *control_file;
+	char *filename;
+	unsigned int package:14;
+} deb_file_t;
+
+
+static void make_hash(const char *key, unsigned int *start, unsigned int *decrement, const int hash_prime)
+{
+	unsigned long int hash_num = key[0];
+	int len = strlen(key);
+	int i;
+
+	/* Maybe i should have uses a "proper" hashing algorithm here instead
+	 * of making one up myself, seems to be working ok though. */
+	for(i = 1; i < len; i++) {
+		/* shifts the ascii based value and adds it to previous value
+		 * shift amount is mod 24 because long int is 32 bit and data
+		 * to be shifted is 8, don't want to shift data to where it has
+		 * no effect*/
+		hash_num += ((key[i] + key[i-1]) << ((key[i] * i) % 24));
+	}
+	*start = (unsigned int) hash_num % hash_prime;
+	*decrement = (unsigned int) 1 + (hash_num % (hash_prime - 1));
+}
+
+/* this adds the key to the hash table */
+static int search_name_hashtable(const char *key)
+{
+	unsigned int probe_address = 0;
+	unsigned int probe_decrement = 0;
+//	char *temp;
+
+	make_hash(key, &probe_address, &probe_decrement, NAME_HASH_PRIME);
+	while(name_hashtable[probe_address] != NULL) {
+		if (strcmp(name_hashtable[probe_address], key) == 0) {
+			return(probe_address);
+		} else {
+			probe_address -= probe_decrement;
+			if ((int)probe_address < 0) {
+				probe_address += NAME_HASH_PRIME;
+			}
+		}
+	}
+	name_hashtable[probe_address] = bb_xstrdup(key);
+	return(probe_address);
+}
+
+/* this DOESNT add the key to the hashtable
+ * TODO make it consistent with search_name_hashtable
+ */
+static unsigned int search_status_hashtable(const char *key)
+{
+	unsigned int probe_address = 0;
+	unsigned int probe_decrement = 0;
+
+	make_hash(key, &probe_address, &probe_decrement, STATUS_HASH_PRIME);
+	while(status_hashtable[probe_address] != NULL) {
+		if (strcmp(key, name_hashtable[package_hashtable[status_hashtable[probe_address]->package]->name]) == 0) {
+			break;
+		} else {
+			probe_address -= probe_decrement;
+			if ((int)probe_address < 0) {
+				probe_address += STATUS_HASH_PRIME;
+			}
+		}
+	}
+	return(probe_address);
+}
+
+/* Need to rethink version comparison, maybe the official dpkg has something i can use ? */
+static int version_compare_part(const char *version1, const char *version2)
+{
+	int upstream_len1 = 0;
+	int upstream_len2 = 0;
+	char *name1_char;
+	char *name2_char;
+	int len1 = 0;
+	int len2 = 0;
+	int tmp_int;
+	int ver_num1;
+	int ver_num2;
+	int ret;
+
+	if (version1 == NULL) {
+		version1 = bb_xstrdup("");
+	}
+	if (version2 == NULL) {
+		version2 = bb_xstrdup("");
+	}
+	upstream_len1 = strlen(version1);
+	upstream_len2 = strlen(version2);
+
+	while ((len1 < upstream_len1) || (len2 < upstream_len2)) {
+		/* Compare non-digit section */
+		tmp_int = strcspn(&version1[len1], "0123456789");
+		name1_char = bb_xstrndup(&version1[len1], tmp_int);
+		len1 += tmp_int;
+		tmp_int = strcspn(&version2[len2], "0123456789");
+		name2_char = bb_xstrndup(&version2[len2], tmp_int);
+		len2 += tmp_int;
+		tmp_int = strcmp(name1_char, name2_char);
+		free(name1_char);
+		free(name2_char);
+		if (tmp_int != 0) {
+			ret = tmp_int;
+			goto cleanup_version_compare_part;
+		}
+
+		/* Compare digits */
+		tmp_int = strspn(&version1[len1], "0123456789");
+		name1_char = bb_xstrndup(&version1[len1], tmp_int);
+		len1 += tmp_int;
+		tmp_int = strspn(&version2[len2], "0123456789");
+		name2_char = bb_xstrndup(&version2[len2], tmp_int);
+		len2 += tmp_int;
+		ver_num1 = atoi(name1_char);
+		ver_num2 = atoi(name2_char);
+		free(name1_char);
+		free(name2_char);
+		if (ver_num1 < ver_num2) {
+			ret = -1;
+			goto cleanup_version_compare_part;
+		}
+		else if (ver_num1 > ver_num2) {
+			ret = 1;
+			goto cleanup_version_compare_part;
+		}
+	}
+	ret = 0;
+cleanup_version_compare_part:
+	return(ret);
+}
+
+/* if ver1 < ver2 return -1,
+ * if ver1 = ver2 return 0,
+ * if ver1 > ver2 return 1,
+ */
+static int version_compare(const unsigned int ver1, const unsigned int ver2)
+{
+	char *ch_ver1 = name_hashtable[ver1];
+	char *ch_ver2 = name_hashtable[ver2];
+
+	char epoch1, epoch2;
+	char *deb_ver1, *deb_ver2;
+	char *ver1_ptr, *ver2_ptr;
+	char *upstream_ver1;
+	char *upstream_ver2;
+	int result;
+
+	/* Compare epoch */
+	if (ch_ver1[1] == ':') {
+		epoch1 = ch_ver1[0];
+		ver1_ptr = strchr(ch_ver1, ':') + 1;
+	} else {
+		epoch1 = '0';
+		ver1_ptr = ch_ver1;
+	}
+	if (ch_ver2[1] == ':') {
+		epoch2 = ch_ver2[0];
+		ver2_ptr = strchr(ch_ver2, ':') + 1;
+	} else {
+		epoch2 = '0';
+		ver2_ptr = ch_ver2;
+	}
+	if (epoch1 < epoch2) {
+		return(-1);
+	}
+	else if (epoch1 > epoch2) {
+		return(1);
+	}
+
+	/* Compare upstream version */
+	upstream_ver1 = bb_xstrdup(ver1_ptr);
+	upstream_ver2 = bb_xstrdup(ver2_ptr);
+
+	/* Chop off debian version, and store for later use */
+	deb_ver1 = strrchr(upstream_ver1, '-');
+	deb_ver2 = strrchr(upstream_ver2, '-');
+	if (deb_ver1) {
+		deb_ver1[0] = '\0';
+		deb_ver1++;
+	}
+	if (deb_ver2) {
+		deb_ver2[0] = '\0';
+		deb_ver2++;
+	}
+	result = version_compare_part(upstream_ver1, upstream_ver2);
+
+	free(upstream_ver1);
+	free(upstream_ver2);
+
+	if (result != 0) {
+		return(result);
+	}
+
+	/* Compare debian versions */
+	return(version_compare_part(deb_ver1, deb_ver2));
+}
+
+static int test_version(const unsigned int version1, const unsigned int version2, const unsigned int operator)
+{
+	const int version_result = version_compare(version1, version2);
+	switch(operator) {
+		case (VER_ANY):
+			return(TRUE);
+		case (VER_EQUAL):
+			if (version_result == 0) {
+				return(TRUE);
+			}
+			break;
+		case (VER_LESS):
+			if (version_result < 0) {
+				return(TRUE);
+			}
+			break;
+		case (VER_LESS_EQUAL):
+			if (version_result <= 0) {
+				return(TRUE);
+			}
+			break;
+		case (VER_MORE):
+			if (version_result > 0) {
+				return(TRUE);
+			}
+			break;
+		case (VER_MORE_EQUAL):
+			if (version_result >= 0) {
+				return(TRUE);
+			}
+			break;
+	}
+	return(FALSE);
+}
+
+
+static int search_package_hashtable(const unsigned int name, const unsigned int version, const unsigned int operator)
+{
+	unsigned int probe_address = 0;
+	unsigned int probe_decrement = 0;
+
+	make_hash(name_hashtable[name], &probe_address, &probe_decrement, PACKAGE_HASH_PRIME);
+	while(package_hashtable[probe_address] != NULL) {
+		if (package_hashtable[probe_address]->name == name) {
+			if (operator == VER_ANY) {
+				return(probe_address);
+			}
+			if (test_version(package_hashtable[probe_address]->version, version, operator)) {
+				return(probe_address);
+			}
+		}
+		probe_address -= probe_decrement;
+		if ((int)probe_address < 0) {
+			probe_address += PACKAGE_HASH_PRIME;
+		}
+	}
+	return(probe_address);
+}
+
+/*
+ * This function searches through the entire package_hashtable looking
+ * for a package which provides "needle". It returns the index into
+ * the package_hashtable for the providing package.
+ *
+ * needle is the index into name_hashtable of the package we are
+ * looking for.
+ *
+ * start_at is the index in the package_hashtable to start looking
+ * at. If start_at is -1 then start at the beginning. This is to allow
+ * for repeated searches since more than one package might provide
+ * needle.
+ *
+ * FIXME: I don't think this is very efficient, but I thought I'd keep
+ * it simple for now until it proves to be a problem.
+ */
+static int search_for_provides(int needle, int start_at) {
+	int i, j;
+	common_node_t *p;
+	for (i = start_at + 1; i < PACKAGE_HASH_PRIME; i++) {
+		p = package_hashtable[i];
+		if ( p == NULL ) continue;
+		for(j = 0; j < p->num_of_edges; j++)
+			if ( p->edge[j]->type == EDGE_PROVIDES && p->edge[j]->name == needle )
+				return i;
+	}
+	return -1;
+}
+
+/*
+ * Add an edge to a node
+ */
+static void add_edge_to_node(common_node_t *node, edge_t *edge)
+{
+	node->num_of_edges++;
+	node->edge = xrealloc(node->edge, sizeof(edge_t) * (node->num_of_edges + 1));
+	node->edge[node->num_of_edges - 1] = edge;
+}
+
+/*
+ * Create one new node and one new edge for every dependency.
+ *
+ * Dependencies which contain multiple alternatives are represented as
+ * an EDGE_OR_PRE_DEPENDS or EDGE_OR_DEPENDS node, followed by a
+ * number of EDGE_PRE_DEPENDS or EDGE_DEPENDS nodes. The name field of
+ * the OR edge contains the full dependency string while the version
+ * field contains the number of EDGE nodes which follow as part of
+ * this alternative.
+ */
+static void add_split_dependencies(common_node_t *parent_node, const char *whole_line, unsigned int edge_type)
+{
+	char *line = bb_xstrdup(whole_line);
+	char *line2;
+	char *line_ptr1 = NULL;
+	char *line_ptr2 = NULL;
+	char *field;
+	char *field2;
+	char *version;
+	edge_t *edge;
+	edge_t *or_edge;
+	int offset_ch;
+
+	field = strtok_r(line, ",", &line_ptr1);
+	do {
+		/* skip leading spaces */
+		field += strspn(field, " ");
+		line2 = bb_xstrdup(field);
+		field2 = strtok_r(line2, "|", &line_ptr2);
+		if ( (edge_type == EDGE_DEPENDS || edge_type == EDGE_PRE_DEPENDS) &&
+		     (strcmp(field, field2) != 0)) {
+			or_edge = (edge_t *)xmalloc(sizeof(edge_t));
+			or_edge->type = edge_type + 1;
+		} else {
+			or_edge = NULL;
+		}
+
+		if ( or_edge ) {
+			or_edge->name = search_name_hashtable(field);
+			or_edge->version = 0; // tracks the number of altenatives
+
+			add_edge_to_node(parent_node, or_edge);
+		}
+
+		do {
+			edge = (edge_t *) xmalloc(sizeof(edge_t));
+			edge->type = edge_type;
+
+			/* Skip any extra leading spaces */
+			field2 += strspn(field2, " ");
+
+			/* Get dependency version info */
+			version = strchr(field2, '(');
+			if (version == NULL) {
+				edge->operator = VER_ANY;
+				/* Get the versions hash number, adding it if the number isnt already in there */
+				edge->version = search_name_hashtable("ANY");
+			} else {
+				/* Skip leading ' ' or '(' */
+				version += strspn(field2, " ");
+				version += strspn(version, "(");
+				/* Calculate length of any operator characters */
+				offset_ch = strspn(version, "<=>");
+				/* Determine operator */
+				if (offset_ch > 0) {
+					if (strncmp(version, "=", offset_ch) == 0) {
+						edge->operator = VER_EQUAL;
+					}
+					else if (strncmp(version, "<<", offset_ch) == 0) {
+						edge->operator = VER_LESS;
+					}
+					else if (strncmp(version, "<=", offset_ch) == 0) {
+						edge->operator = VER_LESS_EQUAL;
+					}
+					else if (strncmp(version, ">>", offset_ch) == 0) {
+						edge->operator = VER_MORE;
+					}
+					else if (strncmp(version, ">=", offset_ch) == 0) {
+						edge->operator = VER_MORE_EQUAL;
+					} else {
+						bb_error_msg_and_die("Illegal operator\n");
+					}
+				}
+				/* skip to start of version numbers */
+				version += offset_ch;
+				version += strspn(version, " ");
+
+				/* Truncate version at trailing ' ' or ')' */
+				version[strcspn(version, " )")] = '\0';
+				/* Get the versions hash number, adding it if the number isnt already in there */
+				edge->version = search_name_hashtable(version);
+			}
+
+			/* Get the dependency name */
+			field2[strcspn(field2, " (")] = '\0';
+			edge->name = search_name_hashtable(field2);
+
+			if ( or_edge )
+				or_edge->version++;
+
+			add_edge_to_node(parent_node, edge);
+		} while ((field2 = strtok_r(NULL, "|", &line_ptr2)) != NULL);
+		free(line2);
+	} while ((field = strtok_r(NULL, ",", &line_ptr1)) != NULL);
+	free(line);
+
+	return;
+}
+
+static void free_package(common_node_t *node)
+{
+	unsigned short i;
+	if (node) {
+		for (i = 0; i < node->num_of_edges; i++) {
+			free(node->edge[i]);
+		}
+		free(node->edge);
+		free(node);
+	}
+}
+
+static unsigned int fill_package_struct(char *control_buffer)
+{
+	static const char *const field_names[] = { "Package", "Version",
+		"Pre-Depends", "Depends","Replaces", "Provides",
+		"Conflicts", "Suggests", "Recommends", "Enhances", 0
+	};
+
+	common_node_t *new_node = (common_node_t *) xzalloc(sizeof(common_node_t));
+	char *field_name;
+	char *field_value;
+	int field_start = 0;
+	int num = -1;
+	int buffer_length = strlen(control_buffer);
+
+	new_node->version = search_name_hashtable("unknown");
+	while (field_start < buffer_length) {
+		unsigned short field_num;
+
+		field_start += read_package_field(&control_buffer[field_start],
+				&field_name, &field_value);
+
+		if (field_name == NULL) {
+			goto fill_package_struct_cleanup; /* Oh no, the dreaded goto statement ! */
+		}
+
+		field_num = compare_string_array(field_names, field_name);
+		switch(field_num) {
+			case 0: /* Package */
+				new_node->name = search_name_hashtable(field_value);
+				break;
+			case 1: /* Version */
+				new_node->version = search_name_hashtable(field_value);
+				break;
+			case 2: /* Pre-Depends */
+				add_split_dependencies(new_node, field_value, EDGE_PRE_DEPENDS);
+				break;
+			case 3: /* Depends */
+				add_split_dependencies(new_node, field_value, EDGE_DEPENDS);
+				break;
+			case 4: /* Replaces */
+				add_split_dependencies(new_node, field_value, EDGE_REPLACES);
+				break;
+			case 5: /* Provides */
+				add_split_dependencies(new_node, field_value, EDGE_PROVIDES);
+				break;
+			case 6: /* Conflicts */
+				add_split_dependencies(new_node, field_value, EDGE_CONFLICTS);
+				break;
+			case 7: /* Suggests */
+				add_split_dependencies(new_node, field_value, EDGE_SUGGESTS);
+				break;
+			case 8: /* Recommends */
+				add_split_dependencies(new_node, field_value, EDGE_RECOMMENDS);
+				break;
+			case 9: /* Enhances */
+				add_split_dependencies(new_node, field_value, EDGE_ENHANCES);
+				break;
+		}
+fill_package_struct_cleanup:
+		free(field_name);
+		free(field_value);
+	}
+
+	if (new_node->version == search_name_hashtable("unknown")) {
+		free_package(new_node);
+		return(-1);
+	}
+	num = search_package_hashtable(new_node->name, new_node->version, VER_EQUAL);
+	if (package_hashtable[num] == NULL) {
+		package_hashtable[num] = new_node;
+	} else {
+		free_package(new_node);
+	}
+	return(num);
+}
+
+/* if num = 1, it returns the want status, 2 returns flag, 3 returns status */
+static unsigned int get_status(const unsigned int status_node, const int num)
+{
+	char *status_string = name_hashtable[status_hashtable[status_node]->status];
+	char *state_sub_string;
+	unsigned int state_sub_num;
+	int len;
+	int i;
+
+	/* set tmp_string to point to the start of the word number */
+	for (i = 1; i < num; i++) {
+		/* skip past a word */
+		status_string += strcspn(status_string, " ");
+		/* skip past the separating spaces */
+		status_string += strspn(status_string, " ");
+	}
+	len = strcspn(status_string, " \n\0");
+	state_sub_string = bb_xstrndup(status_string, len);
+	state_sub_num = search_name_hashtable(state_sub_string);
+	free(state_sub_string);
+	return(state_sub_num);
+}
+
+static void set_status(const unsigned int status_node_num, const char *new_value, const int position)
+{
+	const unsigned int new_value_len = strlen(new_value);
+	const unsigned int new_value_num = search_name_hashtable(new_value);
+	unsigned int want = get_status(status_node_num, 1);
+	unsigned int flag = get_status(status_node_num, 2);
+	unsigned int status = get_status(status_node_num, 3);
+	int want_len = strlen(name_hashtable[want]);
+	int flag_len = strlen(name_hashtable[flag]);
+	int status_len = strlen(name_hashtable[status]);
+	char *new_status;
+
+	switch (position) {
+		case (1):
+			want = new_value_num;
+			want_len = new_value_len;
+			break;
+		case (2):
+			flag = new_value_num;
+			flag_len = new_value_len;
+			break;
+		case (3):
+			status = new_value_num;
+			status_len = new_value_len;
+			break;
+		default:
+			bb_error_msg_and_die("DEBUG ONLY: this shouldnt happen");
+	}
+
+	new_status = bb_xasprintf("%s %s %s", name_hashtable[want], name_hashtable[flag], name_hashtable[status]);
+	status_hashtable[status_node_num]->status = search_name_hashtable(new_status);
+	free(new_status);
+	return;
+}
+
+static const char *describe_status(int status_num) {
+	int status_want, status_state ;
+	if ( status_hashtable[status_num] == NULL || status_hashtable[status_num]->status == 0 )
+		return "is not installed or flagged to be installed\n";
+
+	status_want = get_status(status_num, 1);
+	status_state = get_status(status_num, 3);
+
+	if ( status_state == search_name_hashtable("installed") ) {
+		if ( status_want == search_name_hashtable("install") )
+			return "is installed";
+		if ( status_want == search_name_hashtable("deinstall") )
+			return "is marked to be removed";
+		if ( status_want == search_name_hashtable("purge") )
+			return "is marked to be purged";
+	}
+	if ( status_want ==  search_name_hashtable("unknown") )
+		return "is in an indeterminate state";
+	if ( status_want == search_name_hashtable("install") )
+		return "is marked to be installed";
+
+	return "is not installed or flagged to be installed";
+}
+
+
+static void index_status_file(const char *filename)
+{
+	FILE *status_file;
+	char *control_buffer;
+	char *status_line;
+	status_node_t *status_node = NULL;
+	unsigned int status_num;
+
+	status_file = bb_xfopen(filename, "r");
+	while ((control_buffer = fgets_str(status_file, "\n\n")) != NULL) {
+		const unsigned int package_num = fill_package_struct(control_buffer);
+		if (package_num != -1) {
+			status_node = xmalloc(sizeof(status_node_t));
+			/* fill_package_struct doesnt handle the status field */
+			status_line = strstr(control_buffer, "Status:");
+			if (status_line != NULL) {
+				status_line += 7;
+				status_line += strspn(status_line, " \n\t");
+				status_line = bb_xstrndup(status_line, strcspn(status_line, "\n\0"));
+				status_node->status = search_name_hashtable(status_line);
+				free(status_line);
+			}
+			status_node->package = package_num;
+			status_num = search_status_hashtable(name_hashtable[package_hashtable[status_node->package]->name]);
+			status_hashtable[status_num] = status_node;
+		}
+		free(control_buffer);
+	}
+	fclose(status_file);
+	return;
+}
+
+static void write_buffer_no_status(FILE *new_status_file, const char *control_buffer)
+{
+	char *name;
+	char *value;
+	int start = 0;
+	while (1) {
+		start += read_package_field(&control_buffer[start], &name, &value);
+		if (name == NULL) {
+			break;
+		}
+		if (strcmp(name, "Status") != 0) {
+			fprintf(new_status_file, "%s: %s\n", name, value);
+		}
+	}
+	return;
+}
+
+/* This could do with a cleanup */
+static void write_status_file(deb_file_t **deb_file)
+{
+	FILE *old_status_file = bb_xfopen("/var/lib/dpkg/status", "r");
+	FILE *new_status_file = bb_xfopen("/var/lib/dpkg/status.udeb", "w");
+	char *package_name;
+	char *status_from_file;
+	char *control_buffer = NULL;
+	char *tmp_string;
+	int status_num;
+	int field_start = 0;
+	int write_flag;
+	int i = 0;
+
+	/* Update previously known packages */
+	while ((control_buffer = fgets_str(old_status_file, "\n\n")) != NULL) {
+		if ((tmp_string = strstr(control_buffer, "Package:")) == NULL) {
+			continue;
+		}
+
+		tmp_string += 8;
+		tmp_string += strspn(tmp_string, " \n\t");
+		package_name = bb_xstrndup(tmp_string, strcspn(tmp_string, "\n\0"));
+		write_flag = FALSE;
+		tmp_string = strstr(control_buffer, "Status:");
+		if (tmp_string != NULL) {
+			/* Seperate the status value from the control buffer */
+			tmp_string += 7;
+			tmp_string += strspn(tmp_string, " \n\t");
+			status_from_file = bb_xstrndup(tmp_string, strcspn(tmp_string, "\n"));
+		} else {
+			status_from_file = NULL;
+		}
+
+		/* Find this package in the status hashtable */
+		status_num = search_status_hashtable(package_name);
+		if (status_hashtable[status_num] != NULL) {
+			const char *status_from_hashtable = name_hashtable[status_hashtable[status_num]->status];
+			if (strcmp(status_from_file, status_from_hashtable) != 0) {
+				/* New status isnt exactly the same as old status */
+				const int state_status = get_status(status_num, 3);
+				if ((strcmp("installed", name_hashtable[state_status]) == 0) ||
+					(strcmp("unpacked", name_hashtable[state_status]) == 0)) {
+					/* We need to add the control file from the package */
+					i = 0;
+					while(deb_file[i] != NULL) {
+						if (strcmp(package_name, name_hashtable[package_hashtable[deb_file[i]->package]->name]) == 0) {
+							/* Write a status file entry with a modified status */
+							/* remove trailing \n's */
+							write_buffer_no_status(new_status_file, deb_file[i]->control_file);
+							set_status(status_num, "ok", 2);
+							fprintf(new_status_file, "Status: %s\n\n", name_hashtable[status_hashtable[status_num]->status]);
+							write_flag = TRUE;
+							break;
+						}
+						i++;
+					}
+					/* This is temperary, debugging only */
+					if (deb_file[i] == NULL) {
+						bb_error_msg_and_die("ALERT: Couldnt find a control file, your status file may be broken, status may be incorrect for %s", package_name);
+					}
+				}
+				else if (strcmp("not-installed", name_hashtable[state_status]) == 0) {
+					/* Only write the Package, Status, Priority and Section lines */
+					fprintf(new_status_file, "Package: %s\n", package_name);
+					fprintf(new_status_file, "Status: %s\n", status_from_hashtable);
+
+					while (1) {
+						char *field_name;
+						char *field_value;
+						field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value);
+						if (field_name == NULL) {
+							break;
+						}
+						if ((strcmp(field_name, "Priority") == 0) ||
+							(strcmp(field_name, "Section") == 0)) {
+							fprintf(new_status_file, "%s: %s\n", field_name, field_value);
+						}
+					}
+					write_flag = TRUE;
+					fputs("\n", new_status_file);
+				}
+				else if	(strcmp("config-files", name_hashtable[state_status]) == 0) {
+					/* only change the status line */
+					while (1) {
+						char *field_name;
+						char *field_value;
+						field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value);
+						if (field_name == NULL) {
+							break;
+						}
+						/* Setup start point for next field */
+						if (strcmp(field_name, "Status") == 0) {
+							fprintf(new_status_file, "Status: %s\n", status_from_hashtable);
+						} else {
+							fprintf(new_status_file, "%s: %s\n", field_name, field_value);
+						}
+					}
+					write_flag = TRUE;
+					fputs("\n", new_status_file);
+				}
+			}
+		}
+		/* If the package from the status file wasnt handle above, do it now*/
+		if (! write_flag) {
+			fprintf(new_status_file, "%s\n\n", control_buffer);
+		}
+
+		free(status_from_file);
+		free(package_name);
+		free(control_buffer);
+	}
+
+	/* Write any new packages */
+	for(i = 0; deb_file[i] != NULL; i++) {
+		status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[i]->package]->name]);
+		if (strcmp("reinstreq", name_hashtable[get_status(status_num, 2)]) == 0) {
+			write_buffer_no_status(new_status_file, deb_file[i]->control_file);
+			set_status(status_num, "ok", 2);
+			fprintf(new_status_file, "Status: %s\n\n", name_hashtable[status_hashtable[status_num]->status]);
+		}
+	}
+	fclose(old_status_file);
+	fclose(new_status_file);
+
+
+	/* Create a separate backfile to dpkg */
+	if (rename("/var/lib/dpkg/status", "/var/lib/dpkg/status.udeb.bak") == -1) {
+		struct stat stat_buf;
+		xstat("/var/lib/dpkg/status", &stat_buf);
+		/* Its ok if renaming the status file fails because status
+		 * file doesnt exist, maybe we are starting from scratch */
+		bb_error_msg("No status file found, creating new one");
+	}
+
+	if (rename("/var/lib/dpkg/status.udeb", "/var/lib/dpkg/status") == -1) {
+		bb_error_msg_and_die("DANGER: Couldnt create status file, you need to manually repair your status file");
+	}
+}
+
+/* This function returns TRUE if the given package can satisfy a
+ * dependency of type depend_type.
+ *
+ * A pre-depends is satisfied only if a package is already installed,
+ * which a regular depends can be satisfied by a package which we want
+ * to install.
+ */
+static int package_satisfies_dependency(int package, int depend_type)
+{
+	int status_num = search_status_hashtable(name_hashtable[package_hashtable[package]->name]);
+
+	/* status could be unknown if package is a pure virtual
+	 * provides which cannot satisfy any dependency by itself.
+	 */
+	if ( status_hashtable[status_num] == NULL )
+		return 0;
+
+	switch (depend_type) {
+	case EDGE_PRE_DEPENDS:	return get_status(status_num, 3) == search_name_hashtable("installed");
+	case EDGE_DEPENDS:	return get_status(status_num, 1) == search_name_hashtable("install");
+	}
+	return 0;
+}
+
+static int check_deps(deb_file_t **deb_file, int deb_start, int dep_max_count)
+{
+	int *conflicts = NULL;
+	int conflicts_num = 0;
+	int i = deb_start;
+	int j;
+
+	/* Check for conflicts
+	 * TODO: TEST if conflicts with other packages to be installed
+	 *
+	 * Add install packages and the packages they provide
+	 * to the list of files to check conflicts for
+	 */
+
+	/* Create array of package numbers to check against
+	 * installed package for conflicts*/
+	while (deb_file[i] != NULL) {
+		const unsigned int package_num = deb_file[i]->package;
+		conflicts = xrealloc(conflicts, sizeof(int) * (conflicts_num + 1));
+		conflicts[conflicts_num] = package_num;
+		conflicts_num++;
+		/* add provides to conflicts list */
+		for (j = 0; j <	package_hashtable[package_num]->num_of_edges; j++) {
+			if (package_hashtable[package_num]->edge[j]->type == EDGE_PROVIDES) {
+				const int conflicts_package_num = search_package_hashtable(
+					package_hashtable[package_num]->edge[j]->name,
+					package_hashtable[package_num]->edge[j]->version,
+					package_hashtable[package_num]->edge[j]->operator);
+				if (package_hashtable[conflicts_package_num] == NULL) {
+					/* create a new package */
+					common_node_t *new_node = (common_node_t *) xzalloc(sizeof(common_node_t));
+					new_node->name = package_hashtable[package_num]->edge[j]->name;
+					new_node->version = package_hashtable[package_num]->edge[j]->version;
+					package_hashtable[conflicts_package_num] = new_node;
+				}
+				conflicts = xrealloc(conflicts, sizeof(int) * (conflicts_num + 1));
+				conflicts[conflicts_num] = conflicts_package_num;
+				conflicts_num++;
+			}
+		}
+		i++;
+	}
+
+	/* Check conflicts */
+	i = 0;
+	while (deb_file[i] != NULL) {
+		const common_node_t *package_node = package_hashtable[deb_file[i]->package];
+		int status_num = 0;
+		status_num = search_status_hashtable(name_hashtable[package_node->name]);
+
+		if (get_status(status_num, 3) == search_name_hashtable("installed")) {
+			i++;
+			continue;
+		}
+
+		for (j = 0; j < package_node->num_of_edges; j++) {
+			const edge_t *package_edge = package_node->edge[j];
+
+			if (package_edge->type == EDGE_CONFLICTS) {
+				const unsigned int package_num =
+					search_package_hashtable(package_edge->name,
+								 package_edge->version,
+								 package_edge->operator);
+				int result = 0;
+				if (package_hashtable[package_num] != NULL) {
+					status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]);
+
+					if (get_status(status_num, 1) == search_name_hashtable("install")) {
+						result = test_version(package_hashtable[deb_file[i]->package]->version,
+							package_edge->version, package_edge->operator);
+					}
+				}
+
+				if (result) {
+					bb_error_msg_and_die("Package %s conflicts with %s",
+						name_hashtable[package_node->name],
+						name_hashtable[package_edge->name]);
+				}
+			}
+		}
+		i++;
+	}
+
+
+	/* Check dependendcies */
+	for (i = 0; i < PACKAGE_HASH_PRIME; i++) {
+		int status_num = 0;
+		int number_of_alternatives = 0;
+		const edge_t * root_of_alternatives = NULL;
+		const common_node_t *package_node = package_hashtable[i];
+
+		/* If the package node does not exist then this
+		 * package is a virtual one. In which case there are
+		 * no dependencies to check.
+		 */
+		if ( package_node == NULL ) continue;
+
+		status_num = search_status_hashtable(name_hashtable[package_node->name]);
+
+		/* If there is no status then this package is a
+		 * virtual one provided by something else. In which
+		 * case there are no dependencies to check.
+		 */
+		if ( status_hashtable[status_num] == NULL ) continue;
+
+		/* If we don't want this package installed then we may
+		 * as well ignore it's dependencies.
+		 */
+		if (get_status(status_num, 1) != search_name_hashtable("install")) {
+			continue;
+		}
+
+#if 0
+		/* This might be needed so we don't complain about
+		 * things which are broken but unrelated to the
+		 * packages that are currently being installed
+		 */
+		if (state_status == search_name_hashtable("installed"))
+			continue;
+#endif
+
+		/* This code is tested only for EDGE_DEPENDS, since I
+		 * have no suitable pre-depends available. There is no
+		 * reason that it shouldn't work though :-)
+		 */
+		for (j = 0; j < package_node->num_of_edges; j++) {
+			const edge_t *package_edge = package_node->edge[j];
+			unsigned int package_num;
+
+			if ( package_edge->type == EDGE_OR_PRE_DEPENDS ||
+			     package_edge->type == EDGE_OR_DEPENDS ) {	/* start an EDGE_OR_ list */
+				number_of_alternatives = package_edge->version;
+				root_of_alternatives = package_edge;
+				continue;
+			} else if ( number_of_alternatives == 0 ) {	/* not in the middle of an EDGE_OR_ list */
+				number_of_alternatives = 1;
+				root_of_alternatives = NULL;
+			}
+
+			package_num = search_package_hashtable(package_edge->name, package_edge->version, package_edge->operator);
+
+			if (package_edge->type == EDGE_PRE_DEPENDS ||
+			    package_edge->type == EDGE_DEPENDS ) {
+				int result=1;
+				status_num = 0;
+
+				/* If we are inside an alternative then check
+				 * this edge is the right type.
+				 *
+				 * EDGE_DEPENDS == OR_DEPENDS -1
+				 * EDGE_PRE_DEPENDS == OR_PRE_DEPENDS -1
+				 */
+				if ( root_of_alternatives && package_edge->type != root_of_alternatives->type - 1)
+					bb_error_msg_and_die("Fatal error. Package dependencies corrupt: %d != %d - 1 \n",
+							     package_edge->type, root_of_alternatives->type);
+
+				if (package_hashtable[package_num] != NULL)
+					result = !package_satisfies_dependency(package_num, package_edge->type);
+
+				if (result) { /* check for other package which provide what we are looking for */
+					int provider = -1;
+
+					while ( (provider = search_for_provides(package_edge->name, provider) ) > -1 ) {
+						if ( package_hashtable[provider] == NULL ) {
+							printf("Have a provider but no package information for it\n");
+							continue;
+						}
+						result = !package_satisfies_dependency(provider, package_edge->type);
+
+						if ( result == 0 )
+							break;
+					}
+				}
+
+				/* It must be already installed, or to be installed */
+				number_of_alternatives--;
+				if (result && number_of_alternatives == 0) {
+					if ( root_of_alternatives )
+						bb_error_msg_and_die(
+							"Package %s %sdepends on %s, "
+							"which cannot be satisfied",
+							name_hashtable[package_node->name],
+							package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "",
+							name_hashtable[root_of_alternatives->name]);
+					else
+						bb_error_msg_and_die(
+							"Package %s %sdepends on %s, which %s\n",
+							name_hashtable[package_node->name],
+							package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "",
+							name_hashtable[package_edge->name],
+							describe_status(status_num));
+				} else if ( result == 0 && number_of_alternatives ) {
+					/* we've found a package which
+					 * satisfies the dependency,
+					 * so skip over the rest of
+					 * the alternatives.
+					 */
+					j += number_of_alternatives;
+					number_of_alternatives = 0;
+				}
+			}
+		}
+	}
+	free(conflicts);
+	return(TRUE);
+}
+
+static char **create_list(const char *filename)
+{
+	FILE *list_stream;
+	char **file_list = NULL;
+	char *line = NULL;
+	int count = 0;
+
+	/* don't use [xw]fopen here, handle error ourself */
+	list_stream = fopen(filename, "r");
+	if (list_stream == NULL) {
+		return(NULL);
+	}
+
+	while ((line = bb_get_chomped_line_from_file(list_stream)) != NULL) {
+		file_list = xrealloc(file_list, sizeof(char *) * (count + 2));
+		file_list[count] = line;
+		count++;
+	}
+	fclose(list_stream);
+
+	if (count == 0) {
+		return(NULL);
+	} else {
+		file_list[count] = NULL;
+		return(file_list);
+	}
+}
+
+/* maybe i should try and hook this into remove_file.c somehow */
+static int remove_file_array(char **remove_names, char **exclude_names)
+{
+	struct stat path_stat;
+	int match_flag;
+	int remove_flag = FALSE;
+	int i,j;
+
+	if (remove_names == NULL) {
+		return(FALSE);
+	}
+	for (i = 0; remove_names[i] != NULL; i++) {
+		match_flag = FALSE;
+		if (exclude_names != NULL) {
+			for (j = 0; exclude_names[j] != 0; j++) {
+				if (strcmp(remove_names[i], exclude_names[j]) == 0) {
+					match_flag = TRUE;
+					break;
+				}
+			}
+		}
+		if (!match_flag) {
+			if (lstat(remove_names[i], &path_stat) < 0) {
+				continue;
+			}
+			if (S_ISDIR(path_stat.st_mode)) {
+				if (rmdir(remove_names[i]) != -1) {
+					remove_flag = TRUE;
+				}
+			} else {
+				if (unlink(remove_names[i]) != -1) {
+					remove_flag = TRUE;
+				}
+			}
+		}
+	}
+	return(remove_flag);
+}
+
+static int run_package_script(const char *package_name, const char *script_type)
+{
+	struct stat path_stat;
+	char *script_path;
+	int result;
+
+	script_path = bb_xasprintf("/var/lib/dpkg/info/%s.%s", package_name, script_type);
+
+	/* If the file doesnt exist is isnt a fatal */
+	result = lstat(script_path, &path_stat) < 0 ? EXIT_SUCCESS : system(script_path);
+	free(script_path);
+	return(result);
+}
+
+static const char *all_control_files[] = {"preinst", "postinst", "prerm", "postrm",
+	"list", "md5sums", "shlibs", "conffiles", "config", "templates", NULL };
+
+static char **all_control_list(const char *package_name)
+{
+	unsigned short i = 0;
+	char **remove_files;
+
+	/* Create a list of all /var/lib/dpkg/info/<package> files */
+	remove_files = xzalloc(sizeof(all_control_files));
+	while (all_control_files[i]) {
+		remove_files[i] = bb_xasprintf("/var/lib/dpkg/info/%s.%s", package_name, all_control_files[i]);
+		i++;
+	}
+
+	return(remove_files);
+}
+
+static void free_array(char **array)
+{
+
+	if (array) {
+		unsigned short i = 0;
+		while (array[i]) {
+			free(array[i]);
+			i++;
+		}
+		free(array);
+	}
+}
+
+/* This function lists information on the installed packages. It loops through
+ * the status_hashtable to retrieve the info. This results in smaller code than
+ * scanning the status file. The resulting list, however, is unsorted.
+ */
+static void list_packages(void)
+{
+	int i;
+
+	printf("    Name           Version\n");
+	printf("+++-==============-==============\n");
+
+	/* go through status hash, dereference package hash and finally strings */
+	for (i=0; i<STATUS_HASH_PRIME+1; i++) {
+
+	        if (status_hashtable[i]) {
+		        const char *stat_str;  /* status string */
+			const char *name_str;  /* package name */
+			const char *vers_str;  /* version */
+			char  s1, s2;          /* status abbreviations */
+			int   spccnt;          /* space count */
+			int   j;
+
+			stat_str = name_hashtable[status_hashtable[i]->status];
+			name_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->name];
+			vers_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->version];
+
+			/* get abbreviation for status field 1 */
+			s1 = stat_str[0] == 'i' ? 'i' : 'r';
+
+			/* get abbreviation for status field 2 */
+			for (j=0, spccnt=0; stat_str[j] && spccnt<2; j++) {
+			        if (stat_str[j] == ' ') spccnt++;
+			}
+			s2 = stat_str[j];
+
+			/* print out the line formatted like Debian dpkg */
+			printf("%c%c  %-14s %s\n", s1, s2, name_str, vers_str);
+		}
+    }
+}
+
+static void remove_package(const unsigned int package_num, int noisy)
+{
+	const char *package_name = name_hashtable[package_hashtable[package_num]->name];
+	const char *package_version = name_hashtable[package_hashtable[package_num]->version];
+	const unsigned int status_num = search_status_hashtable(package_name);
+	const int package_name_length = strlen(package_name);
+	char **remove_files;
+	char **exclude_files;
+	char list_name[package_name_length + 25];
+	char conffile_name[package_name_length + 30];
+	int return_value;
+
+	if ( noisy )
+		printf("Removing %s (%s) ...\n", package_name, package_version);
+
+	/* run prerm script */
+	return_value = run_package_script(package_name, "prerm");
+	if (return_value == -1) {
+		bb_error_msg_and_die("script failed, prerm failure");
+	}
+
+	/* Create a list of files to remove, and a separate list of those to keep */
+	sprintf(list_name, "/var/lib/dpkg/info/%s.list", package_name);
+	remove_files = create_list(list_name);
+
+	sprintf(conffile_name, "/var/lib/dpkg/info/%s.conffiles", package_name);
+	exclude_files = create_list(conffile_name);
+
+	/* Some directories cant be removed straight away, so do multiple passes */
+	while (remove_file_array(remove_files, exclude_files));
+	free_array(exclude_files);
+	free_array(remove_files);
+
+	/* Create a list of files in /var/lib/dpkg/info/<package>.* to keep  */
+	exclude_files = xzalloc(sizeof(char*) * 3);
+	exclude_files[0] = bb_xstrdup(conffile_name);
+	exclude_files[1] = bb_xasprintf("/var/lib/dpkg/info/%s.postrm", package_name);
+
+	/* Create a list of all /var/lib/dpkg/info/<package> files */
+	remove_files = all_control_list(package_name);
+
+	remove_file_array(remove_files, exclude_files);
+	free_array(remove_files);
+	free_array(exclude_files);
+
+	/* rename <package>.conffile to <package>.list */
+	rename(conffile_name, list_name);
+
+	/* Change package status */
+	set_status(status_num, "config-files", 3);
+}
+
+static void purge_package(const unsigned int package_num)
+{
+	const char *package_name = name_hashtable[package_hashtable[package_num]->name];
+	const char *package_version = name_hashtable[package_hashtable[package_num]->version];
+	const unsigned int status_num = search_status_hashtable(package_name);
+	char **remove_files;
+	char **exclude_files;
+	char list_name[strlen(package_name) + 25];
+
+	printf("Purging %s (%s) ...\n", package_name, package_version);
+
+	/* run prerm script */
+	if (run_package_script(package_name, "prerm") != 0) {
+		bb_error_msg_and_die("script failed, prerm failure");
+	}
+
+	/* Create a list of files to remove */
+	sprintf(list_name, "/var/lib/dpkg/info/%s.list", package_name);
+	remove_files = create_list(list_name);
+
+	exclude_files = xzalloc(sizeof(char*));
+
+	/* Some directories cant be removed straight away, so do multiple passes */
+	while (remove_file_array(remove_files, exclude_files));
+	free_array(remove_files);
+
+	/* Create a list of all /var/lib/dpkg/info/<package> files */
+	remove_files = all_control_list(package_name);
+	remove_file_array(remove_files, exclude_files);
+	free_array(remove_files);
+	free(exclude_files);
+
+	/* run postrm script */
+	if (run_package_script(package_name, "postrm") == -1) {
+		bb_error_msg_and_die("postrm fialure.. set status to what?");
+	}
+
+	/* Change package status */
+	set_status(status_num, "not-installed", 3);
+}
+
+static archive_handle_t *init_archive_deb_ar(const char *filename)
+{
+	archive_handle_t *ar_handle;
+
+	/* Setup an ar archive handle that refers to the gzip sub archive */
+	ar_handle = init_handle();
+	ar_handle->filter = filter_accept_list_reassign;
+	ar_handle->src_fd = bb_xopen(filename, O_RDONLY);
+
+	return(ar_handle);
+}
+
+static void init_archive_deb_control(archive_handle_t *ar_handle)
+{
+	archive_handle_t *tar_handle;
+
+	/* Setup the tar archive handle */
+	tar_handle = init_handle();
+	tar_handle->src_fd = ar_handle->src_fd;
+
+	/* We don't care about data.tar.* or debian-binary, just control.tar.* */
+#ifdef CONFIG_FEATURE_DEB_TAR_GZ
+	llist_add_to(&(ar_handle->accept), "control.tar.gz");
+#endif
+#ifdef CONFIG_FEATURE_DEB_TAR_BZ2
+	llist_add_to(&(ar_handle->accept), "control.tar.bz2");
+#endif
+
+	/* Assign the tar handle as a subarchive of the ar handle */
+	ar_handle->sub_archive = tar_handle;
+
+	return;
+}
+
+static void init_archive_deb_data(archive_handle_t *ar_handle)
+{
+	archive_handle_t *tar_handle;
+
+	/* Setup the tar archive handle */
+	tar_handle = init_handle();
+	tar_handle->src_fd = ar_handle->src_fd;
+
+	/* We don't care about control.tar.* or debian-binary, just data.tar.* */
+#ifdef CONFIG_FEATURE_DEB_TAR_GZ
+	llist_add_to(&(ar_handle->accept), "data.tar.gz");
+#endif
+#ifdef CONFIG_FEATURE_DEB_TAR_BZ2
+	llist_add_to(&(ar_handle->accept), "data.tar.bz2");
+#endif
+
+	/* Assign the tar handle as a subarchive of the ar handle */
+	ar_handle->sub_archive = tar_handle;
+
+	return;
+}
+
+static char *deb_extract_control_file_to_buffer(archive_handle_t *ar_handle, llist_t *myaccept)
+{
+	ar_handle->sub_archive->action_data = data_extract_to_buffer;
+	ar_handle->sub_archive->accept = myaccept;
+	ar_handle->sub_archive->filter = filter_accept_list;
+
+	unpack_ar_archive(ar_handle);
+	close(ar_handle->src_fd);
+
+	return(ar_handle->sub_archive->buffer);
+}
+
+static void data_extract_all_prefix(archive_handle_t *archive_handle)
+{
+	char *name_ptr = archive_handle->file_header->name;
+
+	name_ptr += strspn(name_ptr, "./");
+	if (name_ptr[0] != '\0') {
+		archive_handle->file_header->name = bb_xasprintf("%s%s", archive_handle->buffer, name_ptr);
+		data_extract_all(archive_handle);
+	}
+	return;
+}
+
+static void unpack_package(deb_file_t *deb_file)
+{
+	const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name];
+	const unsigned int status_num = search_status_hashtable(package_name);
+	const unsigned int status_package_num = status_hashtable[status_num]->package;
+	char *info_prefix;
+	archive_handle_t *archive_handle;
+	FILE *out_stream;
+	llist_t *accept_list = NULL;
+	int i = 0;
+
+	/* If existing version, remove it first */
+	if (strcmp(name_hashtable[get_status(status_num, 3)], "installed") == 0) {
+		/* Package is already installed, remove old version first */
+		printf("Preparing to replace %s %s (using %s) ...\n", package_name,
+			name_hashtable[package_hashtable[status_package_num]->version],
+			deb_file->filename);
+		remove_package(status_package_num, 0);
+	} else {
+		printf("Unpacking %s (from %s) ...\n", package_name, deb_file->filename);
+	}
+
+	/* Extract control.tar.gz to /var/lib/dpkg/info/<package>.filename */
+	info_prefix = bb_xasprintf("/var/lib/dpkg/info/%s.", package_name);
+	archive_handle = init_archive_deb_ar(deb_file->filename);
+	init_archive_deb_control(archive_handle);
+
+	while(all_control_files[i]) {
+		char *c = bb_xasprintf("./%s", all_control_files[i]);
+		llist_add_to(&accept_list, c);
+		i++;
+	}
+	archive_handle->sub_archive->accept = accept_list;
+	archive_handle->sub_archive->filter = filter_accept_list;
+	archive_handle->sub_archive->action_data = data_extract_all_prefix;
+	archive_handle->sub_archive->buffer = info_prefix;
+	archive_handle->sub_archive->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;
+	unpack_ar_archive(archive_handle);
+
+	/* Run the preinst prior to extracting */
+	if (run_package_script(package_name, "preinst") != 0) {
+		/* when preinst returns exit code != 0 then quit installation process */
+		bb_error_msg_and_die("subprocess pre-installation script returned error.");
+	}
+
+	/* Extract data.tar.gz to the root directory */
+	archive_handle = init_archive_deb_ar(deb_file->filename);
+	init_archive_deb_data(archive_handle);
+	archive_handle->sub_archive->action_data = data_extract_all_prefix;
+	archive_handle->sub_archive->buffer = "/";
+	archive_handle->sub_archive->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;
+	unpack_ar_archive(archive_handle);
+
+	/* Create the list file */
+	strcat(info_prefix, "list");
+	out_stream = bb_xfopen(info_prefix, "w");
+	while (archive_handle->sub_archive->passed) {
+		/* the leading . has been stripped by data_extract_all_prefix already */
+		fputs(archive_handle->sub_archive->passed->data, out_stream);
+		fputc('\n', out_stream);
+		archive_handle->sub_archive->passed = archive_handle->sub_archive->passed->link;
+	}
+	fclose(out_stream);
+
+	/* change status */
+	set_status(status_num, "install", 1);
+	set_status(status_num, "unpacked", 3);
+
+	free(info_prefix);
+}
+
+static void configure_package(deb_file_t *deb_file)
+{
+	const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name];
+	const char *package_version = name_hashtable[package_hashtable[deb_file->package]->version];
+	const int status_num = search_status_hashtable(package_name);
+
+	printf("Setting up %s (%s) ...\n", package_name, package_version);
+
+	/* Run the postinst script */
+	if (run_package_script(package_name, "postinst") != 0) {
+		/* TODO: handle failure gracefully */
+		bb_error_msg_and_die("postrm failure.. set status to what?");
+	}
+	/* Change status to reflect success */
+	set_status(status_num, "install", 1);
+	set_status(status_num, "installed", 3);
+}
+
+int dpkg_main(int argc, char **argv)
+{
+	deb_file_t **deb_file = NULL;
+	status_node_t *status_node;
+	int opt;
+	int package_num;
+	int dpkg_opt = 0;
+	int deb_count = 0;
+	int state_status;
+	int status_num;
+	int i;
+
+	while ((opt = getopt(argc, argv, "CF:ilPru")) != -1) {
+		switch (opt) {
+			case 'C': // equivalent to --configure in official dpkg
+				dpkg_opt |= dpkg_opt_configure;
+				dpkg_opt |= dpkg_opt_package_name;
+				break;
+			case 'F': // equivalent to --force in official dpkg
+				if (strcmp(optarg, "depends") == 0) {
+					dpkg_opt |= dpkg_opt_force_ignore_depends;
+				}
+				break;
+			case 'i':
+				dpkg_opt |= dpkg_opt_install;
+				dpkg_opt |= dpkg_opt_filename;
+				break;
+			case 'l':
+				dpkg_opt |= dpkg_opt_list_installed;
+				break;
+			case 'P':
+				dpkg_opt |= dpkg_opt_purge;
+				dpkg_opt |= dpkg_opt_package_name;
+				break;
+			case 'r':
+				dpkg_opt |= dpkg_opt_remove;
+				dpkg_opt |= dpkg_opt_package_name;
+				break;
+			case 'u':	/* Equivalent to --unpack in official dpkg */
+				dpkg_opt |= dpkg_opt_unpack;
+				dpkg_opt |= dpkg_opt_filename;
+				break;
+			default:
+				bb_show_usage();
+		}
+	}
+	/* check for non-otion argument if expected  */
+	if ((dpkg_opt == 0) || ((argc == optind) && !(dpkg_opt && dpkg_opt_list_installed))) {
+		bb_show_usage();
+	}
+
+/*	puts("(Reading database ... xxxxx files and directories installed.)"); */
+	index_status_file("/var/lib/dpkg/status");
+
+	/* if the list action was given print the installed packages and exit */
+	if (dpkg_opt & dpkg_opt_list_installed) {
+		list_packages();
+		return(EXIT_SUCCESS);
+	}
+
+	/* Read arguments and store relevant info in structs */
+	while (optind < argc) {
+		/* deb_count = nb_elem - 1 and we need nb_elem + 1 to allocate terminal node [NULL pointer] */
+		deb_file = xrealloc(deb_file, sizeof(deb_file_t *) * (deb_count + 2));
+		deb_file[deb_count] = (deb_file_t *) xzalloc(sizeof(deb_file_t));
+		if (dpkg_opt & dpkg_opt_filename) {
+			archive_handle_t *archive_handle;
+			llist_t *control_list = NULL;
+
+			/* Extract the control file */
+			llist_add_to(&control_list, "./control");
+			archive_handle = init_archive_deb_ar(argv[optind]);
+			init_archive_deb_control(archive_handle);
+			deb_file[deb_count]->control_file = deb_extract_control_file_to_buffer(archive_handle, control_list);
+			if (deb_file[deb_count]->control_file == NULL) {
+				bb_error_msg_and_die("Couldnt extract control file");
+			}
+			deb_file[deb_count]->filename = bb_xstrdup(argv[optind]);
+			package_num = fill_package_struct(deb_file[deb_count]->control_file);
+
+			if (package_num == -1) {
+				bb_error_msg("Invalid control file in %s", argv[optind]);
+				optind++;
+				continue;
+			}
+			deb_file[deb_count]->package = (unsigned int) package_num;
+
+			/* Add the package to the status hashtable */
+			if ((dpkg_opt & dpkg_opt_unpack) || (dpkg_opt & dpkg_opt_install)) {
+				/* Try and find a currently installed version of this package */
+				status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]);
+				/* If no previous entry was found initialise a new entry */
+				if ((status_hashtable[status_num] == NULL) ||
+					(status_hashtable[status_num]->status == 0)) {
+					status_node = (status_node_t *) xmalloc(sizeof(status_node_t));
+					status_node->package = deb_file[deb_count]->package;
+					/* reinstreq isnt changed to "ok" until the package control info
+					 * is written to the status file*/
+					status_node->status = search_name_hashtable("install reinstreq not-installed");
+					status_hashtable[status_num] = status_node;
+				} else {
+					set_status(status_num, "install", 1);
+					set_status(status_num, "reinstreq", 2);
+				}
+			}
+		}
+		else if (dpkg_opt & dpkg_opt_package_name) {
+			deb_file[deb_count]->package = search_package_hashtable(
+				search_name_hashtable(argv[optind]),
+				search_name_hashtable("ANY"), VER_ANY);
+			if (package_hashtable[deb_file[deb_count]->package] == NULL) {
+				bb_error_msg_and_die("Package %s is uninstalled or unknown\n", argv[optind]);
+			}
+			package_num = deb_file[deb_count]->package;
+			status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]);
+			state_status = get_status(status_num, 3);
+
+			/* check package status is "installed" */
+			if (dpkg_opt & dpkg_opt_remove) {
+				if ((strcmp(name_hashtable[state_status], "not-installed") == 0) ||
+					(strcmp(name_hashtable[state_status], "config-files") == 0)) {
+					bb_error_msg_and_die("%s is already removed.", name_hashtable[package_hashtable[package_num]->name]);
+				}
+				set_status(status_num, "deinstall", 1);
+			}
+			else if (dpkg_opt & dpkg_opt_purge) {
+				/* if package status is "conf-files" then its ok */
+				if (strcmp(name_hashtable[state_status], "not-installed") == 0) {
+					bb_error_msg_and_die("%s is already purged.", name_hashtable[package_hashtable[package_num]->name]);
+				}
+				set_status(status_num, "purge", 1);
+			}
+		}
+		deb_count++;
+		optind++;
+	}
+	deb_file[deb_count] = NULL;
+
+	/* Check that the deb file arguments are installable */
+	if ((dpkg_opt & dpkg_opt_force_ignore_depends) != dpkg_opt_force_ignore_depends) {
+		if (!check_deps(deb_file, 0, deb_count)) {
+			bb_error_msg_and_die("Dependency check failed");
+		}
+	}
+
+	/* TODO: install or remove packages in the correct dependency order */
+	for (i = 0; i < deb_count; i++) {
+		/* Remove or purge packages */
+		if (dpkg_opt & dpkg_opt_remove) {
+			remove_package(deb_file[i]->package, 1);
+		}
+		else if (dpkg_opt & dpkg_opt_purge) {
+			purge_package(deb_file[i]->package);
+		}
+		else if (dpkg_opt & dpkg_opt_unpack) {
+			unpack_package(deb_file[i]);
+		}
+		else if (dpkg_opt & dpkg_opt_install) {
+			unpack_package(deb_file[i]);
+			/* package is configured in second pass below */
+		}
+		else if (dpkg_opt & dpkg_opt_configure) {
+			configure_package(deb_file[i]);
+		}
+	}
+	/* configure installed packages */
+	if (dpkg_opt & dpkg_opt_install) {
+		for (i = 0; i < deb_count; i++)
+			configure_package(deb_file[i]);
+	}
+
+	write_status_file(deb_file);
+
+	for (i = 0; i < deb_count; i++) {
+		free(deb_file[i]->control_file);
+		free(deb_file[i]->filename);
+		free(deb_file[i]);
+	}
+
+	free(deb_file);
+
+	for (i = 0; i < NAME_HASH_PRIME; i++) {
+		free(name_hashtable[i]);
+	}
+
+	for (i = 0; i < PACKAGE_HASH_PRIME; i++) {
+		if (package_hashtable[i] != NULL) {
+			free_package(package_hashtable[i]);
+		}
+	}
+
+	for (i = 0; i < STATUS_HASH_PRIME; i++) {
+		free(status_hashtable[i]);
+	}
+
+	return(EXIT_SUCCESS);
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/dpkg_deb.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/dpkg_deb.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/dpkg_deb.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,101 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * dpkg-deb packs, unpacks and provides information about Debian archives.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "unarchive.h"
+#include "busybox.h"
+
+#define DPKG_DEB_OPT_CONTENTS	1
+#define DPKG_DEB_OPT_CONTROL	2
+#define DPKG_DEB_OPT_FIELD	4
+#define DPKG_DEB_OPT_EXTRACT	8
+#define DPKG_DEB_OPT_EXTRACT_VERBOSE	16
+
+int dpkg_deb_main(int argc, char **argv)
+{
+	archive_handle_t *ar_archive;
+	archive_handle_t *tar_archive;
+	llist_t *control_tar_llist = NULL;
+	unsigned long opt;
+	char *extract_dir = NULL;
+	short argcount = 1;
+
+	/* Setup the tar archive handle */
+	tar_archive = init_handle();
+
+	/* Setup an ar archive handle that refers to the gzip sub archive */
+	ar_archive = init_handle();
+	ar_archive->sub_archive = tar_archive;
+	ar_archive->filter = filter_accept_list_reassign;
+
+#ifdef CONFIG_FEATURE_DEB_TAR_GZ
+	llist_add_to(&(ar_archive->accept), "data.tar.gz");
+	llist_add_to(&control_tar_llist, "control.tar.gz");
+#endif
+
+#ifdef CONFIG_FEATURE_DEB_TAR_BZ2
+	llist_add_to(&(ar_archive->accept), "data.tar.bz2");
+	llist_add_to(&control_tar_llist, "control.tar.bz2");
+#endif
+
+	bb_opt_complementally = "?c--efXx:e--cfXx:f--ceXx:X--cefx:x--cefX";
+	opt = bb_getopt_ulflags(argc, argv, "cefXx");
+
+	if (opt & DPKG_DEB_OPT_CONTENTS) {
+		tar_archive->action_header = header_verbose_list;
+	}
+	if (opt & DPKG_DEB_OPT_CONTROL) {
+		ar_archive->accept = control_tar_llist;
+		tar_archive->action_data = data_extract_all;
+		if (optind + 1 == argc) {
+			extract_dir = "./DEBIAN";
+		} else {
+			argcount++;
+		}
+	}
+	if (opt & DPKG_DEB_OPT_FIELD) {
+		/* Print the entire control file
+		 * it should accept a second argument which specifies a
+		 * specific field to print */
+		ar_archive->accept = control_tar_llist;
+		llist_add_to(&(tar_archive->accept), "./control");
+		tar_archive->filter = filter_accept_list;
+		tar_archive->action_data = data_extract_to_stdout;
+	}
+	if (opt & DPKG_DEB_OPT_EXTRACT) {
+		tar_archive->action_header = header_list;
+	}
+	if (opt & (DPKG_DEB_OPT_EXTRACT_VERBOSE | DPKG_DEB_OPT_EXTRACT)) {
+		tar_archive->action_data = data_extract_all;
+		argcount = 2;
+	}
+
+	if ((optind + argcount) != argc) {
+		bb_show_usage();
+	}
+
+	tar_archive->src_fd = ar_archive->src_fd = bb_xopen(argv[optind++], O_RDONLY);
+
+	/* Workout where to extract the files */
+	/* 2nd argument is a dir name */
+	if (argv[optind]) {
+		extract_dir = argv[optind];
+	}
+	if (extract_dir) {
+		mkdir(extract_dir, 0777); /* bb_make_directory(extract_dir, 0777, 0) */
+		bb_xchdir(extract_dir);
+	}
+	unpack_ar_archive(ar_archive);
+
+	/* Cleanup */
+	close (ar_archive->src_fd);
+
+	return(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/gunzip.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/gunzip.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/gunzip.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,192 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Gzip implementation for busybox
+ *
+ * Based on GNU gzip v1.2.4 Copyright (C) 1992-1993 Jean-loup Gailly.
+ *
+ * Originally adjusted for busybox by Sven Rudolph <sr1 at inf.tu-dresden.de>
+ * based on gzip sources
+ *
+ * Adjusted further by Erik Andersen <andersen at codepoet.org> to support files as
+ * well as stdin/stdout, and to generally behave itself wrt command line
+ * handling.
+ *
+ * General cleanup to better adhere to the style guide and make use of standard
+ * busybox functions by Glenn McGrath <bug1 at iinet.net.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ * gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * The unzip code was written and put in the public domain by Mark Adler.
+ * Portions of the lzw code are derived from the public domain 'compress'
+ * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
+ * Ken Turkowski, Dave Mack and Peter Jannesen.
+ *
+ * See the license_msg below and the file COPYING for the software license.
+ * See the file algorithm.doc for the compression algorithms and file formats.
+ */
+
+#if 0
+static char *license_msg[] = {
+	"   Copyright (C) 1992-1993 Jean-loup Gailly",
+	"   This program is free software; you can redistribute it and/or modify",
+	"   it under the terms of the GNU General Public License as published by",
+	"   the Free Software Foundation; either version 2, or (at your option)",
+	"   any later version.",
+	"",
+	"   This program is distributed in the hope that it will be useful,",
+	"   but WITHOUT ANY WARRANTY; without even the implied warranty of",
+	"   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the",
+	"   GNU General Public License for more details.",
+	"",
+	"   You should have received a copy of the GNU General Public License",
+	"   along with this program; if not, write to the Free Software",
+	"   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.",
+	0
+};
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "busybox.h"
+#include "unarchive.h"
+
+#define GUNZIP_OPT_STDOUT	1
+#define GUNZIP_OPT_FORCE	2
+#define GUNZIP_OPT_TEST		4
+#define GUNZIP_OPT_DECOMPRESS	8
+
+int gunzip_main(int argc, char **argv)
+{
+	char status = EXIT_SUCCESS;
+	unsigned long opt;
+
+	opt = bb_getopt_ulflags(argc, argv, "cftd");
+	/* if called as zcat */
+	if (strcmp(bb_applet_name, "zcat") == 0) {
+		opt |= GUNZIP_OPT_STDOUT;
+	}
+
+	do {
+		struct stat stat_buf;
+		const char *old_path = argv[optind];
+		const char *delete_path = NULL;
+		char *new_path = NULL;
+		int src_fd;
+		int dst_fd;
+
+		optind++;
+
+		if (old_path == NULL || strcmp(old_path, "-") == 0) {
+			src_fd = STDIN_FILENO;
+			opt |= GUNZIP_OPT_STDOUT;
+		} else {
+			src_fd = bb_xopen(old_path, O_RDONLY);
+
+			/* Get the time stamp on the input file. */
+			xstat(old_path, &stat_buf);
+		}
+
+		/* Check that the input is sane.  */
+		if (isatty(src_fd) && ((opt & GUNZIP_OPT_FORCE) == 0)) {
+			bb_error_msg_and_die
+				("compressed data not read from terminal.  Use -f to force it.");
+		}
+
+		/* Set output filename and number */
+		if (opt & GUNZIP_OPT_TEST) {
+			dst_fd = bb_xopen(bb_dev_null, O_WRONLY);	/* why does test use filenum 2 ? */
+		} else if (opt & GUNZIP_OPT_STDOUT) {
+			dst_fd = STDOUT_FILENO;
+		} else {
+			char *extension;
+
+			new_path = bb_xstrdup(old_path);
+
+			extension = strrchr(new_path, '.');
+#ifdef CONFIG_FEATURE_GUNZIP_UNCOMPRESS
+			if (extension && (strcmp(extension, ".Z") == 0)) {
+				*extension = '\0';
+			} else
+#endif
+			if (extension && (strcmp(extension, ".gz") == 0)) {
+				*extension = '\0';
+			} else if (extension && (strcmp(extension, ".tgz") == 0)) {
+				extension[2] = 'a';
+				extension[3] = 'r';
+			} else {
+				bb_error_msg_and_die("Invalid extension");
+			}
+
+			/* Open output file (with correct permissions) */
+			dst_fd = bb_xopen3(new_path, O_WRONLY | O_CREAT, stat_buf.st_mode);
+
+			/* If unzip succeeds remove the old file */
+			delete_path = old_path;
+		}
+
+		/* do the decompression, and cleanup */
+		if (bb_xread_char(src_fd) == 0x1f) {
+			unsigned char magic2;
+
+			magic2 = bb_xread_char(src_fd);
+#ifdef CONFIG_FEATURE_GUNZIP_UNCOMPRESS
+			if (magic2 == 0x9d) {
+				status = uncompress(src_fd, dst_fd);
+			} else
+#endif
+				if (magic2 == 0x8b) {
+					check_header_gzip(src_fd);
+					status = inflate_gunzip(src_fd, dst_fd);
+					if (status != 0) {
+						bb_error_msg_and_die("Error inflating");
+					}
+				} else {
+					bb_error_msg_and_die("Invalid magic");
+				}
+		} else {
+			bb_error_msg_and_die("Invalid magic");
+		}
+
+		if ((status != EXIT_SUCCESS) && (new_path)) {
+			/* Unzip failed, remove new path instead of old path */
+			delete_path = new_path;
+		}
+
+		if (dst_fd != STDOUT_FILENO) {
+			close(dst_fd);
+		}
+		if (src_fd != STDIN_FILENO) {
+			close(src_fd);
+		}
+
+		/* delete_path will be NULL if in test mode or from stdin */
+		if (delete_path && (unlink(delete_path) == -1)) {
+			bb_error_msg_and_die("Couldn't remove %s", delete_path);
+		}
+
+		free(new_path);
+
+	} while (optind < argc);
+
+	return status;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/gzip.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/gzip.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/gzip.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2489 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Gzip implementation for busybox
+ *
+ * Based on GNU gzip Copyright (C) 1992-1993 Jean-loup Gailly.
+ *
+ * Originally adjusted for busybox by Charles P. Wright <cpw at unix.asb.com>
+ *		"this is a stripped down version of gzip I put into busybox, it does
+ *		only standard in to standard out with -9 compression.  It also requires
+ *		the zcat module for some important functions."
+ *
+ * Adjusted further by Erik Andersen <andersen at codepoet.org> to support
+ * files as well as stdin/stdout, and to generally behave itself wrt
+ * command line handling.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#define SMALL_MEM
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <utime.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <time.h>
+#include "busybox.h"
+
+typedef unsigned char uch;
+typedef unsigned short ush;
+typedef unsigned long ulg;
+
+/* Return codes from gzip */
+#define OK      0
+#define ERROR   1
+#define WARNING 2
+
+/* Compression methods (see algorithm.doc) */
+/* Only STORED and DEFLATED are supported by this BusyBox module */
+#define STORED      0
+/* methods 4 to 7 reserved */
+#define DEFLATED    8
+
+/* To save memory for 16 bit systems, some arrays are overlaid between
+ * the various modules:
+ * deflate:  prev+head   window      d_buf  l_buf  outbuf
+ * unlzw:    tab_prefix  tab_suffix  stack  inbuf  outbuf
+ * For compression, input is done in window[]. For decompression, output
+ * is done in window except for unlzw.
+ */
+
+#ifndef	INBUFSIZ
+#  ifdef SMALL_MEM
+#    define INBUFSIZ  0x2000	/* input buffer size */
+#  else
+#    define INBUFSIZ  0x8000	/* input buffer size */
+#  endif
+#endif
+#define INBUF_EXTRA  64	/* required by unlzw() */
+
+#ifndef	OUTBUFSIZ
+#  ifdef SMALL_MEM
+#    define OUTBUFSIZ   8192	/* output buffer size */
+#  else
+#    define OUTBUFSIZ  16384	/* output buffer size */
+#  endif
+#endif
+#define OUTBUF_EXTRA 2048	/* required by unlzw() */
+
+#ifndef DIST_BUFSIZE
+#  ifdef SMALL_MEM
+#    define DIST_BUFSIZE 0x2000	/* buffer for distances, see trees.c */
+#  else
+#    define DIST_BUFSIZE 0x8000	/* buffer for distances, see trees.c */
+#  endif
+#endif
+
+#  define DECLARE(type, array, size)  static type * array
+#  define ALLOC(type, array, size) { \
+      array = (type*)xzalloc((size_t)(((size)+1L)/2) * 2*sizeof(type)); \
+   }
+#  define FREE(array) {free(array), array=NULL;}
+
+#define tab_suffix window
+#define tab_prefix prev	/* hash link (see deflate.c) */
+#define head (prev+WSIZE)	/* hash head (see deflate.c) */
+
+static long bytes_in;	/* number of input bytes */
+
+#define isize bytes_in
+/* for compatibility with old zip sources (to be cleaned) */
+
+typedef int file_t;		/* Do not use stdio */
+
+#define NO_FILE  (-1)	/* in memory compression */
+
+
+#define	PACK_MAGIC     "\037\036"	/* Magic header for packed files */
+#define	GZIP_MAGIC     "\037\213"	/* Magic header for gzip files, 1F 8B */
+#define	OLD_GZIP_MAGIC "\037\236"	/* Magic header for gzip 0.5 = freeze 1.x */
+#define	LZH_MAGIC      "\037\240"	/* Magic header for SCO LZH Compress files */
+#define PKZIP_MAGIC    "\120\113\003\004"	/* Magic header for pkzip files */
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01	/* bit 0 set: file probably ascii text */
+#define CONTINUATION 0x02	/* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04	/* bit 2 set: extra field present */
+#define ORIG_NAME    0x08	/* bit 3 set: original file name present */
+#define COMMENT      0x10	/* bit 4 set: file comment present */
+#define RESERVED     0xC0	/* bit 6,7:   reserved */
+
+/* internal file attribute */
+#define UNKNOWN 0xffff
+#define BINARY  0
+#define ASCII   1
+
+#ifndef WSIZE
+#  define WSIZE 0x8000	/* window size--must be a power of two, and */
+#endif							/*  at least 32K for zip's deflate method */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST  (WSIZE-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+/* put_byte is used for the compressed output */
+#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\
+   flush_outbuf();}
+
+
+/* Output a 32 bit value to the bit stream, lsb first */
+#if 0
+#define put_long(n) { \
+    put_short((n) & 0xffff); \
+    put_short(((ulg)(n)) >> 16); \
+}
+#endif
+
+#define seekable()    0	/* force sequential output */
+#define translate_eol 0	/* no option -a yet */
+
+/* Diagnostic functions */
+#ifdef DEBUG
+#  define Assert(cond,msg) {if(!(cond)) bb_error_msg(msg);}
+#  define Trace(x) fprintf x
+#  define Tracev(x) {if (verbose) fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+#define WARN(msg) {if (!quiet) fprintf msg ; \
+		   if (exit_code == OK) exit_code = WARNING;}
+
+#ifndef MAX_PATH_LEN
+#  define MAX_PATH_LEN   1024	/* max pathname length */
+#endif
+
+
+	/* from zip.c: */
+static int zip(int in, int out);
+static int file_read(char *buf, unsigned size);
+
+		/* from deflate.c */
+static void lm_init(ush * flags);
+static ulg deflate(void);
+
+		/* from trees.c */
+static void ct_init(ush * attr, int *methodp);
+static int ct_tally(int dist, int lc);
+static ulg flush_block(char *buf, ulg stored_len, int eof);
+
+		/* from bits.c */
+static void bi_init(file_t zipfile);
+static void send_bits(int value, int length);
+static unsigned bi_reverse(unsigned value, int length);
+static void bi_windup(void);
+static void copy_block(char *buf, unsigned len, int header);
+static int (*read_buf) (char *buf, unsigned size);
+
+	/* from util.c: */
+static void flush_outbuf(void);
+
+/* lzw.h -- define the lzw functions.
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#ifndef BITS
+#  define BITS 16
+#endif
+#define INIT_BITS 9		/* Initial number of bits per code */
+
+#define BIT_MASK    0x1f	/* Mask for 'number of compression bits' */
+/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
+ * It's a pity that old uncompress does not check bit 0x20. That makes
+ * extension of the format actually undesirable because old compress
+ * would just crash on the new format instead of giving a meaningful
+ * error message. It does check the number of bits, but it's more
+ * helpful to say "unsupported format, get a new version" than
+ * "can only handle 16 bits".
+ */
+
+/* tailor.h -- target dependent definitions
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+/* The target dependent definitions should be defined here only.
+ * The target dependent functions should be defined in tailor.c.
+ */
+
+
+	/* Common defaults */
+
+#ifndef OS_CODE
+#  define OS_CODE  0x03	/* assume Unix */
+#endif
+
+#ifndef PATH_SEP
+#  define PATH_SEP '/'
+#endif
+
+#ifndef OPTIONS_VAR
+#  define OPTIONS_VAR "GZIP"
+#endif
+
+#ifndef Z_SUFFIX
+#  define Z_SUFFIX ".gz"
+#endif
+
+#ifdef MAX_EXT_CHARS
+#  define MAX_SUFFIX  MAX_EXT_CHARS
+#else
+#  define MAX_SUFFIX  30
+#endif
+
+		/* global buffers */
+
+DECLARE(uch, inbuf, INBUFSIZ + INBUF_EXTRA);
+DECLARE(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA);
+DECLARE(ush, d_buf, DIST_BUFSIZE);
+DECLARE(uch, window, 2L * WSIZE);
+DECLARE(ush, tab_prefix, 1L << BITS);
+
+static int foreground;	/* set if program run in foreground */
+static int method = DEFLATED;	/* compression method */
+static int exit_code = OK;	/* program exit code */
+static int part_nb;		/* number of parts in .gz file */
+static long time_stamp;	/* original time stamp (modification time) */
+static long ifile_size;	/* input file size, -1 for devices (debug only) */
+static char z_suffix[MAX_SUFFIX + 1];	/* default suffix (can be set with --suffix) */
+static int z_len;		/* strlen(z_suffix) */
+
+static int ifd;			/* input file descriptor */
+static int ofd;			/* output file descriptor */
+static unsigned insize;	/* valid bytes in inbuf */
+static unsigned outcnt;	/* bytes in output buffer */
+
+static uint32_t *crc_32_tab;
+
+/* Output a 16 bit value, lsb first */
+static void put_short(ush w)
+{
+	if (outcnt < OUTBUFSIZ - 2) {
+		outbuf[outcnt++] = (uch) ((w) & 0xff);
+		outbuf[outcnt++] = (uch) ((ush) (w) >> 8);
+	} else {
+		put_byte((uch) ((w) & 0xff));
+		put_byte((uch) ((ush) (w) >> 8));
+	}
+}
+
+/* ========================================================================
+ * Signal and error handler.
+ */
+static void abort_gzip(int ATTRIBUTE_UNUSED ignored)
+{
+	exit(ERROR);
+}
+
+/* ===========================================================================
+ * Clear input and output buffers
+ */
+static void clear_bufs(void)
+{
+	outcnt = 0;
+	insize = 0;
+	bytes_in = 0L;
+}
+
+/* ===========================================================================
+ * Does the same as write(), but also handles partial pipe writes and checks
+ * for error return.
+ */
+static void write_buf(int fd, void *buf, unsigned cnt)
+{
+	unsigned n;
+
+	while ((n = write(fd, buf, cnt)) != cnt) {
+		if (n == (unsigned) (-1)) bb_error_msg_and_die(bb_msg_write_error);
+		cnt -= n;
+		buf = (void *) ((char *) buf + n);
+	}
+}
+
+/* ===========================================================================
+ * Run a set of bytes through the crc shift register.  If s is a NULL
+ * pointer, then initialize the crc shift register contents instead.
+ * Return the current crc in either case.
+ */
+static uint32_t updcrc(uch * s, unsigned n)
+{
+	static uint32_t crc = ~0;	/* shift register contents */
+	uint32_t c;		/* temporary variable */
+
+	if (s == NULL) {
+		c = ~0;
+	} else {
+		c = crc;
+		if (n)
+			do {
+				c = crc_32_tab[((int) c ^ (*s++)) & 0xff] ^ (c >> 8);
+			} while (--n);
+	}
+	crc = c;
+	return ~c;
+}
+
+/* bits.c -- output variable-length bit strings
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+
+/*
+ *  PURPOSE
+ *
+ *      Output variable-length bit strings. Compression can be done
+ *      to a file or to memory. (The latter is not supported in this version.)
+ *
+ *  DISCUSSION
+ *
+ *      The PKZIP "deflate" file format interprets compressed file data
+ *      as a sequence of bits.  Multi-bit strings in the file may cross
+ *      byte boundaries without restriction.
+ *
+ *      The first bit of each byte is the low-order bit.
+ *
+ *      The routines in this file allow a variable-length bit value to
+ *      be output right-to-left (useful for literal values). For
+ *      left-to-right output (useful for code strings from the tree routines),
+ *      the bits must have been reversed first with bi_reverse().
+ *
+ *      For in-memory compression, the compressed bit stream goes directly
+ *      into the requested output buffer. The input data is read in blocks
+ *      by the mem_read() function. The buffer is limited to 64K on 16 bit
+ *      machines.
+ *
+ *  INTERFACE
+ *
+ *      void bi_init (FILE *zipfile)
+ *          Initialize the bit string routines.
+ *
+ *      void send_bits (int value, int length)
+ *          Write out a bit string, taking the source bits right to
+ *          left.
+ *
+ *      int bi_reverse (int value, int length)
+ *          Reverse the bits of a bit string, taking the source bits left to
+ *          right and emitting them right to left.
+ *
+ *      void bi_windup (void)
+ *          Write out any remaining bits in an incomplete byte.
+ *
+ *      void copy_block(char *buf, unsigned len, int header)
+ *          Copy a stored block to the zip file, storing first the length and
+ *          its one's complement if requested.
+ *
+ */
+
+/* ===========================================================================
+ * Local data used by the "bit string" routines.
+ */
+
+static file_t zfile;	/* output gzip file */
+
+static unsigned short bi_buf;
+
+/* Output buffer. bits are inserted starting at the bottom (least significant
+ * bits).
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+static int bi_valid;
+
+/* Current input function. Set to mem_read for in-memory compression */
+
+#ifdef DEBUG
+ulg bits_sent;			/* bit length of the compressed data */
+#endif
+
+/* ===========================================================================
+ * Initialize the bit string routines.
+ */
+static void bi_init(file_t zipfile)
+{
+	zfile = zipfile;
+	bi_buf = 0;
+	bi_valid = 0;
+#ifdef DEBUG
+	bits_sent = 0L;
+#endif
+
+	/* Set the defaults for file compression. They are set by memcompress
+	 * for in-memory compression.
+	 */
+	if (zfile != NO_FILE) {
+		read_buf = file_read;
+	}
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+static void send_bits(int value, int length)
+{
+#ifdef DEBUG
+	Tracev((stderr, " l %2d v %4x ", length, value));
+	Assert(length > 0 && length <= 15, "invalid length");
+	bits_sent += (ulg) length;
+#endif
+	/* If not enough room in bi_buf, use (valid) bits from bi_buf and
+	 * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+	 * unused bits in value.
+	 */
+	if (bi_valid > (int) Buf_size - length) {
+		bi_buf |= (value << bi_valid);
+		put_short(bi_buf);
+		bi_buf = (ush) value >> (Buf_size - bi_valid);
+		bi_valid += length - Buf_size;
+	} else {
+		bi_buf |= value << bi_valid;
+		bi_valid += length;
+	}
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+static unsigned bi_reverse(unsigned code, int len)
+{
+	register unsigned res = 0;
+
+	do {
+		res |= code & 1;
+		code >>= 1, res <<= 1;
+	} while (--len > 0);
+	return res >> 1;
+}
+
+/* ===========================================================================
+ * Write out any remaining bits in an incomplete byte.
+ */
+static void bi_windup(void)
+{
+	if (bi_valid > 8) {
+		put_short(bi_buf);
+	} else if (bi_valid > 0) {
+		put_byte(bi_buf);
+	}
+	bi_buf = 0;
+	bi_valid = 0;
+#ifdef DEBUG
+	bits_sent = (bits_sent + 7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block to the zip file, storing first the length and its
+ * one's complement if requested.
+ */
+static void copy_block(char *buf, unsigned len, int header)
+{
+	bi_windup();		/* align on byte boundary */
+
+	if (header) {
+		put_short((ush) len);
+		put_short((ush) ~ len);
+#ifdef DEBUG
+		bits_sent += 2 * 16;
+#endif
+	}
+#ifdef DEBUG
+	bits_sent += (ulg) len << 3;
+#endif
+	while (len--) {
+		put_byte(*buf++);
+	}
+}
+
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+/*
+ *  PURPOSE
+ *
+ *      Identify new text as repetitions of old text within a fixed-
+ *      length sliding window trailing behind the new text.
+ *
+ *  DISCUSSION
+ *
+ *      The "deflation" process depends on being able to identify portions
+ *      of the input text which are identical to earlier input (within a
+ *      sliding window trailing behind the input currently being processed).
+ *
+ *      The most straightforward technique turns out to be the fastest for
+ *      most input files: try all possible matches and select the longest.
+ *      The key feature of this algorithm is that insertions into the string
+ *      dictionary are very simple and thus fast, and deletions are avoided
+ *      completely. Insertions are performed at each input character, whereas
+ *      string matches are performed only when the previous match ends. So it
+ *      is preferable to spend more time in matches to allow very fast string
+ *      insertions and avoid deletions. The matching algorithm for small
+ *      strings is inspired from that of Rabin & Karp. A brute force approach
+ *      is used to find longer strings when a small match has been found.
+ *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ *      (by Leonid Broukhis).
+ *         A previous version of this file used a more sophisticated algorithm
+ *      (by Fiala and Greene) which is guaranteed to run in linear amortized
+ *      time, but has a larger average cost, uses more memory and is patented.
+ *      However the F&G algorithm may be faster for some highly redundant
+ *      files if the parameter max_chain_length (described below) is too large.
+ *
+ *  ACKNOWLEDGMENTS
+ *
+ *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ *      I found it in 'freeze' written by Leonid Broukhis.
+ *      Thanks to many info-zippers for bug reports and testing.
+ *
+ *  REFERENCES
+ *
+ *      APPNOTE.TXT documentation file in PKZIP 1.93a distribution.
+ *
+ *      A description of the Rabin and Karp algorithm is given in the book
+ *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ *      Fiala,E.R., and Greene,D.H.
+ *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ *  INTERFACE
+ *
+ *      void lm_init (int pack_level, ush *flags)
+ *          Initialize the "longest match" routines for a new file
+ *
+ *      ulg deflate (void)
+ *          Processes a new input file and return its compressed length. Sets
+ *          the compressed length, crc, deflate flags and internal file
+ *          attributes.
+ */
+
+
+/* ===========================================================================
+ * Configuration parameters
+ */
+
+/* Compile with MEDIUM_MEM to reduce the memory requirements or
+ * with SMALL_MEM to use as little memory as possible. Use BIG_MEM if the
+ * entire input file can be held in memory (not possible on 16 bit systems).
+ * Warning: defining these symbols affects HASH_BITS (see below) and thus
+ * affects the compression ratio. The compressed output
+ * is still correct, and might even be smaller in some cases.
+ */
+
+#ifdef SMALL_MEM
+#   define HASH_BITS  13	/* Number of bits used to hash strings */
+#endif
+#ifdef MEDIUM_MEM
+#   define HASH_BITS  14
+#endif
+#ifndef HASH_BITS
+#   define HASH_BITS  15
+   /* For portability to 16 bit machines, do not use values above 15. */
+#endif
+
+/* To save space (see unlzw.c), we overlay prev+head with tab_prefix and
+ * window with tab_suffix. Check that we can do this:
+ */
+#if (WSIZE<<1) > (1<<BITS)
+#  error cannot overlay window with tab_suffix and prev with tab_prefix0
+#endif
+#if HASH_BITS > BITS-1
+#  error cannot overlay head with tab_prefix1
+#endif
+#define HASH_SIZE (unsigned)(1<<HASH_BITS)
+#define HASH_MASK (HASH_SIZE-1)
+#define WMASK     (WSIZE-1)
+/* HASH_SIZE and WSIZE must be powers of two */
+#define NIL 0
+/* Tail of hash chains */
+#define FAST 4
+#define SLOW 2
+/* speed options for the general purpose bit flag */
+#ifndef TOO_FAR
+#  define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+/* ===========================================================================
+ * Local data used by the "longest match" routines.
+ */
+typedef ush Pos;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+/* DECLARE(uch, window, 2L*WSIZE); */
+/* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least WSIZE
+ * bytes. With this organization, matches are limited to a distance of
+ * WSIZE-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: limit the window size to WSIZE+BSZ if SMALL_MEM (the code would
+ * be less efficient).
+ */
+
+/* DECLARE(Pos, prev, WSIZE); */
+/* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+/* DECLARE(Pos, head, 1<<HASH_BITS); */
+/* Heads of the hash chains or NIL. */
+
+static const ulg window_size = (ulg) 2 * WSIZE;
+
+/* window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the
+ * input file length plus MIN_LOOKAHEAD.
+ */
+
+static long block_start;
+
+/* window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+static unsigned ins_h;	/* hash index of string to be inserted */
+
+#define H_SHIFT  ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH)
+/* Number of bits by which ins_h and del_h must be shifted at each
+ * input step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ *   H_SHIFT * MIN_MATCH >= HASH_BITS
+ */
+
+static unsigned int prev_length;
+
+/* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+static unsigned strstart;	/* start of string to insert */
+static unsigned match_start;	/* start of matching string */
+static int eofile;		/* flag set at end of input file */
+static unsigned lookahead;	/* number of valid bytes ahead in window */
+
+enum {
+	max_chain_length = 4096,
+
+/* To speed up deflation, hash chains are never searched beyond this length.
+ * A higher limit improves compression ratio but degrades the speed.
+ */
+
+	max_lazy_match = 258,
+
+/* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+	max_insert_length = max_lazy_match,
+/* Insert new strings in the hash table only if the match length
+ * is not greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+	good_match = 32,
+
+/* Use a faster search when the previous match is longer than this */
+
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+
+	nice_match = 258	/* Stop searching when current match exceeds this */
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+};
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+/* ===========================================================================
+ *  Prototypes for local functions.
+ */
+static void fill_window(void);
+
+static int longest_match(IPos cur_match);
+
+#ifdef DEBUG
+static void check_match(IPos start, IPos match, int length);
+#endif
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
+ *    input characters, so that a running hash key can be computed from the
+ *    previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(h,c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK)
+
+/* ===========================================================================
+ * Insert string s in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * IN  assertion: all calls to to INSERT_STRING are made with consecutive
+ *    input characters and the first MIN_MATCH bytes of s are valid
+ *    (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#define INSERT_STRING(s, match_head) \
+   (UPDATE_HASH(ins_h, window[(s) + MIN_MATCH-1]), \
+    prev[(s) & WMASK] = match_head = head[ins_h], \
+    head[ins_h] = (s))
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new file
+ */
+static void lm_init(ush * flags)
+{
+	register unsigned j;
+
+	/* Initialize the hash table. */
+	memset(head, 0, HASH_SIZE * sizeof(*head));
+	/* prev will be initialized on the fly */
+
+	*flags |= SLOW;
+	/* ??? reduce max_chain_length for binary files */
+
+	strstart = 0;
+	block_start = 0L;
+
+	lookahead = read_buf((char *) window,
+						 sizeof(int) <= 2 ? (unsigned) WSIZE : 2 * WSIZE);
+
+	if (lookahead == 0 || lookahead == (unsigned) EOF) {
+		eofile = 1, lookahead = 0;
+		return;
+	}
+	eofile = 0;
+	/* Make sure that we always have enough lookahead. This is important
+	 * if input comes from a device such as a tty.
+	 */
+	while (lookahead < MIN_LOOKAHEAD && !eofile)
+		fill_window();
+
+	ins_h = 0;
+	for (j = 0; j < MIN_MATCH - 1; j++)
+		UPDATE_HASH(ins_h, window[j]);
+	/* If lookahead < MIN_MATCH, ins_h is garbage, but this is
+	 * not important since only literal bytes will be emitted.
+	 */
+}
+
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ */
+
+/* For MSDOS, OS/2 and 386 Unix, an optimized version is in match.asm or
+ * match.s. The code is functionally equivalent, so you can use the C version
+ * if desired.
+ */
+static int longest_match(IPos cur_match)
+{
+	unsigned chain_length = max_chain_length;	/* max hash chain length */
+	register uch *scan = window + strstart;	/* current string */
+	register uch *match;	/* matched string */
+	register int len;	/* length of current match */
+	int best_len = prev_length;	/* best match length so far */
+	IPos limit =
+		strstart > (IPos) MAX_DIST ? strstart - (IPos) MAX_DIST : NIL;
+	/* Stop when cur_match becomes <= limit. To simplify the code,
+	 * we prevent matches with the string of window index 0.
+	 */
+
+/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+#if HASH_BITS < 8 || MAX_MATCH != 258
+#  error Code too clever
+#endif
+	register uch *strend = window + strstart + MAX_MATCH;
+	register uch scan_end1 = scan[best_len - 1];
+	register uch scan_end = scan[best_len];
+
+	/* Do not waste too much time if we already have a good match: */
+	if (prev_length >= good_match) {
+		chain_length >>= 2;
+	}
+	Assert(strstart <= window_size - MIN_LOOKAHEAD, "insufficient lookahead");
+
+	do {
+		Assert(cur_match < strstart, "no future");
+		match = window + cur_match;
+
+		/* Skip to next match if the match length cannot increase
+		 * or if the match length is less than 2:
+		 */
+		if (match[best_len] != scan_end ||
+			match[best_len - 1] != scan_end1 ||
+			*match != *scan || *++match != scan[1])
+			continue;
+
+		/* The check at best_len-1 can be removed because it will be made
+		 * again later. (This heuristic is not always a win.)
+		 * It is not necessary to compare scan[2] and match[2] since they
+		 * are always equal when the other bytes match, given that
+		 * the hash keys are equal and that HASH_BITS >= 8.
+		 */
+		scan += 2, match++;
+
+		/* We check for insufficient lookahead only every 8th comparison;
+		 * the 256th check will be made at strstart+258.
+		 */
+		do {
+		} while (*++scan == *++match && *++scan == *++match &&
+				 *++scan == *++match && *++scan == *++match &&
+				 *++scan == *++match && *++scan == *++match &&
+				 *++scan == *++match && *++scan == *++match && scan < strend);
+
+		len = MAX_MATCH - (int) (strend - scan);
+		scan = strend - MAX_MATCH;
+
+		if (len > best_len) {
+			match_start = cur_match;
+			best_len = len;
+			if (len >= nice_match)
+				break;
+			scan_end1 = scan[best_len - 1];
+			scan_end = scan[best_len];
+		}
+	} while ((cur_match = prev[cur_match & WMASK]) > limit
+			 && --chain_length != 0);
+
+	return best_len;
+}
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+static void check_match(IPos start, IPos match, int length)
+{
+	/* check that the match is indeed a match */
+	if (memcmp((char *) window + match,
+			   (char *) window + start, length) != EQUAL) {
+		bb_error_msg(" start %d, match %d, length %d", start, match, length);
+		bb_error_msg("invalid match");
+	}
+	if (verbose > 1) {
+		bb_error_msg("\\[%d,%d]", start - match, length);
+		do {
+			putc(window[start++], stderr);
+		} while (--length != 0);
+	}
+}
+#else
+#  define check_match(start, match, length)
+#endif
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead, and sets eofile if end of input file.
+ * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0
+ * OUT assertions: at least one byte has been read, or eofile is set;
+ *    file reads are performed for at least two bytes (required for the
+ *    translate_eol option).
+ */
+static void fill_window(void)
+{
+	register unsigned n, m;
+	unsigned more =
+		(unsigned) (window_size - (ulg) lookahead - (ulg) strstart);
+	/* Amount of free space at the end of the window. */
+
+	/* If the window is almost full and there is insufficient lookahead,
+	 * move the upper half to the lower one to make room in the upper half.
+	 */
+	if (more == (unsigned) EOF) {
+		/* Very unlikely, but possible on 16 bit machine if strstart == 0
+		 * and lookahead == 1 (input done one byte at time)
+		 */
+		more--;
+	} else if (strstart >= WSIZE + MAX_DIST) {
+		/* By the IN assertion, the window is not empty so we can't confuse
+		 * more == 0 with more == 64K on a 16 bit machine.
+		 */
+		Assert(window_size == (ulg) 2 * WSIZE, "no sliding with BIG_MEM");
+
+		memcpy((char *) window, (char *) window + WSIZE, (unsigned) WSIZE);
+		match_start -= WSIZE;
+		strstart -= WSIZE;	/* we now have strstart >= MAX_DIST: */
+
+		block_start -= (long) WSIZE;
+
+		for (n = 0; n < HASH_SIZE; n++) {
+			m = head[n];
+			head[n] = (Pos) (m >= WSIZE ? m - WSIZE : NIL);
+		}
+		for (n = 0; n < WSIZE; n++) {
+			m = prev[n];
+			prev[n] = (Pos) (m >= WSIZE ? m - WSIZE : NIL);
+			/* If n is not on any hash chain, prev[n] is garbage but
+			 * its value will never be used.
+			 */
+		}
+		more += WSIZE;
+	}
+	/* At this point, more >= 2 */
+	if (!eofile) {
+		n = read_buf((char *) window + strstart + lookahead, more);
+		if (n == 0 || n == (unsigned) EOF) {
+			eofile = 1;
+		} else {
+			lookahead += n;
+		}
+	}
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK(eof) \
+   flush_block(block_start >= 0L ? (char*)&window[(unsigned)block_start] : \
+		(char*)NULL, (long)strstart - block_start, (eof))
+
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+static ulg deflate(void)
+{
+	IPos hash_head;		/* head of hash chain */
+	IPos prev_match;	/* previous match */
+	int flush;			/* set if current block must be flushed */
+	int match_available = 0;	/* set if previous match exists */
+	register unsigned match_length = MIN_MATCH - 1;	/* length of best match */
+
+	/* Process the input block. */
+	while (lookahead != 0) {
+		/* Insert the string window[strstart .. strstart+2] in the
+		 * dictionary, and set hash_head to the head of the hash chain:
+		 */
+		INSERT_STRING(strstart, hash_head);
+
+		/* Find the longest match, discarding those <= prev_length.
+		 */
+		prev_length = match_length, prev_match = match_start;
+		match_length = MIN_MATCH - 1;
+
+		if (hash_head != NIL && prev_length < max_lazy_match &&
+			strstart - hash_head <= MAX_DIST) {
+			/* To simplify the code, we prevent matches with the string
+			 * of window index 0 (in particular we have to avoid a match
+			 * of the string with itself at the start of the input file).
+			 */
+			match_length = longest_match(hash_head);
+			/* longest_match() sets match_start */
+			if (match_length > lookahead)
+				match_length = lookahead;
+
+			/* Ignore a length 3 match if it is too distant: */
+			if (match_length == MIN_MATCH && strstart - match_start > TOO_FAR) {
+				/* If prev_match is also MIN_MATCH, match_start is garbage
+				 * but we will ignore the current match anyway.
+				 */
+				match_length--;
+			}
+		}
+		/* If there was a match at the previous step and the current
+		 * match is not better, output the previous match:
+		 */
+		if (prev_length >= MIN_MATCH && match_length <= prev_length) {
+
+			check_match(strstart - 1, prev_match, prev_length);
+
+			flush =
+				ct_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH);
+
+			/* Insert in hash table all strings up to the end of the match.
+			 * strstart-1 and strstart are already inserted.
+			 */
+			lookahead -= prev_length - 1;
+			prev_length -= 2;
+			do {
+				strstart++;
+				INSERT_STRING(strstart, hash_head);
+				/* strstart never exceeds WSIZE-MAX_MATCH, so there are
+				 * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH
+				 * these bytes are garbage, but it does not matter since the
+				 * next lookahead bytes will always be emitted as literals.
+				 */
+			} while (--prev_length != 0);
+			match_available = 0;
+			match_length = MIN_MATCH - 1;
+			strstart++;
+			if (flush)
+				FLUSH_BLOCK(0), block_start = strstart;
+
+		} else if (match_available) {
+			/* If there was no match at the previous position, output a
+			 * single literal. If there was a match but the current match
+			 * is longer, truncate the previous match to a single literal.
+			 */
+			Tracevv((stderr, "%c", window[strstart - 1]));
+			if (ct_tally(0, window[strstart - 1])) {
+				FLUSH_BLOCK(0), block_start = strstart;
+			}
+			strstart++;
+			lookahead--;
+		} else {
+			/* There is no previous match to compare with, wait for
+			 * the next step to decide.
+			 */
+			match_available = 1;
+			strstart++;
+			lookahead--;
+		}
+		Assert(strstart <= isize && lookahead <= isize, "a bit too far");
+
+		/* Make sure that we always have enough lookahead, except
+		 * at the end of the input file. We need MAX_MATCH bytes
+		 * for the next match, plus MIN_MATCH bytes to insert the
+		 * string following the next match.
+		 */
+		while (lookahead < MIN_LOOKAHEAD && !eofile)
+			fill_window();
+	}
+	if (match_available)
+		ct_tally(0, window[strstart - 1]);
+
+	return FLUSH_BLOCK(1);	/* eof */
+}
+
+/* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * The unzip code was written and put in the public domain by Mark Adler.
+ * Portions of the lzw code are derived from the public domain 'compress'
+ * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
+ * Ken Turkowski, Dave Mack and Peter Jannesen.
+ *
+ * See the license_msg below and the file COPYING for the software license.
+ * See the file algorithm.doc for the compression algorithms and file formats.
+ */
+
+/* Compress files with zip algorithm and 'compress' interface.
+ * See usage() and help() functions below for all options.
+ * Outputs:
+ *        file.gz:   compressed file with same mode, owner, and utimes
+ *     or stdout with -c option or if stdin used as input.
+ * If the output file name had to be truncated, the original name is kept
+ * in the compressed file.
+ */
+
+		/* configuration */
+
+typedef struct dirent dir_type;
+
+/* ======================================================================== */
+int gzip_main(int argc, char **argv)
+{
+	int result;
+	int inFileNum;
+	int outFileNum;
+	struct stat statBuf;
+	char *delFileName;
+	int tostdout = 0;
+	int force = 0;
+	int opt;
+
+	while ((opt = getopt(argc, argv, "cf123456789dq")) != -1) {
+		switch (opt) {
+		case 'c':
+			tostdout = 1;
+			break;
+		case 'f':
+			force = 1;
+			break;
+			/* Ignore 1-9 (compression level) options */
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+			break;
+		case 'q':
+			break;
+#ifdef CONFIG_GUNZIP
+		case 'd':
+			optind = 1;
+			return gunzip_main(argc, argv);
+#endif
+		default:
+			bb_show_usage();
+		}
+	}
+
+	foreground = signal(SIGINT, SIG_IGN) != SIG_IGN;
+	if (foreground) {
+		(void) signal(SIGINT, abort_gzip);
+	}
+#ifdef SIGTERM
+	if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
+		(void) signal(SIGTERM, abort_gzip);
+	}
+#endif
+#ifdef SIGHUP
+	if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
+		(void) signal(SIGHUP, abort_gzip);
+	}
+#endif
+
+	strncpy(z_suffix, Z_SUFFIX, sizeof(z_suffix) - 1);
+	z_len = strlen(z_suffix);
+
+	/* Allocate all global buffers (for DYN_ALLOC option) */
+	ALLOC(uch, inbuf, INBUFSIZ + INBUF_EXTRA);
+	ALLOC(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA);
+	ALLOC(ush, d_buf, DIST_BUFSIZE);
+	ALLOC(uch, window, 2L * WSIZE);
+	ALLOC(ush, tab_prefix, 1L << BITS);
+
+	/* Initialise the CRC32 table */
+	crc_32_tab = bb_crc32_filltable(0);
+	
+	clear_bufs();
+	part_nb = 0;
+
+	if (optind == argc) {
+		time_stamp = 0;
+		ifile_size = -1L;
+		zip(STDIN_FILENO, STDOUT_FILENO);
+	} else {
+		int i;
+
+		for (i = optind; i < argc; i++) {
+			char *path = NULL;
+
+			clear_bufs();
+			if (strcmp(argv[i], "-") == 0) {
+				time_stamp = 0;
+				ifile_size = -1L;
+				inFileNum = STDIN_FILENO;
+				outFileNum = STDOUT_FILENO;
+			} else {
+				inFileNum = bb_xopen3(argv[i], O_RDONLY, 0);
+				if (fstat(inFileNum, &statBuf) < 0)
+					bb_perror_msg_and_die("%s", argv[i]);
+				time_stamp = statBuf.st_ctime;
+				ifile_size = statBuf.st_size;
+
+				if (!tostdout) {
+					path = xmalloc(strlen(argv[i]) + 4);
+					strcpy(path, argv[i]);
+					strcat(path, ".gz");
+
+					/* Open output file */
+#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) && defined O_NOFOLLOW
+					outFileNum =
+						open(path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW);
+#else
+					outFileNum = open(path, O_RDWR | O_CREAT | O_EXCL);
+#endif
+					if (outFileNum < 0) {
+						bb_perror_msg("%s", path);
+						free(path);
+						continue;
+					}
+
+					/* Set permissions on the file */
+					fchmod(outFileNum, statBuf.st_mode);
+				} else
+					outFileNum = STDOUT_FILENO;
+			}
+
+			if (path == NULL && isatty(outFileNum) && force == 0) {
+				bb_error_msg
+					("compressed data not written to a terminal. Use -f to force compression.");
+				free(path);
+				continue;
+			}
+
+			result = zip(inFileNum, outFileNum);
+
+			if (path != NULL) {
+				close(inFileNum);
+				close(outFileNum);
+
+				/* Delete the original file */
+				if (result == OK)
+					delFileName = argv[i];
+				else
+					delFileName = path;
+
+				if (unlink(delFileName) < 0)
+					bb_perror_msg("%s", delFileName);
+			}
+
+			free(path);
+		}
+	}
+
+	return (exit_code);
+}
+
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+/*
+ *  PURPOSE
+ *
+ *      Encode various sets of source values using variable-length
+ *      binary code trees.
+ *
+ *  DISCUSSION
+ *
+ *      The PKZIP "deflation" process uses several Huffman trees. The more
+ *      common source values are represented by shorter bit sequences.
+ *
+ *      Each code tree is stored in the ZIP file in a compressed form
+ *      which is itself a Huffman encoding of the lengths of
+ *      all the code strings (in ascending order by source values).
+ *      The actual code strings are reconstructed from the lengths in
+ *      the UNZIP process, as described in the "application note"
+ *      (APPNOTE.TXT) distributed as part of PKWARE's PKZIP program.
+ *
+ *  REFERENCES
+ *
+ *      Lynch, Thomas J.
+ *          Data Compression:  Techniques and Applications, pp. 53-55.
+ *          Lifetime Learning Publications, 1985.  ISBN 0-534-03418-7.
+ *
+ *      Storer, James A.
+ *          Data Compression:  Methods and Theory, pp. 49-50.
+ *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.
+ *
+ *      Sedgewick, R.
+ *          Algorithms, p290.
+ *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ *
+ *  INTERFACE
+ *
+ *      void ct_init (ush *attr, int *methodp)
+ *          Allocate the match buffer, initialize the various tables and save
+ *          the location of the internal file attribute (ascii/binary) and
+ *          method (DEFLATE/STORE)
+ *
+ *      void ct_tally (int dist, int lc);
+ *          Save the match info and tally the frequency counts.
+ *
+ *      long flush_block (char *buf, ulg stored_len, int eof)
+ *          Determine the best encoding for the current block: dynamic trees,
+ *          static trees or store, and output the encoded block to the zip
+ *          file. Returns the total compressed length for the file so far.
+ *
+ */
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS  256
+/* number of literal bytes 0..255 */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES   30
+/* number of distance codes */
+
+#define BL_CODES  19
+/* number of codes used to transfer the bit lengths */
+
+typedef uch extra_bits_t;
+
+/* extra bits for each length code */
+static const extra_bits_t extra_lbits[LENGTH_CODES]
+	= { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4,
+	4, 4, 5, 5, 5, 5, 0
+};
+
+/* extra bits for each distance code */
+static const extra_bits_t extra_dbits[D_CODES]
+	= { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
+	10, 10, 11, 11, 12, 12, 13, 13
+};
+
+/* extra bits for each bit length code */
+static const extra_bits_t extra_blbits[BL_CODES]
+= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 };
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#ifndef LIT_BUFSIZE
+#  ifdef SMALL_MEM
+#    define LIT_BUFSIZE  0x2000
+#  else
+#  ifdef MEDIUM_MEM
+#    define LIT_BUFSIZE  0x4000
+#  else
+#    define LIT_BUFSIZE  0x8000
+#  endif
+#  endif
+#endif
+#ifndef DIST_BUFSIZE
+#  define DIST_BUFSIZE  LIT_BUFSIZE
+#endif
+/* Sizes of match buffers for literals/lengths and distances.  There are
+ * 4 reasons for limiting LIT_BUFSIZE to 64K:
+ *   - frequencies can be kept in 16 bit counters
+ *   - if compression is not successful for the first block, all input data is
+ *     still in the window so we can still emit a stored block even when input
+ *     comes from standard input.  (This can also be done for all blocks if
+ *     LIT_BUFSIZE is not greater than 32K.)
+ *   - if compression is not successful for a file smaller than 64K, we can
+ *     even emit a stored file instead of a stored block (saving 5 bytes).
+ *   - creating new Huffman trees less frequently may not provide fast
+ *     adaptation to changes in the input data statistics. (Take for
+ *     example a binary file with poorly compressible code followed by
+ *     a highly compressible string table.) Smaller buffer sizes give
+ *     fast adaptation but have of course the overhead of transmitting trees
+ *     more frequently.
+ *   - I can't count above 4
+ * The current code is general and allows DIST_BUFSIZE < LIT_BUFSIZE (to save
+ * memory at the expense of compression). Some optimizations would be possible
+ * if we rely on DIST_BUFSIZE == LIT_BUFSIZE.
+ */
+#if LIT_BUFSIZE > INBUFSIZ
+#error cannot overlay l_buf and inbuf
+#endif
+#define REP_3_6      16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+#define REPZ_3_10    17
+/* repeat a zero length 3-10 times  (3 bits of repeat count) */
+#define REPZ_11_138  18
+/* repeat a zero length 11-138 times  (7 bits of repeat count) */
+
+/* ===========================================================================
+ * Local data
+ */
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data {
+	union {
+		ush freq;		/* frequency count */
+		ush code;		/* bit string */
+	} fc;
+	union {
+		ush dad;		/* father node in Huffman tree */
+		ush len;		/* length of bit string */
+	} dl;
+} ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad  dl.dad
+#define Len  dl.len
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+static ct_data dyn_ltree[HEAP_SIZE];	/* literal and length tree */
+static ct_data dyn_dtree[2 * D_CODES + 1];	/* distance tree */
+
+static ct_data static_ltree[L_CODES + 2];
+
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see ct_init
+ * below).
+ */
+
+static ct_data static_dtree[D_CODES];
+
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+static ct_data bl_tree[2 * BL_CODES + 1];
+
+/* Huffman tree for the bit lengths */
+
+typedef struct tree_desc {
+	ct_data *dyn_tree;	/* the dynamic tree */
+	ct_data *static_tree;	/* corresponding static tree or NULL */
+	const extra_bits_t *extra_bits;	/* extra bits for each code or NULL */
+	int extra_base;		/* base index for extra_bits */
+	int elems;			/* max number of elements in the tree */
+	int max_length;		/* max bit length for the codes */
+	int max_code;		/* largest code with non zero frequency */
+} tree_desc;
+
+static tree_desc l_desc =
+	{ dyn_ltree, static_ltree, extra_lbits, LITERALS + 1, L_CODES,
+	MAX_BITS, 0
+};
+
+static tree_desc d_desc =
+	{ dyn_dtree, static_dtree, extra_dbits, 0, D_CODES, MAX_BITS, 0 };
+
+static tree_desc bl_desc =
+	{ bl_tree, (ct_data *) 0, extra_blbits, 0, BL_CODES, MAX_BL_BITS,
+	0
+};
+
+
+static ush bl_count[MAX_BITS + 1];
+
+/* number of codes at each bit length for an optimal tree */
+
+static const uch bl_order[BL_CODES]
+= { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
+
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+static int heap[2 * L_CODES + 1];	/* heap used to build the Huffman trees */
+static int heap_len;	/* number of elements in the heap */
+static int heap_max;	/* element of largest frequency */
+
+/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+static uch depth[2 * L_CODES + 1];
+
+/* Depth of each subtree used as tie breaker for trees of equal frequency */
+
+static uch length_code[MAX_MATCH - MIN_MATCH + 1];
+
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+static uch dist_code[512];
+
+/* distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+static int base_length[LENGTH_CODES];
+
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+static int base_dist[D_CODES];
+
+/* First normalized distance for each code (0 = distance of 1) */
+
+#define l_buf inbuf
+/* DECLARE(uch, l_buf, LIT_BUFSIZE);  buffer for literals or lengths */
+
+/* DECLARE(ush, d_buf, DIST_BUFSIZE); buffer for distances */
+
+static uch flag_buf[(LIT_BUFSIZE / 8)];
+
+/* flag_buf is a bit array distinguishing literals from lengths in
+ * l_buf, thus indicating the presence or absence of a distance.
+ */
+
+static unsigned last_lit;	/* running index in l_buf */
+static unsigned last_dist;	/* running index in d_buf */
+static unsigned last_flags;	/* running index in flag_buf */
+static uch flags;		/* current flags not yet saved in flag_buf */
+static uch flag_bit;	/* current bit used in flags */
+
+/* bits are filled in flags starting at bit 0 (least significant).
+ * Note: these flags are overkill in the current code since we don't
+ * take advantage of DIST_BUFSIZE == LIT_BUFSIZE.
+ */
+
+static ulg opt_len;		/* bit length of current block with optimal trees */
+static ulg static_len;	/* bit length of current block with static trees */
+
+static ulg compressed_len;	/* total bit length of compressed file */
+
+
+static ush *file_type;	/* pointer to UNKNOWN, BINARY or ASCII */
+static int *file_method;	/* pointer to DEFLATE or STORE */
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+static void init_block(void);
+static void pqdownheap(ct_data * tree, int k);
+static void gen_bitlen(tree_desc * desc);
+static void gen_codes(ct_data * tree, int max_code);
+static void build_tree(tree_desc * desc);
+static void scan_tree(ct_data * tree, int max_code);
+static void send_tree(ct_data * tree, int max_code);
+static int build_bl_tree(void);
+static void send_all_trees(int lcodes, int dcodes, int blcodes);
+static void compress_block(ct_data * ltree, ct_data * dtree);
+static void set_file_type(void);
+
+
+#ifndef DEBUG
+#  define send_code(c, tree) send_bits(tree[c].Code, tree[c].Len)
+   /* Send a code of the given tree. c and tree must not have side effects */
+
+#else							/* DEBUG */
+#  define send_code(c, tree) \
+     { if (verbose>1) bb_error_msg("\ncd %3d ",(c)); \
+       send_bits(tree[c].Code, tree[c].Len); }
+#endif
+
+#define d_code(dist) \
+   ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. dist_code[256] and dist_code[257] are never
+ * used.
+ */
+
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Allocate the match buffer, initialize the various tables and save the
+ * location of the internal file attribute (ascii/binary) and method
+ * (DEFLATE/STORE).
+ */
+static void ct_init(ush * attr, int *methodp)
+{
+	int n;				/* iterates over tree elements */
+	int bits;			/* bit counter */
+	int length;			/* length value */
+	int code;			/* code value */
+	int dist;			/* distance index */
+
+	file_type = attr;
+	file_method = methodp;
+	compressed_len = 0L;
+
+	if (static_dtree[0].Len != 0)
+		return;			/* ct_init already called */
+
+	/* Initialize the mapping length (0..255) -> length code (0..28) */
+	length = 0;
+	for (code = 0; code < LENGTH_CODES - 1; code++) {
+		base_length[code] = length;
+		for (n = 0; n < (1 << extra_lbits[code]); n++) {
+			length_code[length++] = (uch) code;
+		}
+	}
+	Assert(length == 256, "ct_init: length != 256");
+	/* Note that the length 255 (match length 258) can be represented
+	 * in two different ways: code 284 + 5 bits or code 285, so we
+	 * overwrite length_code[255] to use the best encoding:
+	 */
+	length_code[length - 1] = (uch) code;
+
+	/* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+	dist = 0;
+	for (code = 0; code < 16; code++) {
+		base_dist[code] = dist;
+		for (n = 0; n < (1 << extra_dbits[code]); n++) {
+			dist_code[dist++] = (uch) code;
+		}
+	}
+	Assert(dist == 256, "ct_init: dist != 256");
+	dist >>= 7;			/* from now on, all distances are divided by 128 */
+	for (; code < D_CODES; code++) {
+		base_dist[code] = dist << 7;
+		for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
+			dist_code[256 + dist++] = (uch) code;
+		}
+	}
+	Assert(dist == 256, "ct_init: 256+dist != 512");
+
+	/* Construct the codes of the static literal tree */
+	for (bits = 0; bits <= MAX_BITS; bits++)
+		bl_count[bits] = 0;
+	n = 0;
+	while (n <= 143)
+		static_ltree[n++].Len = 8, bl_count[8]++;
+	while (n <= 255)
+		static_ltree[n++].Len = 9, bl_count[9]++;
+	while (n <= 279)
+		static_ltree[n++].Len = 7, bl_count[7]++;
+	while (n <= 287)
+		static_ltree[n++].Len = 8, bl_count[8]++;
+	/* Codes 286 and 287 do not exist, but we must include them in the
+	 * tree construction to get a canonical Huffman tree (longest code
+	 * all ones)
+	 */
+	gen_codes((ct_data *) static_ltree, L_CODES + 1);
+
+	/* The static distance tree is trivial: */
+	for (n = 0; n < D_CODES; n++) {
+		static_dtree[n].Len = 5;
+		static_dtree[n].Code = bi_reverse(n, 5);
+	}
+
+	/* Initialize the first block of the first file: */
+	init_block();
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+static void init_block(void)
+{
+	int n;				/* iterates over tree elements */
+
+	/* Initialize the trees. */
+	for (n = 0; n < L_CODES; n++)
+		dyn_ltree[n].Freq = 0;
+	for (n = 0; n < D_CODES; n++)
+		dyn_dtree[n].Freq = 0;
+	for (n = 0; n < BL_CODES; n++)
+		bl_tree[n].Freq = 0;
+
+	dyn_ltree[END_BLOCK].Freq = 1;
+	opt_len = static_len = 0L;
+	last_lit = last_dist = last_flags = 0;
+	flags = 0;
+	flag_bit = 1;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(tree, top) \
+{\
+    top = heap[SMALLEST]; \
+    heap[SMALLEST] = heap[heap_len--]; \
+    pqdownheap(tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m) \
+   (tree[n].Freq < tree[m].Freq || \
+   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+static void pqdownheap(ct_data * tree, int k)
+{
+	int v = heap[k];
+	int j = k << 1;		/* left son of k */
+
+	while (j <= heap_len) {
+		/* Set j to the smallest of the two sons: */
+		if (j < heap_len && smaller(tree, heap[j + 1], heap[j]))
+			j++;
+
+		/* Exit if v is smaller than both sons */
+		if (smaller(tree, v, heap[j]))
+			break;
+
+		/* Exchange v with the smallest son */
+		heap[k] = heap[j];
+		k = j;
+
+		/* And continue down the tree, setting j to the left son of k */
+		j <<= 1;
+	}
+	heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ *    above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ *     array bl_count contains the frequencies for each bit length.
+ *     The length opt_len is updated; static_len is also updated if stree is
+ *     not null.
+ */
+static void gen_bitlen(tree_desc * desc)
+{
+	ct_data *tree = desc->dyn_tree;
+	const extra_bits_t *extra = desc->extra_bits;
+	int base = desc->extra_base;
+	int max_code = desc->max_code;
+	int max_length = desc->max_length;
+	ct_data *stree = desc->static_tree;
+	int h;				/* heap index */
+	int n, m;			/* iterate over the tree elements */
+	int bits;			/* bit length */
+	int xbits;			/* extra bits */
+	ush f;				/* frequency */
+	int overflow = 0;	/* number of elements with bit length too large */
+
+	for (bits = 0; bits <= MAX_BITS; bits++)
+		bl_count[bits] = 0;
+
+	/* In a first pass, compute the optimal bit lengths (which may
+	 * overflow in the case of the bit length tree).
+	 */
+	tree[heap[heap_max]].Len = 0;	/* root of the heap */
+
+	for (h = heap_max + 1; h < HEAP_SIZE; h++) {
+		n = heap[h];
+		bits = tree[tree[n].Dad].Len + 1;
+		if (bits > max_length)
+			bits = max_length, overflow++;
+		tree[n].Len = (ush) bits;
+		/* We overwrite tree[n].Dad which is no longer needed */
+
+		if (n > max_code)
+			continue;	/* not a leaf node */
+
+		bl_count[bits]++;
+		xbits = 0;
+		if (n >= base)
+			xbits = extra[n - base];
+		f = tree[n].Freq;
+		opt_len += (ulg) f *(bits + xbits);
+
+		if (stree)
+			static_len += (ulg) f *(stree[n].Len + xbits);
+	}
+	if (overflow == 0)
+		return;
+
+	Trace((stderr, "\nbit length overflow\n"));
+	/* This happens for example on obj2 and pic of the Calgary corpus */
+
+	/* Find the first bit length which could increase: */
+	do {
+		bits = max_length - 1;
+		while (bl_count[bits] == 0)
+			bits--;
+		bl_count[bits]--;	/* move one leaf down the tree */
+		bl_count[bits + 1] += 2;	/* move one overflow item as its brother */
+		bl_count[max_length]--;
+		/* The brother of the overflow item also moves one step up,
+		 * but this does not affect bl_count[max_length]
+		 */
+		overflow -= 2;
+	} while (overflow > 0);
+
+	/* Now recompute all bit lengths, scanning in increasing frequency.
+	 * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+	 * lengths instead of fixing only the wrong ones. This idea is taken
+	 * from 'ar' written by Haruhiko Okumura.)
+	 */
+	for (bits = max_length; bits != 0; bits--) {
+		n = bl_count[bits];
+		while (n != 0) {
+			m = heap[--h];
+			if (m > max_code)
+				continue;
+			if (tree[m].Len != (unsigned) bits) {
+				Trace((stderr, "code %d bits %d->%d\n", m, tree[m].Len,
+					   bits));
+				opt_len +=
+					((long) bits - (long) tree[m].Len) * (long) tree[m].Freq;
+				tree[m].Len = (ush) bits;
+			}
+			n--;
+		}
+	}
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ *     zero code length.
+ */
+static void gen_codes(ct_data * tree, int max_code)
+{
+	ush next_code[MAX_BITS + 1];	/* next code value for each bit length */
+	ush code = 0;		/* running code value */
+	int bits;			/* bit index */
+	int n;				/* code index */
+
+	/* The distribution counts are first used to generate the code values
+	 * without bit reversal.
+	 */
+	for (bits = 1; bits <= MAX_BITS; bits++) {
+		next_code[bits] = code = (code + bl_count[bits - 1]) << 1;
+	}
+	/* Check that the bit counts in bl_count are consistent. The last code
+	 * must be all ones.
+	 */
+	Assert(code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1,
+		   "inconsistent bit counts");
+	Tracev((stderr, "\ngen_codes: max_code %d ", max_code));
+
+	for (n = 0; n <= max_code; n++) {
+		int len = tree[n].Len;
+
+		if (len == 0)
+			continue;
+		/* Now reverse the bits */
+		tree[n].Code = bi_reverse(next_code[len]++, len);
+
+		Tracec(tree != static_ltree,
+			   (stderr, "\nn %3d %c l %2d c %4x (%x) ", n,
+				(isgraph(n) ? n : ' '), len, tree[n].Code,
+				next_code[len] - 1));
+	}
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ *     and corresponding code. The length opt_len is updated; static_len is
+ *     also updated if stree is not null. The field max_code is set.
+ */
+static void build_tree(tree_desc * desc)
+{
+	ct_data *tree = desc->dyn_tree;
+	ct_data *stree = desc->static_tree;
+	int elems = desc->elems;
+	int n, m;			/* iterate over heap elements */
+	int max_code = -1;	/* largest code with non zero frequency */
+	int node = elems;	/* next internal node of the tree */
+
+	/* Construct the initial heap, with least frequent element in
+	 * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+	 * heap[0] is not used.
+	 */
+	heap_len = 0, heap_max = HEAP_SIZE;
+
+	for (n = 0; n < elems; n++) {
+		if (tree[n].Freq != 0) {
+			heap[++heap_len] = max_code = n;
+			depth[n] = 0;
+		} else {
+			tree[n].Len = 0;
+		}
+	}
+
+	/* The pkzip format requires that at least one distance code exists,
+	 * and that at least one bit should be sent even if there is only one
+	 * possible code. So to avoid special checks later on we force at least
+	 * two codes of non zero frequency.
+	 */
+	while (heap_len < 2) {
+		int new = heap[++heap_len] = (max_code < 2 ? ++max_code : 0);
+
+		tree[new].Freq = 1;
+		depth[new] = 0;
+		opt_len--;
+		if (stree)
+			static_len -= stree[new].Len;
+		/* new is 0 or 1 so it does not have extra bits */
+	}
+	desc->max_code = max_code;
+
+	/* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+	 * establish sub-heaps of increasing lengths:
+	 */
+	for (n = heap_len / 2; n >= 1; n--)
+		pqdownheap(tree, n);
+
+	/* Construct the Huffman tree by repeatedly combining the least two
+	 * frequent nodes.
+	 */
+	do {
+		pqremove(tree, n);	/* n = node of least frequency */
+		m = heap[SMALLEST];	/* m = node of next least frequency */
+
+		heap[--heap_max] = n;	/* keep the nodes sorted by frequency */
+		heap[--heap_max] = m;
+
+		/* Create a new node father of n and m */
+		tree[node].Freq = tree[n].Freq + tree[m].Freq;
+		depth[node] = (uch) (MAX(depth[n], depth[m]) + 1);
+		tree[n].Dad = tree[m].Dad = (ush) node;
+#ifdef DUMP_BL_TREE
+		if (tree == bl_tree) {
+			bb_error_msg("\nnode %d(%d), sons %d(%d) %d(%d)",
+					node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+		}
+#endif
+		/* and insert the new node in the heap */
+		heap[SMALLEST] = node++;
+		pqdownheap(tree, SMALLEST);
+
+	} while (heap_len >= 2);
+
+	heap[--heap_max] = heap[SMALLEST];
+
+	/* At this point, the fields freq and dad are set. We can now
+	 * generate the bit lengths.
+	 */
+	gen_bitlen((tree_desc *) desc);
+
+	/* The field len is now set, we can generate the bit codes */
+	gen_codes((ct_data *) tree, max_code);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree. Updates opt_len to take into account the repeat
+ * counts. (The contribution of the bit length codes will be added later
+ * during the construction of bl_tree.)
+ */
+static void scan_tree(ct_data * tree, int max_code)
+{
+	int n;				/* iterates over all tree elements */
+	int prevlen = -1;	/* last emitted length */
+	int curlen;			/* length of current code */
+	int nextlen = tree[0].Len;	/* length of next code */
+	int count = 0;		/* repeat count of the current code */
+	int max_count = 7;	/* max repeat count */
+	int min_count = 4;	/* min repeat count */
+
+	if (nextlen == 0)
+		max_count = 138, min_count = 3;
+	tree[max_code + 1].Len = (ush) 0xffff;	/* guard */
+
+	for (n = 0; n <= max_code; n++) {
+		curlen = nextlen;
+		nextlen = tree[n + 1].Len;
+		if (++count < max_count && curlen == nextlen) {
+			continue;
+		} else if (count < min_count) {
+			bl_tree[curlen].Freq += count;
+		} else if (curlen != 0) {
+			if (curlen != prevlen)
+				bl_tree[curlen].Freq++;
+			bl_tree[REP_3_6].Freq++;
+		} else if (count <= 10) {
+			bl_tree[REPZ_3_10].Freq++;
+		} else {
+			bl_tree[REPZ_11_138].Freq++;
+		}
+		count = 0;
+		prevlen = curlen;
+		if (nextlen == 0) {
+			max_count = 138, min_count = 3;
+		} else if (curlen == nextlen) {
+			max_count = 6, min_count = 3;
+		} else {
+			max_count = 7, min_count = 4;
+		}
+	}
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+static void send_tree(ct_data * tree, int max_code)
+{
+	int n;				/* iterates over all tree elements */
+	int prevlen = -1;	/* last emitted length */
+	int curlen;			/* length of current code */
+	int nextlen = tree[0].Len;	/* length of next code */
+	int count = 0;		/* repeat count of the current code */
+	int max_count = 7;	/* max repeat count */
+	int min_count = 4;	/* min repeat count */
+
+/* tree[max_code+1].Len = -1; *//* guard already set */
+	if (nextlen == 0)
+		max_count = 138, min_count = 3;
+
+	for (n = 0; n <= max_code; n++) {
+		curlen = nextlen;
+		nextlen = tree[n + 1].Len;
+		if (++count < max_count && curlen == nextlen) {
+			continue;
+		} else if (count < min_count) {
+			do {
+				send_code(curlen, bl_tree);
+			} while (--count != 0);
+
+		} else if (curlen != 0) {
+			if (curlen != prevlen) {
+				send_code(curlen, bl_tree);
+				count--;
+			}
+			Assert(count >= 3 && count <= 6, " 3_6?");
+			send_code(REP_3_6, bl_tree);
+			send_bits(count - 3, 2);
+
+		} else if (count <= 10) {
+			send_code(REPZ_3_10, bl_tree);
+			send_bits(count - 3, 3);
+
+		} else {
+			send_code(REPZ_11_138, bl_tree);
+			send_bits(count - 11, 7);
+		}
+		count = 0;
+		prevlen = curlen;
+		if (nextlen == 0) {
+			max_count = 138, min_count = 3;
+		} else if (curlen == nextlen) {
+			max_count = 6, min_count = 3;
+		} else {
+			max_count = 7, min_count = 4;
+		}
+	}
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+static int build_bl_tree(void)
+{
+	int max_blindex;	/* index of last bit length code of non zero freq */
+
+	/* Determine the bit length frequencies for literal and distance trees */
+	scan_tree((ct_data *) dyn_ltree, l_desc.max_code);
+	scan_tree((ct_data *) dyn_dtree, d_desc.max_code);
+
+	/* Build the bit length tree: */
+	build_tree((tree_desc *) (&bl_desc));
+	/* opt_len now includes the length of the tree representations, except
+	 * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+	 */
+
+	/* Determine the number of bit length codes to send. The pkzip format
+	 * requires that at least 4 bit length codes be sent. (appnote.txt says
+	 * 3 but the actual value used is 4.)
+	 */
+	for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
+		if (bl_tree[bl_order[max_blindex]].Len != 0)
+			break;
+	}
+	/* Update opt_len to include the bit length tree and counts */
+	opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
+	Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", opt_len, static_len));
+
+	return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+static void send_all_trees(int lcodes, int dcodes, int blcodes)
+{
+	int rank;			/* index in bl_order */
+
+	Assert(lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+	Assert(lcodes <= L_CODES && dcodes <= D_CODES
+		   && blcodes <= BL_CODES, "too many codes");
+	Tracev((stderr, "\nbl counts: "));
+	send_bits(lcodes - 257, 5);	/* not +255 as stated in appnote.txt */
+	send_bits(dcodes - 1, 5);
+	send_bits(blcodes - 4, 4);	/* not -3 as stated in appnote.txt */
+	for (rank = 0; rank < blcodes; rank++) {
+		Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+		send_bits(bl_tree[bl_order[rank]].Len, 3);
+	}
+	Tracev((stderr, "\nbl tree: sent %ld", bits_sent));
+
+	send_tree((ct_data *) dyn_ltree, lcodes - 1);	/* send the literal tree */
+	Tracev((stderr, "\nlit tree: sent %ld", bits_sent));
+
+	send_tree((ct_data *) dyn_dtree, dcodes - 1);	/* send the distance tree */
+	Tracev((stderr, "\ndist tree: sent %ld", bits_sent));
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file. This function
+ * returns the total compressed length for the file so far.
+ */
+static ulg flush_block(char *buf, ulg stored_len, int eof)
+{
+	ulg opt_lenb, static_lenb;	/* opt_len and static_len in bytes */
+	int max_blindex;	/* index of last bit length code of non zero freq */
+
+	flag_buf[last_flags] = flags;	/* Save the flags for the last 8 items */
+
+	/* Check if the file is ascii or binary */
+	if (*file_type == (ush) UNKNOWN)
+		set_file_type();
+
+	/* Construct the literal and distance trees */
+	build_tree((tree_desc *) (&l_desc));
+	Tracev((stderr, "\nlit data: dyn %ld, stat %ld", opt_len, static_len));
+
+	build_tree((tree_desc *) (&d_desc));
+	Tracev((stderr, "\ndist data: dyn %ld, stat %ld", opt_len, static_len));
+	/* At this point, opt_len and static_len are the total bit lengths of
+	 * the compressed block data, excluding the tree representations.
+	 */
+
+	/* Build the bit length tree for the above two trees, and get the index
+	 * in bl_order of the last bit length code to send.
+	 */
+	max_blindex = build_bl_tree();
+
+	/* Determine the best encoding. Compute first the block length in bytes */
+	opt_lenb = (opt_len + 3 + 7) >> 3;
+	static_lenb = (static_len + 3 + 7) >> 3;
+
+	Trace((stderr,
+		   "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ",
+		   opt_lenb, opt_len, static_lenb, static_len, stored_len,
+		   last_lit, last_dist));
+
+	if (static_lenb <= opt_lenb)
+		opt_lenb = static_lenb;
+
+	/* If compression failed and this is the first and last block,
+	 * and if the zip file can be seeked (to rewrite the local header),
+	 * the whole file is transformed into a stored file:
+	 */
+	if (stored_len <= opt_lenb && eof && compressed_len == 0L && seekable()) {
+		/* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
+		if (buf == (char *) 0)
+			bb_error_msg("block vanished");
+
+		copy_block(buf, (unsigned) stored_len, 0);	/* without header */
+		compressed_len = stored_len << 3;
+		*file_method = STORED;
+
+	} else if (stored_len + 4 <= opt_lenb && buf != (char *) 0) {
+		/* 4: two words for the lengths */
+		/* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+		 * Otherwise we can't have processed more than WSIZE input bytes since
+		 * the last block flush, because compression would have been
+		 * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+		 * transform a block into a stored block.
+		 */
+		send_bits((STORED_BLOCK << 1) + eof, 3);	/* send block type */
+		compressed_len = (compressed_len + 3 + 7) & ~7L;
+		compressed_len += (stored_len + 4) << 3;
+
+		copy_block(buf, (unsigned) stored_len, 1);	/* with header */
+
+	} else if (static_lenb == opt_lenb) {
+		send_bits((STATIC_TREES << 1) + eof, 3);
+		compress_block((ct_data *) static_ltree, (ct_data *) static_dtree);
+		compressed_len += 3 + static_len;
+	} else {
+		send_bits((DYN_TREES << 1) + eof, 3);
+		send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1,
+					   max_blindex + 1);
+		compress_block((ct_data *) dyn_ltree, (ct_data *) dyn_dtree);
+		compressed_len += 3 + opt_len;
+	}
+	Assert(compressed_len == bits_sent, "bad compressed size");
+	init_block();
+
+	if (eof) {
+		bi_windup();
+		compressed_len += 7;	/* align on byte boundary */
+	}
+	Tracev((stderr, "\ncomprlen %lu(%lu) ", compressed_len >> 3,
+			compressed_len - 7 * eof));
+
+	return compressed_len >> 3;
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+static int ct_tally(int dist, int lc)
+{
+	l_buf[last_lit++] = (uch) lc;
+	if (dist == 0) {
+		/* lc is the unmatched char */
+		dyn_ltree[lc].Freq++;
+	} else {
+		/* Here, lc is the match length - MIN_MATCH */
+		dist--;			/* dist = match distance - 1 */
+		Assert((ush) dist < (ush) MAX_DIST &&
+			   (ush) lc <= (ush) (MAX_MATCH - MIN_MATCH) &&
+			   (ush) d_code(dist) < (ush) D_CODES, "ct_tally: bad match");
+
+		dyn_ltree[length_code[lc] + LITERALS + 1].Freq++;
+		dyn_dtree[d_code(dist)].Freq++;
+
+		d_buf[last_dist++] = (ush) dist;
+		flags |= flag_bit;
+	}
+	flag_bit <<= 1;
+
+	/* Output the flags if they fill a byte: */
+	if ((last_lit & 7) == 0) {
+		flag_buf[last_flags++] = flags;
+		flags = 0, flag_bit = 1;
+	}
+	/* Try to guess if it is profitable to stop the current block here */
+	if ((last_lit & 0xfff) == 0) {
+		/* Compute an upper bound for the compressed length */
+		ulg out_length = (ulg) last_lit * 8L;
+		ulg in_length = (ulg) strstart - block_start;
+		int dcode;
+
+		for (dcode = 0; dcode < D_CODES; dcode++) {
+			out_length +=
+				(ulg) dyn_dtree[dcode].Freq * (5L + extra_dbits[dcode]);
+		}
+		out_length >>= 3;
+		Trace((stderr,
+			   "\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ",
+			   last_lit, last_dist, in_length, out_length,
+			   100L - out_length * 100L / in_length));
+		if (last_dist < last_lit / 2 && out_length < in_length / 2)
+			return 1;
+	}
+	return (last_lit == LIT_BUFSIZE - 1 || last_dist == DIST_BUFSIZE);
+	/* We avoid equality with LIT_BUFSIZE because of wraparound at 64K
+	 * on 16 bit machines and because stored blocks are restricted to
+	 * 64K-1 bytes.
+	 */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+static void compress_block(ct_data * ltree, ct_data * dtree)
+{
+	unsigned dist;		/* distance of matched string */
+	int lc;				/* match length or unmatched char (if dist == 0) */
+	unsigned lx = 0;	/* running index in l_buf */
+	unsigned dx = 0;	/* running index in d_buf */
+	unsigned fx = 0;	/* running index in flag_buf */
+	uch flag = 0;		/* current flags */
+	unsigned code;		/* the code to send */
+	int extra;			/* number of extra bits to send */
+
+	if (last_lit != 0)
+		do {
+			if ((lx & 7) == 0)
+				flag = flag_buf[fx++];
+			lc = l_buf[lx++];
+			if ((flag & 1) == 0) {
+				send_code(lc, ltree);	/* send a literal byte */
+				Tracecv(isgraph(lc), (stderr, " '%c' ", lc));
+			} else {
+				/* Here, lc is the match length - MIN_MATCH */
+				code = length_code[lc];
+				send_code(code + LITERALS + 1, ltree);	/* send the length code */
+				extra = extra_lbits[code];
+				if (extra != 0) {
+					lc -= base_length[code];
+					send_bits(lc, extra);	/* send the extra length bits */
+				}
+				dist = d_buf[dx++];
+				/* Here, dist is the match distance - 1 */
+				code = d_code(dist);
+				Assert(code < D_CODES, "bad d_code");
+
+				send_code(code, dtree);	/* send the distance code */
+				extra = extra_dbits[code];
+				if (extra != 0) {
+					dist -= base_dist[code];
+					send_bits(dist, extra);	/* send the extra distance bits */
+				}
+			}			/* literal or match pair ? */
+			flag >>= 1;
+		} while (lx < last_lit);
+
+	send_code(END_BLOCK, ltree);
+}
+
+/* ===========================================================================
+ * Set the file type to ASCII or BINARY, using a crude approximation:
+ * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ * IN assertion: the fields freq of dyn_ltree are set and the total of all
+ * frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ */
+static void set_file_type(void)
+{
+	int n = 0;
+	unsigned ascii_freq = 0;
+	unsigned bin_freq = 0;
+
+	while (n < 7)
+		bin_freq += dyn_ltree[n++].Freq;
+	while (n < 128)
+		ascii_freq += dyn_ltree[n++].Freq;
+	while (n < LITERALS)
+		bin_freq += dyn_ltree[n++].Freq;
+	*file_type = bin_freq > (ascii_freq >> 2) ? BINARY : ASCII;
+	if (*file_type == BINARY && translate_eol) {
+		bb_error_msg("-l used on binary file");
+	}
+}
+
+/* zip.c -- compress files to the gzip or pkzip format
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+
+static uint32_t crc;			/* crc on uncompressed file data */
+static long header_bytes;	/* number of bytes in gzip header */
+
+static void put_long(ulg n)
+{
+	put_short((n) & 0xffff);
+	put_short(((ulg) (n)) >> 16);
+}
+
+/* put_header_byte is used for the compressed output
+ * - for the initial 4 bytes that can't overflow the buffer.
+ */
+#define put_header_byte(c) {outbuf[outcnt++]=(uch)(c);}
+
+/* ===========================================================================
+ * Deflate in to out.
+ * IN assertions: the input and output buffers are cleared.
+ *   The variables time_stamp and save_orig_name are initialized.
+ */
+static int zip(int in, int out)
+{
+	uch my_flags = 0;	/* general purpose bit flags */
+	ush attr = 0;		/* ascii/binary flag */
+	ush deflate_flags = 0;	/* pkzip -es, -en or -ex equivalent */
+
+	ifd = in;
+	ofd = out;
+	outcnt = 0;
+
+	/* Write the header to the gzip file. See algorithm.doc for the format */
+
+
+	method = DEFLATED;
+	put_header_byte(GZIP_MAGIC[0]);	/* magic header */
+	put_header_byte(GZIP_MAGIC[1]);
+	put_header_byte(DEFLATED);	/* compression method */
+
+	put_header_byte(my_flags);	/* general flags */
+	put_long(time_stamp);
+
+	/* Write deflated file to zip file */
+	crc = updcrc(0, 0);
+
+	bi_init(out);
+	ct_init(&attr, &method);
+	lm_init(&deflate_flags);
+
+	put_byte((uch) deflate_flags);	/* extra flags */
+	put_byte(OS_CODE);	/* OS identifier */
+
+	header_bytes = (long) outcnt;
+
+	(void) deflate();
+
+	/* Write the crc and uncompressed size */
+	put_long(crc);
+	put_long(isize);
+	header_bytes += 2 * sizeof(long);
+
+	flush_outbuf();
+	return OK;
+}
+
+
+/* ===========================================================================
+ * Read a new buffer from the current input file, perform end-of-line
+ * translation, and update the crc and input file size.
+ * IN assertion: size >= 2 (for end-of-line translation)
+ */
+static int file_read(char *buf, unsigned size)
+{
+	unsigned len;
+
+	Assert(insize == 0, "inbuf not empty");
+
+	len = read(ifd, buf, size);
+	if (len == (unsigned) (-1) || len == 0)
+		return (int) len;
+
+	crc = updcrc((uch *) buf, len);
+	isize += (ulg) len;
+	return (int) len;
+}
+
+/* ===========================================================================
+ * Write the output buffer outbuf[0..outcnt-1] and update bytes_out.
+ * (used for the compressed data only)
+ */
+static void flush_outbuf(void)
+{
+	if (outcnt == 0)
+		return;
+
+	write_buf(ofd, (char *) outbuf, outcnt);
+	outcnt = 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,36 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+ifndef top_srcdir
+top_srcdir=../..
+endif
+ifndef top_builddir
+top_builddir=../..
+endif
+srcdir=$(top_srcdir)/archival/libunarchive
+LIBUNARCHIVE_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include $(srcdir)/Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,84 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+
+LIBUNARCHIVE_AR:=libunarchive.a
+ifndef $(LIBUNARCHIVE_DIR)
+LIBUNARCHIVE_DIR:=$(top_builddir)/archival/libunarchive
+endif
+srcdir=$(top_srcdir)/archival/libunarchive
+
+LIBUNARCHIVE-obj:=$(LIBUNARCHIVE_DIR)/$(LIBUNARCHIVE_AR)
+
+libraries-y+=$(LIBUNARCHIVE-obj)
+
+LIBUNARCHIVE-y:= \
+\
+	data_skip.o \
+	data_extract_all.o \
+	data_extract_to_stdout.o \
+	data_extract_to_buffer.o \
+\
+	filter_accept_all.o \
+	filter_accept_list.o \
+	filter_accept_reject_list.o \
+\
+	header_skip.o \
+	header_list.o \
+	header_verbose_list.o \
+\
+	archive_xread_all.o \
+	archive_xread_all_eof.o \
+\
+	seek_by_char.o \
+	seek_by_jump.o \
+\
+	data_align.o \
+	find_list_entry.o \
+	open_transformer.o \
+	init_handle.o
+
+GUNZIP_FILES:= check_header_gzip.o decompress_unzip.o
+DPKG_FILES:= \
+	get_header_ar.o \
+	unpack_ar_archive.o \
+	get_header_tar.o \
+	filter_accept_list_reassign.o
+
+LIBUNARCHIVE-$(CONFIG_AR) += get_header_ar.o unpack_ar_archive.o
+LIBUNARCHIVE-$(CONFIG_BUNZIP2) += decompress_bunzip2.o
+LIBUNARCHIVE-$(CONFIG_UNLZMA) += decompress_unlzma.o
+LIBUNARCHIVE-$(CONFIG_CPIO) += get_header_cpio.o
+LIBUNARCHIVE-$(CONFIG_DPKG) += $(DPKG_FILES)
+LIBUNARCHIVE-$(CONFIG_DPKG_DEB) += $(DPKG_FILES)
+LIBUNARCHIVE-$(CONFIG_FEATURE_DEB_TAR_GZ) += $(GUNZIP_FILES) get_header_tar_gz.o
+LIBUNARCHIVE-$(CONFIG_FEATURE_DEB_TAR_BZ2) += decompress_bunzip2.o get_header_tar_bz2.o
+LIBUNARCHIVE-$(CONFIG_FEATURE_DEB_TAR_LZMA) += decompress_unlzma.o get_header_tar_lzma.o
+LIBUNARCHIVE-$(CONFIG_GUNZIP) += $(GUNZIP_FILES)
+LIBUNARCHIVE-$(CONFIG_FEATURE_GUNZIP_UNCOMPRESS) += decompress_uncompress.o
+LIBUNARCHIVE-$(CONFIG_RPM2CPIO) += $(GUNZIP_FILES) get_header_cpio.o
+LIBUNARCHIVE-$(CONFIG_RPM) += $(GUNZIP_FILES) get_header_cpio.o
+LIBUNARCHIVE-$(CONFIG_TAR) += get_header_tar.o
+LIBUNARCHIVE-$(CONFIG_FEATURE_TAR_BZIP2) += decompress_bunzip2.o get_header_tar_bz2.o
+LIBUNARCHIVE-$(CONFIG_FEATURE_TAR_LZMA) += decompress_unlzma.o get_header_tar_lzma.o
+LIBUNARCHIVE-$(CONFIG_FEATURE_TAR_GZIP) += $(GUNZIP_FILES) get_header_tar_gz.o
+LIBUNARCHIVE-$(CONFIG_FEATURE_TAR_COMPRESS) += decompress_uncompress.o
+LIBUNARCHIVE-$(CONFIG_UNCOMPRESS) += decompress_uncompress.o
+LIBUNARCHIVE-$(CONFIG_UNZIP) += $(GUNZIP_FILES)
+LIBUNARCHIVE-$(CONFIG_FEATURE_COMPRESS_USAGE) += decompress_bunzip2.o
+
+
+LIBUNARCHIVE-y:=$(sort $(LIBUNARCHIVE-y))
+
+LIBUNARCHIVE_SRC-y:=$(patsubst %,$(srcdir)/%,$(subst .o,.c,$(LIBUNARCHIVE-y)))
+LIBUNARCHIVE_SRC-a:=$(wildcard $(srcdir)/*.c)
+LIBRARY_SRC-y+=$(LIBUNARCHIVE_SRC-y)
+LIBRARY_SRC-a+=$(LIBUNARCHIVE_SRC-a)
+
+$(LIBUNARCHIVE_DIR)/$(LIBUNARCHIVE_AR): $(patsubst %,$(LIBUNARCHIVE_DIR)/%,$(LIBUNARCHIVE-y))
+	$(do_ar)
+
+$(LIBUNARCHIVE_DIR)/%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/archive_xread_all.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/archive_xread_all.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/archive_xread_all.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,32 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "unarchive.h"
+#include "libbb.h"
+
+void archive_xread_all(const archive_handle_t *archive_handle, void *buf, const size_t count)
+{
+	ssize_t size;
+
+	size = bb_full_read(archive_handle->src_fd, buf, count);
+	if (size != count) {
+		bb_error_msg_and_die("Short read");
+	}
+	return;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/archive_xread_all_eof.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/archive_xread_all_eof.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/archive_xread_all_eof.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,32 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "unarchive.h"
+#include "libbb.h"
+
+ssize_t archive_xread_all_eof(archive_handle_t *archive_handle, unsigned char *buf, size_t count)
+{
+	ssize_t size;
+
+	size = bb_full_read(archive_handle->src_fd, buf, count);
+	if ((size != 0) && (size != count)) {
+		bb_perror_msg_and_die("Short read, read %ld of %ld", (long)size, (long)count);
+	}
+	return(size);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/check_header_gzip.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/check_header_gzip.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/check_header_gzip.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,58 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include "libbb.h"
+#include "unarchive.h" /* for external decl of check_header_gzip */
+
+void check_header_gzip(int src_fd)
+{
+	union {
+		unsigned char raw[8];
+		struct {
+			unsigned char method;
+			unsigned char flags;
+			unsigned int mtime;
+			unsigned char xtra_flags;
+			unsigned char os_flags;
+		} formated;
+	} header;
+
+	bb_xread_all(src_fd, header.raw, 8);
+
+	/* Check the compression method */
+	if (header.formated.method != 8) {
+		bb_error_msg_and_die("Unknown compression method %d",
+						  header.formated.method);
+	}
+
+	if (header.formated.flags & 0x04) {
+		/* bit 2 set: extra field present */
+		unsigned char extra_short;
+
+		extra_short = bb_xread_char(src_fd) + (bb_xread_char(src_fd) << 8);
+		while (extra_short > 0) {
+			/* Ignore extra field */
+			bb_xread_char(src_fd);
+			extra_short--;
+		}
+	}
+
+	/* Discard original name if any */
+	if (header.formated.flags & 0x08) {
+		/* bit 3 set: original file name present */
+		while(bb_xread_char(src_fd) != 0);
+	}
+
+	/* Discard file comment if any */
+	if (header.formated.flags & 0x10) {
+		/* bit 4 set: file comment present */
+		while(bb_xread_char(src_fd) != 0);
+	}
+
+	/* Read the header checksum */
+	if (header.formated.flags & 0x02) {
+		bb_xread_char(src_fd);
+		bb_xread_char(src_fd);
+	}
+
+	return;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_align.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_align.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_align.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,33 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include "libbb.h"
+#include "unarchive.h"
+
+void data_align(archive_handle_t *archive_handle, const unsigned short boundary)
+{
+	const unsigned short skip_amount = (boundary - (archive_handle->offset % boundary)) % boundary;
+
+	archive_handle->seek(archive_handle, skip_amount);
+	archive_handle->offset += skip_amount;
+
+	return;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_extract_all.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_extract_all.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_extract_all.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,128 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <utime.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "libbb.h"
+#include "unarchive.h"
+
+void data_extract_all(archive_handle_t *archive_handle)
+{
+	file_header_t *file_header = archive_handle->file_header;
+	int dst_fd;
+	int res;
+
+	if (archive_handle->flags & ARCHIVE_CREATE_LEADING_DIRS) {
+		char *name = bb_xstrdup(file_header->name);
+		bb_make_directory (dirname(name), -1, FILEUTILS_RECUR);
+		free(name);
+	}
+
+	/* Check if the file already exists */
+	if (archive_handle->flags & ARCHIVE_EXTRACT_UNCONDITIONAL) {
+		/* Remove the existing entry if it exists */
+		if (((file_header->mode & S_IFMT) != S_IFDIR) && (unlink(file_header->name) == -1) && (errno != ENOENT)) {
+			bb_perror_msg_and_die("Couldnt remove old file");
+		}
+	}
+	else if (archive_handle->flags & ARCHIVE_EXTRACT_NEWER) {
+		/* Remove the existing entry if its older than the extracted entry */
+		struct stat statbuf;
+		if (lstat(file_header->name, &statbuf) == -1) {
+			if (errno != ENOENT) {
+				bb_perror_msg_and_die("Couldnt stat old file");
+			}
+		}
+		else if (statbuf.st_mtime <= file_header->mtime) {
+			if (!(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
+				bb_error_msg("%s not created: newer or same age file exists", file_header->name);
+			}
+			data_skip(archive_handle);
+			return;
+		}
+		else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {
+			bb_perror_msg_and_die("Couldnt remove old file %s", file_header->name);
+		}
+	}
+
+	/* Handle hard links separately
+	 * We identified hard links as regular files of size 0 with a symlink */
+	if (S_ISREG(file_header->mode) && (file_header->link_name) && (file_header->size == 0)) {
+		/* hard link */
+		res = link(file_header->link_name, file_header->name);
+		if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
+			bb_perror_msg("Couldnt create hard link");
+		}
+	} else {
+		/* Create the filesystem entry */
+		switch(file_header->mode & S_IFMT) {
+			case S_IFREG: {
+				/* Regular file */
+				dst_fd = bb_xopen(file_header->name, O_WRONLY | O_CREAT | O_EXCL);
+				bb_copyfd_size(archive_handle->src_fd, dst_fd, file_header->size);
+				close(dst_fd);
+				break;
+				}
+			case S_IFDIR:
+				res = mkdir(file_header->name, file_header->mode);
+				if ((errno != EISDIR) && (res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
+					bb_perror_msg("extract_archive: %s", file_header->name);
+				}
+				break;
+			case S_IFLNK:
+				/* Symlink */
+				res = symlink(file_header->link_name, file_header->name);
+				if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
+					bb_perror_msg("Cannot create symlink from %s to '%s'", file_header->name, file_header->link_name);
+				}
+				break;
+			case S_IFSOCK:
+			case S_IFBLK:
+			case S_IFCHR:
+			case S_IFIFO:
+				res = mknod(file_header->name, file_header->mode, file_header->device);
+				if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
+					bb_perror_msg("Cannot create node %s", file_header->name);
+				}
+				break;
+			default:
+				bb_error_msg_and_die("Unrecognised file type");
+		}
+	}
+
+	if (!(archive_handle->flags & ARCHIVE_NOPRESERVE_OWN)) {
+		lchown(file_header->name, file_header->uid, file_header->gid);
+	}
+	if (!(archive_handle->flags & ARCHIVE_NOPRESERVE_PERM) &&
+		 (file_header->mode & S_IFMT) != S_IFLNK)
+	{
+		chmod(file_header->name, file_header->mode);
+	}
+
+	if (archive_handle->flags & ARCHIVE_PRESERVE_DATE) {
+		struct utimbuf t;
+		t.actime = t.modtime = file_header->mtime;
+		utime(file_header->name, &t);
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_extract_to_buffer.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_extract_to_buffer.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_extract_to_buffer.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2002 Glenn McGrath
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "unarchive.h"
+
+void data_extract_to_buffer(archive_handle_t *archive_handle)
+{
+	const unsigned int size = archive_handle->file_header->size;
+
+	archive_handle->buffer = xzalloc(size + 1);
+
+	archive_xread_all(archive_handle, archive_handle->buffer, size);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_extract_to_stdout.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_extract_to_stdout.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_extract_to_stdout.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "unarchive.h"
+#include <unistd.h>
+
+void data_extract_to_stdout(archive_handle_t *archive_handle)
+{
+	bb_copyfd_size(archive_handle->src_fd, STDOUT_FILENO, archive_handle->file_header->size);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_skip.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_skip.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/data_skip.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,27 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "unarchive.h"
+#include "libbb.h"
+
+void data_skip(archive_handle_t *archive_handle)
+{
+	archive_handle->seek(archive_handle, archive_handle->file_header->size);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/decompress_bunzip2.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/decompress_bunzip2.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/decompress_bunzip2.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,735 @@
+/* vi: set sw=4 ts=4: */
+/* Small bzip2 deflate implementation, by Rob Landley (rob at landley.net).
+
+   Based on bzip2 decompression code by Julian R Seward (jseward at acm.org),
+   which also acknowledges contributions by Mike Burrows, David Wheeler,
+   Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten,
+   Robert Sedgewick, and Jon L. Bentley.
+
+   Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+*/
+
+/*
+	Size and speed optimizations by Manuel Novoa III  (mjn3 at codepoet.org).
+
+	More efficient reading of Huffman codes, a streamlined read_bunzip()
+	function, and various other tweaks.  In (limited) tests, approximately
+	20% faster than bzcat on x86 and about 10% faster on arm.
+
+	Note that about 2/3 of the time is spent in read_unzip() reversing
+	the Burrows-Wheeler transformation.  Much of that time is delay
+	resulting from cache misses.
+
+	I would ask that anyone benefiting from this work, especially those
+	using it in commercial products, consider making a donation to my local
+	non-profit hospice organization (www.hospiceacadiana.com) in the name of
+	the woman I loved, Toni W. Hagan, who passed away Feb. 12, 2003.
+
+	Manuel
+ */
+
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "libbb.h"
+
+#include "unarchive.h"
+
+/* Constants for Huffman coding */
+#define MAX_GROUPS			6
+#define GROUP_SIZE			50		/* 64 would have been more efficient */
+#define MAX_HUFCODE_BITS	20		/* Longest Huffman code allowed */
+#define MAX_SYMBOLS			258		/* 256 literals + RUNA + RUNB */
+#define SYMBOL_RUNA			0
+#define SYMBOL_RUNB			1
+
+/* Status return values */
+#define RETVAL_OK						0
+#define RETVAL_LAST_BLOCK				(-1)
+#define RETVAL_NOT_BZIP_DATA			(-2)
+#define RETVAL_UNEXPECTED_INPUT_EOF		(-3)
+#define RETVAL_UNEXPECTED_OUTPUT_EOF	(-4)
+#define RETVAL_DATA_ERROR				(-5)
+#define RETVAL_OUT_OF_MEMORY			(-6)
+#define RETVAL_OBSOLETE_INPUT			(-7)
+
+/* Other housekeeping constants */
+#define IOBUF_SIZE			4096
+
+/* This is what we know about each Huffman coding group */
+struct group_data {
+	/* We have an extra slot at the end of limit[] for a sentinal value. */
+	int limit[MAX_HUFCODE_BITS+1],base[MAX_HUFCODE_BITS],permute[MAX_SYMBOLS];
+	int minLen, maxLen;
+};
+
+/* Structure holding all the housekeeping data, including IO buffers and
+   memory that persists between calls to bunzip */
+
+typedef struct {
+	/* State for interrupting output loop */
+
+	int writeCopies,writePos,writeRunCountdown,writeCount,writeCurrent;
+
+	/* I/O tracking data (file handles, buffers, positions, etc.) */
+
+	int in_fd,out_fd,inbufCount,inbufPos /*,outbufPos*/;
+	unsigned char *inbuf /*,*outbuf*/;
+	unsigned int inbufBitCount, inbufBits;
+
+	/* The CRC values stored in the block header and calculated from the data */
+
+	uint32_t headerCRC, totalCRC, writeCRC;
+	uint32_t *crc32Table;
+	/* Intermediate buffer and its size (in bytes) */
+
+	unsigned int *dbuf, dbufSize;
+
+	/* These things are a bit too big to go on the stack */
+
+	unsigned char selectors[32768];			/* nSelectors=15 bits */
+	struct group_data groups[MAX_GROUPS];	/* Huffman coding tables */
+
+	/* For I/O error handling */
+
+	jmp_buf jmpbuf;
+} bunzip_data;
+
+/* Return the next nnn bits of input.  All reads from the compressed input
+   are done through this function.  All reads are big endian */
+
+static unsigned int get_bits(bunzip_data *bd, char bits_wanted)
+{
+	unsigned int bits=0;
+
+	/* If we need to get more data from the byte buffer, do so.  (Loop getting
+	   one byte at a time to enforce endianness and avoid unaligned access.) */
+
+	while (bd->inbufBitCount<bits_wanted) {
+
+		/* If we need to read more data from file into byte buffer, do so */
+
+		if(bd->inbufPos==bd->inbufCount) {
+			if((bd->inbufCount = read(bd->in_fd, bd->inbuf, IOBUF_SIZE)) <= 0)
+				longjmp(bd->jmpbuf,RETVAL_UNEXPECTED_INPUT_EOF);
+			bd->inbufPos=0;
+		}
+
+		/* Avoid 32-bit overflow (dump bit buffer to top of output) */
+
+		if(bd->inbufBitCount>=24) {
+			bits=bd->inbufBits&((1<<bd->inbufBitCount)-1);
+			bits_wanted-=bd->inbufBitCount;
+			bits<<=bits_wanted;
+			bd->inbufBitCount=0;
+		}
+
+		/* Grab next 8 bits of input from buffer. */
+
+		bd->inbufBits=(bd->inbufBits<<8)|bd->inbuf[bd->inbufPos++];
+		bd->inbufBitCount+=8;
+	}
+
+	/* Calculate result */
+
+	bd->inbufBitCount-=bits_wanted;
+	bits|=(bd->inbufBits>>bd->inbufBitCount)&((1<<bits_wanted)-1);
+
+	return bits;
+}
+
+/* Unpacks the next block and sets up for the inverse burrows-wheeler step. */
+
+static int get_next_block(bunzip_data *bd)
+{
+	struct group_data *hufGroup;
+	int dbufCount,nextSym,dbufSize,groupCount,*base,*limit,selector,
+		i,j,k,t,runPos,symCount,symTotal,nSelectors,byteCount[256];
+	unsigned char uc, symToByte[256], mtfSymbol[256], *selectors;
+	unsigned int *dbuf,origPtr;
+
+	dbuf=bd->dbuf;
+	dbufSize=bd->dbufSize;
+	selectors=bd->selectors;
+
+	/* Reset longjmp I/O error handling */
+
+	i=setjmp(bd->jmpbuf);
+	if(i) return i;
+
+	/* Read in header signature and CRC, then validate signature.
+	   (last block signature means CRC is for whole file, return now) */
+
+	i = get_bits(bd,24);
+	j = get_bits(bd,24);
+	bd->headerCRC=get_bits(bd,32);
+	if ((i == 0x177245) && (j == 0x385090)) return RETVAL_LAST_BLOCK;
+	if ((i != 0x314159) || (j != 0x265359)) return RETVAL_NOT_BZIP_DATA;
+
+	/* We can add support for blockRandomised if anybody complains.  There was
+	   some code for this in busybox 1.0.0-pre3, but nobody ever noticed that
+	   it didn't actually work. */
+
+	if(get_bits(bd,1)) return RETVAL_OBSOLETE_INPUT;
+	if((origPtr=get_bits(bd,24)) > dbufSize) return RETVAL_DATA_ERROR;
+
+	/* mapping table: if some byte values are never used (encoding things
+	   like ascii text), the compression code removes the gaps to have fewer
+	   symbols to deal with, and writes a sparse bitfield indicating which
+	   values were present.  We make a translation table to convert the symbols
+	   back to the corresponding bytes. */
+
+	t=get_bits(bd, 16);
+	symTotal=0;
+	for (i=0;i<16;i++) {
+		if(t&(1<<(15-i))) {
+			k=get_bits(bd,16);
+			for(j=0;j<16;j++)
+				if(k&(1<<(15-j))) symToByte[symTotal++]=(16*i)+j;
+		}
+	}
+
+	/* How many different Huffman coding groups does this block use? */
+
+	groupCount=get_bits(bd,3);
+	if (groupCount<2 || groupCount>MAX_GROUPS) return RETVAL_DATA_ERROR;
+
+	/* nSelectors: Every GROUP_SIZE many symbols we select a new Huffman coding
+	   group.  Read in the group selector list, which is stored as MTF encoded
+	   bit runs.  (MTF=Move To Front, as each value is used it's moved to the
+	   start of the list.) */
+
+	if(!(nSelectors=get_bits(bd, 15))) return RETVAL_DATA_ERROR;
+	for(i=0; i<groupCount; i++) mtfSymbol[i] = i;
+	for(i=0; i<nSelectors; i++) {
+
+		/* Get next value */
+
+		for(j=0;get_bits(bd,1);j++) if (j>=groupCount) return RETVAL_DATA_ERROR;
+
+		/* Decode MTF to get the next selector */
+
+		uc = mtfSymbol[j];
+		for(;j;j--) mtfSymbol[j] = mtfSymbol[j-1];
+		mtfSymbol[0]=selectors[i]=uc;
+	}
+
+	/* Read the Huffman coding tables for each group, which code for symTotal
+	   literal symbols, plus two run symbols (RUNA, RUNB) */
+
+	symCount=symTotal+2;
+	for (j=0; j<groupCount; j++) {
+		unsigned char length[MAX_SYMBOLS],temp[MAX_HUFCODE_BITS+1];
+		int	minLen,	maxLen, pp;
+
+		/* Read Huffman code lengths for each symbol.  They're stored in
+		   a way similar to mtf; record a starting value for the first symbol,
+		   and an offset from the previous value for everys symbol after that.
+		   (Subtracting 1 before the loop and then adding it back at the end is
+		   an optimization that makes the test inside the loop simpler: symbol
+		   length 0 becomes negative, so an unsigned inequality catches it.) */
+
+		t=get_bits(bd, 5)-1;
+		for (i = 0; i < symCount; i++) {
+			for(;;) {
+				if (((unsigned)t) > (MAX_HUFCODE_BITS-1))
+					return RETVAL_DATA_ERROR;
+
+				/* If first bit is 0, stop.  Else second bit indicates whether
+				   to increment or decrement the value.  Optimization: grab 2
+				   bits and unget the second if the first was 0. */
+
+				k = get_bits(bd,2);
+				if (k < 2) {
+					bd->inbufBitCount++;
+					break;
+				}
+
+				/* Add one if second bit 1, else subtract 1.  Avoids if/else */
+
+				t+=(((k+1)&2)-1);
+			}
+
+			/* Correct for the initial -1, to get the final symbol length */
+
+			length[i]=t+1;
+		}
+
+		/* Find largest and smallest lengths in this group */
+
+		minLen=maxLen=length[0];
+		for(i = 1; i < symCount; i++) {
+			if(length[i] > maxLen) maxLen = length[i];
+			else if(length[i] < minLen) minLen = length[i];
+		}
+
+		/* Calculate permute[], base[], and limit[] tables from length[].
+		 *
+		 * permute[] is the lookup table for converting Huffman coded symbols
+		 * into decoded symbols.  base[] is the amount to subtract from the
+		 * value of a Huffman symbol of a given length when using permute[].
+		 *
+		 * limit[] indicates the largest numerical value a symbol with a given
+		 * number of bits can have.  This is how the Huffman codes can vary in
+		 * length: each code with a value>limit[length] needs another bit.
+		 */
+
+		hufGroup=bd->groups+j;
+		hufGroup->minLen = minLen;
+		hufGroup->maxLen = maxLen;
+
+		/* Note that minLen can't be smaller than 1, so we adjust the base
+		   and limit array pointers so we're not always wasting the first
+		   entry.  We do this again when using them (during symbol decoding).*/
+
+		base=hufGroup->base-1;
+		limit=hufGroup->limit-1;
+
+		/* Calculate permute[].  Concurently, initialize temp[] and limit[]. */
+
+		pp=0;
+		for(i=minLen;i<=maxLen;i++) {
+			temp[i]=limit[i]=0;
+			for(t=0;t<symCount;t++)
+				if(length[t]==i) hufGroup->permute[pp++] = t;
+		}
+
+		/* Count symbols coded for at each bit length */
+
+		for (i=0;i<symCount;i++) temp[length[i]]++;
+
+		/* Calculate limit[] (the largest symbol-coding value at each bit
+		 * length, which is (previous limit<<1)+symbols at this level), and
+		 * base[] (number of symbols to ignore at each bit length, which is
+		 * limit minus the cumulative count of symbols coded for already). */
+
+		pp=t=0;
+		for (i=minLen; i<maxLen; i++) {
+			pp+=temp[i];
+
+			/* We read the largest possible symbol size and then unget bits
+			   after determining how many we need, and those extra bits could
+			   be set to anything.  (They're noise from future symbols.)  At
+			   each level we're really only interested in the first few bits,
+			   so here we set all the trailing to-be-ignored bits to 1 so they
+			   don't affect the value>limit[length] comparison. */
+
+			limit[i]= (pp << (maxLen - i)) - 1;
+			pp<<=1;
+			base[i+1]=pp-(t+=temp[i]);
+		}
+		limit[maxLen+1] = INT_MAX; /* Sentinal value for reading next sym. */
+		limit[maxLen]=pp+temp[maxLen]-1;
+		base[minLen]=0;
+	}
+
+	/* We've finished reading and digesting the block header.  Now read this
+	   block's Huffman coded symbols from the file and undo the Huffman coding
+	   and run length encoding, saving the result into dbuf[dbufCount++]=uc */
+
+	/* Initialize symbol occurrence counters and symbol Move To Front table */
+
+	for(i=0;i<256;i++) {
+		byteCount[i] = 0;
+		mtfSymbol[i]=(unsigned char)i;
+	}
+
+	/* Loop through compressed symbols. */
+
+	runPos=dbufCount=selector=0;
+	for(;;) {
+
+		/* fetch next Huffman coding group from list. */
+
+		symCount=GROUP_SIZE-1;
+		if(selector>=nSelectors) return RETVAL_DATA_ERROR;
+		hufGroup=bd->groups+selectors[selector++];
+		base=hufGroup->base-1;
+		limit=hufGroup->limit-1;
+continue_this_group:
+
+		/* Read next Huffman-coded symbol. */
+
+		/* Note: It is far cheaper to read maxLen bits and back up than it is
+		   to read minLen bits and then an additional bit at a time, testing
+		   as we go.  Because there is a trailing last block (with file CRC),
+		   there is no danger of the overread causing an unexpected EOF for a
+		   valid compressed file.  As a further optimization, we do the read
+		   inline (falling back to a call to get_bits if the buffer runs
+		   dry).  The following (up to got_huff_bits:) is equivalent to
+		   j=get_bits(bd,hufGroup->maxLen);
+		 */
+
+		while (bd->inbufBitCount<hufGroup->maxLen) {
+			if(bd->inbufPos==bd->inbufCount) {
+				j = get_bits(bd,hufGroup->maxLen);
+				goto got_huff_bits;
+			}
+			bd->inbufBits=(bd->inbufBits<<8)|bd->inbuf[bd->inbufPos++];
+			bd->inbufBitCount+=8;
+		};
+		bd->inbufBitCount-=hufGroup->maxLen;
+		j = (bd->inbufBits>>bd->inbufBitCount)&((1<<hufGroup->maxLen)-1);
+
+got_huff_bits:
+
+		/* Figure how how many bits are in next symbol and unget extras */
+
+		i=hufGroup->minLen;
+		while(j>limit[i]) ++i;
+		bd->inbufBitCount += (hufGroup->maxLen - i);
+
+		/* Huffman decode value to get nextSym (with bounds checking) */
+
+		if ((i > hufGroup->maxLen)
+			|| (((unsigned)(j=(j>>(hufGroup->maxLen-i))-base[i]))
+				>= MAX_SYMBOLS))
+			return RETVAL_DATA_ERROR;
+		nextSym = hufGroup->permute[j];
+
+		/* We have now decoded the symbol, which indicates either a new literal
+		   byte, or a repeated run of the most recent literal byte.  First,
+		   check if nextSym indicates a repeated run, and if so loop collecting
+		   how many times to repeat the last literal. */
+
+		if (((unsigned)nextSym) <= SYMBOL_RUNB) { /* RUNA or RUNB */
+
+			/* If this is the start of a new run, zero out counter */
+
+			if(!runPos) {
+				runPos = 1;
+				t = 0;
+			}
+
+			/* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at
+			   each bit position, add 1 or 2 instead.  For example,
+			   1011 is 1<<0 + 1<<1 + 2<<2.  1010 is 2<<0 + 2<<1 + 1<<2.
+			   You can make any bit pattern that way using 1 less symbol than
+			   the basic or 0/1 method (except all bits 0, which would use no
+			   symbols, but a run of length 0 doesn't mean anything in this
+			   context).  Thus space is saved. */
+
+			t += (runPos << nextSym); /* +runPos if RUNA; +2*runPos if RUNB */
+			if(runPos < dbufSize) runPos <<= 1;
+			goto end_of_huffman_loop;
+		}
+
+		/* When we hit the first non-run symbol after a run, we now know
+		   how many times to repeat the last literal, so append that many
+		   copies to our buffer of decoded symbols (dbuf) now.  (The last
+		   literal used is the one at the head of the mtfSymbol array.) */
+
+		if(runPos) {
+			runPos=0;
+			if(dbufCount+t>=dbufSize) return RETVAL_DATA_ERROR;
+
+			uc = symToByte[mtfSymbol[0]];
+			byteCount[uc] += t;
+			while(t--) dbuf[dbufCount++]=uc;
+		}
+
+		/* Is this the terminating symbol? */
+
+		if(nextSym>symTotal) break;
+
+		/* At this point, nextSym indicates a new literal character.  Subtract
+		   one to get the position in the MTF array at which this literal is
+		   currently to be found.  (Note that the result can't be -1 or 0,
+		   because 0 and 1 are RUNA and RUNB.  But another instance of the
+		   first symbol in the mtf array, position 0, would have been handled
+		   as part of a run above.  Therefore 1 unused mtf position minus
+		   2 non-literal nextSym values equals -1.) */
+
+		if(dbufCount>=dbufSize) return RETVAL_DATA_ERROR;
+		i = nextSym - 1;
+		uc = mtfSymbol[i];
+
+		/* Adjust the MTF array.  Since we typically expect to move only a
+		 * small number of symbols, and are bound by 256 in any case, using
+		 * memmove here would typically be bigger and slower due to function
+		 * call overhead and other assorted setup costs. */
+
+		do {
+			mtfSymbol[i] = mtfSymbol[i-1];
+		} while (--i);
+		mtfSymbol[0] = uc;
+		uc=symToByte[uc];
+
+		/* We have our literal byte.  Save it into dbuf. */
+
+		byteCount[uc]++;
+		dbuf[dbufCount++] = (unsigned int)uc;
+
+		/* Skip group initialization if we're not done with this group.  Done
+		 * this way to avoid compiler warning. */
+
+end_of_huffman_loop:
+		if(symCount--) goto continue_this_group;
+	}
+
+	/* At this point, we've read all the Huffman-coded symbols (and repeated
+       runs) for this block from the input stream, and decoded them into the
+	   intermediate buffer.  There are dbufCount many decoded bytes in dbuf[].
+	   Now undo the Burrows-Wheeler transform on dbuf.
+	   See http://dogma.net/markn/articles/bwt/bwt.htm
+	 */
+
+	/* Turn byteCount into cumulative occurrence counts of 0 to n-1. */
+
+	j=0;
+	for(i=0;i<256;i++) {
+		k=j+byteCount[i];
+		byteCount[i] = j;
+		j=k;
+	}
+
+	/* Figure out what order dbuf would be in if we sorted it. */
+
+	for (i=0;i<dbufCount;i++) {
+		uc=(unsigned char)(dbuf[i] & 0xff);
+		dbuf[byteCount[uc]] |= (i << 8);
+		byteCount[uc]++;
+	}
+
+	/* Decode first byte by hand to initialize "previous" byte.  Note that it
+	   doesn't get output, and if the first three characters are identical
+	   it doesn't qualify as a run (hence writeRunCountdown=5). */
+
+	if(dbufCount) {
+		if(origPtr>=dbufCount) return RETVAL_DATA_ERROR;
+		bd->writePos=dbuf[origPtr];
+	    bd->writeCurrent=(unsigned char)(bd->writePos&0xff);
+		bd->writePos>>=8;
+		bd->writeRunCountdown=5;
+	}
+	bd->writeCount=dbufCount;
+
+	return RETVAL_OK;
+}
+
+/* Undo burrows-wheeler transform on intermediate buffer to produce output.
+   If start_bunzip was initialized with out_fd=-1, then up to len bytes of
+   data are written to outbuf.  Return value is number of bytes written or
+   error (all errors are negative numbers).  If out_fd!=-1, outbuf and len
+   are ignored, data is written to out_fd and return is RETVAL_OK or error.
+*/
+
+static int read_bunzip(bunzip_data *bd, char *outbuf, int len)
+{
+	const unsigned int *dbuf;
+	int pos,current,previous,gotcount;
+
+	/* If last read was short due to end of file, return last block now */
+	if(bd->writeCount<0) return bd->writeCount;
+
+	gotcount = 0;
+	dbuf=bd->dbuf;
+	pos=bd->writePos;
+	current=bd->writeCurrent;
+
+	/* We will always have pending decoded data to write into the output
+	   buffer unless this is the very first call (in which case we haven't
+	   Huffman-decoded a block into the intermediate buffer yet). */
+
+	if (bd->writeCopies) {
+
+		/* Inside the loop, writeCopies means extra copies (beyond 1) */
+
+		--bd->writeCopies;
+
+		/* Loop outputting bytes */
+
+		for(;;) {
+
+			/* If the output buffer is full, snapshot state and return */
+
+			if(gotcount >= len) {
+				bd->writePos=pos;
+				bd->writeCurrent=current;
+				bd->writeCopies++;
+				return len;
+			}
+
+			/* Write next byte into output buffer, updating CRC */
+
+			outbuf[gotcount++] = current;
+			bd->writeCRC=(((bd->writeCRC)<<8)
+						  ^bd->crc32Table[((bd->writeCRC)>>24)^current]);
+
+			/* Loop now if we're outputting multiple copies of this byte */
+
+			if (bd->writeCopies) {
+				--bd->writeCopies;
+				continue;
+			}
+decode_next_byte:
+			if (!bd->writeCount--) break;
+			/* Follow sequence vector to undo Burrows-Wheeler transform */
+			previous=current;
+			pos=dbuf[pos];
+			current=pos&0xff;
+			pos>>=8;
+
+			/* After 3 consecutive copies of the same byte, the 4th is a repeat
+			   count.  We count down from 4 instead
+			 * of counting up because testing for non-zero is faster */
+
+			if(--bd->writeRunCountdown) {
+				if(current!=previous) bd->writeRunCountdown=4;
+			} else {
+
+				/* We have a repeated run, this byte indicates the count */
+
+				bd->writeCopies=current;
+				current=previous;
+				bd->writeRunCountdown=5;
+
+				/* Sometimes there are just 3 bytes (run length 0) */
+
+				if(!bd->writeCopies) goto decode_next_byte;
+
+				/* Subtract the 1 copy we'd output anyway to get extras */
+
+				--bd->writeCopies;
+			}
+		}
+
+		/* Decompression of this block completed successfully */
+
+		bd->writeCRC=~bd->writeCRC;
+		bd->totalCRC=((bd->totalCRC<<1) | (bd->totalCRC>>31)) ^ bd->writeCRC;
+
+		/* If this block had a CRC error, force file level CRC error. */
+
+		if(bd->writeCRC!=bd->headerCRC) {
+			bd->totalCRC=bd->headerCRC+1;
+			return RETVAL_LAST_BLOCK;
+		}
+	}
+
+	/* Refill the intermediate buffer by Huffman-decoding next block of input */
+	/* (previous is just a convenient unused temp variable here) */
+
+	previous=get_next_block(bd);
+	if(previous) {
+		bd->writeCount=previous;
+		return (previous!=RETVAL_LAST_BLOCK) ? previous : gotcount;
+	}
+	bd->writeCRC=~0;
+	pos=bd->writePos;
+	current=bd->writeCurrent;
+	goto decode_next_byte;
+}
+
+/* Allocate the structure, read file header.  If in_fd==-1, inbuf must contain
+   a complete bunzip file (len bytes long).  If in_fd!=-1, inbuf and len are
+   ignored, and data is read from file handle into temporary buffer. */
+
+static int start_bunzip(bunzip_data **bdp, int in_fd, unsigned char *inbuf,
+						int len)
+{
+	bunzip_data *bd;
+	unsigned int i;
+	const unsigned int BZh0=(((unsigned int)'B')<<24)+(((unsigned int)'Z')<<16)
+							+(((unsigned int)'h')<<8)+(unsigned int)'0';
+
+	/* Figure out how much data to allocate */
+
+	i=sizeof(bunzip_data);
+	if(in_fd!=-1) i+=IOBUF_SIZE;
+
+	/* Allocate bunzip_data.  Most fields initialize to zero. */
+
+	bd=*bdp=xzalloc(i);
+
+	/* Setup input buffer */
+
+	if(-1==(bd->in_fd=in_fd)) {
+		bd->inbuf=inbuf;
+		bd->inbufCount=len;
+	} else bd->inbuf=(unsigned char *)(bd+1);
+
+	/* Init the CRC32 table (big endian) */
+
+	bd->crc32Table = bb_crc32_filltable(1);
+
+	/* Setup for I/O error handling via longjmp */
+
+	i=setjmp(bd->jmpbuf);
+	if(i) return i;
+
+	/* Ensure that file starts with "BZh['1'-'9']." */
+
+	i = get_bits(bd,32);
+	if (((unsigned int)(i-BZh0-1)) >= 9) return RETVAL_NOT_BZIP_DATA;
+
+	/* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of
+	   uncompressed data.  Allocate intermediate buffer for block. */
+
+	bd->dbufSize=100000*(i-BZh0);
+
+	bd->dbuf=xmalloc(bd->dbufSize * sizeof(int));
+	return RETVAL_OK;
+}
+
+/* Example usage: decompress src_fd to dst_fd.  (Stops at end of bzip data,
+   not end of file.) */
+
+int uncompressStream(int src_fd, int dst_fd)
+{
+	char *outbuf;
+	bunzip_data *bd;
+	int i;
+
+	outbuf=xmalloc(IOBUF_SIZE);
+	if(!(i=start_bunzip(&bd,src_fd,0,0))) {
+		for(;;) {
+			if((i=read_bunzip(bd,outbuf,IOBUF_SIZE)) <= 0) break;
+			if(i!=write(dst_fd,outbuf,i)) {
+				i=RETVAL_UNEXPECTED_OUTPUT_EOF;
+				break;
+			}
+		}
+	}
+
+	/* Check CRC and release memory */
+
+	if(i==RETVAL_LAST_BLOCK) {
+		if (bd->headerCRC!=bd->totalCRC) {
+			bb_error_msg("Data integrity error when decompressing.");
+		} else {
+			i=RETVAL_OK;
+		}
+	} else if (i==RETVAL_UNEXPECTED_OUTPUT_EOF) {
+		bb_error_msg("Compressed file ends unexpectedly");
+	} else {
+		bb_error_msg("Decompression failed");
+	}
+	free(bd->dbuf);
+	free(bd);
+	free(outbuf);
+
+	return i;
+}
+
+#ifdef TESTING
+
+static char * const bunzip_errors[]={NULL,"Bad file checksum","Not bzip data",
+		"Unexpected input EOF","Unexpected output EOF","Data error",
+		 "Out of memory","Obsolete (pre 0.9.5) bzip format not supported."};
+
+/* Dumb little test thing, decompress stdin to stdout */
+int main(int argc, char *argv[])
+{
+	int i=uncompressStream(0,1);
+	char c;
+
+	if(i) fprintf(stderr,"%s\n", bunzip_errors[-i]);
+    else if(read(0,&c,1)) fprintf(stderr,"Trailing garbage ignored\n");
+	return -i;
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/decompress_uncompress.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/decompress_uncompress.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/decompress_uncompress.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,289 @@
+#include "libbb.h"
+
+/* uncompress for busybox -- (c) 2002 Robert Griebl
+ *
+ * based on the original compress42.c source
+ * (see disclaimer below)
+ */
+
+
+/* (N)compress42.c - File compression ala IEEE Computer, Mar 1992.
+ *
+ * Authors:
+ *   Spencer W. Thomas   (decvax!harpo!utah-cs!utah-gr!thomas)
+ *   Jim McKie           (decvax!mcvax!jim)
+ *   Steve Davies        (decvax!vax135!petsd!peora!srd)
+ *   Ken Turkowski       (decvax!decwrl!turtlevax!ken)
+ *   James A. Woods      (decvax!ihnp4!ames!jaw)
+ *   Joe Orost           (decvax!vax135!petsd!joe)
+ *   Dave Mack           (csu at alembic.acs.com)
+ *   Peter Jannesen, Network Communication Systems
+ *                       (peter at ncs.nl)
+ *
+ * marc at suse.de : a small security fix for a buffer overflow
+ *
+ * [... History snipped ...]
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Default input buffer size */
+#define	IBUFSIZ	2048
+
+/* Default output buffer size */
+#define	OBUFSIZ	2048
+
+/* Defines for third byte of header */
+#define	MAGIC_1		(char_type)'\037'	/* First byte of compressed file               */
+#define	MAGIC_2		(char_type)'\235'	/* Second byte of compressed file              */
+#define BIT_MASK	0x1f	/* Mask for 'number of compresssion bits'       */
+							/* Masks 0x20 and 0x40 are free.                */
+							/* I think 0x20 should mean that there is       */
+							/* a fourth header byte (for expansion).        */
+#define BLOCK_MODE	0x80	/* Block compresssion if table is full and      */
+			/* compression rate is dropping flush tables    */
+			/* the next two codes should not be changed lightly, as they must not   */
+			/* lie within the contiguous general code space.                        */
+#define FIRST	257		/* first free entry                             */
+#define	CLEAR	256		/* table clear output code                      */
+
+#define INIT_BITS 9		/* initial number of bits/code */
+
+
+/* machine variants which require cc -Dmachine:  pdp11, z8000, DOS */
+#define FAST
+
+#define	HBITS		17	/* 50% occupancy */
+#define	HSIZE	   (1<<HBITS)
+#define	HMASK	   (HSIZE-1)
+#define	HPRIME		 9941
+#define	BITS		   16
+#undef	MAXSEG_64K
+#define MAXCODE(n)	(1L << (n))
+
+/* Block compress mode -C compatible with 2.0 */
+static int block_mode = BLOCK_MODE;
+
+/* user settable max # bits/code */
+static int maxbits = BITS;
+
+/* Input buffer */
+static unsigned char inbuf[IBUFSIZ + 64];
+
+/* Output buffer */
+static unsigned char outbuf[OBUFSIZ + 2048];
+
+
+static unsigned char htab[HSIZE];
+static unsigned short codetab[HSIZE];
+
+#define	htabof(i)				htab[i]
+#define	codetabof(i)			codetab[i]
+#define	tab_prefixof(i)			codetabof(i)
+#define	tab_suffixof(i)			((unsigned char *)(htab))[i]
+#define	de_stack				((unsigned char *)&(htab[HSIZE-1]))
+#define	clear_htab()			memset(htab, -1, sizeof(htab))
+#define	clear_tab_prefixof()	memset(codetab, 0, 256);
+
+
+/*
+ * Decompress stdin to stdout.  This routine adapts to the codes in the
+ * file building the "string" table on-the-fly; requiring no table to
+ * be stored in the compressed file.  The tables used herein are shared
+ * with those of the compress() routine.  See the definitions above.
+ */
+
+int uncompress(int fd_in, int fd_out)
+{
+	unsigned char *stackp;
+	long int code;
+	int finchar;
+	long int oldcode;
+	long int incode;
+	int inbits;
+	int posbits;
+	int outpos;
+	int insize;
+	int bitmask;
+	long int free_ent;
+	long int maxcode;
+	long int maxmaxcode;
+	int n_bits;
+	int rsize = 0;
+
+	insize = 0;
+
+	inbuf[0] = bb_xread_char(fd_in);
+
+	maxbits = inbuf[0] & BIT_MASK;
+	block_mode = inbuf[0] & BLOCK_MODE;
+	maxmaxcode = MAXCODE(maxbits);
+
+	if (maxbits > BITS) {
+		bb_error_msg("compressed with %d bits, can only handle %d bits", maxbits,
+				  BITS);
+		return -1;
+	}
+
+	maxcode = MAXCODE(n_bits = INIT_BITS) - 1;
+	bitmask = (1 << n_bits) - 1;
+	oldcode = -1;
+	finchar = 0;
+	outpos = 0;
+	posbits = 0 << 3;
+
+	free_ent = ((block_mode) ? FIRST : 256);
+
+	/* As above, initialize the first 256 entries in the table. */
+	clear_tab_prefixof();
+
+	for (code = 255; code >= 0; --code) {
+		tab_suffixof(code) = (unsigned char) code;
+	}
+
+	do {
+	  resetbuf:;
+		{
+			int i;
+			int e;
+			int o;
+
+			e = insize - (o = (posbits >> 3));
+
+			for (i = 0; i < e; ++i)
+				inbuf[i] = inbuf[i + o];
+
+			insize = e;
+			posbits = 0;
+		}
+
+		if (insize < (int) sizeof(inbuf) - IBUFSIZ) {
+			rsize = safe_read(fd_in, inbuf + insize, IBUFSIZ);
+			insize += rsize;
+		}
+
+		inbits = ((rsize > 0) ? (insize - insize % n_bits) << 3 :
+				  (insize << 3) - (n_bits - 1));
+
+		while (inbits > posbits) {
+			if (free_ent > maxcode) {
+				posbits =
+					((posbits - 1) +
+					 ((n_bits << 3) -
+					  (posbits - 1 + (n_bits << 3)) % (n_bits << 3)));
+				++n_bits;
+				if (n_bits == maxbits) {
+					maxcode = maxmaxcode;
+				} else {
+					maxcode = MAXCODE(n_bits) - 1;
+				}
+				bitmask = (1 << n_bits) - 1;
+				goto resetbuf;
+			}
+			{
+				unsigned char *p = &inbuf[posbits >> 3];
+
+				code =
+					((((long) (p[0])) | ((long) (p[1]) << 8) |
+					  ((long) (p[2]) << 16)) >> (posbits & 0x7)) & bitmask;
+			}
+			posbits += n_bits;
+
+
+			if (oldcode == -1) {
+				outbuf[outpos++] = (unsigned char) (finchar =
+												(int) (oldcode = code));
+				continue;
+			}
+
+			if (code == CLEAR && block_mode) {
+				clear_tab_prefixof();
+				free_ent = FIRST - 1;
+				posbits =
+					((posbits - 1) +
+					 ((n_bits << 3) -
+					  (posbits - 1 + (n_bits << 3)) % (n_bits << 3)));
+				maxcode = MAXCODE(n_bits = INIT_BITS) - 1;
+				bitmask = (1 << n_bits) - 1;
+				goto resetbuf;
+			}
+
+			incode = code;
+			stackp = de_stack;
+
+			/* Special case for KwKwK string. */
+			if (code >= free_ent) {
+				if (code > free_ent) {
+					unsigned char *p;
+
+					posbits -= n_bits;
+					p = &inbuf[posbits >> 3];
+
+					bb_error_msg
+						("insize:%d posbits:%d inbuf:%02X %02X %02X %02X %02X (%d)",
+						 insize, posbits, p[-1], p[0], p[1], p[2], p[3],
+						 (posbits & 07));
+					bb_error_msg("uncompress: corrupt input");
+					return -1;
+				}
+
+				*--stackp = (unsigned char) finchar;
+				code = oldcode;
+			}
+
+			/* Generate output characters in reverse order */
+			while ((long int) code >= (long int) 256) {
+				*--stackp = tab_suffixof(code);
+				code = tab_prefixof(code);
+			}
+
+			*--stackp = (unsigned char) (finchar = tab_suffixof(code));
+
+			/* And put them out in forward order */
+			{
+				int i;
+
+				if (outpos + (i = (de_stack - stackp)) >= OBUFSIZ) {
+					do {
+						if (i > OBUFSIZ - outpos) {
+							i = OBUFSIZ - outpos;
+						}
+
+						if (i > 0) {
+							memcpy(outbuf + outpos, stackp, i);
+							outpos += i;
+						}
+
+						if (outpos >= OBUFSIZ) {
+							write(fd_out, outbuf, outpos);
+							outpos = 0;
+						}
+						stackp += i;
+					} while ((i = (de_stack - stackp)) > 0);
+				} else {
+					memcpy(outbuf + outpos, stackp, i);
+					outpos += i;
+				}
+			}
+
+			/* Generate the new entry. */
+			if ((code = free_ent) < maxmaxcode) {
+				tab_prefixof(code) = (unsigned short) oldcode;
+				tab_suffixof(code) = (unsigned char) finchar;
+				free_ent = code + 1;
+			}
+
+			/* Remember previous code.  */
+			oldcode = incode;
+		}
+
+	} while (rsize > 0);
+
+	if (outpos > 0) {
+		write(fd_out, outbuf, outpos);
+	}
+
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/decompress_unlzma.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/decompress_unlzma.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/decompress_unlzma.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,471 @@
+/* vi:set ts=4: */
+/*
+ * Small lzma deflate implementation.
+ * Copyright (C) 2006  Aurelien Jacobs <aurel at gnuage.org>
+ *
+ * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/)
+ * Copyright (C) 1999-2005  Igor Pavlov
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "unarchive.h"
+
+#ifdef CONFIG_FEATURE_LZMA_FAST
+#  define speed_inline ATTRIBUTE_ALWAYS_INLINE
+#else
+#  define speed_inline
+#endif
+
+
+typedef struct {
+	int fd;
+	uint8_t *ptr;
+	uint8_t *buffer;
+	uint8_t *buffer_end;
+	int buffer_size;
+	uint32_t code;
+	uint32_t range;
+	uint32_t bound;
+} rc_t;
+
+
+#define RC_TOP_BITS 24
+#define RC_MOVE_BITS 5
+#define RC_MODEL_TOTAL_BITS 11
+
+
+/* Called twice: once at startup and once in rc_normalize() */
+static void rc_read(rc_t * rc)
+{
+	rc->buffer_size = read(rc->fd, rc->buffer, rc->buffer_size);
+	if (rc->buffer_size <= 0)
+		bb_error_msg_and_die("unexpected EOF");
+	rc->ptr = rc->buffer;
+	rc->buffer_end = rc->buffer + rc->buffer_size;
+}
+
+/* Called once */
+static void rc_init(rc_t * rc, int fd, int buffer_size)
+{
+	int i;
+
+	rc->fd = fd;
+	rc->buffer = xmalloc(buffer_size);
+	rc->buffer_size = buffer_size;
+	rc->buffer_end = rc->buffer + rc->buffer_size;
+	rc->ptr = rc->buffer_end;
+
+	rc->code = 0;
+	rc->range = 0xFFFFFFFF;
+	for (i = 0; i < 5; i++) {
+		if (rc->ptr >= rc->buffer_end)
+			rc_read(rc);
+		rc->code = (rc->code << 8) | *rc->ptr++;
+	}
+}
+
+/* Called once. TODO: bb_maybe_free() */
+static ATTRIBUTE_ALWAYS_INLINE void rc_free(rc_t * rc)
+{
+	if (ENABLE_FEATURE_CLEAN_UP)
+		free(rc->buffer);
+}
+
+/* Called twice, but one callsite is in speed_inline'd rc_is_bit_0_helper() */
+static void rc_do_normalize(rc_t * rc)
+{
+	if (rc->ptr >= rc->buffer_end)
+		rc_read(rc);
+	rc->range <<= 8;
+	rc->code = (rc->code << 8) | *rc->ptr++;
+}
+static ATTRIBUTE_ALWAYS_INLINE void rc_normalize(rc_t * rc)
+{
+	if (rc->range < (1 << RC_TOP_BITS)) {
+		rc_do_normalize(rc);
+	}
+}
+
+/* Called 9 times */
+/* Why rc_is_bit_0_helper exists?
+ * Because we want to always expose (rc->code < rc->bound) to optimizer
+ */
+static speed_inline uint32_t rc_is_bit_0_helper(rc_t * rc, uint16_t * p)
+{
+	rc_normalize(rc);
+	rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS);
+	return rc->bound;
+}
+static ATTRIBUTE_ALWAYS_INLINE int rc_is_bit_0(rc_t * rc, uint16_t * p)
+{
+	uint32_t t = rc_is_bit_0_helper(rc, p);
+	return rc->code < t;
+}
+
+/* Called ~10 times, but very small, thus inlined */
+static speed_inline void rc_update_bit_0(rc_t * rc, uint16_t * p)
+{
+	rc->range = rc->bound;
+	*p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS;
+}
+static speed_inline void rc_update_bit_1(rc_t * rc, uint16_t * p)
+{
+	rc->range -= rc->bound;
+	rc->code -= rc->bound;
+	*p -= *p >> RC_MOVE_BITS;
+}
+
+/* Called 4 times in unlzma loop */
+static int rc_get_bit(rc_t * rc, uint16_t * p, int *symbol)
+{
+	if (rc_is_bit_0(rc, p)) {
+		rc_update_bit_0(rc, p);
+		*symbol *= 2;
+		return 0;
+	} else {
+		rc_update_bit_1(rc, p);
+		*symbol = *symbol * 2 + 1;
+		return 1;
+	}
+}
+
+/* Called once */
+static ATTRIBUTE_ALWAYS_INLINE int rc_direct_bit(rc_t * rc)
+{
+	rc_normalize(rc);
+	rc->range >>= 1;
+	if (rc->code >= rc->range) {
+		rc->code -= rc->range;
+		return 1;
+	}
+	return 0;
+}
+
+/* Called twice */
+static speed_inline void
+rc_bit_tree_decode(rc_t * rc, uint16_t * p, int num_levels, int *symbol)
+{
+	int i = num_levels;
+
+	*symbol = 1;
+	while (i--)
+		rc_get_bit(rc, p + *symbol, symbol);
+	*symbol -= 1 << num_levels;
+}
+
+
+typedef struct {
+	uint8_t pos;
+	uint32_t dict_size;
+	uint64_t dst_size;
+} __attribute__ ((packed)) lzma_header_t;
+
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_NUM_POS_BITS_MAX 4
+
+#define LZMA_LEN_NUM_LOW_BITS 3
+#define LZMA_LEN_NUM_MID_BITS 3
+#define LZMA_LEN_NUM_HIGH_BITS 8
+
+#define LZMA_LEN_CHOICE 0
+#define LZMA_LEN_CHOICE_2 (LZMA_LEN_CHOICE + 1)
+#define LZMA_LEN_LOW (LZMA_LEN_CHOICE_2 + 1)
+#define LZMA_LEN_MID (LZMA_LEN_LOW \
+		      + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS)))
+#define LZMA_LEN_HIGH (LZMA_LEN_MID \
+		       +(1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS)))
+#define LZMA_NUM_LEN_PROBS (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS))
+
+#define LZMA_NUM_STATES 12
+#define LZMA_NUM_LIT_STATES 7
+
+#define LZMA_START_POS_MODEL_INDEX 4
+#define LZMA_END_POS_MODEL_INDEX 14
+#define LZMA_NUM_FULL_DISTANCES (1 << (LZMA_END_POS_MODEL_INDEX >> 1))
+
+#define LZMA_NUM_POS_SLOT_BITS 6
+#define LZMA_NUM_LEN_TO_POS_STATES 4
+
+#define LZMA_NUM_ALIGN_BITS 4
+
+#define LZMA_MATCH_MIN_LEN 2
+
+#define LZMA_IS_MATCH 0
+#define LZMA_IS_REP (LZMA_IS_MATCH + (LZMA_NUM_STATES <<LZMA_NUM_POS_BITS_MAX))
+#define LZMA_IS_REP_G0 (LZMA_IS_REP + LZMA_NUM_STATES)
+#define LZMA_IS_REP_G1 (LZMA_IS_REP_G0 + LZMA_NUM_STATES)
+#define LZMA_IS_REP_G2 (LZMA_IS_REP_G1 + LZMA_NUM_STATES)
+#define LZMA_IS_REP_0_LONG (LZMA_IS_REP_G2 + LZMA_NUM_STATES)
+#define LZMA_POS_SLOT (LZMA_IS_REP_0_LONG \
+		       + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX))
+#define LZMA_SPEC_POS (LZMA_POS_SLOT \
+		       +(LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS))
+#define LZMA_ALIGN (LZMA_SPEC_POS \
+		    + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX)
+#define LZMA_LEN_CODER (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS))
+#define LZMA_REP_LEN_CODER (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS)
+#define LZMA_LITERAL (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS)
+
+
+int unlzma(int src_fd, int dst_fd)
+{
+	lzma_header_t header;
+	int lc, pb, lp;
+	uint32_t pos_state_mask;
+	uint32_t literal_pos_mask;
+	uint32_t pos;
+	uint16_t *p;
+	uint16_t *prob;
+	uint16_t *prob_lit;
+	int num_bits;
+	int num_probs;
+	rc_t rc;
+	int i, mi;
+	uint8_t *buffer;
+	uint8_t previous_byte = 0;
+	size_t buffer_pos = 0, global_pos = 0;
+	int len = 0;
+	int state = 0;
+	uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+
+	if (read(src_fd, &header, sizeof(header)) != sizeof(header))
+		bb_error_msg_and_die("can't read header");
+
+	if (header.pos >= (9 * 5 * 5))
+		bb_error_msg_and_die("bad header");
+	mi = header.pos / 9;
+	lc = header.pos % 9;
+	pb = mi / 5;
+	lp = mi % 5;
+	pos_state_mask = (1 << pb) - 1;
+	literal_pos_mask = (1 << lp) - 1;
+
+	header.dict_size = SWAP_LE32(header.dict_size);
+	header.dst_size = SWAP_LE64(header.dst_size);
+
+	if (header.dict_size == 0)
+		header.dict_size = 1;
+
+	buffer = xmalloc(MIN(header.dst_size, header.dict_size));
+
+	num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp));
+	p = xmalloc(num_probs * sizeof(*p));
+	num_probs = LZMA_LITERAL + (LZMA_LIT_SIZE << (lc + lp));
+	for (i = 0; i < num_probs; i++)
+		p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1;
+
+	rc_init(&rc, src_fd, 0x10000);
+
+	while (global_pos + buffer_pos < header.dst_size) {
+		int pos_state = (buffer_pos + global_pos) & pos_state_mask;
+
+		prob =
+			p + LZMA_IS_MATCH + (state << LZMA_NUM_POS_BITS_MAX) + pos_state;
+		if (rc_is_bit_0(&rc, prob)) {
+			mi = 1;
+			rc_update_bit_0(&rc, prob);
+			prob = (p + LZMA_LITERAL + (LZMA_LIT_SIZE
+					* ((((buffer_pos + global_pos) & literal_pos_mask) << lc)
+					+ (previous_byte >> (8 - lc)))));
+
+			if (state >= LZMA_NUM_LIT_STATES) {
+				int match_byte;
+
+				pos = buffer_pos - rep0;
+				while (pos >= header.dict_size)
+					pos += header.dict_size;
+				match_byte = buffer[pos];
+				do {
+					int bit;
+
+					match_byte <<= 1;
+					bit = match_byte & 0x100;
+					prob_lit = prob + 0x100 + bit + mi;
+					if (rc_get_bit(&rc, prob_lit, &mi)) {
+						if (!bit)
+							break;
+					} else {
+						if (bit)
+							break;
+					}
+				} while (mi < 0x100);
+			}
+			while (mi < 0x100) {
+				prob_lit = prob + mi;
+				rc_get_bit(&rc, prob_lit, &mi);
+			}
+			previous_byte = (uint8_t) mi;
+
+			buffer[buffer_pos++] = previous_byte;
+			if (buffer_pos == header.dict_size) {
+				buffer_pos = 0;
+				global_pos += header.dict_size;
+				write(dst_fd, buffer, header.dict_size);
+			}
+			if (state < 4)
+				state = 0;
+			else if (state < 10)
+				state -= 3;
+			else
+				state -= 6;
+		} else {
+			int offset;
+			uint16_t *prob_len;
+
+			rc_update_bit_1(&rc, prob);
+			prob = p + LZMA_IS_REP + state;
+			if (rc_is_bit_0(&rc, prob)) {
+				rc_update_bit_0(&rc, prob);
+				rep3 = rep2;
+				rep2 = rep1;
+				rep1 = rep0;
+				state = state < LZMA_NUM_LIT_STATES ? 0 : 3;
+				prob = p + LZMA_LEN_CODER;
+			} else {
+				rc_update_bit_1(&rc, prob);
+				prob = p + LZMA_IS_REP_G0 + state;
+				if (rc_is_bit_0(&rc, prob)) {
+					rc_update_bit_0(&rc, prob);
+					prob = (p + LZMA_IS_REP_0_LONG
+							+ (state << LZMA_NUM_POS_BITS_MAX) + pos_state);
+					if (rc_is_bit_0(&rc, prob)) {
+						rc_update_bit_0(&rc, prob);
+
+						state = state < LZMA_NUM_LIT_STATES ? 9 : 11;
+						pos = buffer_pos - rep0;
+						while (pos >= header.dict_size)
+							pos += header.dict_size;
+						previous_byte = buffer[pos];
+						buffer[buffer_pos++] = previous_byte;
+						if (buffer_pos == header.dict_size) {
+							buffer_pos = 0;
+							global_pos += header.dict_size;
+							write(dst_fd, buffer, header.dict_size);
+						}
+						continue;
+					} else {
+						rc_update_bit_1(&rc, prob);
+					}
+				} else {
+					uint32_t distance;
+
+					rc_update_bit_1(&rc, prob);
+					prob = p + LZMA_IS_REP_G1 + state;
+					if (rc_is_bit_0(&rc, prob)) {
+						rc_update_bit_0(&rc, prob);
+						distance = rep1;
+					} else {
+						rc_update_bit_1(&rc, prob);
+						prob = p + LZMA_IS_REP_G2 + state;
+						if (rc_is_bit_0(&rc, prob)) {
+							rc_update_bit_0(&rc, prob);
+							distance = rep2;
+						} else {
+							rc_update_bit_1(&rc, prob);
+							distance = rep3;
+							rep3 = rep2;
+						}
+						rep2 = rep1;
+					}
+					rep1 = rep0;
+					rep0 = distance;
+				}
+				state = state < LZMA_NUM_LIT_STATES ? 8 : 11;
+				prob = p + LZMA_REP_LEN_CODER;
+			}
+
+			prob_len = prob + LZMA_LEN_CHOICE;
+			if (rc_is_bit_0(&rc, prob_len)) {
+				rc_update_bit_0(&rc, prob_len);
+				prob_len = (prob + LZMA_LEN_LOW
+							+ (pos_state << LZMA_LEN_NUM_LOW_BITS));
+				offset = 0;
+				num_bits = LZMA_LEN_NUM_LOW_BITS;
+			} else {
+				rc_update_bit_1(&rc, prob_len);
+				prob_len = prob + LZMA_LEN_CHOICE_2;
+				if (rc_is_bit_0(&rc, prob_len)) {
+					rc_update_bit_0(&rc, prob_len);
+					prob_len = (prob + LZMA_LEN_MID
+								+ (pos_state << LZMA_LEN_NUM_MID_BITS));
+					offset = 1 << LZMA_LEN_NUM_LOW_BITS;
+					num_bits = LZMA_LEN_NUM_MID_BITS;
+				} else {
+					rc_update_bit_1(&rc, prob_len);
+					prob_len = prob + LZMA_LEN_HIGH;
+					offset = ((1 << LZMA_LEN_NUM_LOW_BITS)
+							  + (1 << LZMA_LEN_NUM_MID_BITS));
+					num_bits = LZMA_LEN_NUM_HIGH_BITS;
+				}
+			}
+			rc_bit_tree_decode(&rc, prob_len, num_bits, &len);
+			len += offset;
+
+			if (state < 4) {
+				int pos_slot;
+
+				state += LZMA_NUM_LIT_STATES;
+				prob =
+					p + LZMA_POS_SLOT +
+					((len <
+					  LZMA_NUM_LEN_TO_POS_STATES ? len :
+					  LZMA_NUM_LEN_TO_POS_STATES - 1)
+					 << LZMA_NUM_POS_SLOT_BITS);
+				rc_bit_tree_decode(&rc, prob, LZMA_NUM_POS_SLOT_BITS,
+								   &pos_slot);
+				if (pos_slot >= LZMA_START_POS_MODEL_INDEX) {
+					num_bits = (pos_slot >> 1) - 1;
+					rep0 = 2 | (pos_slot & 1);
+					if (pos_slot < LZMA_END_POS_MODEL_INDEX) {
+						rep0 <<= num_bits;
+						prob = p + LZMA_SPEC_POS + rep0 - pos_slot - 1;
+					} else {
+						num_bits -= LZMA_NUM_ALIGN_BITS;
+						while (num_bits--)
+							rep0 = (rep0 << 1) | rc_direct_bit(&rc);
+						prob = p + LZMA_ALIGN;
+						rep0 <<= LZMA_NUM_ALIGN_BITS;
+						num_bits = LZMA_NUM_ALIGN_BITS;
+					}
+					i = 1;
+					mi = 1;
+					while (num_bits--) {
+						if (rc_get_bit(&rc, prob + mi, &mi))
+							rep0 |= i;
+						i <<= 1;
+					}
+				} else
+					rep0 = pos_slot;
+				if (++rep0 == 0)
+					break;
+			}
+
+			len += LZMA_MATCH_MIN_LEN;
+
+			do {
+				pos = buffer_pos - rep0;
+				while (pos >= header.dict_size)
+					pos += header.dict_size;
+				previous_byte = buffer[pos];
+				buffer[buffer_pos++] = previous_byte;
+				if (buffer_pos == header.dict_size) {
+					buffer_pos = 0;
+					global_pos += header.dict_size;
+					write(dst_fd, buffer, header.dict_size);
+				}
+				len--;
+			} while (len != 0 && buffer_pos < header.dst_size);
+		}
+	}
+
+	write(dst_fd, buffer, buffer_pos);
+	rc_free(&rc);
+	return 0;
+}
+
+/* vi:set ts=4: */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/decompress_unzip.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/decompress_unzip.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/decompress_unzip.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,922 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * gunzip implementation for busybox
+ *
+ * Based on GNU gzip v1.2.4 Copyright (C) 1992-1993 Jean-loup Gailly.
+ *
+ * Originally adjusted for busybox by Sven Rudolph <sr1 at inf.tu-dresden.de>
+ * based on gzip sources
+ *
+ * Adjusted further by Erik Andersen <andersen at codepoet.org> to support
+ * files as well as stdin/stdout, and to generally behave itself wrt
+ * command line handling.
+ *
+ * General cleanup to better adhere to the style guide and make use of standard
+ * busybox functions by Glenn McGrath <bug1 at iinet.net.au>
+ *
+ * read_gz interface + associated hacking by Laurence Anderson
+ *
+ * Fixed huft_build() so decoding end-of-block code does not grab more bits
+ * than necessary (this is required by unzip applet), added inflate_cleanup()
+ * to free leaked bytebuffer memory (used in unzip.c), and some minor style
+ * guide cleanups by Ed Clark
+ *
+ * gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * The unzip code was written and put in the public domain by Mark Adler.
+ * Portions of the lzw code are derived from the public domain 'compress'
+ * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
+ * Ken Turkowski, Dave Mack and Peter Jannesen.
+ *
+ * See the file algorithm.doc for the compression algorithms and file formats.
+ * 
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include <sys/wait.h>
+#include <signal.h>
+#include "unarchive.h"
+
+typedef struct huft_s {
+	unsigned char e;	/* number of extra bits or operation */
+	unsigned char b;	/* number of bits in this code or subcode */
+	union {
+		unsigned short n;	/* literal, length base, or distance base */
+		struct huft_s *t;	/* pointer to next level of table */
+	} v;
+} huft_t;
+
+static int gunzip_src_fd;
+unsigned int gunzip_bytes_out;	/* number of output bytes */
+static unsigned int gunzip_outbuf_count;	/* bytes in output buffer */
+
+/* gunzip_window size--must be a power of two, and
+ *  at least 32K for zip's deflate method */
+enum { gunzip_wsize = 0x8000 };
+static unsigned char *gunzip_window;
+
+static uint32_t *gunzip_crc_table;
+uint32_t gunzip_crc;
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16	/* maximum bit length of any code (16 for explode) */
+#define N_MAX 288	/* maximum number of codes in any set */
+
+/* bitbuffer */
+static unsigned int gunzip_bb;	/* bit buffer */
+static unsigned char gunzip_bk;	/* bits in bit buffer */
+
+/* These control the size of the bytebuffer */
+static unsigned int bytebuffer_max = 0x8000;
+static unsigned char *bytebuffer = NULL;
+static unsigned int bytebuffer_offset = 0;
+static unsigned int bytebuffer_size = 0;
+
+static const unsigned short mask_bits[] = {
+	0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+	0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+/* Copy lengths for literal codes 257..285 */
+static const unsigned short cplens[] = {
+	3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
+	67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+};
+
+/* note: see note #13 above about the 258 in this list. */
+/* Extra bits for literal codes 257..285 */
+static const unsigned char cplext[] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5,
+	5, 5, 5, 0, 99, 99
+};						/* 99==invalid */
+
+/* Copy offsets for distance codes 0..29 */
+static const unsigned short cpdist[] = {
+	1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
+	769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
+};
+
+/* Extra bits for distance codes */
+static const unsigned char cpdext[] = {
+	0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10,
+	11, 11, 12, 12, 13, 13
+};
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+/* Order of the bit length code lengths */
+static const unsigned char border[] = {
+	16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+};
+
+static unsigned int fill_bitbuffer(unsigned int bitbuffer, unsigned int *current, const unsigned int required)
+{
+	while (*current < required) {
+		if (bytebuffer_offset >= bytebuffer_size) {
+			/* Leave the first 4 bytes empty so we can always unwind the bitbuffer
+			 * to the front of the bytebuffer, leave 4 bytes free at end of tail
+			 * so we can easily top up buffer in check_trailer_gzip() */
+			if (!(bytebuffer_size = bb_xread(gunzip_src_fd, &bytebuffer[4], bytebuffer_max - 8))) {
+				bb_error_msg_and_die("unexpected end of file");
+			}
+			bytebuffer_size += 4;
+			bytebuffer_offset = 4;
+		}
+		bitbuffer |= ((unsigned int) bytebuffer[bytebuffer_offset]) << *current;
+		bytebuffer_offset++;
+		*current += 8;
+	}
+	return(bitbuffer);
+}
+
+/*
+ * Free the malloc'ed tables built by huft_build(), which makes a linked
+ * list of the tables it made, with the links in a dummy first entry of
+ * each table.
+ * t: table to free
+ */
+static int huft_free(huft_t * t)
+{
+	huft_t *p;
+	huft_t *q;
+
+	/* Go through linked list, freeing from the malloced (t[-1]) address. */
+	p = t;
+	while (p != (huft_t *) NULL) {
+		q = (--p)->v.t;
+		free((char *) p);
+		p = q;
+	}
+	return 0;
+}
+
+/* Given a list of code lengths and a maximum table size, make a set of
+ * tables to decode that set of codes.  Return zero on success, one if
+ * the given code set is incomplete (the tables are still built in this
+ * case), two if the input is invalid (all zero length codes or an
+ * oversubscribed set of lengths), and three if not enough memory.
+ *
+ * b:	code lengths in bits (all assumed <= BMAX)
+ * n:	number of codes (assumed <= N_MAX)
+ * s:	number of simple-valued codes (0..s-1)
+ * d:	list of base values for non-simple codes
+ * e:	list of extra bits for non-simple codes
+ * t:	result: starting table
+ * m:	maximum lookup bits, returns actual
+ */
+static
+int huft_build(unsigned int *b, const unsigned int n,
+			   const unsigned int s, const unsigned short *d,
+			   const unsigned char *e, huft_t ** t, unsigned int *m)
+{
+	unsigned a;				/* counter for codes of length k */
+	unsigned c[BMAX + 1];	/* bit length count table */
+	unsigned eob_len;		/* length of end-of-block code (value 256) */
+	unsigned f;				/* i repeats in table every f entries */
+	int g;					/* maximum code length */
+	int htl;				/* table level */
+	unsigned i;				/* counter, current code */
+	unsigned j;				/* counter */
+	int k;					/* number of bits in current code */
+	unsigned *p;			/* pointer into c[], b[], or v[] */
+	huft_t *q;				/* points to current table */
+	huft_t r;				/* table entry for structure assignment */
+	huft_t *u[BMAX];		/* table stack */
+	unsigned v[N_MAX];		/* values in order of bit length */
+	int ws[BMAX+1];			/* bits decoded stack */
+	int w;					/* bits decoded */
+	unsigned x[BMAX + 1];	/* bit offsets, then code stack */
+	unsigned *xp;			/* pointer into x */
+	int y;					/* number of dummy codes added */
+	unsigned z;				/* number of entries in current table */
+
+	/* Length of EOB code, if any */
+	eob_len = n > 256 ? b[256] : BMAX;
+
+	/* Generate counts for each bit length */
+	memset((void *)c, 0, sizeof(c));
+	p = b;
+	i = n;
+	do {
+		c[*p]++; /* assume all entries <= BMAX */
+		p++; /* Can't combine with above line (Solaris bug) */
+	} while (--i);
+	if (c[0] == n) { /* null input--all zero length codes */
+		*t = (huft_t *) NULL;
+		*m = 0;
+		return 2;
+	}
+
+	/* Find minimum and maximum length, bound *m by those */
+	for (j = 1; (c[j] == 0) && (j <= BMAX); j++);
+	k = j; /* minimum code length */
+	for (i = BMAX; (c[i] == 0) && i; i--);
+	g = i; /* maximum code length */
+	*m = (*m < j) ? j : ((*m > i) ? i : *m);
+
+	/* Adjust last length count to fill out codes, if needed */
+	for (y = 1 << j; j < i; j++, y <<= 1) {
+		if ((y -= c[j]) < 0) {
+			return 2; /* bad input: more codes than bits */
+		}
+	}
+	if ((y -= c[i]) < 0) {
+		return 2;
+	}
+	c[i] += y;
+
+	/* Generate starting offsets into the value table for each length */
+	x[1] = j = 0;
+	p = c + 1;
+	xp = x + 2;
+	while (--i) { /* note that i == g from above */
+		*xp++ = (j += *p++);
+	}
+
+	/* Make a table of values in order of bit lengths */
+	p = b;
+	i = 0;
+	do {
+		if ((j = *p++) != 0) {
+			v[x[j]++] = i;
+		}
+	} while (++i < n);
+
+	/* Generate the Huffman codes and for each, make the table entries */
+	x[0] = i = 0;			/* first Huffman code is zero */
+	p = v;					/* grab values in bit order */
+	htl = -1;				/* no tables yet--level -1 */
+	w = ws[0] = 0;			/* bits decoded */
+	u[0] = (huft_t *) NULL;	/* just to keep compilers happy */
+	q = (huft_t *) NULL;	/* ditto */
+	z = 0;					/* ditto */
+
+	/* go through the bit lengths (k already is bits in shortest code) */
+	for (; k <= g; k++) {
+		a = c[k];
+		while (a--) {
+			/* here i is the Huffman code of length k bits for value *p */
+			/* make tables up to required level */
+			while (k > ws[htl + 1]) {
+				w = ws[++htl];
+
+				/* compute minimum size table less than or equal to *m bits */
+				z = (z = g - w) > *m ? *m : z; /* upper limit on table size */
+				if ((f = 1 << (j = k - w)) > a + 1) { /* try a k-w bit table */
+					/* too few codes for k-w bit table */
+					f -= a + 1; /* deduct codes from patterns left */
+					xp = c + k;
+					while (++j < z) { /* try smaller tables up to z bits */
+						if ((f <<= 1) <= *++xp) {
+							break; /* enough codes to use up j bits */
+						}
+						f -= *xp; /* else deduct codes from patterns */
+					}
+				}
+				j = (w + j > eob_len && w < eob_len) ? eob_len - w : j;	/* make EOB code end at table */
+				z = 1 << j;	/* table entries for j-bit table */
+				ws[htl+1] = w + j;	/* set bits decoded in stack */
+
+				/* allocate and link in new table */
+				q = (huft_t *) xzalloc((z + 1) * sizeof(huft_t));
+				*t = q + 1;	/* link to list for huft_free() */
+				t = &(q->v.t);
+				u[htl] = ++q;	/* table starts after link */
+
+				/* connect to last table, if there is one */
+				if (htl) {
+					x[htl] = i; /* save pattern for backing up */
+					r.b = (unsigned char) (w - ws[htl - 1]); /* bits to dump before this table */
+					r.e = (unsigned char) (16 + j); /* bits in this table */
+					r.v.t = q; /* pointer to this table */
+					j = (i & ((1 << w) - 1)) >> ws[htl - 1];
+					u[htl - 1][j] = r; /* connect to last table */
+				}
+			}
+
+			/* set up table entry in r */
+			r.b = (unsigned char) (k - w);
+			if (p >= v + n) {
+				r.e = 99; /* out of values--invalid code */
+			} else if (*p < s) {
+				r.e = (unsigned char) (*p < 256 ? 16 : 15);	/* 256 is EOB code */
+				r.v.n = (unsigned short) (*p++); /* simple code is just the value */
+			} else {
+				r.e = (unsigned char) e[*p - s]; /* non-simple--look up in lists */
+				r.v.n = d[*p++ - s];
+			}
+
+			/* fill code-like entries with r */
+			f = 1 << (k - w);
+			for (j = i >> w; j < z; j += f) {
+				q[j] = r;
+			}
+
+			/* backwards increment the k-bit code i */
+			for (j = 1 << (k - 1); i & j; j >>= 1) {
+				i ^= j;
+			}
+			i ^= j;
+
+			/* backup over finished tables */
+			while ((i & ((1 << w) - 1)) != x[htl]) {
+				w = ws[--htl];
+			}
+		}
+	}
+
+	/* return actual size of base table */
+	*m = ws[1];
+
+	/* Return true (1) if we were given an incomplete table */
+	return y != 0 && g != 1;
+}
+
+/*
+ * inflate (decompress) the codes in a deflated (compressed) block.
+ * Return an error code or zero if it all goes ok.
+ *
+ * tl, td: literal/length and distance decoder tables
+ * bl, bd: number of bits decoded by tl[] and td[]
+ */
+static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned int my_bl, const unsigned int my_bd, int setup)
+{
+	static unsigned int e;	/* table entry flag/number of extra bits */
+	static unsigned int n, d;	/* length and index for copy */
+	static unsigned int w;	/* current gunzip_window position */
+	static huft_t *t;			/* pointer to table entry */
+	static unsigned int ml, md;	/* masks for bl and bd bits */
+	static unsigned int b;	/* bit buffer */
+	static unsigned int k;			/* number of bits in bit buffer */
+	static huft_t *tl, *td;
+	static unsigned int bl, bd;
+	static int resumeCopy = 0;
+
+	if (setup) { // 1st time we are called, copy in variables
+		tl = my_tl;
+		td = my_td;
+		bl = my_bl;
+		bd = my_bd;
+		/* make local copies of globals */
+		b = gunzip_bb;				/* initialize bit buffer */
+		k = gunzip_bk;
+		w = gunzip_outbuf_count;			/* initialize gunzip_window position */
+
+		/* inflate the coded data */
+		ml = mask_bits[bl];	/* precompute masks for speed */
+		md = mask_bits[bd];
+		return 0; // Don't actually do anything the first time
+	}
+
+	if (resumeCopy) goto do_copy;
+
+	while (1) {			/* do until end of block */
+		b = fill_bitbuffer(b, &k, bl);
+		if ((e = (t = tl + ((unsigned) b & ml))->e) > 16)
+			do {
+				if (e == 99) {
+					bb_error_msg_and_die("inflate_codes error 1");
+				}
+				b >>= t->b;
+				k -= t->b;
+				e -= 16;
+				b = fill_bitbuffer(b, &k, e);
+			} while ((e =
+					  (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
+		b >>= t->b;
+		k -= t->b;
+		if (e == 16) {	/* then it's a literal */
+			gunzip_window[w++] = (unsigned char) t->v.n;
+			if (w == gunzip_wsize) {
+				gunzip_outbuf_count = (w);
+				//flush_gunzip_window();
+				w = 0;
+				return 1; // We have a block to read
+			}
+		} else {		/* it's an EOB or a length */
+
+			/* exit if end of block */
+			if (e == 15) {
+				break;
+			}
+
+			/* get length of block to copy */
+			b = fill_bitbuffer(b, &k, e);
+			n = t->v.n + ((unsigned) b & mask_bits[e]);
+			b >>= e;
+			k -= e;
+
+			/* decode distance of block to copy */
+			b = fill_bitbuffer(b, &k, bd);
+			if ((e = (t = td + ((unsigned) b & md))->e) > 16)
+				do {
+					if (e == 99)
+						bb_error_msg_and_die("inflate_codes error 2");
+					b >>= t->b;
+					k -= t->b;
+					e -= 16;
+					b = fill_bitbuffer(b, &k, e);
+				} while ((e =
+						  (t =
+						   t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
+			b >>= t->b;
+			k -= t->b;
+			b = fill_bitbuffer(b, &k, e);
+			d = w - t->v.n - ((unsigned) b & mask_bits[e]);
+			b >>= e;
+			k -= e;
+
+			/* do the copy */
+do_copy:		do {
+				n -= (e =
+					  (e =
+					   gunzip_wsize - ((d &= gunzip_wsize - 1) > w ? d : w)) > n ? n : e);
+			   /* copy to new buffer to prevent possible overwrite */
+				if (w - d >= e) {	/* (this test assumes unsigned comparison) */
+					memcpy(gunzip_window + w, gunzip_window + d, e);
+					w += e;
+					d += e;
+				} else {
+				   /* do it slow to avoid memcpy() overlap */
+				   /* !NOMEMCPY */
+					do {
+						gunzip_window[w++] = gunzip_window[d++];
+					} while (--e);
+				}
+				if (w == gunzip_wsize) {
+					gunzip_outbuf_count = (w);
+					if (n) resumeCopy = 1;
+					else resumeCopy = 0;
+					//flush_gunzip_window();
+					w = 0;
+					return 1;
+				}
+			} while (n);
+			resumeCopy = 0;
+		}
+	}
+
+	/* restore the globals from the locals */
+	gunzip_outbuf_count = w;			/* restore global gunzip_window pointer */
+	gunzip_bb = b;				/* restore global bit buffer */
+	gunzip_bk = k;
+
+	/* normally just after call to inflate_codes, but save code by putting it here */
+	/* free the decoding tables, return */
+	huft_free(tl);
+	huft_free(td);
+
+	/* done */
+	return 0;
+}
+
+static int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup)
+{
+	static unsigned int n, b_stored, k_stored, w;
+	if (setup) {
+		n = my_n;
+		b_stored = my_b_stored;
+		k_stored = my_k_stored;
+		w = gunzip_outbuf_count;		/* initialize gunzip_window position */
+		return 0; // Don't do anything first time
+	}
+
+	/* read and output the compressed data */
+	while (n--) {
+		b_stored = fill_bitbuffer(b_stored, &k_stored, 8);
+		gunzip_window[w++] = (unsigned char) b_stored;
+		if (w == gunzip_wsize) {
+			gunzip_outbuf_count = (w);
+			//flush_gunzip_window();
+			w = 0;
+			b_stored >>= 8;
+			k_stored -= 8;
+			return 1; // We have a block
+		}
+		b_stored >>= 8;
+		k_stored -= 8;
+	}
+
+	/* restore the globals from the locals */
+	gunzip_outbuf_count = w;		/* restore global gunzip_window pointer */
+	gunzip_bb = b_stored;	/* restore global bit buffer */
+	gunzip_bk = k_stored;
+	return 0; // Finished
+}
+
+/*
+ * decompress an inflated block
+ * e: last block flag
+ *
+ * GLOBAL VARIABLES: bb, kk,
+ */
+ // Return values: -1 = inflate_stored, -2 = inflate_codes
+static int inflate_block(int *e)
+{
+	unsigned t;			/* block type */
+	register unsigned int b;	/* bit buffer */
+	unsigned int k;	/* number of bits in bit buffer */
+
+	/* make local bit buffer */
+
+	b = gunzip_bb;
+	k = gunzip_bk;
+
+	/* read in last block bit */
+	b = fill_bitbuffer(b, &k, 1);
+	*e = (int) b & 1;
+	b >>= 1;
+	k -= 1;
+
+	/* read in block type */
+	b = fill_bitbuffer(b, &k, 2);
+	t = (unsigned) b & 3;
+	b >>= 2;
+	k -= 2;
+
+	/* restore the global bit buffer */
+	gunzip_bb = b;
+	gunzip_bk = k;
+
+	/* inflate that block type */
+	switch (t) {
+	case 0:			/* Inflate stored */
+	{
+		unsigned int n;	/* number of bytes in block */
+		unsigned int b_stored;	/* bit buffer */
+		unsigned int k_stored;	/* number of bits in bit buffer */
+
+		/* make local copies of globals */
+		b_stored = gunzip_bb;	/* initialize bit buffer */
+		k_stored = gunzip_bk;
+
+		/* go to byte boundary */
+		n = k_stored & 7;
+		b_stored >>= n;
+		k_stored -= n;
+
+		/* get the length and its complement */
+		b_stored = fill_bitbuffer(b_stored, &k_stored, 16);
+		n = ((unsigned) b_stored & 0xffff);
+		b_stored >>= 16;
+		k_stored -= 16;
+
+		b_stored = fill_bitbuffer(b_stored, &k_stored, 16);
+		if (n != (unsigned) ((~b_stored) & 0xffff)) {
+			return 1;	/* error in compressed data */
+		}
+		b_stored >>= 16;
+		k_stored -= 16;
+
+		inflate_stored(n, b_stored, k_stored, 1); // Setup inflate_stored
+		return -1;
+	}
+	case 1:			/* Inflate fixed
+						   * decompress an inflated type 1 (fixed Huffman codes) block.  We should
+						   * either replace this with a custom decoder, or at least precompute the
+						   * Huffman tables.
+						 */
+	{
+		int i;			/* temporary variable */
+		huft_t *tl;		/* literal/length code table */
+		huft_t *td;		/* distance code table */
+		unsigned int bl;			/* lookup bits for tl */
+		unsigned int bd;			/* lookup bits for td */
+		unsigned int l[288];	/* length list for huft_build */
+
+		/* set up literal table */
+		for (i = 0; i < 144; i++) {
+			l[i] = 8;
+		}
+		for (; i < 256; i++) {
+			l[i] = 9;
+		}
+		for (; i < 280; i++) {
+			l[i] = 7;
+		}
+		for (; i < 288; i++) {	/* make a complete, but wrong code set */
+			l[i] = 8;
+		}
+		bl = 7;
+		if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0) {
+			return i;
+		}
+
+		/* set up distance table */
+		for (i = 0; i < 30; i++) {	/* make an incomplete code set */
+			l[i] = 5;
+		}
+		bd = 5;
+		if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1) {
+			huft_free(tl);
+			return i;
+		}
+
+		/* decompress until an end-of-block code */
+		inflate_codes(tl, td, bl, bd, 1); // Setup inflate_codes
+
+		/* huft_free code moved into inflate_codes */
+
+		return -2;
+	}
+	case 2:			/* Inflate dynamic */
+	{
+		const int dbits = 6;	/* bits in base distance lookup table */
+		const int lbits = 9;	/* bits in base literal/length lookup table */
+
+		huft_t *tl;		/* literal/length code table */
+		huft_t *td;		/* distance code table */
+		unsigned int i;			/* temporary variables */
+		unsigned int j;
+		unsigned int l;		/* last length */
+		unsigned int m;		/* mask for bit lengths table */
+		unsigned int n;		/* number of lengths to get */
+		unsigned int bl;			/* lookup bits for tl */
+		unsigned int bd;			/* lookup bits for td */
+		unsigned int nb;	/* number of bit length codes */
+		unsigned int nl;	/* number of literal/length codes */
+		unsigned int nd;	/* number of distance codes */
+
+		unsigned int ll[286 + 30];	/* literal/length and distance code lengths */
+		unsigned int b_dynamic;	/* bit buffer */
+		unsigned int k_dynamic;	/* number of bits in bit buffer */
+
+		/* make local bit buffer */
+		b_dynamic = gunzip_bb;
+		k_dynamic = gunzip_bk;
+
+		/* read in table lengths */
+		b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 5);
+		nl = 257 + ((unsigned int) b_dynamic & 0x1f);	/* number of literal/length codes */
+
+		b_dynamic >>= 5;
+		k_dynamic -= 5;
+		b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 5);
+		nd = 1 + ((unsigned int) b_dynamic & 0x1f);	/* number of distance codes */
+
+		b_dynamic >>= 5;
+		k_dynamic -= 5;
+		b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 4);
+		nb = 4 + ((unsigned int) b_dynamic & 0xf);	/* number of bit length codes */
+
+		b_dynamic >>= 4;
+		k_dynamic -= 4;
+		if (nl > 286 || nd > 30) {
+			return 1;	/* bad lengths */
+		}
+
+		/* read in bit-length-code lengths */
+		for (j = 0; j < nb; j++) {
+			b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 3);
+			ll[border[j]] = (unsigned int) b_dynamic & 7;
+			b_dynamic >>= 3;
+			k_dynamic -= 3;
+		}
+		for (; j < 19; j++) {
+			ll[border[j]] = 0;
+		}
+
+		/* build decoding table for trees--single level, 7 bit lookup */
+		bl = 7;
+		i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl);
+		if (i != 0) {
+			if (i == 1) {
+				huft_free(tl);
+			}
+			return i;	/* incomplete code set */
+		}
+
+		/* read in literal and distance code lengths */
+		n = nl + nd;
+		m = mask_bits[bl];
+		i = l = 0;
+		while ((unsigned int) i < n) {
+			b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, (unsigned int)bl);
+			j = (td = tl + ((unsigned int) b_dynamic & m))->b;
+			b_dynamic >>= j;
+			k_dynamic -= j;
+			j = td->v.n;
+			if (j < 16) {	/* length of code in bits (0..15) */
+				ll[i++] = l = j;	/* save last length in l */
+			} else if (j == 16) {	/* repeat last length 3 to 6 times */
+				b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 2);
+				j = 3 + ((unsigned int) b_dynamic & 3);
+				b_dynamic >>= 2;
+				k_dynamic -= 2;
+				if ((unsigned int) i + j > n) {
+					return 1;
+				}
+				while (j--) {
+					ll[i++] = l;
+				}
+			} else if (j == 17) {	/* 3 to 10 zero length codes */
+				b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 3);
+				j = 3 + ((unsigned int) b_dynamic & 7);
+				b_dynamic >>= 3;
+				k_dynamic -= 3;
+				if ((unsigned int) i + j > n) {
+					return 1;
+				}
+				while (j--) {
+					ll[i++] = 0;
+				}
+				l = 0;
+			} else {	/* j == 18: 11 to 138 zero length codes */
+				b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 7);
+				j = 11 + ((unsigned int) b_dynamic & 0x7f);
+				b_dynamic >>= 7;
+				k_dynamic -= 7;
+				if ((unsigned int) i + j > n) {
+					return 1;
+				}
+				while (j--) {
+					ll[i++] = 0;
+				}
+				l = 0;
+			}
+		}
+
+		/* free decoding table for trees */
+		huft_free(tl);
+
+		/* restore the global bit buffer */
+		gunzip_bb = b_dynamic;
+		gunzip_bk = k_dynamic;
+
+		/* build the decoding tables for literal/length and distance codes */
+		bl = lbits;
+
+		if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) {
+			if (i == 1) {
+				bb_error_msg_and_die("Incomplete literal tree");
+				huft_free(tl);
+			}
+			return i;	/* incomplete code set */
+		}
+
+		bd = dbits;
+		if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) {
+			if (i == 1) {
+				bb_error_msg_and_die("incomplete distance tree");
+				huft_free(td);
+			}
+			huft_free(tl);
+			return i;	/* incomplete code set */
+		}
+
+		/* decompress until an end-of-block code */
+		inflate_codes(tl, td, bl, bd, 1); // Setup inflate_codes
+
+		/* huft_free code moved into inflate_codes */
+
+		return -2;
+	}
+	default:
+		/* bad block type */
+		bb_error_msg_and_die("bad block type %d\n", t);
+	}
+}
+
+static void calculate_gunzip_crc(void)
+{
+	int n;
+	for (n = 0; n < gunzip_outbuf_count; n++) {
+		gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8);
+	}
+	gunzip_bytes_out += gunzip_outbuf_count;
+}
+
+static int inflate_get_next_window(void)
+{
+	static int method = -1; // Method == -1 for stored, -2 for codes
+	static int e = 0;
+	static int needAnotherBlock = 1;
+
+	gunzip_outbuf_count = 0;
+
+	while(1) {
+		int ret;
+
+		if (needAnotherBlock) {
+			if(e) {
+				calculate_gunzip_crc();
+				e = 0;
+				needAnotherBlock = 1;
+				return 0;
+			} // Last block
+			method = inflate_block(&e);
+			needAnotherBlock = 0;
+		}
+
+		switch (method) {
+			case -1:	ret = inflate_stored(0,0,0,0);
+					break;
+			case -2:	ret = inflate_codes(0,0,0,0,0);
+					break;
+			default:	bb_error_msg_and_die("inflate error %d", method);
+		}
+
+		if (ret == 1) {
+			calculate_gunzip_crc();
+			return 1; // More data left
+		} else needAnotherBlock = 1; // End of that block
+	}
+	/* Doesnt get here */
+}
+
+/* Initialise bytebuffer, be careful not to overfill the buffer */
+void inflate_init(unsigned int bufsize)
+{
+	/* Set the bytebuffer size, default is same as gunzip_wsize */
+	bytebuffer_max = bufsize + 8;
+	bytebuffer_offset = 4;
+	bytebuffer_size = 0;
+}
+
+void inflate_cleanup(void)
+{
+	free(bytebuffer);
+}
+
+int inflate_unzip(int in, int out)
+{
+	ssize_t nwrote;
+	typedef void (*sig_type) (int);
+
+	/* Allocate all global buffers (for DYN_ALLOC option) */
+	gunzip_window = xmalloc(gunzip_wsize);
+	gunzip_outbuf_count = 0;
+	gunzip_bytes_out = 0;
+	gunzip_src_fd = in;
+
+	/* initialize gunzip_window, bit buffer */
+	gunzip_bk = 0;
+	gunzip_bb = 0;
+
+	/* Create the crc table */
+	gunzip_crc_table = bb_crc32_filltable(0);
+	gunzip_crc = ~0;
+	
+	/* Allocate space for buffer */
+	bytebuffer = xmalloc(bytebuffer_max);
+
+	while(1) {
+		int ret = inflate_get_next_window();
+		nwrote = bb_full_write(out, gunzip_window, gunzip_outbuf_count);
+		if (nwrote == -1) {
+			bb_perror_msg("write");
+			return -1;
+		}
+		if (ret == 0) break;
+	}
+
+	/* Cleanup */
+	free(gunzip_window);
+	free(gunzip_crc_table);
+
+	/* Store unused bytes in a global buffer so calling applets can access it */
+	if (gunzip_bk >= 8) {
+		/* Undo too much lookahead. The next read will be byte aligned
+		 * so we can discard unused bits in the last meaningful byte. */
+		bytebuffer_offset--;
+		bytebuffer[bytebuffer_offset] = gunzip_bb & 0xff;
+		gunzip_bb >>= 8;
+		gunzip_bk -= 8;
+	}
+	return 0;
+}
+
+int inflate_gunzip(int in, int out)
+{
+	uint32_t stored_crc = 0;
+	unsigned int count;
+
+	inflate_unzip(in, out);
+
+	/* top up the input buffer with the rest of the trailer */
+	count = bytebuffer_size - bytebuffer_offset;
+	if (count < 8) {
+		bb_xread_all(in, &bytebuffer[bytebuffer_size], 8 - count);
+		bytebuffer_size += 8 - count;
+	}
+	for (count = 0; count != 4; count++) {
+		stored_crc |= (bytebuffer[bytebuffer_offset] << (count * 8));
+		bytebuffer_offset++;
+	}
+
+	/* Validate decompression - crc */
+	if (stored_crc != (~gunzip_crc)) {
+		bb_error_msg("crc error");
+		return -1;
+	}
+
+	/* Validate decompression - size */
+	if (gunzip_bytes_out !=
+		(bytebuffer[bytebuffer_offset] | (bytebuffer[bytebuffer_offset+1] << 8) |
+		(bytebuffer[bytebuffer_offset+2] << 16) | (bytebuffer[bytebuffer_offset+3] << 24))) {
+		bb_error_msg("Incorrect length");
+		return -1;
+	}
+
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/filter_accept_all.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/filter_accept_all.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/filter_accept_all.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,19 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2002 by Glenn McGrath
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdlib.h>
+#include "unarchive.h"
+
+/* Accept any non-null name, its not really a filter at all */
+char filter_accept_all(archive_handle_t *archive_handle)
+{
+	if (archive_handle->file_header->name) {
+		return(EXIT_SUCCESS);
+	} else {
+		return(EXIT_FAILURE);
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/filter_accept_list.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/filter_accept_list.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/filter_accept_list.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,21 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2002 by Glenn McGrath
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdlib.h>
+#include "unarchive.h"
+
+/*
+ * Accept names that are in the accept list, ignoring reject list.
+ */
+char filter_accept_list(archive_handle_t *archive_handle)
+{
+	if (find_list_entry(archive_handle->accept, archive_handle->file_header->name)) {
+		return(EXIT_SUCCESS);
+	} else {
+		return(EXIT_FAILURE);
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/filter_accept_list_reassign.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/filter_accept_list_reassign.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/filter_accept_list_reassign.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,59 @@
+/*
+ *  Copyright (C) 2002 by Glenn McGrath
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libbb.h"
+#include "unarchive.h"
+
+/*
+ *	Reassign the subarchive metadata parser based on the filename extension
+ *  e.g. if its a .tar.gz modify archive_handle->sub_archive to process a .tar.gz
+ *       or if its a .tar.bz2 make archive_handle->sub_archive handle that
+ */
+char filter_accept_list_reassign(archive_handle_t *archive_handle)
+{
+	/* Check the file entry is in the accept list */
+	if (find_list_entry(archive_handle->accept, archive_handle->file_header->name)) {
+		const char *name_ptr;
+
+		/* Extract the last 2 extensions */
+		name_ptr = strrchr(archive_handle->file_header->name, '.');
+
+		/* Modify the subarchive handler based on the extension */
+#ifdef CONFIG_FEATURE_DEB_TAR_GZ
+		if (strcmp(name_ptr, ".gz") == 0) {
+			archive_handle->action_data_subarchive = get_header_tar_gz;
+			return(EXIT_SUCCESS);
+		}
+#endif
+#ifdef CONFIG_FEATURE_DEB_TAR_BZ2
+		if (strcmp(name_ptr, ".bz2") == 0) {
+			archive_handle->action_data_subarchive = get_header_tar_bz2;
+			return(EXIT_SUCCESS);
+		}
+#endif
+		if (ENABLE_FEATURE_DEB_TAR_LZMA && !strcmp(name_ptr, ".lzma")) {
+			archive_handle->action_data_subarchive = get_header_tar_lzma;
+			return(EXIT_SUCCESS);
+		}
+	}
+	return(EXIT_FAILURE);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/filter_accept_reject_list.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/filter_accept_reject_list.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/filter_accept_reject_list.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,33 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2002 by Glenn McGrath
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdlib.h>
+#include "unarchive.h"
+
+/*
+ * Accept names that are in the accept list and not in the reject list
+ */
+char filter_accept_reject_list(archive_handle_t *archive_handle)
+{
+	const char *key = archive_handle->file_header->name;
+	const llist_t *reject_entry = find_list_entry(archive_handle->reject, key);
+	const llist_t *accept_entry;
+
+	/* If the key is in a reject list fail */
+	if (reject_entry) {
+		return(EXIT_FAILURE);
+	}
+	accept_entry = find_list_entry(archive_handle->accept, key);
+
+	/* Fail if an accept list was specified and the key wasnt in there */
+	if ((accept_entry == NULL) && archive_handle->accept) {
+		return(EXIT_FAILURE);
+	}
+
+	/* Accepted */
+	return(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/find_list_entry.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/find_list_entry.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/find_list_entry.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,22 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2002 by Glenn McGrath
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <fnmatch.h>
+#include <stdlib.h>
+#include "unarchive.h"
+
+/* Find a string in a list */
+const llist_t *find_list_entry(const llist_t *list, const char *filename)
+{
+	while (list) {
+		if (fnmatch(list->data, filename, 0) == 0) {
+			return (list);
+		}
+		list = list->link;
+	}
+	return(NULL);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_ar.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_ar.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_ar.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,115 @@
+/* Copyright 2001 Glenn McGrath.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "unarchive.h"
+#include "libbb.h"
+
+char get_header_ar(archive_handle_t *archive_handle)
+{
+	file_header_t *typed = archive_handle->file_header;
+	union {
+		char raw[60];
+		struct {
+			char name[16];
+			char date[12];
+			char uid[6];
+			char gid[6];
+			char mode[8];
+			char size[10];
+			char magic[2];
+		} formated;
+	} ar;
+#ifdef CONFIG_FEATURE_AR_LONG_FILENAMES
+	static char *ar_long_names;
+	static unsigned int ar_long_name_size;
+#endif
+
+	/* dont use bb_xread as we want to handle the error ourself */
+	if (read(archive_handle->src_fd, ar.raw, 60) != 60) {
+		/* End Of File */
+		return(EXIT_FAILURE);
+	}
+
+	/* ar header starts on an even byte (2 byte aligned)
+	 * '\n' is used for padding
+	 */
+	if (ar.raw[0] == '\n') {
+		/* fix up the header, we started reading 1 byte too early */
+		memmove(ar.raw, &ar.raw[1], 59);
+		ar.raw[59] = bb_xread_char(archive_handle->src_fd);
+		archive_handle->offset++;
+	}
+	archive_handle->offset += 60;
+
+	/* align the headers based on the header magic */
+	if ((ar.formated.magic[0] != '`') || (ar.formated.magic[1] != '\n')) {
+		bb_error_msg_and_die("Invalid ar header");
+	}
+
+	typed->mode = strtol(ar.formated.mode, NULL, 8);
+	typed->mtime = atoi(ar.formated.date);
+	typed->uid = atoi(ar.formated.uid);
+	typed->gid = atoi(ar.formated.gid);
+	typed->size = atoi(ar.formated.size);
+
+	/* long filenames have '/' as the first character */
+	if (ar.formated.name[0] == '/') {
+#ifdef CONFIG_FEATURE_AR_LONG_FILENAMES
+		if (ar.formated.name[1] == '/') {
+			/* If the second char is a '/' then this entries data section
+			 * stores long filename for multiple entries, they are stored
+			 * in static variable long_names for use in future entries */
+			ar_long_name_size = typed->size;
+			ar_long_names = xmalloc(ar_long_name_size);
+			bb_xread_all(archive_handle->src_fd, ar_long_names, ar_long_name_size);
+			archive_handle->offset += ar_long_name_size;
+			/* This ar entries data section only contained filenames for other records
+			 * they are stored in the static ar_long_names for future reference */
+			return (get_header_ar(archive_handle)); /* Return next header */
+		} else if (ar.formated.name[1] == ' ') {
+			/* This is the index of symbols in the file for compilers */
+			data_skip(archive_handle);
+			archive_handle->offset += typed->size;
+			return (get_header_ar(archive_handle)); /* Return next header */
+		} else {
+			/* The number after the '/' indicates the offset in the ar data section
+			(saved in variable long_name) that conatains the real filename */
+			const unsigned int long_offset = atoi(&ar.formated.name[1]);
+			if (long_offset >= ar_long_name_size) {
+				bb_error_msg_and_die("Cant resolve long filename");
+			}
+			typed->name = bb_xstrdup(ar_long_names + long_offset);
+		}
+#else
+		bb_error_msg_and_die("long filenames not supported");
+#endif
+	} else {
+		/* short filenames */
+	       typed->name = bb_xstrndup(ar.formated.name, 16);
+	}
+
+	typed->name[strcspn(typed->name, " /")] = '\0';
+
+	if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
+		archive_handle->action_header(typed);
+		if (archive_handle->sub_archive) {
+			while (archive_handle->action_data_subarchive(archive_handle->sub_archive) == EXIT_SUCCESS);
+		} else {
+			archive_handle->action_data(archive_handle);
+		}
+	} else {
+		data_skip(archive_handle);
+	}
+
+	archive_handle->offset += typed->size;
+	/* Set the file pointer to the correct spot, we may have been reading a compressed file */
+	lseek(archive_handle->src_fd, archive_handle->offset, SEEK_SET);
+
+	return(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_cpio.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_cpio.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_cpio.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,148 @@
+/* Copyright 2002 Laurence Anderson
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/sysmacros.h>     /* major() and minor() */
+#include "unarchive.h"
+#include "libbb.h"
+
+typedef struct hardlinks_s {
+	file_header_t *entry;
+	int inode;
+	struct hardlinks_s *next;
+} hardlinks_t;
+
+char get_header_cpio(archive_handle_t *archive_handle)
+{
+	static hardlinks_t *saved_hardlinks = NULL;
+	static unsigned short pending_hardlinks = 0;
+	file_header_t *file_header = archive_handle->file_header;
+	char cpio_header[110];
+	int namesize;
+	char dummy[16];
+	int major, minor, nlink, inode;
+
+	if (pending_hardlinks) { /* Deal with any pending hardlinks */
+		hardlinks_t *tmp;
+		hardlinks_t *oldtmp;
+
+		tmp = saved_hardlinks;
+		oldtmp = NULL;
+
+		while (tmp) {
+			bb_error_msg_and_die("need to fix this\n");
+			if (tmp->entry->link_name) { /* Found a hardlink ready to be extracted */
+				file_header = tmp->entry;
+				if (oldtmp) {
+					oldtmp->next = tmp->next; /* Remove item from linked list */
+				} else {
+					saved_hardlinks = tmp->next;
+				}
+				free(tmp);
+				continue;
+			}
+			oldtmp = tmp;
+			tmp = tmp->next;
+		}
+		pending_hardlinks = 0; /* No more pending hardlinks, read next file entry */
+	}
+
+	/* There can be padding before archive header */
+	data_align(archive_handle, 4);
+
+	if (archive_xread_all_eof(archive_handle, (unsigned char*)cpio_header, 110) == 0) {
+		return(EXIT_FAILURE);
+	}
+	archive_handle->offset += 110;
+
+	if ((strncmp(&cpio_header[0], "07070", 5) != 0) || ((cpio_header[5] != '1') && (cpio_header[5] != '2'))) {
+		bb_error_msg_and_die("Unsupported cpio format, use newc or crc");
+	}
+
+	{
+	    unsigned long tmpsize;
+	    sscanf(cpio_header, "%6c%8x%8x%8x%8x%8x%8lx%8lx%16c%8x%8x%8x%8c",
+		    dummy, &inode, (unsigned int*)&file_header->mode,
+		    (unsigned int*)&file_header->uid, (unsigned int*)&file_header->gid,
+		    &nlink, &file_header->mtime, &tmpsize,
+		    dummy, &major, &minor, &namesize, dummy);
+	    file_header->size = tmpsize;
+	}
+
+	file_header->name = (char *) xzalloc(namesize + 1);
+	archive_xread_all(archive_handle, file_header->name, namesize); /* Read in filename */
+	archive_handle->offset += namesize;
+
+	/* Update offset amount and skip padding before file contents */
+	data_align(archive_handle, 4);
+
+	if (strcmp(file_header->name, "TRAILER!!!") == 0) {
+		printf("%d blocks\n", (int) (archive_handle->offset % 512 ? (archive_handle->offset / 512) + 1 : archive_handle->offset / 512)); /* Always round up */
+		if (saved_hardlinks) { /* Bummer - we still have unresolved hardlinks */
+			hardlinks_t *tmp = saved_hardlinks;
+			hardlinks_t *oldtmp = NULL;
+			while (tmp) {
+				bb_error_msg("%s not created: cannot resolve hardlink", tmp->entry->name);
+				oldtmp = tmp;
+				tmp = tmp->next;
+				free (oldtmp->entry->name);
+				free (oldtmp->entry);
+				free (oldtmp);
+			}
+			saved_hardlinks = NULL;
+			pending_hardlinks = 0;
+		}
+		return(EXIT_FAILURE);
+	}
+
+	if (S_ISLNK(file_header->mode)) {
+		file_header->link_name = (char *) xzalloc(file_header->size + 1);
+		archive_xread_all(archive_handle, file_header->link_name, file_header->size);
+		archive_handle->offset += file_header->size;
+		file_header->size = 0; /* Stop possible seeks in future */
+	} else {
+		file_header->link_name = NULL;
+	}
+	if (nlink > 1 && !S_ISDIR(file_header->mode)) {
+		if (file_header->size == 0) { /* Put file on a linked list for later */
+			hardlinks_t *new = xmalloc(sizeof(hardlinks_t));
+			new->next = saved_hardlinks;
+			new->inode = inode;
+			new->entry = file_header;
+			saved_hardlinks = new;
+			return(EXIT_SUCCESS); // Skip this one
+		} else { /* Found the file with data in */
+			hardlinks_t *tmp = saved_hardlinks;
+			pending_hardlinks = 1;
+			while (tmp) {
+				if (tmp->inode == inode) {
+					tmp->entry->link_name = bb_xstrdup(file_header->name);
+					nlink--;
+				}
+				tmp = tmp->next;
+			}
+			if (nlink > 1) {
+				bb_error_msg("error resolving hardlink: did you create the archive with GNU cpio 2.0-2.2?");
+			}
+		}
+	}
+	file_header->device = makedev(major, minor);
+
+	if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
+		archive_handle->action_data(archive_handle);
+		archive_handle->action_header(archive_handle->file_header);
+	} else {
+		data_skip(archive_handle);
+	}
+
+	archive_handle->offset += file_header->size;
+
+	free(file_header->link_name);
+
+	return (EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_tar.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_tar.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_tar.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,215 @@
+/* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ *  FIXME:
+ *    In privileged mode if uname and gname map to a uid and gid then use the
+ *    mapped value instead of the uid/gid values in tar header
+ *
+ *  References:
+ *    GNU tar and star man pages,
+ *    Opengroup's ustar interchange format,
+ *	http://www.opengroup.org/onlinepubs/007904975/utilities/pax.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/sysmacros.h>	/* For makedev */
+#include "unarchive.h"
+#include "libbb.h"
+
+#ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
+static char *longname = NULL;
+static char *linkname = NULL;
+#endif
+
+char get_header_tar(archive_handle_t *archive_handle)
+{
+	file_header_t *file_header = archive_handle->file_header;
+	union {
+		/* ustar header, Posix 1003.1 */
+		unsigned char raw[512];
+		struct {
+			char name[100];	/*   0-99 */
+			char mode[8];	/* 100-107 */
+			char uid[8];	/* 108-115 */
+			char gid[8];	/* 116-123 */
+			char size[12];	/* 124-135 */
+			char mtime[12];	/* 136-147 */
+			char chksum[8];	/* 148-155 */
+			char typeflag;	/* 156-156 */
+			char linkname[100];	/* 157-256 */
+			char magic[6];	/* 257-262 */
+			char version[2];	/* 263-264 */
+			char uname[32];	/* 265-296 */
+			char gname[32];	/* 297-328 */
+			char devmajor[8];	/* 329-336 */
+			char devminor[8];	/* 337-344 */
+			char prefix[155];	/* 345-499 */
+			char padding[12];	/* 500-512 */
+		} formated;
+	} tar;
+	long sum = 0;
+	long i;
+	static int end = 0;
+
+	/* Align header */
+	data_align(archive_handle, 512);
+
+	if (bb_full_read(archive_handle->src_fd, tar.raw, 512) != 512) {
+		/* Assume end of file */
+		bb_error_msg_and_die("Short header");
+		//return(EXIT_FAILURE);
+	}
+	archive_handle->offset += 512;
+
+	/* If there is no filename its an empty header */
+	if (tar.formated.name[0] == 0) {
+		if (end) {
+			/* This is the second consecutive empty header! End of archive!
+			 * Read until the end to empty the pipe from gz or bz2
+			 */
+			while (bb_full_read(archive_handle->src_fd, tar.raw, 512) == 512);
+			return(EXIT_FAILURE);
+		}
+		end = 1;
+		return(EXIT_SUCCESS);
+	}
+	end = 0;
+
+	/* Check header has valid magic, "ustar" is for the proper tar
+	 * 0's are for the old tar format
+	 */
+	if (strncmp(tar.formated.magic, "ustar", 5) != 0) {
+#ifdef CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY
+		if (strncmp(tar.formated.magic, "\0\0\0\0\0", 5) != 0)
+#endif
+			bb_error_msg_and_die("Invalid tar magic");
+	}
+	/* Do checksum on headers */
+	for (i =  0; i < 148 ; i++) {
+		sum += tar.raw[i];
+	}
+	sum += ' ' * 8;
+	for (i =  156; i < 512 ; i++) {
+		sum += tar.raw[i];
+	}
+	if (sum != strtol(tar.formated.chksum, NULL, 8)) {
+		bb_error_msg("Invalid tar header checksum");
+		return(EXIT_FAILURE);
+	}
+
+#ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
+	if (longname) {
+		file_header->name = longname;
+		longname = NULL;
+	}
+	else if (linkname) {
+		file_header->name = linkname;
+		linkname = NULL;
+	} else
+#endif
+	{
+		file_header->name = bb_xstrndup(tar.formated.name,100);
+
+		if (tar.formated.prefix[0]) {
+			char *temp = file_header->name;
+			file_header->name = concat_path_file(tar.formated.prefix, temp);
+			free(temp);
+		}
+	}
+
+	file_header->uid = strtol(tar.formated.uid, NULL, 8);
+	file_header->gid = strtol(tar.formated.gid, NULL, 8);
+	file_header->size = strtol(tar.formated.size, NULL, 8);
+	file_header->mtime = strtol(tar.formated.mtime, NULL, 8);
+	file_header->link_name = (tar.formated.linkname[0] != '\0') ?
+	    bb_xstrdup(tar.formated.linkname) : NULL;
+	file_header->device = makedev(strtol(tar.formated.devmajor, NULL, 8),
+		strtol(tar.formated.devminor, NULL, 8));
+
+	/* Set bits 0-11 of the files mode */
+	file_header->mode = 07777 & strtol(tar.formated.mode, NULL, 8);
+
+	/* Set bits 12-15 of the files mode */
+	switch (tar.formated.typeflag) {
+	/* busybox identifies hard links as being regular files with 0 size and a link name */
+	case '1':
+		file_header->mode |= S_IFREG;
+		break;
+	case '7':
+		/* Reserved for high performance files, treat as normal file */
+	case 0:
+	case '0':
+#ifdef CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY
+		if (last_char_is(file_header->name, '/')) {
+			file_header->mode |= S_IFDIR;
+		} else
+#endif
+			file_header->mode |= S_IFREG;
+		break;
+	case '2':
+		file_header->mode |= S_IFLNK;
+		break;
+	case '3':
+		file_header->mode |= S_IFCHR;
+		break;
+	case '4':
+		file_header->mode |= S_IFBLK;
+		break;
+	case '5':
+		file_header->mode |= S_IFDIR;
+		break;
+	case '6':
+		file_header->mode |= S_IFIFO;
+		break;
+#ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
+	case 'L': {
+			longname = xzalloc(file_header->size + 1);
+			archive_xread_all(archive_handle, longname, file_header->size);
+			archive_handle->offset += file_header->size;
+
+			return(get_header_tar(archive_handle));
+		}
+	case 'K': {
+			linkname = xzalloc(file_header->size + 1);
+			archive_xread_all(archive_handle, linkname, file_header->size);
+			archive_handle->offset += file_header->size;
+
+			file_header->name = linkname;
+			return(get_header_tar(archive_handle));
+		}
+	case 'D':	/* GNU dump dir */
+	case 'M':	/* Continuation of multi volume archive*/
+	case 'N':	/* Old GNU for names > 100 characters */
+	case 'S':	/* Sparse file */
+	case 'V':	/* Volume header */
+#endif
+	case 'g':	/* pax global header */
+	case 'x':	/* pax extended header */
+		bb_error_msg("Ignoring extension type %c", tar.formated.typeflag);
+		break;
+	default:
+		bb_error_msg("Unknown typeflag: 0x%x", tar.formated.typeflag);
+	}
+	{	/* Strip trailing '/' in directories */
+		/* Must be done after mode is set as '/' is used to check if its a directory */
+		char *tmp = last_char_is(file_header->name, '/');
+		if (tmp) {
+			*tmp = '\0';
+		}
+	}
+
+	if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
+		archive_handle->action_header(archive_handle->file_header);
+		archive_handle->flags |= ARCHIVE_EXTRACT_QUIET;
+		archive_handle->action_data(archive_handle);
+		llist_add_to(&(archive_handle->passed), file_header->name);
+	} else {
+		data_skip(archive_handle);
+	}
+	archive_handle->offset += file_header->size;
+
+	free(file_header->link_name);
+
+	return(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_tar_bz2.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_tar_bz2.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_tar_bz2.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,38 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "libbb.h"
+#include "unarchive.h"
+
+char get_header_tar_bz2(archive_handle_t *archive_handle)
+{
+	/* Cant lseek over pipe's */
+	archive_handle->seek = seek_by_char;
+
+	archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompressStream);
+	archive_handle->offset = 0;
+	while (get_header_tar(archive_handle) == EXIT_SUCCESS);
+
+	/* Can only do one file at a time */
+	return(EXIT_FAILURE);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_tar_gz.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_tar_gz.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_tar_gz.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,42 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+
+#include "libbb.h"
+#include "unarchive.h"
+
+char get_header_tar_gz(archive_handle_t *archive_handle)
+{
+	unsigned char magic[2];
+
+	/* Cant lseek over pipe's */
+	archive_handle->seek = seek_by_char;
+
+	archive_xread_all(archive_handle, &magic, 2);
+	if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) {
+		bb_error_msg_and_die("Invalid gzip magic");
+	}
+
+	check_header_gzip(archive_handle->src_fd);
+
+	archive_handle->src_fd = open_transformer(archive_handle->src_fd, inflate_gunzip);
+	archive_handle->offset = 0;
+	while (get_header_tar(archive_handle) == EXIT_SUCCESS);
+
+	/* Can only do one file at a time */
+	return(EXIT_FAILURE);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_tar_lzma.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_tar_lzma.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/get_header_tar_lzma.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+/*
+ * Small lzma deflate implementation.
+ * Copyright (C) 2006  Aurelien Jacobs <aurel at gnuage.org>
+ *
+ * Licensed under GPL v2, see file LICENSE in this tarball for details.
+ */
+
+#include "unarchive.h"
+
+char get_header_tar_lzma(archive_handle_t * archive_handle)
+{
+	/* Can't lseek over pipes */
+	archive_handle->seek = seek_by_char;
+
+	archive_handle->src_fd = open_transformer(archive_handle->src_fd, unlzma);
+	archive_handle->offset = 0;
+	while (get_header_tar(archive_handle) == EXIT_SUCCESS);
+
+	/* Can only do one file at a time */
+	return EXIT_FAILURE;
+}
+
+/* vi:set ts=4: */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/header_list.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/header_list.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/header_list.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include "unarchive.h"
+
+void header_list(const file_header_t *file_header)
+{
+	puts(file_header->name);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/header_skip.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/header_skip.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/header_skip.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,6 @@
+#include <stdio.h>
+#include "unarchive.h"
+
+void header_skip(const file_header_t *file_header ATTRIBUTE_UNUSED)
+{
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/header_verbose_list.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/header_verbose_list.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/header_verbose_list.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include "libbb.h"
+#include "unarchive.h"
+
+void header_verbose_list(const file_header_t *file_header)
+{
+	struct tm *mtime = localtime(&(file_header->mtime));
+
+	printf("%s %d/%d%10u %4u-%02u-%02u %02u:%02u:%02u %s",
+		bb_mode_string(file_header->mode),
+		file_header->uid,
+		file_header->gid,
+		(unsigned int) file_header->size,
+		1900 + mtime->tm_year,
+		1 + mtime->tm_mon,
+		mtime->tm_mday,
+		mtime->tm_hour,
+		mtime->tm_min,
+		mtime->tm_sec,
+		file_header->name);
+
+	if (file_header->link_name) {
+		printf(" -> %s", file_header->link_name);
+	}
+	/* putchar isnt used anywhere else i dont think */
+	puts("");
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/init_handle.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/init_handle.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/init_handle.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,35 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include "libbb.h"
+#include "unarchive.h"
+
+archive_handle_t *init_handle(void)
+{
+	archive_handle_t *archive_handle;
+
+	/* Initialise default values */
+	archive_handle = xzalloc(sizeof(archive_handle_t));
+	archive_handle->file_header = xmalloc(sizeof(file_header_t));
+	archive_handle->action_header = header_skip;
+	archive_handle->action_data = data_skip;
+	archive_handle->filter = filter_accept_all;
+	archive_handle->seek = seek_by_jump;
+
+	return(archive_handle);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/open_transformer.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/open_transformer.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/open_transformer.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,41 @@
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "libbb.h"
+
+#include "unarchive.h"
+
+/* transformer(), more than meets the eye */
+int open_transformer(int src_fd, int (*transformer)(int src_fd, int dst_fd))
+{
+	int fd_pipe[2];
+	int pid;
+
+	if (pipe(fd_pipe) != 0) {
+		bb_perror_msg_and_die("Can't create pipe");
+	}
+
+	pid = fork();
+	if (pid == -1) {
+		bb_perror_msg_and_die("Fork failed");
+	}
+
+	if (pid == 0) {
+		/* child process */
+	    close(fd_pipe[0]); /* We don't wan't to read from the parent */
+	    transformer(src_fd, fd_pipe[1]);
+	    close(fd_pipe[1]); /* Send EOF */
+		close(src_fd);
+	    exit(0);
+	    /* notreached */
+	}
+
+	/* parent process */
+	close(fd_pipe[1]); /* Don't want to write to the child */
+
+	return(fd_pipe[0]);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/seek_by_char.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/seek_by_char.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/seek_by_char.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+/* vi:set ts=4:*/
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdlib.h>
+
+#include "unarchive.h"
+#include "libbb.h"
+
+
+
+/*	If we are reading through a pipe(), or from stdin then we cant lseek,
+ *  we must read and discard the data to skip over it.
+ *
+ *  TODO: rename to seek_by_read
+ */
+void seek_by_char(const archive_handle_t *archive_handle, const unsigned int jump_size)
+{
+	if (jump_size) {
+		bb_copyfd_size(archive_handle->src_fd, -1, jump_size);
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/seek_by_jump.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/seek_by_jump.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/seek_by_jump.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,35 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "libbb.h"
+#include "unarchive.h"
+
+void seek_by_jump(const archive_handle_t *archive_handle, const unsigned int amount)
+{
+	if (lseek(archive_handle->src_fd, (off_t) amount, SEEK_CUR) == (off_t) -1) {
+#ifdef CONFIG_FEATURE_UNARCHIVE_TAPE
+		if (errno == ESPIPE) {
+			seek_by_char(archive_handle, amount);
+		} else
+#endif
+			bb_perror_msg_and_die("Seek failure");
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/unpack_ar_archive.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/unpack_ar_archive.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/libunarchive/unpack_ar_archive.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,22 @@
+/* vi:set ts=4:*/
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include "unarchive.h"
+#include "libbb.h"
+
+void unpack_ar_archive(archive_handle_t *ar_archive)
+{
+	char magic[7];
+
+	archive_xread_all(ar_archive, magic, 7);
+	if (strncmp(magic, "!<arch>", 7) != 0) {
+		bb_error_msg_and_die("Invalid ar magic");
+	}
+	ar_archive->offset += 7;
+
+	while (get_header_ar(ar_archive) == EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/rpm.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/rpm.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/rpm.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,337 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini rpm applet for busybox
+ *
+ * Copyright (C) 2001,2002 by Laurence Anderson
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <netinet/in.h> /* For ntohl & htonl function */
+#include <string.h> /* For strncmp */
+#include <sys/mman.h> /* For mmap */
+#include <time.h> /* For ctime */
+
+#include "busybox.h"
+#include "unarchive.h"
+
+#define RPM_HEADER_MAGIC "\216\255\350"
+#define RPM_CHAR_TYPE		1
+#define RPM_INT8_TYPE		2
+#define RPM_INT16_TYPE		3
+#define RPM_INT32_TYPE		4
+/* #define RPM_INT64_TYPE	5   ---- These aren't supported (yet) */
+#define RPM_STRING_TYPE		6
+#define RPM_BIN_TYPE		7
+#define RPM_STRING_ARRAY_TYPE	8
+#define RPM_I18NSTRING_TYPE	9
+
+#define	RPMTAG_NAME				1000
+#define	RPMTAG_VERSION			1001
+#define	RPMTAG_RELEASE			1002
+#define	RPMTAG_SUMMARY			1004
+#define	RPMTAG_DESCRIPTION		1005
+#define	RPMTAG_BUILDTIME		1006
+#define	RPMTAG_BUILDHOST		1007
+#define	RPMTAG_SIZE			1009
+#define	RPMTAG_VENDOR			1011
+#define	RPMTAG_LICENSE			1014
+#define	RPMTAG_PACKAGER			1015
+#define	RPMTAG_GROUP			1016
+#define RPMTAG_URL			1020
+#define	RPMTAG_PREIN			1023
+#define	RPMTAG_POSTIN			1024
+#define	RPMTAG_FILEFLAGS		1037
+#define	RPMTAG_FILEUSERNAME		1039
+#define	RPMTAG_FILEGROUPNAME		1040
+#define	RPMTAG_SOURCERPM		1044
+#define	RPMTAG_PREINPROG		1085
+#define	RPMTAG_POSTINPROG		1086
+#define	RPMTAG_PREFIXS			1098
+#define	RPMTAG_DIRINDEXES		1116
+#define	RPMTAG_BASENAMES		1117
+#define	RPMTAG_DIRNAMES			1118
+#define	RPMFILE_CONFIG			(1 << 0)
+#define	RPMFILE_DOC			(1 << 1)
+
+enum rpm_functions_e {
+	rpm_query = 1,
+	rpm_install = 2,
+	rpm_query_info = 4,
+	rpm_query_package = 8,
+	rpm_query_list = 16,
+	rpm_query_list_doc = 32,
+	rpm_query_list_config = 64
+};
+
+typedef struct {
+	uint32_t tag; /* 4 byte tag */
+	uint32_t type; /* 4 byte type */
+	uint32_t offset; /* 4 byte offset */
+	uint32_t count; /* 4 byte count */
+} rpm_index;
+
+static void *map;
+static rpm_index **mytags;
+static int tagcount;
+
+void extract_cpio_gz(int fd);
+rpm_index **rpm_gettags(int fd, int *num_tags);
+int bsearch_rpmtag(const void *key, const void *item);
+char *rpm_getstring(int tag, int itemindex);
+int rpm_getint(int tag, int itemindex);
+int rpm_getcount(int tag);
+void exec_script(int progtag, int datatag, char *prefix);
+void fileaction_dobackup(char *filename, int fileref);
+void fileaction_setowngrp(char *filename, int fileref);
+void fileaction_list(char *filename, int itemno);
+void loop_through_files(int filetag, void (*fileaction)(char *filename, int fileref));
+
+int rpm_main(int argc, char **argv)
+{
+	int opt = 0, func = 0, rpm_fd, offset;
+
+	while ((opt = getopt(argc, argv, "iqpldc")) != -1) {
+		switch (opt) {
+		case 'i': // First arg: Install mode, with q: Information
+			if (!func) func |= rpm_install;
+			else func |= rpm_query_info;
+			break;
+		case 'q': // First arg: Query mode
+			if (!func) func |= rpm_query;
+			else bb_show_usage();
+			break;
+		case 'p': // Query a package
+			func |= rpm_query_package;
+			break;
+		case 'l': // List files in a package
+			func |= rpm_query_list;
+			break;
+		case 'd': // List doc files in a package (implies list)
+			func |= rpm_query_list;
+			func |= rpm_query_list_doc;
+			break;
+		case 'c': // List config files in a package (implies list)
+			func |= rpm_query_list;
+			func |= rpm_query_list_config;
+			break;
+		default:
+			bb_show_usage();
+		}
+	}
+
+	if (optind == argc) bb_show_usage();
+	while (optind < argc) {
+		rpm_fd = bb_xopen(argv[optind], O_RDONLY);
+		mytags = rpm_gettags(rpm_fd, (int *) &tagcount);
+		offset = lseek(rpm_fd, 0, SEEK_CUR);
+		if (!mytags) { printf("Error reading rpm header\n"); exit(-1); }
+		map = mmap(0, offset > getpagesize() ? (offset + offset % getpagesize()) : getpagesize(), PROT_READ, MAP_PRIVATE, rpm_fd, 0); // Mimimum is one page
+		if (func & rpm_install) {
+			loop_through_files(RPMTAG_BASENAMES, fileaction_dobackup); /* Backup any config files */
+			extract_cpio_gz(rpm_fd); // Extact the archive
+			loop_through_files(RPMTAG_BASENAMES, fileaction_setowngrp); /* Set the correct file uid/gid's */
+		} else if (func & rpm_query && func & rpm_query_package) {
+			if (!((func & rpm_query_info) || (func & rpm_query_list))) { // If just a straight query, just give package name
+				printf("%s-%s-%s\n", rpm_getstring(RPMTAG_NAME, 0), rpm_getstring(RPMTAG_VERSION, 0), rpm_getstring(RPMTAG_RELEASE, 0));
+			}
+			if (func & rpm_query_info) {
+				/* Do the nice printout */
+				time_t bdate_time;
+				struct tm *bdate;
+				char bdatestring[50];
+				printf("Name        : %-29sRelocations: %s\n", rpm_getstring(RPMTAG_NAME, 0), rpm_getstring(RPMTAG_PREFIXS, 0) ? rpm_getstring(RPMTAG_PREFIXS, 0) : "(not relocateable)");
+				printf("Version     : %-34sVendor: %s\n", rpm_getstring(RPMTAG_VERSION, 0), rpm_getstring(RPMTAG_VENDOR, 0) ? rpm_getstring(RPMTAG_VENDOR, 0) : "(none)");
+				bdate_time = rpm_getint(RPMTAG_BUILDTIME, 0);
+				bdate = localtime((time_t *) &bdate_time);
+				strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate);
+				printf("Release     : %-30sBuild Date: %s\n", rpm_getstring(RPMTAG_RELEASE, 0), bdatestring);
+				printf("Install date: %-30sBuild Host: %s\n", "(not installed)", rpm_getstring(RPMTAG_BUILDHOST, 0));
+				printf("Group       : %-30sSource RPM: %s\n", rpm_getstring(RPMTAG_GROUP, 0), rpm_getstring(RPMTAG_SOURCERPM, 0));
+				printf("Size        : %-33dLicense: %s\n", rpm_getint(RPMTAG_SIZE, 0), rpm_getstring(RPMTAG_LICENSE, 0));
+				printf("URL         : %s\n", rpm_getstring(RPMTAG_URL, 0));
+				printf("Summary     : %s\n", rpm_getstring(RPMTAG_SUMMARY, 0));
+				printf("Description :\n%s\n", rpm_getstring(RPMTAG_DESCRIPTION, 0));
+			}
+			if (func & rpm_query_list) {
+				int count, it, flags;
+				count = rpm_getcount(RPMTAG_BASENAMES);
+				for (it = 0; it < count; it++) {
+					flags = rpm_getint(RPMTAG_FILEFLAGS, it);
+					switch ((func & rpm_query_list_doc) + (func & rpm_query_list_config))
+					{
+						case rpm_query_list_doc: if (!(flags & RPMFILE_DOC)) continue; break;
+						case rpm_query_list_config: if (!(flags & RPMFILE_CONFIG)) continue; break;
+						case rpm_query_list_doc + rpm_query_list_config: if (!((flags & RPMFILE_CONFIG) || (flags & RPMFILE_DOC))) continue; break;
+					}
+					printf("%s%s\n", rpm_getstring(RPMTAG_DIRNAMES, rpm_getint(RPMTAG_DIRINDEXES, it)), rpm_getstring(RPMTAG_BASENAMES, it));
+				}
+			}
+		}
+		optind++;
+		free (mytags);
+	}
+	return 0;
+}
+
+void extract_cpio_gz(int fd) {
+	archive_handle_t *archive_handle;
+	unsigned char magic[2];
+
+	/* Initialise */
+	archive_handle = init_handle();
+	archive_handle->seek = seek_by_char;
+	//archive_handle->action_header = header_list;
+	archive_handle->action_data = data_extract_all;
+	archive_handle->flags |= ARCHIVE_PRESERVE_DATE;
+	archive_handle->flags |= ARCHIVE_CREATE_LEADING_DIRS;
+	archive_handle->src_fd = fd;
+	archive_handle->offset = 0;
+
+	bb_xread_all(archive_handle->src_fd, &magic, 2);
+	if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) {
+		bb_error_msg_and_die("Invalid gzip magic");
+	}
+	check_header_gzip(archive_handle->src_fd);
+	bb_xchdir("/"); // Install RPM's to root
+
+	archive_handle->src_fd = open_transformer(archive_handle->src_fd, inflate_gunzip);
+	archive_handle->offset = 0;
+	while (get_header_cpio(archive_handle) == EXIT_SUCCESS);
+}
+
+
+rpm_index **rpm_gettags(int fd, int *num_tags)
+{
+	rpm_index **tags = xzalloc(200 * sizeof(struct rpmtag *)); /* We should never need mode than 200, and realloc later */
+	int pass, tagindex = 0;
+	lseek(fd, 96, SEEK_CUR); /* Seek past the unused lead */
+
+	for (pass = 0; pass < 2; pass++) { /* 1st pass is the signature headers, 2nd is the main stuff */
+		struct {
+			char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */
+			uint8_t version; /* 1 byte version number */
+			uint32_t reserved; /* 4 bytes reserved */
+			uint32_t entries; /* Number of entries in header (4 bytes) */
+			uint32_t size; /* Size of store (4 bytes) */
+		} header;
+		rpm_index *tmpindex;
+		int storepos;
+
+		read(fd, &header, sizeof(header));
+		if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) return NULL; /* Invalid magic */
+		if (header.version != 1) return NULL; /* This program only supports v1 headers */
+		header.size = ntohl(header.size);
+		header.entries = ntohl(header.entries);
+		storepos = lseek(fd,0,SEEK_CUR) + header.entries * 16;
+
+		while (header.entries--) {
+			tmpindex = tags[tagindex++] = xmalloc(sizeof(rpm_index));
+			read(fd, tmpindex, sizeof(rpm_index));
+			tmpindex->tag = ntohl(tmpindex->tag); tmpindex->type = ntohl(tmpindex->type); tmpindex->count = ntohl(tmpindex->count);
+			tmpindex->offset = storepos + ntohl(tmpindex->offset);
+			if (pass==0) tmpindex->tag -= 743;
+		}
+		lseek(fd, header.size, SEEK_CUR); /* Seek past store */
+		if (pass==0) lseek(fd, (8 - (lseek(fd,0,SEEK_CUR) % 8)) % 8, SEEK_CUR); /* Skip padding to 8 byte boundary after reading signature headers */
+	}
+	tags = realloc(tags, tagindex * sizeof(struct rpmtag *)); /* realloc tags to save space */
+	*num_tags = tagindex;
+	return tags; /* All done, leave the file at the start of the gzipped cpio archive */
+}
+
+int bsearch_rpmtag(const void *key, const void *item)
+{
+	int *tag = (int *)key;
+	rpm_index **tmp = (rpm_index **) item;
+	return (*tag - tmp[0]->tag);
+}
+
+int rpm_getcount(int tag)
+{
+	rpm_index **found;
+	found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag);
+	if (!found) return 0;
+	else return found[0]->count;
+}
+
+char *rpm_getstring(int tag, int itemindex)
+{
+	rpm_index **found;
+	found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag);
+	if (!found || itemindex >= found[0]->count) return NULL;
+	if (found[0]->type == RPM_STRING_TYPE || found[0]->type == RPM_I18NSTRING_TYPE || found[0]->type == RPM_STRING_ARRAY_TYPE) {
+		int n;
+		char *tmpstr = (char *) (map + found[0]->offset);
+		for (n=0; n < itemindex; n++) tmpstr = tmpstr + strlen(tmpstr) + 1;
+		return tmpstr;
+	} else return NULL;
+}
+
+int rpm_getint(int tag, int itemindex)
+{
+	rpm_index **found;
+	int n, *tmpint;
+	/* gcc throws warnings here when sizeof(void*)!=sizeof(int) ...
+	 * it's ok to ignore it because tag won't be used as a pointer */
+	found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag);
+	if (!found || itemindex >= found[0]->count) return -1;
+	tmpint = (int *) (map + found[0]->offset);
+	if (found[0]->type == RPM_INT32_TYPE) {
+		for (n=0; n<itemindex; n++) tmpint = (int *) ((void *) tmpint + 4);
+		return ntohl(*tmpint);
+	} else if (found[0]->type == RPM_INT16_TYPE) {
+		for (n=0; n<itemindex; n++) tmpint = (int *) ((void *) tmpint + 2);
+		return ntohs(*tmpint);
+	} else if (found[0]->type == RPM_INT8_TYPE) {
+		for (n=0; n<itemindex; n++) tmpint = (int *) ((void *) tmpint + 1);
+		return ntohs(*tmpint);
+	} else return -1;
+}
+
+void fileaction_dobackup(char *filename, int fileref)
+{
+	struct stat oldfile;
+	int stat_res;
+	char *newname;
+	if (rpm_getint(RPMTAG_FILEFLAGS, fileref) & RPMFILE_CONFIG) { /* Only need to backup config files */
+		stat_res = lstat (filename, &oldfile);
+		if (stat_res == 0 && S_ISREG(oldfile.st_mode)) { /* File already exists  - really should check MD5's etc to see if different */
+			newname = bb_xstrdup(filename);
+			newname = strcat(newname, ".rpmorig");
+			copy_file(filename, newname, FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS);
+			remove_file(filename, FILEUTILS_RECUR | FILEUTILS_FORCE);
+			free(newname);
+		}
+	}
+}
+
+void fileaction_setowngrp(char *filename, int fileref)
+{
+	int uid, gid;
+	uid = bb_xgetpwnam(rpm_getstring(RPMTAG_FILEUSERNAME, fileref));
+	gid = bb_xgetgrnam(rpm_getstring(RPMTAG_FILEGROUPNAME, fileref));
+	chown (filename, uid, gid);
+}
+
+void fileaction_list(char *filename, int ATTRIBUTE_UNUSED fileref)
+{
+	printf("%s\n", filename);
+}
+
+void loop_through_files(int filetag, void (*fileaction)(char *filename, int fileref))
+{
+	int count = 0;
+	while (rpm_getstring(filetag, count)) {
+		char * filename = bb_xasprintf("%s%s",
+			rpm_getstring(RPMTAG_DIRNAMES, rpm_getint(RPMTAG_DIRINDEXES,
+			count)), rpm_getstring(RPMTAG_BASENAMES, count));
+		fileaction(filename, count++);
+		free(filename);
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/rpm2cpio.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/rpm2cpio.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/rpm2cpio.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,106 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini rpm2cpio implementation for busybox
+ *
+ * Copyright (C) 2001 by Laurence Anderson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <sys/types.h>
+#include <netinet/in.h> /* For ntohl & htonl function */
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include "busybox.h"
+#include "unarchive.h"
+
+#define RPM_MAGIC "\355\253\356\333"
+#define RPM_HEADER_MAGIC "\216\255\350"
+
+struct rpm_lead {
+    unsigned char magic[4];
+    uint8_t major, minor;
+    uint16_t type;
+    uint16_t archnum;
+    char name[66];
+    uint16_t osnum;
+    uint16_t signature_type;
+    char reserved[16];
+};
+
+struct rpm_header {
+	char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */
+	uint8_t version; /* 1 byte version number */
+	uint32_t reserved; /* 4 bytes reserved */
+	uint32_t entries; /* Number of entries in header (4 bytes) */
+	uint32_t size; /* Size of store (4 bytes) */
+};
+
+static void skip_header(int rpm_fd)
+{
+	struct rpm_header header;
+
+	bb_xread_all(rpm_fd, &header, sizeof(struct rpm_header));
+	if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) {
+		bb_error_msg_and_die("Invalid RPM header magic"); /* Invalid magic */
+	}
+	if (header.version != 1) {
+		bb_error_msg_and_die("Unsupported RPM header version"); /* This program only supports v1 headers */
+	}
+	header.entries = ntohl(header.entries);
+	header.size = ntohl(header.size);
+	lseek (rpm_fd, 16 * header.entries, SEEK_CUR); /* Seek past index entries */
+	lseek (rpm_fd, header.size, SEEK_CUR); /* Seek past store */
+}
+
+/* No getopt required */
+int rpm2cpio_main(int argc, char **argv)
+{
+	struct rpm_lead lead;
+	int rpm_fd;
+	unsigned char magic[2];
+
+	if (argc == 1) {
+		rpm_fd = STDIN_FILENO;
+	} else {
+		rpm_fd = bb_xopen(argv[1], O_RDONLY);
+	}
+
+	bb_xread_all(rpm_fd, &lead, sizeof(struct rpm_lead));
+	if (strncmp((char *) &lead.magic, RPM_MAGIC, 4) != 0) {
+		bb_error_msg_and_die("Invalid RPM magic"); /* Just check the magic, the rest is irrelevant */
+	}
+
+	/* Skip the signature header */
+	skip_header(rpm_fd);
+	lseek(rpm_fd, (8 - (lseek(rpm_fd, 0, SEEK_CUR) % 8)) % 8, SEEK_CUR);
+
+	/* Skip the main header */
+	skip_header(rpm_fd);
+
+	bb_xread_all(rpm_fd, &magic, 2);
+	if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) {
+		bb_error_msg_and_die("Invalid gzip magic");
+	}
+
+	check_header_gzip(rpm_fd);
+	if (inflate_gunzip(rpm_fd, STDOUT_FILENO) != 0) {
+		bb_error_msg("Error inflating");
+	}
+
+	close(rpm_fd);
+
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/tar.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/tar.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/tar.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,870 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini tar implementation for busybox
+ *
+ * Modified to use common extraction code used by ar, cpio, dpkg-deb, dpkg
+ *  Glenn McGrath <bug1 at iinet.net.au>
+ *
+ * Note, that as of BusyBox-0.43, tar has been completely rewritten from the
+ * ground up.  It still has remnants of the old code lying about, but it is
+ * very different now (i.e., cleaner, less global variables, etc.)
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Based in part in the tar implementation in sash
+ *  Copyright (c) 1999 by David I. Bell
+ *  Permission is granted to use, distribute, or modify this source,
+ *  provided that this copyright notice remains intact.
+ *  Permission to distribute sash derived code under the GPL has been granted.
+ *
+ * Based in part on the tar implementation from busybox-0.28
+ *  Copyright (C) 1995 Bruce Perens
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <fcntl.h>
+#include <getopt.h>
+#include <search.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fnmatch.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/sysmacros.h>     /* major() and minor() */
+#include "unarchive.h"
+#include "busybox.h"
+
+#ifdef CONFIG_FEATURE_TAR_CREATE
+
+/* Tar file constants  */
+
+#define TAR_BLOCK_SIZE		512
+
+/* POSIX tar Header Block, from POSIX 1003.1-1990  */
+#define NAME_SIZE			100
+struct TarHeader {		/* byte offset */
+	char name[NAME_SIZE];	/*   0-99 */
+	char mode[8];		/* 100-107 */
+	char uid[8];		/* 108-115 */
+	char gid[8];		/* 116-123 */
+	char size[12];		/* 124-135 */
+	char mtime[12];		/* 136-147 */
+	char chksum[8];		/* 148-155 */
+	char typeflag;		/* 156-156 */
+	char linkname[NAME_SIZE];	/* 157-256 */
+	char magic[6];		/* 257-262 */
+	char version[2];	/* 263-264 */
+	char uname[32];		/* 265-296 */
+	char gname[32];		/* 297-328 */
+	char devmajor[8];	/* 329-336 */
+	char devminor[8];	/* 337-344 */
+	char prefix[155];	/* 345-499 */
+	char padding[12];	/* 500-512 (pad to exactly the TAR_BLOCK_SIZE) */
+};
+typedef struct TarHeader TarHeader;
+
+/*
+** writeTarFile(),  writeFileToTarball(), and writeTarHeader() are
+** the only functions that deal with the HardLinkInfo structure.
+** Even these functions use the xxxHardLinkInfo() functions.
+*/
+typedef struct HardLinkInfo HardLinkInfo;
+struct HardLinkInfo {
+	HardLinkInfo *next;	/* Next entry in list */
+	dev_t dev;			/* Device number */
+	ino_t ino;			/* Inode number */
+	short linkCount;	/* (Hard) Link Count */
+	char name[1];		/* Start of filename (must be last) */
+};
+
+/* Some info to be carried along when creating a new tarball */
+struct TarBallInfo {
+	char *fileName;			/* File name of the tarball */
+	int tarFd;				/* Open-for-write file descriptor
+							   for the tarball */
+	struct stat statBuf;	/* Stat info for the tarball, letting
+							   us know the inode and device that the
+							   tarball lives, so we can avoid trying
+							   to include the tarball into itself */
+	int verboseFlag;		/* Whether to print extra stuff or not */
+	const llist_t *excludeList;	/* List of files to not include */
+	HardLinkInfo *hlInfoHead;	/* Hard Link Tracking Information */
+	HardLinkInfo *hlInfo;	/* Hard Link Info for the current file */
+};
+typedef struct TarBallInfo TarBallInfo;
+
+/* A nice enum with all the possible tar file content types */
+enum TarFileType {
+	REGTYPE = '0',		/* regular file */
+	REGTYPE0 = '\0',	/* regular file (ancient bug compat) */
+	LNKTYPE = '1',		/* hard link */
+	SYMTYPE = '2',		/* symbolic link */
+	CHRTYPE = '3',		/* character special */
+	BLKTYPE = '4',		/* block special */
+	DIRTYPE = '5',		/* directory */
+	FIFOTYPE = '6',		/* FIFO special */
+	CONTTYPE = '7',		/* reserved */
+	GNULONGLINK = 'K',	/* GNU long (>100 chars) link name */
+	GNULONGNAME = 'L',	/* GNU long (>100 chars) file name */
+};
+typedef enum TarFileType TarFileType;
+
+/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */
+static inline void addHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr,
+					struct stat *statbuf,
+					const char *name)
+{
+	/* Note: hlInfoHeadPtr can never be NULL! */
+	HardLinkInfo *hlInfo;
+
+	hlInfo = (HardLinkInfo *) xmalloc(sizeof(HardLinkInfo) + strlen(name));
+	hlInfo->next = *hlInfoHeadPtr;
+	*hlInfoHeadPtr = hlInfo;
+	hlInfo->dev = statbuf->st_dev;
+	hlInfo->ino = statbuf->st_ino;
+	hlInfo->linkCount = statbuf->st_nlink;
+	strcpy(hlInfo->name, name);
+}
+
+static void freeHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr)
+{
+	HardLinkInfo *hlInfo = NULL;
+	HardLinkInfo *hlInfoNext = NULL;
+
+	if (hlInfoHeadPtr) {
+		hlInfo = *hlInfoHeadPtr;
+		while (hlInfo) {
+			hlInfoNext = hlInfo->next;
+			free(hlInfo);
+			hlInfo = hlInfoNext;
+		}
+		*hlInfoHeadPtr = NULL;
+	}
+	return;
+}
+
+/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */
+static inline HardLinkInfo *findHardLinkInfo(HardLinkInfo * hlInfo, struct stat *statbuf)
+{
+	while (hlInfo) {
+		if ((statbuf->st_ino == hlInfo->ino) && (statbuf->st_dev == hlInfo->dev))
+			break;
+		hlInfo = hlInfo->next;
+	}
+	return (hlInfo);
+}
+
+/* Put an octal string into the specified buffer.
+ * The number is zero and space padded and possibly null padded.
+ * Returns TRUE if successful.  */
+static int putOctal(char *cp, int len, long value)
+{
+	int tempLength;
+	char tempBuffer[32];
+	char *tempString = tempBuffer;
+
+	/* Create a string of the specified length with an initial space,
+	 * leading zeroes and the octal number, and a trailing null.  */
+	sprintf(tempString, "%0*lo", len - 1, value);
+
+	/* If the string is too large, suppress the leading space.  */
+	tempLength = strlen(tempString) + 1;
+	if (tempLength > len) {
+		tempLength--;
+		tempString++;
+	}
+
+	/* If the string is still too large, suppress the trailing null.  */
+	if (tempLength > len)
+		tempLength--;
+
+	/* If the string is still too large, fail.  */
+	if (tempLength > len)
+		return FALSE;
+
+	/* Copy the string to the field.  */
+	memcpy(cp, tempString, len);
+
+	return TRUE;
+}
+
+/* Write out a tar header for the specified file/directory/whatever */
+static inline int writeTarHeader(struct TarBallInfo *tbInfo,
+		const char *header_name, const char *real_name, struct stat *statbuf)
+{
+	long chksum = 0;
+	struct TarHeader header;
+	const unsigned char *cp = (const unsigned char *) &header;
+	ssize_t size = sizeof(struct TarHeader);
+
+	memset(&header, 0, size);
+
+	safe_strncpy(header.name, header_name, sizeof(header.name));
+
+	putOctal(header.mode, sizeof(header.mode), statbuf->st_mode);
+	putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
+	putOctal(header.gid, sizeof(header.gid), statbuf->st_gid);
+	putOctal(header.size, sizeof(header.size), 0);	/* Regular file size is handled later */
+	putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime);
+	strcpy(header.magic, "ustar  ");
+
+	/* Enter the user and group names (default to root if it fails) */
+	if (bb_getpwuid(header.uname, statbuf->st_uid, sizeof(header.uname)) == NULL)
+		strcpy(header.uname, "root");
+	if (bb_getgrgid(header.gname, statbuf->st_gid, sizeof(header.gname)) == NULL)
+		strcpy(header.gname, "root");
+
+	if (tbInfo->hlInfo) {
+		/* This is a hard link */
+		header.typeflag = LNKTYPE;
+		strncpy(header.linkname, tbInfo->hlInfo->name,
+				sizeof(header.linkname));
+	} else if (S_ISLNK(statbuf->st_mode)) {
+		char *lpath = xreadlink(real_name);
+
+		if (!lpath)		/* Already printed err msg inside xreadlink() */
+			return (FALSE);
+		header.typeflag = SYMTYPE;
+		strncpy(header.linkname, lpath, sizeof(header.linkname));
+		free(lpath);
+	} else if (S_ISDIR(statbuf->st_mode)) {
+		header.typeflag = DIRTYPE;
+		strncat(header.name, "/", sizeof(header.name));
+	} else if (S_ISCHR(statbuf->st_mode)) {
+		header.typeflag = CHRTYPE;
+		putOctal(header.devmajor, sizeof(header.devmajor),
+				 major(statbuf->st_rdev));
+		putOctal(header.devminor, sizeof(header.devminor),
+				 minor(statbuf->st_rdev));
+	} else if (S_ISBLK(statbuf->st_mode)) {
+		header.typeflag = BLKTYPE;
+		putOctal(header.devmajor, sizeof(header.devmajor),
+				 major(statbuf->st_rdev));
+		putOctal(header.devminor, sizeof(header.devminor),
+				 minor(statbuf->st_rdev));
+	} else if (S_ISFIFO(statbuf->st_mode)) {
+		header.typeflag = FIFOTYPE;
+	} else if (S_ISREG(statbuf->st_mode)) {
+		header.typeflag = REGTYPE;
+		putOctal(header.size, sizeof(header.size), statbuf->st_size);
+	} else {
+		bb_error_msg("%s: Unknown file type", real_name);
+		return (FALSE);
+	}
+
+	/* Calculate and store the checksum (i.e., the sum of all of the bytes of
+	 * the header).  The checksum field must be filled with blanks for the
+	 * calculation.  The checksum field is formatted differently from the
+	 * other fields: it has [6] digits, a null, then a space -- rather than
+	 * digits, followed by a null like the other fields... */
+	memset(header.chksum, ' ', sizeof(header.chksum));
+	cp = (const unsigned char *) &header;
+	while (size-- > 0)
+		chksum += *cp++;
+	putOctal(header.chksum, 7, chksum);
+
+	/* Now write the header out to disk */
+	if ((size =
+		 bb_full_write(tbInfo->tarFd, (char *) &header,
+					sizeof(struct TarHeader))) < 0) {
+		bb_error_msg(bb_msg_io_error, real_name);
+		return (FALSE);
+	}
+	/* Pad the header up to the tar block size */
+	for (; size < TAR_BLOCK_SIZE; size++) {
+		write(tbInfo->tarFd, "\0", 1);
+	}
+	/* Now do the verbose thing (or not) */
+
+	if (tbInfo->verboseFlag) {
+		FILE *vbFd = stdout;
+
+		if (tbInfo->tarFd == STDOUT_FILENO)	/* If the archive goes to stdout, verbose to stderr */
+			vbFd = stderr;
+
+		fprintf(vbFd, "%s\n", header.name);
+	}
+
+	return (TRUE);
+}
+
+# ifdef CONFIG_FEATURE_TAR_FROM
+static inline int exclude_file(const llist_t *excluded_files, const char *file)
+{
+	while (excluded_files) {
+		if (excluded_files->data[0] == '/') {
+			if (fnmatch(excluded_files->data, file,
+						FNM_PATHNAME | FNM_LEADING_DIR) == 0)
+				return 1;
+		} else {
+			const char *p;
+
+			for (p = file; p[0] != '\0'; p++) {
+				if ((p == file || p[-1] == '/') && p[0] != '/' &&
+					fnmatch(excluded_files->data, p,
+							FNM_PATHNAME | FNM_LEADING_DIR) == 0)
+					return 1;
+			}
+		}
+		excluded_files = excluded_files->link;
+	}
+
+	return 0;
+}
+# else
+#define exclude_file(excluded_files, file) 0
+# endif
+
+static int writeFileToTarball(const char *fileName, struct stat *statbuf,
+							  void *userData)
+{
+	struct TarBallInfo *tbInfo = (struct TarBallInfo *) userData;
+	const char *header_name;
+	int inputFileFd = -1;
+
+	/*
+	   ** Check to see if we are dealing with a hard link.
+	   ** If so -
+	   ** Treat the first occurance of a given dev/inode as a file while
+	   ** treating any additional occurances as hard links.  This is done
+	   ** by adding the file information to the HardLinkInfo linked list.
+	 */
+	tbInfo->hlInfo = NULL;
+	if (statbuf->st_nlink > 1) {
+		tbInfo->hlInfo = findHardLinkInfo(tbInfo->hlInfoHead, statbuf);
+		if (tbInfo->hlInfo == NULL)
+			addHardLinkInfo(&tbInfo->hlInfoHead, statbuf, fileName);
+	}
+
+	/* It is against the rules to archive a socket */
+	if (S_ISSOCK(statbuf->st_mode)) {
+		bb_error_msg("%s: socket ignored", fileName);
+		return (TRUE);
+	}
+
+	/* It is a bad idea to store the archive we are in the process of creating,
+	 * so check the device and inode to be sure that this particular file isn't
+	 * the new tarball */
+	if (tbInfo->statBuf.st_dev == statbuf->st_dev &&
+		tbInfo->statBuf.st_ino == statbuf->st_ino) {
+		bb_error_msg("%s: file is the archive; skipping", fileName);
+		return (TRUE);
+	}
+
+	header_name = fileName;
+	while (header_name[0] == '/') {
+		static int alreadyWarned = FALSE;
+
+		if (alreadyWarned == FALSE) {
+			bb_error_msg("Removing leading '/' from member names");
+			alreadyWarned = TRUE;
+		}
+		header_name++;
+	}
+
+	if (strlen(fileName) >= NAME_SIZE) {
+		bb_error_msg(bb_msg_name_longer_than_foo, NAME_SIZE);
+		return (TRUE);
+	}
+
+	if (header_name[0] == '\0')
+		return TRUE;
+
+	if (ENABLE_FEATURE_TAR_FROM &&
+			exclude_file(tbInfo->excludeList, header_name)) {
+		return SKIP;
+	}
+
+	/* Is this a regular file? */
+	if ((tbInfo->hlInfo == NULL) && (S_ISREG(statbuf->st_mode))) {
+
+		/* open the file we want to archive, and make sure all is well */
+		if ((inputFileFd = open(fileName, O_RDONLY)) < 0) {
+			bb_perror_msg("%s: Cannot open", fileName);
+			return (FALSE);
+		}
+	}
+
+	/* Add an entry to the tarball */
+	if (writeTarHeader(tbInfo, header_name, fileName, statbuf) == FALSE) {
+		return (FALSE);
+	}
+
+	/* If it was a regular file, write out the body */
+	if (inputFileFd >= 0 ) {
+		ssize_t readSize = 0;
+
+		/* write the file to the archive */
+		readSize = bb_copyfd_eof(inputFileFd, tbInfo->tarFd);
+		close(inputFileFd);
+
+		/* Pad the file up to the tar block size */
+		for (; (readSize % TAR_BLOCK_SIZE) != 0; readSize++)
+			write(tbInfo->tarFd, "\0", 1);
+	}
+
+	return (TRUE);
+}
+
+static inline int writeTarFile(const int tar_fd, const int verboseFlag,
+	const unsigned long dereferenceFlag, const llist_t *include,
+	const llist_t *exclude, const int gzip)
+{
+	pid_t gzipPid = 0;
+
+	int errorFlag = FALSE;
+	ssize_t size;
+	struct TarBallInfo tbInfo;
+
+	tbInfo.hlInfoHead = NULL;
+
+	fchmod(tar_fd, 0644);
+	tbInfo.tarFd = tar_fd;
+	tbInfo.verboseFlag = verboseFlag;
+
+	/* Store the stat info for the tarball's file, so
+	 * can avoid including the tarball into itself....  */
+	if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0)
+		bb_perror_msg_and_die("Couldnt stat tar file");
+
+	if ((ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2) && gzip) {
+		int gzipDataPipe[2] = { -1, -1 };
+		int gzipStatusPipe[2] = { -1, -1 };
+		volatile int vfork_exec_errno = 0;
+		char *zip_exec = (gzip == 1) ? "gzip" : "bzip2";
+
+
+		if (pipe(gzipDataPipe) < 0 || pipe(gzipStatusPipe) < 0)
+			bb_perror_msg_and_die("create pipe");
+
+		signal(SIGPIPE, SIG_IGN);	/* we only want EPIPE on errors */
+
+# if __GNUC__
+			/* Avoid vfork clobbering */
+			(void) &include;
+			(void) &errorFlag;
+			(void) &zip_exec;
+# endif
+
+		gzipPid = vfork();
+
+		if (gzipPid == 0) {
+			dup2(gzipDataPipe[0], 0);
+			close(gzipDataPipe[1]);
+
+			if (tbInfo.tarFd != 1)
+				dup2(tbInfo.tarFd, 1);
+
+			close(gzipStatusPipe[0]);
+			fcntl(gzipStatusPipe[1], F_SETFD, FD_CLOEXEC);	/* close on exec shows success */
+
+			execlp(zip_exec, zip_exec, "-f", NULL);
+			vfork_exec_errno = errno;
+
+			close(gzipStatusPipe[1]);
+			exit(-1);
+		} else if (gzipPid > 0) {
+			close(gzipDataPipe[0]);
+			close(gzipStatusPipe[1]);
+
+			while (1) {
+				char buf;
+
+				int n = bb_full_read(gzipStatusPipe[0], &buf, 1);
+
+				if (n == 0 && vfork_exec_errno != 0) {
+					errno = vfork_exec_errno;
+					bb_perror_msg_and_die("Could not exec %s", zip_exec);
+				} else if ((n < 0) && (errno == EAGAIN || errno == EINTR))
+					continue;	/* try it again */
+				break;
+			}
+			close(gzipStatusPipe[0]);
+
+			tbInfo.tarFd = gzipDataPipe[1];
+		} else bb_perror_msg_and_die("vfork gzip");
+	}
+
+	tbInfo.excludeList = exclude;
+
+	/* Read the directory/files and iterate over them one at a time */
+	while (include) {
+		if (!recursive_action(include->data, TRUE, dereferenceFlag,
+				FALSE, writeFileToTarball, writeFileToTarball, &tbInfo))
+		{
+			errorFlag = TRUE;
+		}
+		include = include->link;
+	}
+	/* Write two empty blocks to the end of the archive */
+	for (size = 0; size < (2 * TAR_BLOCK_SIZE); size++)
+		write(tbInfo.tarFd, "\0", 1);
+
+	/* To be pedantically correct, we would check if the tarball
+	 * is smaller than 20 tar blocks, and pad it if it was smaller,
+	 * but that isn't necessary for GNU tar interoperability, and
+	 * so is considered a waste of space */
+
+	/* Close so the child process (if any) will exit */
+	close(tbInfo.tarFd);
+
+	/* Hang up the tools, close up shop, head home */
+	if (ENABLE_FEATURE_CLEAN_UP)
+		freeHardLinkInfo(&tbInfo.hlInfoHead);
+
+	if (errorFlag)
+		bb_error_msg("Error exit delayed from previous errors");
+
+	if (gzipPid && waitpid(gzipPid, NULL, 0)==-1)
+		bb_error_msg("Couldnt wait");
+
+	return !errorFlag;
+}
+#else
+int writeTarFile(const int tar_fd, const int verboseFlag,
+	const unsigned long dereferenceFlag, const llist_t *include,
+	const llist_t *exclude, const int gzip);
+#endif	/* tar_create */
+
+#ifdef CONFIG_FEATURE_TAR_FROM
+static llist_t *append_file_list_to_list(llist_t *list)
+{
+	FILE *src_stream;
+	llist_t *cur = list;
+	llist_t *tmp;
+	char *line;
+	llist_t *newlist = NULL;
+
+	while (cur) {
+		src_stream = bb_xfopen(cur->data, "r");
+		tmp = cur;
+		cur = cur->link;
+		free(tmp);
+		while ((line = bb_get_chomped_line_from_file(src_stream)) != NULL)
+				llist_add_to(&newlist, line);
+		fclose(src_stream);
+	}
+	return newlist;
+}
+#else
+#define append_file_list_to_list(x)	0
+#endif
+
+#ifdef CONFIG_FEATURE_TAR_COMPRESS
+static char get_header_tar_Z(archive_handle_t *archive_handle)
+{
+	/* Cant lseek over pipe's */
+	archive_handle->seek = seek_by_char;
+
+	/* do the decompression, and cleanup */
+	if (bb_xread_char(archive_handle->src_fd) != 0x1f ||
+		bb_xread_char(archive_handle->src_fd) != 0x9d)
+	{
+		bb_error_msg_and_die("Invalid magic");
+	}
+
+	archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompress);
+	archive_handle->offset = 0;
+	while (get_header_tar(archive_handle) == EXIT_SUCCESS);
+
+	/* Can only do one file at a time */
+	return(EXIT_FAILURE);
+}
+#else
+#define get_header_tar_Z	0
+#endif
+
+#define CTX_TEST                          (1 << 0)
+#define CTX_EXTRACT                       (1 << 1)
+#define TAR_OPT_BASEDIR                   (1 << 2)
+#define TAR_OPT_TARNAME                   (1 << 3)
+#define TAR_OPT_2STDOUT                   (1 << 4)
+#define TAR_OPT_P                         (1 << 5)
+#define TAR_OPT_VERBOSE                   (1 << 6)
+#define TAR_OPT_KEEP_OLD                  (1 << 7)
+
+#define TAR_OPT_AFTER_START               8
+
+#define CTX_CREATE                        (1 << (TAR_OPT_AFTER_START))
+#define TAR_OPT_DEREFERENCE               (1 << (TAR_OPT_AFTER_START + 1))
+#ifdef CONFIG_FEATURE_TAR_CREATE
+# define TAR_OPT_STR_CREATE               "ch"
+# define TAR_OPT_AFTER_CREATE             TAR_OPT_AFTER_START + 2
+#else
+# define TAR_OPT_STR_CREATE               ""
+# define TAR_OPT_AFTER_CREATE             TAR_OPT_AFTER_START
+#endif
+
+#define TAR_OPT_BZIP2                     (1 << (TAR_OPT_AFTER_CREATE))
+#ifdef CONFIG_FEATURE_TAR_BZIP2
+# define TAR_OPT_STR_BZIP2                "j"
+# define TAR_OPT_AFTER_BZIP2              TAR_OPT_AFTER_CREATE + 1
+#else
+# define TAR_OPT_STR_BZIP2                ""
+# define TAR_OPT_AFTER_BZIP2              TAR_OPT_AFTER_CREATE
+#endif
+
+#define TAR_OPT_LZMA                      (1 << (TAR_OPT_AFTER_BZIP2))
+#ifdef CONFIG_FEATURE_TAR_LZMA
+# define TAR_OPT_STR_LZMA                 "a"
+# define TAR_OPT_AFTER_LZMA               TAR_OPT_AFTER_BZIP2 + 1
+#else
+# define TAR_OPT_STR_LZMA                 ""
+# define TAR_OPT_AFTER_LZMA               TAR_OPT_AFTER_BZIP2
+#endif
+
+#define TAR_OPT_INCLUDE_FROM              (1 << (TAR_OPT_AFTER_LZMA))
+#define TAR_OPT_EXCLUDE_FROM              (1 << (TAR_OPT_AFTER_LZMA + 1))
+#ifdef CONFIG_FEATURE_TAR_FROM
+# define TAR_OPT_STR_FROM                 "T:X:"
+# define TAR_OPT_AFTER_FROM               TAR_OPT_AFTER_LZMA + 2
+#else
+# define TAR_OPT_STR_FROM                 ""
+# define TAR_OPT_AFTER_FROM               TAR_OPT_AFTER_LZMA
+#endif
+
+#define TAR_OPT_GZIP                      (1 << (TAR_OPT_AFTER_FROM))
+#ifdef CONFIG_FEATURE_TAR_GZIP
+# define TAR_OPT_STR_GZIP                 "z"
+# define TAR_OPT_AFTER_GZIP               TAR_OPT_AFTER_FROM + 1
+#else
+# define TAR_OPT_STR_GZIP                 ""
+# define TAR_OPT_AFTER_GZIP               TAR_OPT_AFTER_FROM
+#endif
+
+#define TAR_OPT_UNCOMPRESS                (1 << (TAR_OPT_AFTER_GZIP))
+#ifdef CONFIG_FEATURE_TAR_COMPRESS
+# define TAR_OPT_STR_COMPRESS             "Z"
+# define TAR_OPT_AFTER_COMPRESS           TAR_OPT_AFTER_GZIP + 1
+#else
+# define TAR_OPT_STR_COMPRESS             ""
+# define TAR_OPT_AFTER_COMPRESS           TAR_OPT_AFTER_GZIP
+#endif
+
+#define TAR_OPT_NOPRESERVE_OWN            (1 << (TAR_OPT_AFTER_COMPRESS))
+#define TAR_OPT_NOPRESERVE_PERM           (1 << (TAR_OPT_AFTER_COMPRESS + 1))
+#define TAR_OPT_STR_NOPRESERVE            "\203\213"
+#define TAR_OPT_AFTER_NOPRESERVE          TAR_OPT_AFTER_COMPRESS + 2
+
+static const char tar_options[]="txC:f:Opvk" \
+	TAR_OPT_STR_CREATE \
+	TAR_OPT_STR_BZIP2 \
+	TAR_OPT_STR_LZMA \
+	TAR_OPT_STR_FROM \
+	TAR_OPT_STR_GZIP \
+	TAR_OPT_STR_COMPRESS \
+	TAR_OPT_STR_NOPRESERVE;
+
+#ifdef CONFIG_FEATURE_TAR_LONG_OPTIONS
+static const struct option tar_long_options[] = {
+	{ "list",				0,	NULL,	't' },
+	{ "extract",			0,	NULL,	'x' },
+	{ "directory",			1,	NULL,	'C' },
+	{ "file",				1,	NULL,	'f' },
+	{ "to-stdout",			0,	NULL,	'O' },
+	{ "same-permissions",	0,	NULL,	'p' },
+	{ "verbose",			0,	NULL,	'v' },
+	{ "keep-old",			0,	NULL,	'k' },
+	{ "no-same-owner",		0,	NULL,	'\203' },
+	{ "no-same-permissions",0,	NULL,	'\213' },
+# ifdef CONFIG_FEATURE_TAR_CREATE
+	{ "create",				0,	NULL,	'c' },
+	{ "dereference",		0,	NULL,	'h' },
+# endif
+# ifdef CONFIG_FEATURE_TAR_BZIP2
+	{ "bzip2",				0,	NULL,	'j' },
+# endif
+# ifdef CONFIG_FEATURE_TAR_LZMA
+	{ "lzma",				0,	NULL,	'a' },
+# endif
+# ifdef CONFIG_FEATURE_TAR_FROM
+	{ "files-from",			1,	NULL,	'T' },
+	{ "exclude-from",		1,	NULL,	'X' },
+	{ "exclude",			1,	NULL,	'\n' },
+# endif
+# ifdef CONFIG_FEATURE_TAR_GZIP
+	{ "gzip",				0,	NULL,	'z' },
+# endif
+# ifdef CONFIG_FEATURE_TAR_COMPRESS
+	{ "compress",			0,	NULL,	'Z' },
+# endif
+	{ 0,					0, 0, 0 }
+};
+#else
+#define tar_long_options	0
+#endif
+
+int tar_main(int argc, char **argv)
+{
+	char (*get_header_ptr)(archive_handle_t *) = get_header_tar;
+	archive_handle_t *tar_handle;
+	char *base_dir = NULL;
+	const char *tar_filename = "-";
+	unsigned long opt;
+	llist_t *excludes = NULL;
+
+	/* Initialise default values */
+	tar_handle = init_handle();
+	tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS | ARCHIVE_PRESERVE_DATE | ARCHIVE_EXTRACT_UNCONDITIONAL;
+
+	/* Prepend '-' to the first argument if required */
+	bb_opt_complementally = ENABLE_FEATURE_TAR_CREATE ?
+		"--:X::T::\n::c:t:x:?:c--tx:t--cx:x--ct" :
+		"--:X::T::\n::t:x:?:t--x:x--t";
+	if (ENABLE_FEATURE_TAR_LONG_OPTIONS)
+		bb_applet_long_options = tar_long_options;
+	opt = bb_getopt_ulflags(argc, argv, tar_options,
+				&base_dir,      /* Change to dir <optarg> */
+				&tar_filename /* archive filename */
+#ifdef CONFIG_FEATURE_TAR_FROM
+				, &(tar_handle->accept),
+				&(tar_handle->reject),
+				&excludes
+#endif
+				);
+
+	if (opt & CTX_TEST) {
+		if ((tar_handle->action_header == header_list) ||
+			(tar_handle->action_header == header_verbose_list))
+		{
+				tar_handle->action_header = header_verbose_list;
+		} else tar_handle->action_header = header_list;
+	}
+	if((opt & CTX_EXTRACT) && tar_handle->action_data != data_extract_to_stdout)
+		tar_handle->action_data = data_extract_all;
+
+	if (opt & TAR_OPT_2STDOUT)
+		tar_handle->action_data = data_extract_to_stdout;
+
+	if (opt & TAR_OPT_VERBOSE) {
+		if ((tar_handle->action_header == header_list) ||
+			(tar_handle->action_header == header_verbose_list))
+		{
+			tar_handle->action_header = header_verbose_list;
+		} else
+			tar_handle->action_header = header_list;
+	}
+	if (opt & TAR_OPT_KEEP_OLD)
+		tar_handle->flags &= ~ARCHIVE_EXTRACT_UNCONDITIONAL;
+
+	if (opt & TAR_OPT_NOPRESERVE_OWN)
+		tar_handle->flags |= ARCHIVE_NOPRESERVE_OWN;
+
+	if (opt & TAR_OPT_NOPRESERVE_PERM)
+		tar_handle->flags |= ARCHIVE_NOPRESERVE_PERM;
+
+	if (ENABLE_FEATURE_TAR_GZIP && (opt & TAR_OPT_GZIP))
+		get_header_ptr = get_header_tar_gz;
+
+	if (ENABLE_FEATURE_TAR_BZIP2 && (opt & TAR_OPT_BZIP2))
+		get_header_ptr = get_header_tar_bz2;
+
+	if (ENABLE_FEATURE_TAR_LZMA && (opt & TAR_OPT_LZMA))
+		get_header_ptr = get_header_tar_lzma;
+
+	if (ENABLE_FEATURE_TAR_COMPRESS && (opt & TAR_OPT_UNCOMPRESS))
+		get_header_ptr = get_header_tar_Z;
+
+	if (ENABLE_FEATURE_TAR_FROM) {
+		tar_handle->reject = append_file_list_to_list(tar_handle->reject);
+		/* Append excludes to reject */
+		while (excludes) {
+			llist_t *temp = excludes->link;
+			excludes->link = tar_handle->reject;
+			tar_handle->reject = excludes;
+			excludes = temp;
+		}
+		tar_handle->accept = append_file_list_to_list(tar_handle->accept);
+	}
+
+	/* Check if we are reading from stdin */
+	if (argv[optind] && *argv[optind] == '-') {
+		/* Default is to read from stdin, so just skip to next arg */
+		optind++;
+	}
+
+	/* Setup an array of filenames to work with */
+	/* TODO: This is the same as in ar, separate function ? */
+	while (optind < argc) {
+		char *filename_ptr = last_char_is(argv[optind], '/');
+		if (filename_ptr > argv[optind])
+			*filename_ptr = '\0';
+
+		llist_add_to(&(tar_handle->accept), argv[optind]);
+		optind++;
+	}
+
+	if ((tar_handle->accept) || (tar_handle->reject))
+		tar_handle->filter = filter_accept_reject_list;
+
+	/* Open the tar file */
+	{
+		FILE *tar_stream;
+		int flags;
+
+		if (ENABLE_FEATURE_TAR_CREATE && (opt & CTX_CREATE)) {
+			/* Make sure there is at least one file to tar up.  */
+			if (tar_handle->accept == NULL)
+				bb_error_msg_and_die("empty archive");
+
+			tar_stream = stdout;
+			flags = O_WRONLY | O_CREAT | O_EXCL;
+			unlink(tar_filename);
+		} else {
+			tar_stream = stdin;
+			flags = O_RDONLY;
+		}
+
+		if ((tar_filename[0] == '-') && (tar_filename[1] == '\0')) {
+			tar_handle->src_fd = fileno(tar_stream);
+			tar_handle->seek = seek_by_char;
+		} else {
+			tar_handle->src_fd = bb_xopen(tar_filename, flags);
+		}
+	}
+
+	if (base_dir)
+		bb_xchdir(base_dir);
+
+	/* create an archive */
+	if (ENABLE_FEATURE_TAR_CREATE && (opt & CTX_CREATE)) {
+		int verboseFlag = FALSE;
+		int zipMode = 0;
+
+		if (ENABLE_FEATURE_TAR_GZIP && get_header_ptr == get_header_tar_gz)
+			zipMode = 1;
+		if (ENABLE_FEATURE_TAR_BZIP2 && get_header_ptr == get_header_tar_bz2)
+			zipMode = 2;
+
+		if ((tar_handle->action_header == header_list) ||
+				(tar_handle->action_header == header_verbose_list))
+		{
+			verboseFlag = TRUE;
+		}
+		writeTarFile(tar_handle->src_fd, verboseFlag, opt & TAR_OPT_DEREFERENCE,
+				tar_handle->accept,
+			tar_handle->reject, zipMode);
+	} else {
+		while (get_header_ptr(tar_handle) == EXIT_SUCCESS);
+
+		/* Check that every file that should have been extracted was */
+		while (tar_handle->accept) {
+			if (!find_list_entry(tar_handle->reject, tar_handle->accept->data)
+				&& !find_list_entry(tar_handle->passed, tar_handle->accept->data))
+			{
+				bb_error_msg_and_die("%s: Not found in archive", tar_handle->accept->data);
+			}
+			tar_handle->accept = tar_handle->accept->link;
+		}
+	}
+
+	if (ENABLE_FEATURE_CLEAN_UP && tar_handle->src_fd != STDIN_FILENO)
+		close(tar_handle->src_fd);
+
+	return(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/uncompress.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/uncompress.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/uncompress.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,100 @@
+/* vi: set sw=4 ts=4: */
+/*
+ *	Uncompress applet for busybox (c) 2002 Glenn McGrath
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "busybox.h"
+#include "unarchive.h"
+
+#define GUNZIP_TO_STDOUT	1
+#define GUNZIP_FORCE	2
+
+int uncompress_main(int argc, char **argv)
+{
+	int status = EXIT_SUCCESS;
+	unsigned long flags;
+
+	flags = bb_getopt_ulflags(argc, argv, "cf");
+
+	while (optind < argc) {
+		const char *compressed_file = argv[optind++];
+		const char *delete_path = NULL;
+		char *uncompressed_file = NULL;
+		int src_fd;
+		int dst_fd;
+
+		if (strcmp(compressed_file, "-") == 0) {
+			src_fd = STDIN_FILENO;
+			flags |= GUNZIP_TO_STDOUT;
+		} else {
+			src_fd = bb_xopen(compressed_file, O_RDONLY);
+		}
+
+		/* Check that the input is sane.  */
+		if (isatty(src_fd) && ((flags & GUNZIP_FORCE) == 0)) {
+			bb_error_msg_and_die
+				("compressed data not read from terminal.  Use -f to force it.");
+		}
+
+		/* Set output filename and number */
+		if (flags & GUNZIP_TO_STDOUT) {
+			dst_fd = STDOUT_FILENO;
+		} else {
+			struct stat stat_buf;
+			char *extension;
+
+			uncompressed_file = bb_xstrdup(compressed_file);
+
+			extension = strrchr(uncompressed_file, '.');
+			if (!extension || (strcmp(extension, ".Z") != 0)) {
+				bb_error_msg_and_die("Invalid extension");
+			}
+			*extension = '\0';
+
+			/* Open output file */
+			xstat(compressed_file, &stat_buf);
+			dst_fd = bb_xopen3(uncompressed_file, O_WRONLY | O_CREAT,
+					stat_buf.st_mode);
+
+			/* If unzip succeeds remove the old file */
+			delete_path = compressed_file;
+		}
+
+		/* do the decompression, and cleanup */
+		if ((bb_xread_char(src_fd) != 0x1f) || (bb_xread_char(src_fd) != 0x9d)) {
+			bb_error_msg_and_die("Invalid magic");
+		}
+
+		status = uncompress(src_fd, dst_fd);
+
+		if ((status != EXIT_SUCCESS) && (uncompressed_file)) {
+			/* Unzip failed, remove the uncomressed file instead of compressed file */
+			delete_path = uncompressed_file;
+		}
+
+		if (dst_fd != STDOUT_FILENO) {
+			close(dst_fd);
+		}
+		if (src_fd != STDIN_FILENO) {
+			close(src_fd);
+		}
+
+		/* delete_path will be NULL if in test mode or from stdin */
+		if (delete_path && (unlink(delete_path) == -1)) {
+			bb_error_msg_and_die("Couldn't remove %s", delete_path);
+		}
+
+		free(uncompressed_file);
+	}
+
+	return status;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/unlzma.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/unlzma.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/unlzma.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,67 @@
+/*
+ * Small lzma deflate implementation.
+ * Copyright (C) 2006  Aurelien Jacobs <aurel at gnuage.org>
+ *
+ * Based on bunzip.c from busybox
+ *
+ * Licensed under GPL v2, see file LICENSE in this tarball for details.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "busybox.h"
+#include "unarchive.h"
+
+#define UNLZMA_OPT_STDOUT	1
+
+int unlzma_main(int argc, char **argv)
+{
+	char *filename;
+	unsigned long opt;
+	int status, src_fd, dst_fd;
+
+	opt = bb_getopt_ulflags(argc, argv, "c");
+
+	/* Set input filename and number */
+	filename = argv[optind];
+	if ((filename) && (filename[0] != '-') && (filename[1] != '\0')) {
+		/* Open input file */
+		src_fd = bb_xopen(filename, O_RDONLY);
+	} else {
+		src_fd = STDIN_FILENO;
+		filename = 0;
+	}
+
+	/* if called as lzmacat force the stdout flag */
+	if ((opt & UNLZMA_OPT_STDOUT) || bb_applet_name[4] == 'c')
+		filename = 0;
+
+	if (filename) {
+		struct stat stat_buf;
+		char *extension = filename + strlen(filename) - 5;
+
+		if (strcmp(extension, ".lzma") != 0) {
+			bb_error_msg_and_die("Invalid extension");
+		}
+		xstat(filename, &stat_buf);
+		*extension = 0;
+		dst_fd = bb_xopen3(filename, O_WRONLY | O_CREAT, stat_buf.st_mode);
+	} else
+		dst_fd = STDOUT_FILENO;
+	status = unlzma(src_fd, dst_fd);
+	if (filename) {
+		if (!status)
+			filename[strlen(filename)] = '.';
+		if (unlink(filename) < 0) {
+			bb_error_msg_and_die("Couldn't remove %s", filename);
+		}
+	}
+
+	return status;
+}
+
+/* vi:set ts=4: */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/unzip.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/unzip.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/archival/unzip.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,418 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini unzip implementation for busybox
+ *
+ * Copyright (C) 2004 by Ed Clark
+ *
+ * Loosely based on original busybox unzip applet by Laurence Anderson.
+ * All options and features should work in this version.
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+/* For reference see
+ * http://www.pkware.com/company/standards/appnote/
+ * http://www.info-zip.org/pub/infozip/doc/appnote-iz-latest.zip
+ */
+
+/* TODO
+ * Endian issues
+ * Zip64 + other methods
+ * Improve handling of zip format, ie.
+ * - deferred CRC, comp. & uncomp. lengths (zip header flags bit 3)
+ * - unix file permissions, etc.
+ * - central directory
+ */
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include "unarchive.h"
+#include "busybox.h"
+
+#if BB_BIG_ENDIAN
+static inline unsigned short
+__swap16(unsigned short x) {
+	return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
+}
+
+static inline uint32_t
+__swap32(uint32_t x) {
+	 return (((x & 0xFF) << 24) |
+		((x & 0xFF00) << 8) |
+		((x & 0xFF0000) >> 8) |
+		((x & 0xFF000000) >> 24));
+}
+#else /* it's little-endian */
+# define __swap16(x) (x)
+# define __swap32(x) (x)
+#endif /* BB_BIG_ENDIAN */
+
+#define ZIP_FILEHEADER_MAGIC		__swap32(0x04034b50)
+#define ZIP_CDS_MAGIC			__swap32(0x02014b50)
+#define ZIP_CDS_END_MAGIC		__swap32(0x06054b50)
+#define ZIP_DD_MAGIC			__swap32(0x08074b50)
+
+extern unsigned int gunzip_crc;
+extern unsigned int gunzip_bytes_out;
+
+typedef union {
+	unsigned char raw[26];
+	struct {
+		unsigned short version;	/* 0-1 */
+		unsigned short flags;	/* 2-3 */
+		unsigned short method;	/* 4-5 */
+		unsigned short modtime;	/* 6-7 */
+		unsigned short moddate;	/* 8-9 */
+		unsigned int crc32 ATTRIBUTE_PACKED;	/* 10-13 */
+		unsigned int cmpsize ATTRIBUTE_PACKED;	/* 14-17 */
+		unsigned int ucmpsize ATTRIBUTE_PACKED;	/* 18-21 */
+		unsigned short filename_len;	/* 22-23 */
+		unsigned short extra_len;		/* 24-25 */
+	} formated ATTRIBUTE_PACKED;
+} zip_header_t;
+
+static void unzip_skip(int fd, off_t skip)
+{
+	if (lseek(fd, skip, SEEK_CUR) == (off_t)-1) {
+		if ((errno != ESPIPE) || (bb_copyfd_size(fd, -1, skip) != skip)) {
+			bb_error_msg_and_die("Seek failure");
+		}
+	}
+}
+
+static void unzip_read(int fd, void *buf, size_t count)
+{
+	if (bb_xread(fd, buf, count) != count) {
+		bb_error_msg_and_die(bb_msg_read_error);
+	}
+}
+
+static void unzip_create_leading_dirs(char *fn)
+{
+	/* Create all leading directories */
+	char *name = bb_xstrdup(fn);
+	if (bb_make_directory(dirname(name), 0777, FILEUTILS_RECUR)) {
+		bb_error_msg_and_die("Exiting"); /* bb_make_directory is noisy */
+	}
+	free(name);
+}
+
+static int unzip_extract(zip_header_t *zip_header, int src_fd, int dst_fd)
+{
+	if (zip_header->formated.method == 0) {
+		/* Method 0 - stored (not compressed) */
+		int size = zip_header->formated.ucmpsize;
+		if (size && (bb_copyfd_size(src_fd, dst_fd, size) != size)) {
+			bb_error_msg_and_die("Cannot complete extraction");
+		}
+
+	} else {
+		/* Method 8 - inflate */
+		inflate_init(zip_header->formated.cmpsize);
+		inflate_unzip(src_fd, dst_fd);
+		inflate_cleanup();
+		/* Validate decompression - crc */
+		if (zip_header->formated.crc32 != (gunzip_crc ^ 0xffffffffL)) {
+			bb_error_msg("Invalid compressed data--crc error");
+			return 1;
+		}
+		/* Validate decompression - size */
+		if (zip_header->formated.ucmpsize != gunzip_bytes_out) {
+			bb_error_msg("Invalid compressed data--length error");
+			return 1;
+		}
+	}
+	return 0;
+}
+
+int unzip_main(int argc, char **argv)
+{
+	zip_header_t zip_header;
+	enum {v_silent, v_normal, v_list} verbosity = v_normal;
+	enum {o_prompt, o_never, o_always} overwrite = o_prompt;
+	unsigned int total_size = 0;
+	unsigned int total_entries = 0;
+	int src_fd = -1, dst_fd = -1;
+	char *src_fn = NULL, *dst_fn = NULL;
+	llist_t *zaccept = NULL;
+	llist_t *zreject = NULL;
+	char *base_dir = NULL;
+	int failed, i, opt, opt_range = 0, list_header_done = 0;
+	char key_buf[512];
+	struct stat stat_buf;
+
+	while((opt = getopt(argc, argv, "-d:lnopqx")) != -1) {
+		switch(opt_range) {
+		case 0: /* Options */
+			switch(opt) {
+			case 'l': /* List */
+				verbosity = v_list;
+				break;
+
+			case 'n': /* Never overwrite existing files */
+				overwrite = o_never;
+				break;
+
+			case 'o': /* Always overwrite existing files */
+				overwrite = o_always;
+				break;
+
+			case 'p': /* Extract files to stdout and fall through to set verbosity */
+				dst_fd = STDOUT_FILENO;
+
+			case 'q': /* Be quiet */
+				verbosity = (verbosity == v_normal) ? v_silent : verbosity;
+				break;
+
+			case 1 : /* The zip file */
+				src_fn = bb_xstrndup(optarg, strlen(optarg)+4);
+				opt_range++;
+				break;
+
+			default:
+				bb_show_usage();
+
+			}
+			break;
+
+		case 1: /* Include files */
+			if (opt == 1) {
+				llist_add_to(&zaccept, optarg);
+
+			} else if (opt == 'd') {
+				base_dir = optarg;
+				opt_range += 2;
+
+			} else if (opt == 'x') {
+				opt_range++;
+
+			} else {
+				bb_show_usage();
+			}
+			break;
+
+		case 2 : /* Exclude files */
+			if (opt == 1) {
+				llist_add_to(&zreject, optarg);
+
+			} else if (opt == 'd') { /* Extract to base directory */
+				base_dir = optarg;
+				opt_range++;
+
+			} else {
+				bb_show_usage();
+			}
+			break;
+
+		default:
+			bb_show_usage();
+		}
+	}
+
+	if (src_fn == NULL) {
+		bb_show_usage();
+	}
+
+	/* Open input file */
+	if (strcmp("-", src_fn) == 0) {
+		src_fd = STDIN_FILENO;
+		/* Cannot use prompt mode since zip data is arriving on STDIN */
+		overwrite = (overwrite == o_prompt) ? o_never : overwrite;
+
+	} else {
+		static const char *const extn[] = {"", ".zip", ".ZIP"};
+		int orig_src_fn_len = strlen(src_fn);
+		for(i = 0; (i < 3) && (src_fd == -1); i++) {
+			strcpy(src_fn + orig_src_fn_len, extn[i]);
+			src_fd = open(src_fn, O_RDONLY);
+		}
+		if (src_fd == -1) {
+			src_fn[orig_src_fn_len] = 0;
+			bb_error_msg_and_die("Cannot open %s, %s.zip, %s.ZIP", src_fn, src_fn, src_fn);
+		}
+	}
+
+	/* Change dir if necessary */
+	if (base_dir)
+		bb_xchdir(base_dir);
+
+	if (verbosity != v_silent)
+		printf("Archive:  %s\n", src_fn);
+
+	failed = 0;
+
+	while (1) {
+		unsigned int magic;
+
+		/* Check magic number */
+		unzip_read(src_fd, &magic, 4);
+		if (magic == ZIP_CDS_MAGIC) {
+			break;
+		} else if (magic != ZIP_FILEHEADER_MAGIC) {
+			bb_error_msg_and_die("Invalid zip magic %08X", magic);
+		}
+
+		/* Read the file header */
+		unzip_read(src_fd, zip_header.raw, 26);
+#if BB_BIG_ENDIAN
+		zip_header.formated.version = __swap16(zip_header.formated.version);
+		zip_header.formated.flags = __swap16(zip_header.formated.flags);
+		zip_header.formated.method = __swap16(zip_header.formated.method);
+		zip_header.formated.modtime = __swap16(zip_header.formated.modtime);
+		zip_header.formated.moddate = __swap16(zip_header.formated.moddate);
+		zip_header.formated.crc32 = __swap32(zip_header.formated.crc32);
+		zip_header.formated.cmpsize = __swap32(zip_header.formated.cmpsize);
+		zip_header.formated.ucmpsize = __swap32(zip_header.formated.ucmpsize);
+		zip_header.formated.filename_len = __swap16(zip_header.formated.filename_len);
+		zip_header.formated.extra_len = __swap16(zip_header.formated.extra_len);
+#endif /* BB_BIG_ENDIAN */
+		if ((zip_header.formated.method != 0) && (zip_header.formated.method != 8)) {
+			bb_error_msg_and_die("Unsupported compression method %d", zip_header.formated.method);
+		}
+
+		/* Read filename */
+		free(dst_fn);
+		dst_fn = xzalloc(zip_header.formated.filename_len + 1);
+		unzip_read(src_fd, dst_fn, zip_header.formated.filename_len);
+
+		/* Skip extra header bytes */
+		unzip_skip(src_fd, zip_header.formated.extra_len);
+
+		if ((verbosity == v_list) && !list_header_done){
+			printf("  Length     Date   Time    Name\n"
+				   " --------    ----   ----    ----\n");
+			list_header_done = 1;
+		}
+
+		/* Filter zip entries */
+		if (find_list_entry(zreject, dst_fn) ||
+			(zaccept && !find_list_entry(zaccept, dst_fn))) { /* Skip entry */
+			i = 'n';
+
+		} else { /* Extract entry */
+			total_size += zip_header.formated.ucmpsize;
+
+			if (verbosity == v_list) { /* List entry */
+				unsigned int dostime = zip_header.formated.modtime | (zip_header.formated.moddate << 16);
+				printf("%9u  %02u-%02u-%02u %02u:%02u   %s\n",
+					   zip_header.formated.ucmpsize,
+					   (dostime & 0x01e00000) >> 21,
+					   (dostime & 0x001f0000) >> 16,
+					   (((dostime & 0xfe000000) >> 25) + 1980) % 100,
+					   (dostime & 0x0000f800) >> 11,
+					   (dostime & 0x000007e0) >> 5,
+					   dst_fn);
+				total_entries++;
+				i = 'n';
+
+			} else if (dst_fd == STDOUT_FILENO) { /* Extracting to STDOUT */
+				i = -1;
+
+			} else if (last_char_is(dst_fn, '/')) { /* Extract directory */
+				if (stat(dst_fn, &stat_buf) == -1) {
+					if (errno != ENOENT) {
+						bb_perror_msg_and_die("Cannot stat '%s'",dst_fn);
+					}
+					if (verbosity == v_normal) {
+						printf("   creating: %s\n", dst_fn);
+					}
+					unzip_create_leading_dirs(dst_fn);
+					if (bb_make_directory(dst_fn, 0777, 0)) {
+						bb_error_msg_and_die("Exiting");
+					}
+				} else {
+					if (!S_ISDIR(stat_buf.st_mode)) {
+						bb_error_msg_and_die("'%s' exists but is not directory", dst_fn);
+					}
+				}
+				i = 'n';
+
+			} else {  /* Extract file */
+			_check_file:
+				if (stat(dst_fn, &stat_buf) == -1) { /* File does not exist */
+					if (errno != ENOENT) {
+						bb_perror_msg_and_die("Cannot stat '%s'",dst_fn);
+					}
+					i = 'y';
+
+				} else { /* File already exists */
+					if (overwrite == o_never) {
+						i = 'n';
+
+					} else if (S_ISREG(stat_buf.st_mode)) { /* File is regular file */
+						if (overwrite == o_always) {
+							i = 'y';
+						} else {
+							printf("replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ", dst_fn);
+							if (!fgets(key_buf, 512, stdin)) {
+								bb_perror_msg_and_die("Cannot read input");
+							}
+							i = key_buf[0];
+						}
+
+					} else { /* File is not regular file */
+						bb_error_msg_and_die("'%s' exists but is not regular file",dst_fn);
+					}
+				}
+			}
+		}
+
+		switch (i) {
+		case 'A':
+			overwrite = o_always;
+		case 'y': /* Open file and fall into unzip */
+			unzip_create_leading_dirs(dst_fn);
+			dst_fd = bb_xopen(dst_fn, O_WRONLY | O_CREAT);
+		case -1: /* Unzip */
+			if (verbosity == v_normal) {
+				printf("  inflating: %s\n", dst_fn);
+			}
+			if (unzip_extract(&zip_header, src_fd, dst_fd)) {
+			    failed = 1;
+			}
+			if (dst_fd != STDOUT_FILENO) {
+				/* closing STDOUT is potentially bad for future business */
+				close(dst_fd);
+			}
+			break;
+
+		case 'N':
+			overwrite = o_never;
+		case 'n':
+			/* Skip entry data */
+			unzip_skip(src_fd, zip_header.formated.cmpsize);
+			break;
+
+		case 'r':
+			/* Prompt for new name */
+			printf("new name: ");
+			if (!fgets(key_buf, 512, stdin)) {
+				bb_perror_msg_and_die("Cannot read input");
+			}
+			free(dst_fn);
+			dst_fn = bb_xstrdup(key_buf);
+			chomp(dst_fn);
+			goto _check_file;
+
+		default:
+			printf("error: invalid response [%c]\n",(char)i);
+			goto _check_file;
+		}
+
+		/* Data descriptor section */
+		if (zip_header.formated.flags & 4) {
+			/* skip over duplicate crc, compressed size and uncompressed size */
+			unzip_skip(src_fd, 12);
+		}
+	}
+
+	if (verbosity == v_list) {
+		printf(" --------                   -------\n"
+		       "%9d                   %d files\n", total_size, total_entries);
+	}
+
+	return failed;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/changelog
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/changelog	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/changelog	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,598 @@
+Various bug fixes that apply to busybox 1.2.0, cherry-picked from the
+ongoing development branch.  This will form the basis for busybox 1.2.1.
+
+I'll append fixes to this as they come up.  (Check the file date, or the bug
+list below.)  This file is basically a concatenation of the following:
+
+http://busybox.net/downloads/patches/svn-15575.patch
+http://busybox.net/downloads/patches/svn-15653.patch
+http://busybox.net/downloads/patches/svn-15656.patch
+http://busybox.net/downloads/patches/svn-15658.patch
+http://busybox.net/downloads/patches/svn-15659.patch
+http://busybox.net/downloads/patches/svn-15660.patch
+http://busybox.net/downloads/patches/svn-15670.patch
+http://busybox.net/downloads/patches/svn-15698.patch
+http://busybox.net/downloads/patches/svn-15700.patch
+http://busybox.net/downloads/patches/svn-15702.patch
+http://busybox.net/downloads/patches/svn-15705.patch
+http://busybox.net/downloads/patches/svn-15727.patch
+
+ ------------------------------------------------------------------------
+r15575 | landley | 2006-07-01 13:19:02 -0400 (Sat, 01 Jul 2006) | 2 lines
+Changed paths:
+   M /trunk/busybox/shell/lash.c
+
+Patch from Shaun Jackman moving the var=value logic to where it can do some
+good.
+
+ ------------------------------------------------------------------------
+Index: shell/lash.c
+===================================================================
+--- shell/lash.c	(revision 15574)
++++ shell/lash.c	(revision 15575)
+@@ -1171,12 +1171,6 @@
+ {
+ 	struct built_in_command *x;
+ 
+-	/* Check if the command sets an environment variable. */
+-	if( strchr(child->argv[0], '=') != NULL ) {
+-		child->argv[1] = child->argv[0];
+-		_exit(builtin_export(child));
+-	}
+-
+ 	/* Check if the command matches any of the non-forking builtins.
+ 	 * Depending on context, this might be redundant.  But it's
+ 	 * easier to waste a few CPU cycles than it is to figure out
+@@ -1300,6 +1294,12 @@
+ 		 * is doomed to failure, and doesn't work on bash, either.
+ 		 */
+ 		if (newjob->num_progs == 1) {
++			/* Check if the command sets an environment variable. */
++			if (strchr(child->argv[0], '=') != NULL) {
++				child->argv[1] = child->argv[0];
++				return builtin_export(child);
++			}
++
+ 			for (x = bltins; x->cmd; x++) {
+ 				if (strcmp(child->argv[0], x->cmd) == 0 ) {
+ 					int rcode;
+ ------------------------------------------------------------------------
+r15653 | landley | 2006-07-05 21:09:21 -0400 (Wed, 05 Jul 2006) | 6 lines
+Changed paths:
+   M /trunk/busybox/shell/ash.c
+
+Bug fix from Vladimir Oleynic via Paul Fox for:
+echo "+bond0" > /sys/class/net/bonding_masters
+while true; do
+  echo hello
+done  
+
+ ------------------------------------------------------------------------
+Index: shell/ash.c
+===================================================================
+--- shell/ash.c	(revision 15652)
++++ shell/ash.c	(revision 15653)
+@@ -3469,6 +3469,7 @@
+ 	flushall();
+ cmddone:
+ 	exitstatus |= ferror(stdout);
++	clearerr(stdout);
+ 	commandname = savecmdname;
+ 	exsig = 0;
+ 	handler = savehandler;
+ ------------------------------------------------------------------------
+r15656 | landley | 2006-07-06 12:41:56 -0400 (Thu, 06 Jul 2006) | 5 lines
+Changed paths:
+   M /trunk/busybox/util-linux/dmesg.c
+
+Fix three embarassing thinkos in the new dmesg.c:
+1) the c argument shouldn't have had a : after that, dunno how that got there.
+2) the xgetlarg for level was using size
+3) because xgetlarg's error message _SUCKS_ (it does a show_usage() rather than giving any specific info about the range that was violated) I dropped the range down to 2 bytes.  (Which works fine, I dunno why we were nit-picking about that...)
+
+ ------------------------------------------------------------------------
+Index: util-linux/dmesg.c
+===================================================================
+--- util-linux/dmesg.c	(revision 15655)
++++ util-linux/dmesg.c	(revision 15656)
+@@ -15,16 +15,16 @@
+ int dmesg_main(int argc, char *argv[])
+ {
+ 	char *size, *level;
+-	int flags = bb_getopt_ulflags(argc, argv, "c:s:n:", &size, &level);
++	int flags = bb_getopt_ulflags(argc, argv, "cs:n:", &size, &level);
+ 
+ 	if (flags & 4) {
+-		if(klogctl(8, NULL, bb_xgetlarg(size, 10, 0, 10)))
++		if(klogctl(8, NULL, bb_xgetlarg(level, 10, 0, 10)))
+ 			bb_perror_msg_and_die("klogctl");
+ 	} else {
+ 		int len;
+ 		char *buf;
+ 
+-		len = (flags & 2) ? bb_xgetlarg(size, 10, 4096, INT_MAX) : 16384;
++		len = (flags & 2) ? bb_xgetlarg(size, 10, 2, INT_MAX) : 16384;
+ 		buf = xmalloc(len);
+ 		if (0 > (len = klogctl(3 + (flags & 1), buf, len)))
+ 			bb_perror_msg_and_die("klogctl");
+ ------------------------------------------------------------------------
+r15658 | pgf | 2006-07-06 16:00:43 -0400 (Thu, 06 Jul 2006) | 4 lines
+Changed paths:
+   M /trunk/busybox/Makefile
+
+fix dependencies so that compressed usage gets rebuilt if
+    a) include/usage.h is changed, and 
+    b) after "make clean".
+
+ ------------------------------------------------------------------------
+Index: Makefile
+===================================================================
+--- Makefile	(revision 15657)
++++ Makefile	(revision 15658)
+@@ -436,13 +436,16 @@
+ 
+ ifeq ($(strip $(CONFIG_FEATURE_COMPRESS_USAGE)),y)
+ USAGE_BIN:=scripts/usage
+-$(USAGE_BIN): $(top_srcdir)/scripts/usage.c .config
++$(USAGE_BIN): $(top_srcdir)/scripts/usage.c .config \
++		$(top_srcdir)/include/usage.h
+ 	$(do_link.h)
+ 
+ DEP_INCLUDES += include/usage_compressed.h
+ 
+-include/usage_compressed.h: .config $(USAGE_BIN) $(top_srcdir)/scripts/usage_compressed
+-	$(Q)SED="$(SED)" $(SHELL) $(top_srcdir)/scripts/usage_compressed "$(top_builddir)/scripts" > $@
++include/usage_compressed.h: .config $(USAGE_BIN) \
++		$(top_srcdir)/scripts/usage_compressed
++	$(Q)SED="$(SED)" $(SHELL) $(top_srcdir)/scripts/usage_compressed \
++	"$(top_builddir)/scripts" > $@
+ endif # CONFIG_FEATURE_COMPRESS_USAGE
+ 
+ # workaround alleged bug in make-3.80, make-3.81
+@@ -470,7 +473,8 @@
+ 	    docs/BusyBox.txt docs/BusyBox.1 docs/BusyBox.html \
+ 	    docs/busybox.net/BusyBox.html busybox.links \
+ 	    libbusybox.so* \
+-	    .config.old busybox busybox_unstripped
++	    .config.old busybox busybox_unstripped \
++	    include/usage_compressed.h scripts/usage
+ 	- rm -r -f _install testsuite/links
+ 	- find . -name .\*.flags -o -name \*.o  -o -name \*.om -o -name \*.syn \
+ 	    -o -name \*.os -o -name \*.osm -o -name \*.a | xargs rm -f
+ ------------------------------------------------------------------------
+r15659 | landley | 2006-07-06 16:02:47 -0400 (Thu, 06 Jul 2006) | 3 lines
+Changed paths:
+   M /trunk/busybox/libbb/Makefile
+
+Attempt to address Shaun Jackman's problem adding "busybox: busybox.bflt" to
+.config.mak.
+
+ ------------------------------------------------------------------------
+Index: libbb/Makefile
+===================================================================
+--- libbb/Makefile	(revision 15658)
++++ libbb/Makefile	(revision 15659)
+@@ -12,6 +12,12 @@
+ endif
+ srcdir=$(top_srcdir)/libbb
+ LIBBB_DIR:=./
++
++# Ensure "all" is still the default target when make is run by itself in
++# libbb, even if the files we include define rules for targets.
++
++all:
++
+ include $(top_srcdir)/Rules.mak
+ include $(top_builddir)/.config
+ include Makefile.in
+ ------------------------------------------------------------------------
+r15660 | landley | 2006-07-06 16:30:19 -0400 (Thu, 06 Jul 2006) | 3 lines
+Changed paths:
+   M /trunk/busybox/archival/libunarchive/get_header_tar.c
+
+Fix tar so it can extract git-generated tarballs, based on a suggestion
+from Erik Frederiksen.
+
+ ------------------------------------------------------------------------
+Index: archival/libunarchive/get_header_tar.c
+===================================================================
+--- archival/libunarchive/get_header_tar.c	(revision 15659)
++++ archival/libunarchive/get_header_tar.c	(revision 15660)
+@@ -137,10 +137,6 @@
+ 	case '1':
+ 		file_header->mode |= S_IFREG;
+ 		break;
+-	case 'x':
+-	case 'g':
+-		bb_error_msg_and_die("pax is not tar");
+-		break;
+ 	case '7':
+ 		/* Reserved for high performance files, treat as normal file */
+ 	case 0:
+@@ -188,8 +184,11 @@
+ 	case 'N':	/* Old GNU for names > 100 characters */
+ 	case 'S':	/* Sparse file */
+ 	case 'V':	/* Volume header */
+-		bb_error_msg("Ignoring GNU extension type %c", tar.formated.typeflag);
+ #endif
++	case 'g':	/* pax global header */
++	case 'x':	/* pax extended header */
++		bb_error_msg("Ignoring extension type %c", tar.formated.typeflag);
++		break;
+ 	default:
+ 		bb_error_msg("Unknown typeflag: 0x%x", tar.formated.typeflag);
+ 	}
+ ------------------------------------------------------------------------
+r15670 | landley | 2006-07-09 13:03:07 -0400 (Sun, 09 Jul 2006) | 3 lines
+Changed paths:
+   M /trunk/busybox/shell/lash.c
+
+Bugfix from Shaun Jackman (check that argv[optind] isn't null before
+dereferencing it) plus a bunch of tweaks from me.
+
+ ------------------------------------------------------------------------
+Index: shell/lash.c
+===================================================================
+--- shell/lash.c	(revision 15669)
++++ shell/lash.c	(revision 15670)
+@@ -1498,6 +1498,8 @@
+ 		remove_job(&job_list, job_list.fg);
+ 	}
+ }
++#else
++void free_memory(void);
+ #endif
+ 
+ #ifdef CONFIG_LASH_JOB_CONTROL
+@@ -1528,7 +1530,7 @@
+ 	/* Put ourselves in our own process group.  */
+ 	setsid();
+ 	shell_pgrp = getpid ();
+-	setpgid (shell_pgrp, shell_pgrp);
++	setpgid(shell_pgrp, shell_pgrp);
+ 
+ 	/* Grab control of the terminal.  */
+ 	tcsetpgrp(shell_terminal, shell_pgrp);
+@@ -1577,7 +1579,7 @@
+ 				argv = argv+optind;
+ 				break;
+ 			case 'i':
+-				interactive = TRUE;
++				interactive++;
+ 				break;
+ 			default:
+ 				bb_show_usage();
+@@ -1591,18 +1593,18 @@
+ 	 *    standard output is a terminal
+ 	 *    Refer to Posix.2, the description of the `sh' utility. */
+ 	if (argv[optind]==NULL && input==stdin &&
+-			isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
+-		interactive=TRUE;
++			isatty(STDIN_FILENO) && isatty(STDOUT_FILENO))
++	{
++		interactive++;
+ 	}
+ 	setup_job_control();
+-	if (interactive==TRUE) {
+-		//printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
++	if (interactive) {
+ 		/* Looks like they want an interactive shell */
+-#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
+-		printf( "\n\n%s Built-in shell (lash)\n", BB_BANNER);
+-		printf( "Enter 'help' for a list of built-in commands.\n\n");
+-#endif
+-	} else if (local_pending_command==NULL) {
++		if (!ENABLE_FEATURE_SH_EXTRA_QUIET) {
++			printf( "\n\n%s Built-in shell (lash)\n", BB_BANNER);
++			printf( "Enter 'help' for a list of built-in commands.\n\n");
++		}
++	} else if (!local_pending_command && argv[optind]) {
+ 		//printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
+ 		input = bb_xfopen(argv[optind], "r");
+ 		/* be lazy, never mark this closed */
+@@ -1614,15 +1616,10 @@
+ 	if (!cwd)
+ 		cwd = bb_msg_unknown;
+ 
+-#ifdef CONFIG_FEATURE_CLEAN_UP
+-	atexit(free_memory);
+-#endif
++	if (ENABLE_FEATURE_CLEAN_UP) atexit(free_memory);
+ 
+-#ifdef CONFIG_FEATURE_COMMAND_EDITING
+-	cmdedit_set_initial_prompt();
+-#else
+-	PS1 = NULL;
+-#endif
++	if (ENABLE_FEATURE_COMMAND_EDITING) cmdedit_set_initial_prompt();
++	else PS1 = NULL;
+ 
+ 	return (busy_loop(input));
+ }
+ ------------------------------------------------------------------------
+r15698 | vapier | 2006-07-14 23:59:00 -0400 (Fri, 14 Jul 2006) | 2 lines
+Changed paths:
+   M /trunk/busybox/libbb/obscure.c
+
+Tito writes: If the gecos field of an user is empty, obscure reports a false "similar to gecos" error.
+
+ ------------------------------------------------------------------------
+Index: libbb/obscure.c
+===================================================================
+--- libbb/obscure.c	(revision 15697)
++++ libbb/obscure.c	(revision 15698)
+@@ -109,7 +109,7 @@
+ 		return "similar to username";
+ 	}
+ 	/* no gecos as-is, as sub-string, reversed, capitalized, doubled */
+-	if (string_checker(new_p, pw->pw_gecos)) {
++	if (*pw->pw_gecos && string_checker(new_p, pw->pw_gecos)) {
+ 		return "similar to gecos";
+ 	}
+ 	/* hostname as-is, as sub-string, reversed, capitalized, doubled */
+ ------------------------------------------------------------------------
+r15700 | landley | 2006-07-15 19:00:46 -0400 (Sat, 15 Jul 2006) | 4 lines
+Changed paths:
+   M /trunk/busybox/include/libbb.h
+   M /trunk/busybox/libbb/xfuncs.c
+
+We need xsetuid() and xsetgid() because per-user process resource limits can
+prevent a process from switching to a user that has too many processes, and
+when that happens WE'RE STILL ROOT.  See http://lwn.net/Articles/190331/
+
+ ------------------------------------------------------------------------
+Index: libbb/xfuncs.c
+===================================================================
+--- libbb/xfuncs.c	(revision 15699)
++++ libbb/xfuncs.c	(revision 15700)
+@@ -232,3 +232,15 @@
+  	return 0;
+ }
+ #endif	
++
++#ifdef L_setuid
++void xsetgid(gid_t gid)
++{
++	if (setgid(gid)) bb_error_msg_and_die("setgid");
++}
++
++void xsetuid(uid_t uid)
++{
++	if (setuid(uid)) bb_error_msg_and_die("setuid");
++}
++#endif
+Index: include/libbb.h
+===================================================================
+--- include/libbb.h	(revision 15699)
++++ include/libbb.h	(revision 15700)
+@@ -185,6 +185,8 @@
+ extern bb_xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
+ extern void bb_xlisten(int s, int backlog);
+ extern void bb_xchdir(const char *path);
++extern void xsetgid(gid_t gid);
++extern void xsetuid(uid_t uid);
+ 
+ #define BB_GETOPT_ERROR 0x80000000UL
+ extern const char *bb_opt_complementally;
+ ------------------------------------------------------------------------
+r15702 | landley | 2006-07-16 04:06:34 -0400 (Sun, 16 Jul 2006) | 2 lines
+Changed paths:
+   M /trunk/busybox/loginutils/passwd.c
+   M /trunk/busybox/networking/arping.c
+   M /trunk/busybox/networking/ether-wake.c
+   M /trunk/busybox/networking/fakeidentd.c
+   M /trunk/busybox/networking/inetd.c
+   M /trunk/busybox/networking/traceroute.c
+
+Convert setuid/setgid users to xsetuid/xsetgid.
+
+ ------------------------------------------------------------------------
+Index: networking/fakeidentd.c
+===================================================================
+--- networking/fakeidentd.c	(revision 15701)
++++ networking/fakeidentd.c	(revision 15702)
+@@ -159,8 +159,8 @@
+ 
+ 		close(0);
+ 		inetbind();
+-		if (setgid(nogrp))   bb_error_msg_and_die("Could not setgid()");
+-		if (setuid(nobody))  bb_error_msg_and_die("Could not setuid()");
++		xsetgid(nogrp);
++		xsetuid(nobody);
+ 		close(1);
+ 		close(2);
+ 
+Index: networking/ether-wake.c
+===================================================================
+--- networking/ether-wake.c	(revision 15701)
++++ networking/ether-wake.c	(revision 15702)
+@@ -145,7 +145,7 @@
+ 	s = make_socket();
+ 
+ 	/* now that we have a raw socket we can drop root */
+-	setuid(getuid());
++	xsetuid(getuid());
+ 
+ 	/* look up the dest mac address */
+ 	get_dest_addr(argv[optind], &eaddr);
+Index: networking/inetd.c
+===================================================================
+--- networking/inetd.c	(revision 15701)
++++ networking/inetd.c	(revision 15702)
+@@ -1513,11 +1513,11 @@
+ 			  if (sep->se_group) {
+ 				pwd->pw_gid = grp->gr_gid;
+ 			  }
+-			  setgid ((gid_t) pwd->pw_gid);
++			  xsetgid ((gid_t) pwd->pw_gid);
+ 			  initgroups (pwd->pw_name, pwd->pw_gid);
+-			  setuid ((uid_t) pwd->pw_uid);
++			  xsetuid((uid_t) pwd->pw_uid);
+ 			} else if (sep->se_group) {
+-			  setgid (grp->gr_gid);
++			  xsetgid(grp->gr_gid);
+ 			  setgroups (1, &grp->gr_gid);
+ 			}
+ 			dup2 (ctrl, 0);
+Index: networking/traceroute.c
+===================================================================
+--- networking/traceroute.c	(revision 15701)
++++ networking/traceroute.c	(revision 15702)
+@@ -941,7 +941,6 @@
+ #endif
+ 	u_short off = 0;
+ 	struct IFADDRLIST *al;
+-	int uid = getuid();
+ 	char *device = NULL;
+ 	int max_ttl = 30;
+ 	char *max_ttl_str = NULL;
+@@ -1010,8 +1009,7 @@
+ 	     * set the ip source address of the outbound
+ 	     * probe (e.g., on a multi-homed host).
+ 	     */
+-	     if (uid)
+-		bb_error_msg_and_die("-s %s: Permission denied", source);
++	     if (getuid()) bb_error_msg_and_die("-s %s: Permission denied", source);
+ 	}
+ 	if(waittime_str)
+ 		waittime = str2val(waittime_str, "wait time", 2, 24 * 60 * 60);
+@@ -1160,8 +1158,8 @@
+ 		    sizeof(on));
+ 
+ 	/* Revert to non-privileged user after opening sockets */
+-	setgid(getgid());
+-	setuid(uid);
++	xsetgid(getgid());
++	xsetuid(getuid());
+ 
+ 	outip = (struct ip *)xcalloc(1, (unsigned)packlen);
+ 
+Index: networking/arping.c
+===================================================================
+--- networking/arping.c	(revision 15701)
++++ networking/arping.c	(revision 15702)
+@@ -262,7 +262,8 @@
+ 	s = socket(PF_PACKET, SOCK_DGRAM, 0);
+ 	ifindex = errno;
+ 
+-	setuid(getuid());
++	// Drop suid root privileges
++	xsetuid(getuid());
+ 
+ 	{
+ 		unsigned long opt;
+Index: loginutils/passwd.c
+===================================================================
+--- loginutils/passwd.c	(revision 15701)
++++ loginutils/passwd.c	(revision 15702)
+@@ -227,10 +227,7 @@
+ 	signal(SIGINT, SIG_IGN);
+ 	signal(SIGQUIT, SIG_IGN);
+ 	umask(077);
+-	if (setuid(0)) {
+-		syslog(LOG_ERR, "can't setuid(0)");
+-		bb_error_msg_and_die( "Cannot change ID to root.\n");
+-	}
++	xsetuid(0);
+ 	if (!update_passwd(pw, crypt_passwd)) {
+ 		syslog(LOG_INFO, "password for `%s' changed by user `%s'", name,
+ 			   myname);
+ ------------------------------------------------------------------------
+r15705 | landley | 2006-07-16 14:58:18 -0400 (Sun, 16 Jul 2006) | 2 lines
+Changed paths:
+   M /trunk/busybox/loginutils/adduser.c
+
+Bugfix from Tito to make sure /etc/group gets updated.
+
+ ------------------------------------------------------------------------
+Index: loginutils/adduser.c
+===================================================================
+--- loginutils/adduser.c	(revision 15704)
++++ loginutils/adduser.c	(revision 15705)
+@@ -96,6 +96,7 @@
+ static int adduser(struct passwd *p, unsigned long flags)
+ {
+ 	FILE *file;
++	int addgroup = !p->pw_gid;
+ 
+ 	/* make sure everything is kosher and setup uid && gid */
+ 	file = bb_xfopen(bb_path_passwd_file, "a");
+@@ -132,9 +133,8 @@
+ 	/* add to group */
+ 	/* addgroup should be responsible for dealing w/ gshadow */
+ 	/* if using a pre-existing group, don't create one */
+-	if (p->pw_gid == 0) {
+-		addgroup_wrapper(p);
+-	}
++	if (addgroup) addgroup_wrapper(p);
++
+ 	/* Clear the umask for this process so it doesn't
+ 	 * * screw up the permissions on the mkdir and chown. */
+ 	umask(0);
+ ------------------------------------------------------------------------
+r15727 | landley | 2006-07-19 17:33:42 -0400 (Wed, 19 Jul 2006) | 4 lines
+Changed paths:
+   M /trunk/busybox/modutils/modprobe.c
+
+Patch from Yann Morin to look for modules.conf in the right place on 2.6.
+Fixes http://bugs.busybox.net/view.php?id=942
+
+
+ ------------------------------------------------------------------------
+Index: modutils/modprobe.c
+===================================================================
+--- modutils/modprobe.c	(revision 15726)
++++ modutils/modprobe.c	(revision 15727)
+@@ -545,29 +545,37 @@
+ 	}
+ 	close ( fd );
+ 
++	/*
++	 * First parse system-specific options and aliases
++	 * as they take precedence over the kernel ones.
++	 */
+ 	if (!ENABLE_FEATURE_2_6_MODULES
+ 			|| ( fd = open ( "/etc/modprobe.conf", O_RDONLY )) < 0 )
+ 		if (( fd = open ( "/etc/modules.conf", O_RDONLY )) < 0 )
+-			if (( fd = open ( "/etc/conf.modules", O_RDONLY )) < 0 )
+-				return first;
++			fd = open ( "/etc/conf.modules", O_RDONLY );
+ 
+-	include_conf (&first, &current, buffer, sizeof(buffer), fd);
+-	close(fd);
++	if (fd >= 0) {
++		include_conf (&first, &current, buffer, sizeof(buffer), fd);
++		close(fd);
++	}
+ 
+-	filename = bb_xasprintf("/lib/modules/%s/modules.alias", un.release);
+-	fd = open ( filename, O_RDONLY );
+-	if (ENABLE_FEATURE_CLEAN_UP)
+-		free(filename);
+-	if (fd < 0) {
+-		/* Ok, that didn't work.  Fall back to looking in /lib/modules */
+-		if (( fd = open ( "/lib/modules/modules.alias", O_RDONLY )) < 0 ) {
+-			return first;
++	/* Only 2.6 has a modules.alias file */
++	if (ENABLE_FEATURE_2_6_MODULES) {
++		/* Parse kernel-declared aliases */
++		filename = bb_xasprintf("/lib/modules/%s/modules.alias", un.release);
++		if ((fd = open ( filename, O_RDONLY )) < 0) {
++			/* Ok, that didn't work.  Fall back to looking in /lib/modules */
++			fd = open ( "/lib/modules/modules.alias", O_RDONLY );
+ 		}
++		if (ENABLE_FEATURE_CLEAN_UP)
++			free(filename);
++
++		if (fd >= 0) {
++			include_conf (&first, &current, buffer, sizeof(buffer), fd);
++			close(fd);
++		}
+ 	}
+ 
+-	include_conf (&first, &current, buffer, sizeof(buffer), fd);
+-	close(fd);
+-
+ 	return first;
+ }
+ 

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,88 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Console Utilities"
+
+config CONFIG_CHVT
+	bool "chvt"
+	default n
+	help
+	  This program is used to change to another terminal.
+	  Example: chvt 4 (change to terminal /dev/tty4)
+
+config CONFIG_CLEAR
+	bool "clear"
+	default n
+	help
+	  This program clears the terminal screen.
+
+config CONFIG_DEALLOCVT
+	bool "deallocvt"
+	default n
+	help
+	  This program deallocates unused virtual consoles.
+
+config CONFIG_DUMPKMAP
+	bool "dumpkmap"
+	default n
+	help
+	  This program dumps the kernel's keyboard translation table to
+	  stdout, in binary format. You can then use loadkmap to load it.
+
+config CONFIG_LOADFONT
+	bool "loadfont"
+	default n
+	help
+	  This program loads a console font from standard input.
+
+config CONFIG_LOADKMAP
+	bool "loadkmap"
+	default n
+	help
+	  This program loads a keyboard translation table from
+	  standard input.
+
+config CONFIG_OPENVT
+	bool "openvt"
+	default n
+	help
+	  This program is used to start a command on an unused
+	  virtual terminal.
+
+config CONFIG_RESET
+	bool "reset"
+	default n
+	help
+	  This program is used to reset the terminal screen, if it
+	  gets messed up.
+
+config CONFIG_SETCONSOLE
+	bool "setconsole"
+	default n
+	help
+	  This program redirects the system console to another device,
+	  like the current tty while logged in via telnet.
+
+config CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS
+	bool "Enable long options"
+	default n
+	depends on CONFIG_SET_CONSOLE && CONFIG_GETOPT_LONG
+	help
+	  Support long options for the setconsole applet.
+
+config CONFIG_SETKEYCODES
+	bool "setkeycodes"
+	default n
+	help
+	  This program loads entries into the kernel's scancode-to-keycode
+	  map, allowing unusual keyboards to generate usable keycodes.
+
+config CONFIG_SETLOGCONS
+	bool "setlogcons"
+	default n
+	help
+	  This program redirects the output console of kernel messages.
+
+endmenu

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/console/tools
+CONSOLETOOLS_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include $(srcdir)/Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,38 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+CONSOLETOOLS_AR:=console-tools.a
+ifndef $(CONSOLETOOLS_DIR)
+CONSOLETOOLS_DIR:=$(top_builddir)/console-tools/
+endif
+srcdir=$(top_srcdir)/console-tools
+
+CONSOLETOOLS-y:=
+CONSOLETOOLS-$(CONFIG_CHVT)		+= chvt.o
+CONSOLETOOLS-$(CONFIG_CLEAR)	+= clear.o
+CONSOLETOOLS-$(CONFIG_DEALLOCVT)	+= deallocvt.o
+CONSOLETOOLS-$(CONFIG_DUMPKMAP)	+= dumpkmap.o
+CONSOLETOOLS-$(CONFIG_SETCONSOLE)	+= setconsole.o
+CONSOLETOOLS-$(CONFIG_LOADFONT)	+= loadfont.o
+CONSOLETOOLS-$(CONFIG_LOADKMAP)	+= loadkmap.o
+CONSOLETOOLS-$(CONFIG_OPENVT)	+= openvt.o
+CONSOLETOOLS-$(CONFIG_RESET)	+= reset.o
+CONSOLETOOLS-$(CONFIG_SETKEYCODES)	+= setkeycodes.o
+CONSOLETOOLS-$(CONFIG_SETLOGCONS)	+= setlogcons.o
+
+ifneq ($(strip $(CONSOLETOOLS-y)),)
+libraries-y+=$(CONSOLETOOLS_DIR)$(CONSOLETOOLS_AR)
+endif
+CONSOLETOOLS_SRC-y:=$(patsubst %.o,$(srcdir)/%.c,$(CONSOLETOOLS-y))
+CONSOLETOOLS_SRC-a:=$(wildcard $(srcdir)/*.c)
+APPLET_SRC-y+=$(CONSOLETOOLS_SRC-y)
+APPLET_SRC-a+=$(CONSOLETOOLS_SRC-a)
+
+$(CONSOLETOOLS_DIR)$(CONSOLETOOLS_AR): $(patsubst %,$(CONSOLETOOLS_DIR)%, $(CONSOLETOOLS-y))
+	$(do_ar)
+
+$(CONSOLETOOLS_DIR)%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/chvt.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/chvt.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/chvt.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,38 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini chvt implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include "busybox.h"
+
+/* From <linux/vt.h> */
+enum {
+	VT_ACTIVATE = 0x5606,   /* make vt active */
+	VT_WAITACTIVE = 0x5607  /* wait for vt active */
+};
+
+int chvt_main(int argc, char **argv)
+{
+	int fd, num;
+
+	if (argc != 2) {
+		bb_show_usage();
+	}
+
+	fd = get_console_fd();
+	num =  bb_xgetlarg(argv[1], 10, 0, INT_MAX);
+	if ((-1 == ioctl(fd, VT_ACTIVATE, num))
+	|| (-1 == ioctl(fd, VT_WAITACTIVE, num))) {
+		bb_perror_msg_and_die("ioctl");
+	}
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/clear.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/clear.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/clear.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,33 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini clear implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* no options, no getopt */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+
+int clear_main(int argc, char **argv)
+{
+	return printf("\033[H\033[J") != 6;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/deallocvt.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/deallocvt.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/deallocvt.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,56 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Disallocate virtual terminal(s)
+ *
+ * Copyright (C) 2003 by Tito Ragusa <farmatito at tiscali.it>
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* no options, no getopt */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include "busybox.h"
+
+/* From <linux/vt.h> */
+enum { VT_DISALLOCATE = 0x5608 }; /* free memory associated to vt */
+
+int deallocvt_main(int argc, char *argv[])
+{
+	/* num = 0 deallocate all unused consoles */
+	int num = 0;
+
+	switch (argc) {
+		case 2:
+			if ((num = bb_xgetlarg(argv[1], 10, 0, INT_MAX)) == 0) {
+				bb_error_msg_and_die("0: illegal VT number");
+			}
+		/* Fallthrough */
+		case 1:
+			break;
+		default:
+			bb_show_usage();
+	}
+
+	if (-1 == ioctl(get_console_fd(), VT_DISALLOCATE, num)) {
+		bb_perror_msg_and_die("VT_DISALLOCATE");
+	}
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/dumpkmap.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/dumpkmap.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/dumpkmap.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,84 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini dumpkmap implementation for busybox
+ *
+ * Copyright (C) Arne Bernin <arne at matrix.loopback.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include "busybox.h"
+
+/* From <linux/kd.h> */
+struct kbentry {
+	unsigned char kb_table;
+	unsigned char kb_index;
+	unsigned short kb_value;
+};
+#define KDGKBENT 0x4B46  /* gets one entry in translation table */
+
+/* From <linux/keyboard.h> */
+#define NR_KEYS 128
+#define MAX_NR_KEYMAPS 256
+
+int dumpkmap_main(int argc, char **argv)
+{
+	struct kbentry ke;
+	int i, j, fd;
+	char flags[MAX_NR_KEYMAPS], magic[] = "bkeymap";
+
+	if (argc >= 2 && *argv[1] == '-')
+		bb_show_usage();
+
+	fd = bb_xopen(CURRENT_VC, O_RDWR);
+
+	write(1, magic, 7);
+
+	/* Here we want to set everything to 0 except for indexes:
+	 * [0-2] [4-6] [8-10] [12] */
+	memset(flags, 0x00, MAX_NR_KEYMAPS);
+	memset(flags, 0x01, 13);
+	flags[3] = flags[7] = flags[11] = 0;
+
+	/* dump flags */
+	write(1, flags, MAX_NR_KEYMAPS);
+
+	for (i = 0; i < MAX_NR_KEYMAPS; i++) {
+		if (flags[i] == 1) {
+			for (j = 0; j < NR_KEYS; j++) {
+				ke.kb_index = j;
+				ke.kb_table = i;
+				if (ioctl(fd, KDGKBENT, &ke) < 0) {
+					bb_perror_msg("ioctl failed with %s, %s, %p",
+						(char *)&ke.kb_index,
+						(char *)&ke.kb_table,
+						&ke.kb_value);
+				} else {
+					write(1, (void*)&ke.kb_value, 2);
+				}
+			}
+		}
+	}
+	close(fd);
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/loadfont.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/loadfont.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/loadfont.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,208 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * loadfont.c - Eugene Crosser & Andries Brouwer
+ *
+ * Version 0.96bb
+ *
+ * Loads the console font, and possibly the corresponding screen map(s).
+ * (Adapted for busybox by Matej Vela.)
+ */
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/kd.h>
+#include <endian.h>
+#include "busybox.h"
+
+enum{
+	PSF_MAGIC1 = 0x36,
+	PSF_MAGIC2 = 0x04,
+
+	PSF_MODE512 = 0x01,
+	PSF_MODEHASTAB = 0x02,
+	PSF_MAXMODE = 0x03,
+	PSF_SEPARATOR = 0xFFFF
+};
+
+struct psf_header {
+	unsigned char magic1, magic2;	/* Magic number */
+	unsigned char mode;			/* PSF font mode */
+	unsigned char charsize;		/* Character size */
+};
+
+#define PSF_MAGIC_OK(x)	((x).magic1 == PSF_MAGIC1 && (x).magic2 == PSF_MAGIC2)
+
+static void loadnewfont(int fd);
+
+int loadfont_main(int argc, char **argv)
+{
+	int fd;
+
+	if (argc != 1)
+		bb_show_usage();
+
+	fd = bb_xopen(CURRENT_VC, O_RDWR);
+	loadnewfont(fd);
+
+	return EXIT_SUCCESS;
+}
+
+static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize)
+{
+	char buf[16384];
+	int i;
+
+	memset(buf, 0, sizeof(buf));
+
+	if (unit < 1 || unit > 32)
+		bb_error_msg_and_die("Bad character size %d", unit);
+
+	for (i = 0; i < fontsize; i++)
+		memcpy(buf + (32 * i), inbuf + (unit * i), unit);
+
+#if defined( PIO_FONTX ) && !defined( __sparc__ )
+	{
+		struct consolefontdesc cfd;
+
+		cfd.charcount = fontsize;
+		cfd.charheight = unit;
+		cfd.chardata = buf;
+
+		if (ioctl(fd, PIO_FONTX, &cfd) == 0)
+			return;				/* success */
+		bb_perror_msg("PIO_FONTX ioctl error (trying PIO_FONT)");
+	}
+#endif
+	if (ioctl(fd, PIO_FONT, buf))
+		bb_perror_msg_and_die("PIO_FONT ioctl error");
+}
+
+static void
+do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize)
+{
+	struct unimapinit advice;
+	struct unimapdesc ud;
+	struct unipair *up;
+	int ct = 0, maxct;
+	int glyph;
+	u_short unicode;
+
+	maxct = tailsz;				/* more than enough */
+	up = (struct unipair *) xmalloc(maxct * sizeof(struct unipair));
+
+	for (glyph = 0; glyph < fontsize; glyph++) {
+		while (tailsz >= 2) {
+			unicode = (((u_short) inbuf[1]) << 8) + inbuf[0];
+			tailsz -= 2;
+			inbuf += 2;
+			if (unicode == PSF_SEPARATOR)
+				break;
+			up[ct].unicode = unicode;
+			up[ct].fontpos = glyph;
+			ct++;
+		}
+	}
+
+	/* Note: after PIO_UNIMAPCLR and before PIO_UNIMAP
+	   this printf did not work on many kernels */
+
+	advice.advised_hashsize = 0;
+	advice.advised_hashstep = 0;
+	advice.advised_hashlevel = 0;
+	if (ioctl(fd, PIO_UNIMAPCLR, &advice)) {
+#ifdef ENOIOCTLCMD
+		if (errno == ENOIOCTLCMD) {
+			bb_error_msg("It seems this kernel is older than 1.1.92");
+			bb_error_msg_and_die("No Unicode mapping table loaded.");
+		} else
+#endif
+			bb_perror_msg_and_die("PIO_UNIMAPCLR");
+	}
+	ud.entry_ct = ct;
+	ud.entries = up;
+	if (ioctl(fd, PIO_UNIMAP, &ud)) {
+#if 0
+		if (errno == ENOMEM) {
+			/* change advice parameters */
+		}
+#endif
+		bb_perror_msg_and_die("PIO_UNIMAP");
+	}
+}
+
+static void loadnewfont(int fd)
+{
+	int unit;
+	unsigned char inbuf[32768];			/* primitive */
+	unsigned int inputlth, offset;
+
+	/*
+	 * We used to look at the length of the input file
+	 * with stat(); now that we accept compressed files,
+	 * just read the entire file.
+	 */
+	inputlth = fread(inbuf, 1, sizeof(inbuf), stdin);
+	if (ferror(stdin))
+		bb_perror_msg_and_die("Error reading input font");
+	/* use malloc/realloc in case of giant files;
+	   maybe these do not occur: 16kB for the font,
+	   and 16kB for the map leaves 32 unicode values
+	   for each font position */
+	if (!feof(stdin))
+		bb_perror_msg_and_die("Font too large");
+
+	/* test for psf first */
+	{
+		struct psf_header psfhdr;
+		int fontsize;
+		int hastable;
+		unsigned int head0, head;
+
+		if (inputlth < sizeof(struct psf_header))
+			goto no_psf;
+
+		psfhdr = *(struct psf_header *) &inbuf[0];
+
+		if (!PSF_MAGIC_OK(psfhdr))
+			goto no_psf;
+
+		if (psfhdr.mode > PSF_MAXMODE)
+			bb_error_msg_and_die("Unsupported psf file mode");
+		fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256);
+#if !defined( PIO_FONTX ) || defined( __sparc__ )
+		if (fontsize != 256)
+			bb_error_msg_and_die("Only fontsize 256 supported");
+#endif
+		hastable = (psfhdr.mode & PSF_MODEHASTAB);
+		unit = psfhdr.charsize;
+		head0 = sizeof(struct psf_header);
+
+		head = head0 + fontsize * unit;
+		if (head > inputlth || (!hastable && head != inputlth))
+			bb_error_msg_and_die("Input file: bad length");
+		do_loadfont(fd, inbuf + head0, unit, fontsize);
+		if (hastable)
+			do_loadtable(fd, inbuf + head, inputlth - head, fontsize);
+		return;
+	}
+  no_psf:
+
+	/* file with three code pages? */
+	if (inputlth == 9780) {
+		offset = 40;
+		unit = 16;
+	} else {
+		/* bare font */
+		if (inputlth & 0377)
+			bb_error_msg_and_die("Bad input file size");
+		offset = 0;
+		unit = inputlth / 256;
+	}
+	do_loadfont(fd, inbuf + offset, unit, 256);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/loadkmap.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/loadkmap.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/loadkmap.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,82 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini loadkmap implementation for busybox
+ *
+ * Copyright (C) 1998 Enrique Zanardi <ezanardi at ull.es>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include "busybox.h"
+
+#define BINARY_KEYMAP_MAGIC "bkeymap"
+
+/* From <linux/kd.h> */
+struct kbentry {
+	unsigned char kb_table;
+	unsigned char kb_index;
+	unsigned short kb_value;
+};
+/* sets one entry in translation table */
+#define KDSKBENT        0x4B47
+
+/* From <linux/keyboard.h> */
+#define NR_KEYS         128
+#define MAX_NR_KEYMAPS  256
+
+int loadkmap_main(int argc, char **argv)
+{
+	struct kbentry ke;
+	int i, j, fd;
+	u_short ibuff[NR_KEYS];
+	char flags[MAX_NR_KEYMAPS];
+	char buff[7];
+
+	if (argc != 1)
+		bb_show_usage();
+
+	fd = bb_xopen(CURRENT_VC, O_RDWR);
+
+	if ((bb_full_read(0, buff, 7) != 7) || (strncmp(buff, BINARY_KEYMAP_MAGIC, 7) != 0))
+		bb_error_msg_and_die("This is not a valid binary keymap.");
+
+	if (bb_full_read(0, flags, MAX_NR_KEYMAPS) != MAX_NR_KEYMAPS)
+		bb_perror_msg_and_die("Error reading keymap flags");
+
+	for (i = 0; i < MAX_NR_KEYMAPS; i++) {
+		if (flags[i] == 1) {
+			bb_full_read(0, ibuff, NR_KEYS * sizeof(u_short));
+			for (j = 0; j < NR_KEYS; j++) {
+				ke.kb_index = j;
+				ke.kb_table = i;
+				ke.kb_value = ibuff[j];
+				ioctl(fd, KDSKBENT, &ke);
+			}
+		}
+	}
+
+	/* Don't bother to close files.  Exit does that
+	 * automagically, so we can save a few bytes */
+	/* close(fd); */
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/openvt.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/openvt.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/openvt.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,53 @@
+/* vi: set sw=4 ts=4: */
+/*
+ *  openvt.c - open a vt to run a command.
+ *
+ *  busyboxed by Quy Tonthat <quy at signal3.com>
+ *  hacked by Tito <farmatito at tiscali.it>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* getopt not needed */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+#include <ctype.h>
+
+#include "busybox.h"
+
+int openvt_main(int argc, char **argv)
+{
+	int fd;
+	char vtname[sizeof(VC_FORMAT) + 2];
+
+
+	if (argc < 3) {
+		bb_show_usage();
+	}
+	/* check for Illegal vt number: < 1 or > 12 */
+	sprintf(vtname, VC_FORMAT, (int)bb_xgetlarg(argv[1], 10, 1, 12));
+
+	if (fork() == 0) {
+		/* leave current vt */
+		if (setsid() < 0) {
+			bb_perror_msg_and_die("setsid");
+		}
+		close(0);			/* so that new vt becomes stdin */
+
+		/* and grab new one */
+		fd = bb_xopen(vtname, O_RDWR);
+
+		/* Reassign stdout and sterr */
+		dup2(fd, STDOUT_FILENO);
+		dup2(fd, STDERR_FILENO);
+
+		execvp(argv[2], &argv[2]);
+		_exit(1);
+	}
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/reset.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/reset.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/reset.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,45 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini reset implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ * Written by Erik Andersen and Kent Robotti <robotti at metconnect.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* no options, no getopt */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+int reset_main(int argc, char **argv)
+{
+	if (isatty(1)) {
+		/* See 'man 4 console_codes' for details:
+		 * "ESC c"			-- Reset
+		 * "ESC ( K"		-- Select user mapping
+		 * "ESC [ J"		-- Erase display
+		 * "ESC [ 0 m"		-- Reset all display attributes
+		 * "ESC [ ? 25 h"	-- Make cursor visible.
+		 */
+		printf("\033c\033(K\033[J\033[0m\033[?25h");
+	}
+	return EXIT_SUCCESS;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/setconsole.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/setconsole.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/setconsole.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,54 @@
+/* vi: set sw=4 ts=4: */
+/*
+ *  setconsole.c - redirect system console output
+ *
+ *  Copyright (C) 2004,2005  Enrik Berkhan <Enrik.Berkhan at inka.de>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <getopt.h> /* struct option */
+
+#include "busybox.h"
+
+#if ENABLE_FEATURE_SETCONSOLE_LONG_OPTIONS
+static const struct option setconsole_long_options[] = {
+	{ "reset", 0, NULL, 'r' },
+	{ 0, 0, 0, 0 }
+};
+#endif
+
+#define OPT_SETCONS_RESET 1
+
+int setconsole_main(int argc, char **argv)
+{
+	unsigned long flags;
+	const char *device = CURRENT_TTY;
+
+#if ENABLE_FEATURE_SETCONSOLE_LONG_OPTIONS
+	bb_applet_long_options = setconsole_long_options;
+#endif
+	flags = bb_getopt_ulflags(argc, argv, "r");
+
+	if (argc - optind > 1)
+		bb_show_usage();
+
+	if (argc - optind == 1) {
+		if (flags & OPT_SETCONS_RESET)
+			bb_show_usage();
+		device = argv[optind];
+	} else {
+		if (flags & OPT_SETCONS_RESET)
+			device = CONSOLE_DEV;
+	}
+
+	if (-1 == ioctl(bb_xopen(device, O_RDONLY), TIOCCONS)) {
+		bb_perror_msg_and_die("TIOCCONS");
+	}
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/setkeycodes.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/setkeycodes.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/setkeycodes.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,74 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * setkeycodes
+ *
+ * Copyright (C) 1994-1998 Andries E. Brouwer <aeb at cwi.nl>
+ *
+ * Adjusted for BusyBox by Erik Andersen <andersen at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "busybox.h"
+
+
+/* From <linux/kd.h> */
+struct kbkeycode {
+	unsigned int scancode, keycode;
+};
+enum {
+	KDSETKEYCODE = 0x4B4D  /* write kernel keycode table entry */
+};
+
+extern int
+setkeycodes_main(int argc, char** argv)
+{
+    char *ep;
+    int fd, sc;
+    struct kbkeycode a;
+
+    if (argc % 2 != 1 || argc < 2) {
+      bb_show_usage();
+	}
+
+	fd = get_console_fd();
+
+    while (argc > 2) {
+	a.keycode = atoi(argv[2]);
+	a.scancode = sc = strtol(argv[1], &ep, 16);
+	if (*ep) {
+      bb_error_msg_and_die("error reading SCANCODE: '%s'", argv[1]);
+	}
+	if (a.scancode > 127) {
+	    a.scancode -= 0xe000;
+	    a.scancode += 128;
+	}
+	if (a.scancode > 255 || a.keycode > 127) {
+      bb_error_msg_and_die("SCANCODE or KEYCODE outside bounds");
+	}
+	if (ioctl(fd,KDSETKEYCODE,&a)) {
+	    perror("KDSETKEYCODE");
+		bb_error_msg_and_die("failed to set SCANCODE %x to KEYCODE %d", sc, a.keycode);
+	}
+	argc -= 2;
+	argv += 2;
+    }
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/setlogcons.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/setlogcons.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/console-tools/setlogcons.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,34 @@
+/*
+ * setlogcons: Send kernel messages to the current console or to console N 
+ *
+ * Copyright (C) 2006 by Jan Kiszka <jan.kiszka at web.de>
+ *
+ * Based on setlogcons (kbd-1.12) by Andries E. Brouwer
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "busybox.h"
+
+extern int setlogcons_main(int argc, char **argv)
+{
+	struct {
+		char fn;
+		char subarg;
+	} arg;
+
+	arg.fn = 11;    /* redirect kernel messages */
+	arg.subarg = 0; /* to specified console (current as default) */
+
+	if (argc == 2)
+		arg.subarg = atoi(argv[1]);
+
+	if (ioctl(bb_xopen(VC_1, O_RDONLY), TIOCLINUX, &arg))
+		bb_perror_msg_and_die("TIOCLINUX");;
+
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,775 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Coreutils"
+
+config CONFIG_BASENAME
+	bool "basename"
+	default n
+	help
+	  basename is used to strip the directory and suffix from filenames,
+	  leaving just the filename itself.  Enable this option if you wish
+	  to enable the 'basename' utility.
+
+config CONFIG_CAL
+	bool "cal"
+	default n
+	help
+	  cal is used to display a monthly calender.
+
+config CONFIG_CAT
+	bool "cat"
+	default n
+	help
+	  cat is used to concatenate files and print them to the standard
+	  output.  Enable this option if you wish to enable the 'cat' utility.
+
+config CONFIG_CATV
+	bool "catv"
+	default n
+	help
+	  Display nonprinting characters as escape sequences (like some
+	  implementations' cat -v option).
+
+config CONFIG_CHGRP
+	bool "chgrp"
+	default n
+	help
+	  chgrp is used to change the group ownership of files.
+
+config CONFIG_CHMOD
+	bool "chmod"
+	default n
+	help
+	  chmod is used to change the access permission of files.
+
+config CONFIG_CHOWN
+	bool "chown"
+	default n
+	help
+	  chown is used to change the user and/or group ownership
+	  of files.
+
+config CONFIG_CHROOT
+	bool "chroot"
+	default n
+	help
+	  chroot is used to change the root directory and run a command.
+	  The default command is `/bin/sh'.
+
+config CONFIG_CKSUM
+	bool "cksum"
+	default n
+	help
+	  cksum is used to calculate the CRC32 checksum of a file.
+
+config CONFIG_CMP
+	bool "cmp"
+	default n
+	help
+	  cmp is used to compare two files and returns the result
+	  to standard output.
+
+config CONFIG_COMM
+	bool "comm"
+	default n
+	help
+	  comm is used to compare two files line by line and return
+	  a three-column output.
+
+config CONFIG_CP
+	bool "cp"
+	default n
+	help
+	  cp is used to copy files and directories.
+
+config CONFIG_CUT
+	bool "cut"
+	default n
+	help
+	  cut is used to print selected parts of lines from
+	  each file to stdout.
+
+config CONFIG_DATE
+	bool "date"
+	default n
+	help
+	  date is used to set the system date or display the
+	  current time in the given format.
+
+config CONFIG_FEATURE_DATE_ISOFMT
+	bool "Enable ISO date format output (-I)"
+	default y
+	depends on CONFIG_DATE
+	help
+	  Enable option (-I) to output an ISO-8601 compliant
+	  date/time string.
+
+config CONFIG_DD
+	bool "dd"
+	default n
+	help
+	  dd copies a file (from standard input to standard output,
+	  by default) using specific input and output blocksizes,
+	  while optionally performing conversions on it.
+
+config CONFIG_FEATURE_DD_SIGNAL_HANDLING
+	bool "Enable DD signal handling for status reporting"
+	default y
+	depends on CONFIG_DD
+	help
+	  sending a SIGUSR1 signal to a running `dd' process makes it 
+	  print to standard error the number of records read and written 
+	  so far, then to resume copying.
+
+	  $ dd if=/dev/zero of=/dev/null& pid=$! $ kill -USR1 $pid; sleep 1; kill $pid 
+	  10899206+0 records in 10899206+0 records out
+
+config CONFIG_FEATURE_DD_IBS_OBS
+	bool "Enable ibs, obs and conv options"
+	default n
+	depends on CONFIG_DD
+	help
+	  Enables support for writing a certain number of bytes in and out,
+	  at a time, and performing conversions on the data stream.
+
+config CONFIG_DF
+	bool "df"
+	default n
+	help
+	  df reports the amount of disk space used and available
+	  on filesystems.
+
+config CONFIG_DIFF
+	bool "diff"
+	default n
+	help
+	  diff compares two files or directories and outputs the
+	  differences between them in a form that can be given to
+	  the patch command.
+
+config CONFIG_FEATURE_DIFF_BINARY
+	bool "Enable checks for binary files"
+	default y
+	depends on CONFIG_DIFF
+	help
+	  This option enables support for checking for binary files
+	  before a comparison is carried out.
+
+config CONFIG_FEATURE_DIFF_DIR
+	bool "Enable directory support"
+	default y
+	depends on CONFIG_DIFF
+	help
+	  This option enables support for directory and subdirectory
+	  comparison.
+
+config CONFIG_FEATURE_DIFF_MINIMAL
+	bool "Enable -d option to find smaller sets of changes"
+	default n
+	depends on CONFIG_DIFF
+	help
+	  Enabling this option allows the use of -d to make diff
+	  try hard to find the smallest possible set of changes.
+
+config CONFIG_DIRNAME
+	bool "dirname"
+	default n
+	help
+	  dirname is used to strip a non-directory suffix from
+	  a file name.
+
+config CONFIG_DOS2UNIX
+	bool "dos2unix/unix2dos"
+	default n
+	help
+	  dos2unix is used to convert a text file from DOS format to
+	  UNIX format, and vice versa.
+
+config CONFIG_UNIX2DOS
+	bool
+	default y
+	depends on CONFIG_DOS2UNIX
+	help
+	  unix2dos is used to convert a text file from UNIX format to
+	  DOS format, and vice versa.
+
+config CONFIG_DU
+	bool "du (default blocksize of 512 bytes)"
+	default n
+	help
+	  du is used to report the amount of disk space used
+	  for specified files.
+
+config CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
+	bool "Use a default blocksize of 1024 bytes (1K)"
+	default y
+	depends on CONFIG_DU
+	help
+	  Use a blocksize of (1K) instead of the default 512b.
+
+config CONFIG_ECHO
+	bool "echo (basic SuSv3 version taking no options)"
+	default n
+	help
+	  echo is used to print a specified string to stdout.
+
+# this entry also appears in shell/Config.in, next to the echo builtin
+config CONFIG_FEATURE_FANCY_ECHO
+	bool "Enable echo options (-n and -e)"
+	default y
+	depends on CONFIG_ECHO
+	help
+	  This adds options (-n and -e) to echo.
+
+config CONFIG_ENV
+	bool "env"
+	default n
+	help
+	  env is used to set an environment variable and run
+	  a command; without options it displays the current
+	  environment.
+
+config CONFIG_FEATURE_ENV_LONG_OPTIONS
+	bool "Enable long options"
+	default n
+	depends on CONFIG_ENV && CONFIG_GETOPT_LONG
+	help
+	  Support long options for the env applet.
+
+config CONFIG_EXPR
+	bool "expr"
+	default n
+	help
+	  expr is used to calculate numbers and print the result
+	  to standard output.
+
+config CONFIG_EXPR_MATH_SUPPORT_64
+	bool "Extend Posix numbers support to 64 bit"
+	default n
+	depends on CONFIG_EXPR
+	help
+	  Enable 64-bit math support in the expr applet.  This will make
+	  the applet slightly larger, but will allow computation with very
+	  large numbers.
+
+config CONFIG_FALSE
+	bool "false"
+	default n
+	help
+	  false returns an exit code of FALSE (1).
+
+config CONFIG_FOLD
+	bool "fold"
+	default n
+	help
+	  Wrap text to fit a specific width.
+
+config CONFIG_HEAD
+	bool "head"
+	default n
+	help
+	  head is used to print the first specified number of lines
+	  from files.
+
+config CONFIG_FEATURE_FANCY_HEAD
+	bool "Enable head options (-c, -q, and -v)"
+	default n
+	depends on CONFIG_HEAD
+	help
+	  This enables the head options (-c, -q, and -v).
+
+config CONFIG_HOSTID
+	bool "hostid"
+	default n
+	help
+	  hostid prints the numeric identifier (in hexadecimal) for
+	  the current host.
+
+config CONFIG_ID
+	bool "id"
+	default n
+	help
+	  id displays the current user and group ID names.
+
+config CONFIG_INSTALL
+	bool "install"
+	default n
+	help
+	  Copy files and set attributes.
+
+config CONFIG_FEATURE_INSTALL_LONG_OPTIONS
+	bool "Enable long options"
+	default n
+	depends on CONFIG_INSTALL && CONFIG_GETOPT_LONG
+	help
+	  Support long options for the install applet.
+
+config CONFIG_LENGTH
+	bool "length"
+	default n
+	help
+	  length is used to print out the length of a specified string.
+
+config CONFIG_LN
+	bool "ln"
+	default n
+	help
+	  ln is used to create hard or soft links between files.
+
+config CONFIG_LOGNAME
+	bool "logname"
+	default n
+	help
+	  logname is used to print the current user's login name.
+
+config CONFIG_LS
+	bool "ls"
+	default n
+	help
+	  ls is used to list the contents of directories.
+
+config CONFIG_FEATURE_LS_FILETYPES
+	bool "Enable filetyping options (-p and -F)"
+	default y
+	depends on CONFIG_LS
+	help
+	  Enable the ls options (-p and -F).
+
+config CONFIG_FEATURE_LS_FOLLOWLINKS
+	bool "Enable symlinks dereferencing (-L)"
+	default y
+	depends on CONFIG_LS
+	help
+	  Enable the ls option (-L).
+
+config CONFIG_FEATURE_LS_RECURSIVE
+	bool "Enable recursion (-R)"
+	default y
+	depends on CONFIG_LS
+	help
+	  Enable the ls option (-R).
+
+config CONFIG_FEATURE_LS_SORTFILES
+	bool "Sort the file names"
+	default y
+	depends on CONFIG_LS
+	help
+	  Allow ls to sort file names alphabetically.
+
+config CONFIG_FEATURE_LS_TIMESTAMPS
+	bool "Show file timestamps"
+	default y
+	depends on CONFIG_LS
+	help
+	  Allow ls to display timestamps for files.
+
+config CONFIG_FEATURE_LS_USERNAME
+	bool "Show username/groupnames"
+	default y
+	depends on CONFIG_LS
+	help
+	  Allow ls to display username/groupname for files.
+
+config CONFIG_FEATURE_LS_COLOR
+	bool "Allow use of color to identify file types"
+	default y
+	depends on CONFIG_LS && CONFIG_GETOPT_LONG
+	help
+	  This enables the --color option to ls.
+
+config CONFIG_FEATURE_LS_COLOR_IS_DEFAULT
+	bool "Produce colored ls output by default"
+	default n
+	depends on CONFIG_FEATURE_LS_COLOR
+	help
+	  Saying yes here will turn coloring on by default,
+	  even if no "--color" option is given to the ls command.
+	  This is not recommended, since the colors are not
+	  configurable, and the output may not be legible on
+	  many output screens.
+
+config CONFIG_MD5SUM
+	bool "md5sum"
+	default n
+	help
+	  md5sum is used to print or check MD5 checksums.
+
+config CONFIG_MKDIR
+	bool "mkdir"
+	default n
+	help
+	  mkdir is used to create directories with the specified names.
+
+config CONFIG_FEATURE_MKDIR_LONG_OPTIONS
+	bool "Enable long options"
+	default n
+	depends on CONFIG_MKDIR && CONFIG_GETOPT_LONG
+	help
+	  Support long options for the mkdir applet.
+
+config CONFIG_MKFIFO
+	bool "mkfifo"
+	default n
+	help
+	  mkfifo is used to create FIFOs (named pipes).
+	  The `mknod' program can also create FIFOs.
+
+config CONFIG_MKNOD
+	bool "mknod"
+	default n
+	help
+	  mknod is used to create FIFOs or block/character special
+	  files with the specified names.
+
+config CONFIG_MV
+	bool "mv"
+	default n
+	help
+	  mv is used to move or rename files or directories.
+
+config CONFIG_FEATURE_MV_LONG_OPTIONS
+	bool "Enable long options"
+	default n
+	depends on CONFIG_MV && CONFIG_GETOPT_LONG
+	help
+	  Support long options for the mv applet.
+
+config CONFIG_NICE
+	bool "nice"
+	default n
+	help
+	  nice runs a program with modified scheduling priority.
+
+config CONFIG_NOHUP
+	bool "nohup"
+	default n
+	help
+	  run a command immune to hangups, with output to a non-tty.
+
+config CONFIG_OD
+	bool "od"
+	default n
+	help
+	  od is used to dump binary files in octal and other formats.
+
+config CONFIG_PRINTENV
+	bool "printenv"
+	default n
+	help
+	  printenv is used to print all or part of environment.
+
+config CONFIG_PRINTF
+	bool "printf"
+	default n
+	help
+	  printf is used to format and print specified strings.
+	  It's similar to `echo' except it has more options.
+
+config CONFIG_PWD
+	bool "pwd"
+	default n
+	help
+	  pwd is used to print the current directory.
+
+config CONFIG_REALPATH
+	bool "realpath"
+	default n
+	help
+	  Return the canonicalized absolute pathname.
+	  This isn't provided by GNU shellutils, but where else does it belong.
+
+config CONFIG_RM
+	bool "rm"
+	default n
+	help
+	  rm is used to remove files or directories.
+
+config CONFIG_RMDIR
+	bool "rmdir"
+	default n
+	help
+	  rmdir is used to remove empty directories.
+
+config CONFIG_SEQ
+	bool "seq"
+	default n
+	help
+	  print a sequence of numbers
+
+config CONFIG_SHA1SUM
+	bool "sha1sum"
+	default n
+	help
+	  Compute and check SHA1 message digest
+
+config CONFIG_SLEEP
+	bool "sleep (single integer arg with no suffix)"
+	default n
+	help
+	  sleep is used to pause for a specified number of seconds,
+
+config CONFIG_FEATURE_FANCY_SLEEP
+	bool "Enable multiple integer args and optional time suffixes"
+	default n
+	depends on CONFIG_SLEEP
+	help
+	  Allow sleep to pause for specified minutes, hours, and days.
+
+config CONFIG_SORT
+	bool "sort"
+	default n
+	help
+	  sort is used to sort lines of text in specified files.
+
+config CONFIG_FEATURE_SORT_BIG
+	bool "full SuSv3 compliant sort (Support -ktcsbdfiozgM)"
+	default y
+	depends on CONFIG_SORT
+	help
+	  Without this, sort only supports  -r, -u, and an integer version
+	  of -n.  Selecting this adds sort keys, floating point support, and
+	  more.  This adds a little over 3k to a nonstatic build on x86.
+
+	  The SuSv3 sort standard is available at:
+	  http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html
+
+config CONFIG_STAT
+	bool "stat"
+	default n
+	help
+	  display file or filesystem status.
+
+config CONFIG_FEATURE_STAT_FORMAT
+	bool "Enable custom formats (-c)"
+	default n
+	depends on CONFIG_STAT
+	help
+	  Without this, stat will not support the '-c format' option where
+	  users can pass a custom format string for output.  This adds about
+	  7k to a nonstatic build on amd64.
+
+config CONFIG_STTY
+	bool "stty"
+	default n
+	help
+	  stty is used to change and print terminal line settings.
+
+config CONFIG_SUM
+	bool "sum"
+	default n
+	help
+	  checksum and count the blocks in a file
+
+config CONFIG_SYNC
+	bool "sync"
+	default n
+	help
+	  sync is used to flush filesystem buffers.
+
+config CONFIG_TAIL
+	bool "tail"
+	default n
+	help
+	  tail is used to print the last specified number of lines
+	  from files.
+
+config CONFIG_FEATURE_FANCY_TAIL
+	bool "Enable extra tail options (-q, -s, and -v)"
+	default y
+	depends on CONFIG_TAIL
+	help
+	  The options (-q, -s, and -v) are provided by GNU tail, but
+	  are not specific in the SUSv3 standard.
+
+config CONFIG_TEE
+	bool "tee"
+	default n
+	help
+	  tee is used to read from standard input and write
+	  to standard output and files.
+
+config CONFIG_FEATURE_TEE_USE_BLOCK_IO
+	bool "Enable block i/o (larger/faster) instead of byte i/o."
+	default n
+	depends on CONFIG_TEE
+	help
+	  Enable this option for a faster tee, at expense of size.
+
+config CONFIG_TEST
+	bool "test"
+	default n
+	help
+	  test is used to check file types and compare values,
+	  returning an appropriate exit code.  The bash shell
+	  has test built in, ash can build it in optionally.
+
+config CONFIG_FEATURE_TEST_64
+	bool "Extend test to 64 bit"
+	default n
+	depends on CONFIG_TEST
+	help
+	  Enable 64-bit support in test.
+
+config CONFIG_TOUCH
+	bool "touch"
+	default n
+	help
+	  touch is used to create or change the access and/or
+	  modification timestamp of specified files.
+
+config CONFIG_TR
+	bool "tr"
+	default n
+	help
+	  tr is used to squeeze, and/or delete characters from standard
+	  input, writing to standard output.
+
+config CONFIG_FEATURE_TR_CLASSES
+	bool "Enable character classes (such as [:upper:])"
+	default n
+	depends on CONFIG_TR
+	help
+	  Enable character classes, enabling commands such as:
+	  tr [:upper:] [:lower:] to convert input into lowercase.
+
+config CONFIG_FEATURE_TR_EQUIV
+	bool "Enable equivalence classes"
+	default n
+	depends on CONFIG_TR
+	help
+	  Enable equivalence classes, which essentially add the enclosed
+	  character to the current set. For instance, tr [=a=] xyz would
+	  replace all instances of 'a' with 'xyz'. This option is mainly
+	  useful for cases when no other way of expressing a character
+	  is possible.
+
+config CONFIG_TRUE
+	bool "true"
+	default n
+	help
+	  true returns an exit code of TRUE (0).
+
+config CONFIG_TTY
+	bool "tty"
+	default n
+	help
+	  tty is used to print the name of the current terminal to
+	  standard output.
+
+config CONFIG_UNAME
+	bool "uname"
+	default n
+	help
+	  uname is used to print system information.
+
+config CONFIG_UNIQ
+	bool "uniq"
+	default n
+	help
+	  uniq is used to remove duplicate lines from a sorted file.
+
+config CONFIG_USLEEP
+	bool "usleep"
+	default n
+	help
+	  usleep is used to pause for a specified number of microseconds.
+
+config CONFIG_UUDECODE
+	bool "uudecode"
+	default n
+	help
+	  uudecode is used to decode a uuencoded file.
+
+config CONFIG_UUENCODE
+	bool "uuencode"
+	default n
+	help
+	  uuencode is used to uuencode a file.
+
+config CONFIG_WATCH
+	bool "watch"
+	default n
+	select CONFIG_DATE
+	help
+	  watch is used to execute a program periodically, showing
+	  output to the screen.
+
+config CONFIG_WC
+	bool "wc"
+	default n
+	help
+	  wc is used to print the number of bytes, words, and lines,
+	  in specified files.
+
+config CONFIG_WHO
+	bool "who"
+	default n
+	select CONFIG_FEATURE_UTMP
+	help
+	  who is used to show who is logged on.
+
+config CONFIG_WHOAMI
+	bool "whoami"
+	default n
+	help
+	  whoami is used to print the username of the current
+	  user id (same as id -un).
+
+config CONFIG_YES
+	bool "yes"
+	default n
+	help
+	  yes is used to repeatedly output a specific string, or
+	  the default string `y'.
+
+comment "Common options for cp and mv"
+	depends on CONFIG_CP || CONFIG_MV
+
+config CONFIG_FEATURE_PRESERVE_HARDLINKS
+	bool "Preserve hard links"
+	default n
+	depends on CONFIG_CP || CONFIG_MV
+	help
+	  Allow cp and mv to preserve hard links.
+
+comment "Common options for ls, more and telnet"
+	depends on CONFIG_LS || CONFIG_MORE || CONFIG_TELNET
+
+config CONFIG_FEATURE_AUTOWIDTH
+	bool "Calculate terminal & column widths"
+	default y
+	depends on CONFIG_LS || CONFIG_MORE || CONFIG_TELNET
+	help
+	  This option allows utilities such as 'ls', 'more' and 'telnet'
+	  to determine the width of the screen, which can allow them to 
+	  display additional text or avoid wrapping text onto the next line.
+	  If you leave this disabled, your utilities will be especially 
+	  primitive and will be unable to determine the current screen width.
+
+comment "Common options for df, du, ls"
+	depends on CONFIG_DF || CONFIG_DU || CONFIG_LS
+
+config CONFIG_FEATURE_HUMAN_READABLE
+	bool "Support for human readable output (example 13k, 23M, 235G)"
+	default n
+	depends on CONFIG_DF || CONFIG_DU || CONFIG_LS
+	help
+	  Allow df, du, and ls to have human readable output.
+
+comment "Common options for md5sum, sha1sum"
+	depends on CONFIG_MD5SUM || CONFIG_SHA1SUM
+
+config CONFIG_FEATURE_MD5_SHA1_SUM_CHECK
+	bool "Enable -c, -s and -w options"
+	default n
+	depends on CONFIG_MD5SUM || CONFIG_SHA1SUM
+	help
+	  Enabling the -c options allows files to be checked
+	  against pre-calculated hash values.
+
+	  -s and -w are useful options when verifying checksums.
+
+endmenu

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/coreutils
+SHELLUTILS_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include $(srcdir)/Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,102 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+COREUTILS_AR:=coreutils.a
+ifndef $(COREUTILS_DIR)
+COREUTILS_DIR:=$(top_builddir)/coreutils/
+endif
+srcdir=$(top_srcdir)/coreutils
+
+COREUTILS-y:=
+COREUTILS-$(CONFIG_BASENAME)  += basename.o
+COREUTILS-$(CONFIG_CAL)       += cal.o
+COREUTILS-$(CONFIG_CAT)       += cat.o
+COREUTILS-$(CONFIG_CATV)      += catv.o
+COREUTILS-$(CONFIG_CHGRP)     += chgrp.o
+COREUTILS-$(CONFIG_CHMOD)     += chmod.o
+COREUTILS-$(CONFIG_CHOWN)     += chown.o
+COREUTILS-$(CONFIG_CHROOT)    += chroot.o
+COREUTILS-$(CONFIG_CKSUM)     += cksum.o
+COREUTILS-$(CONFIG_CMP)       += cmp.o
+COREUTILS-$(CONFIG_COMM)      += comm.o
+COREUTILS-$(CONFIG_CP)        += cp.o
+COREUTILS-$(CONFIG_CUT)       += cut.o
+COREUTILS-$(CONFIG_DATE)      += date.o
+COREUTILS-$(CONFIG_DD)        += dd.o
+COREUTILS-$(CONFIG_DF)        += df.o
+COREUTILS-$(CONFIG_DIFF)      += diff.o
+COREUTILS-$(CONFIG_DIRNAME)   += dirname.o
+COREUTILS-$(CONFIG_DOS2UNIX)  += dos2unix.o
+COREUTILS-$(CONFIG_DU)        += du.o
+COREUTILS-$(CONFIG_ECHO)      += echo.o
+COREUTILS-$(CONFIG_ENV)       += env.o
+COREUTILS-$(CONFIG_EXPR)      += expr.o
+COREUTILS-$(CONFIG_FALSE)     += false.o
+COREUTILS-$(CONFIG_FOLD)      += fold.o
+COREUTILS-$(CONFIG_HEAD)      += head.o
+COREUTILS-$(CONFIG_HOSTID)    += hostid.o
+COREUTILS-$(CONFIG_ID)        += id.o
+COREUTILS-$(CONFIG_INSTALL)   += install.o
+COREUTILS-$(CONFIG_LENGTH)    += length.o
+COREUTILS-$(CONFIG_LN)        += ln.o
+COREUTILS-$(CONFIG_LOGNAME)   += logname.o
+COREUTILS-$(CONFIG_LS)        += ls.o
+COREUTILS-$(CONFIG_MD5SUM)    += md5_sha1_sum.o
+COREUTILS-$(CONFIG_MKDIR)     += mkdir.o
+COREUTILS-$(CONFIG_MKFIFO)    += mkfifo.o
+COREUTILS-$(CONFIG_MKNOD)     += mknod.o
+COREUTILS-$(CONFIG_MV)        += mv.o
+COREUTILS-$(CONFIG_NICE)      += nice.o
+COREUTILS-$(CONFIG_NOHUP)     += nohup.o
+COREUTILS-$(CONFIG_OD)        += od.o
+COREUTILS-$(CONFIG_PRINTENV)  += printenv.o
+COREUTILS-$(CONFIG_PRINTF)    += printf.o
+COREUTILS-$(CONFIG_PWD)       += pwd.o
+COREUTILS-$(CONFIG_REALPATH)  += realpath.o
+COREUTILS-$(CONFIG_RM)        += rm.o
+COREUTILS-$(CONFIG_RMDIR)     += rmdir.o
+COREUTILS-$(CONFIG_SEQ)       += seq.o
+COREUTILS-$(CONFIG_SHA1SUM)   += md5_sha1_sum.o
+COREUTILS-$(CONFIG_SLEEP)     += sleep.o
+COREUTILS-$(CONFIG_SORT)      += sort.o
+COREUTILS-$(CONFIG_STAT)      += stat.o
+COREUTILS-$(CONFIG_STTY)      += stty.o
+COREUTILS-$(CONFIG_SUM)       += sum.o
+COREUTILS-$(CONFIG_SYNC)      += sync.o
+COREUTILS-$(CONFIG_TAIL)      += tail.o
+COREUTILS-$(CONFIG_TEE)       += tee.o
+COREUTILS-$(CONFIG_TEST)      += test.o
+COREUTILS-$(CONFIG_TOUCH)     += touch.o
+COREUTILS-$(CONFIG_TR)        += tr.o
+COREUTILS-$(CONFIG_TRUE)      += true.o
+COREUTILS-$(CONFIG_TTY)       += tty.o
+COREUTILS-$(CONFIG_UNAME)     += uname.o
+COREUTILS-$(CONFIG_UNIQ)      += uniq.o
+COREUTILS-$(CONFIG_USLEEP)    += usleep.o
+COREUTILS-$(CONFIG_UUDECODE)  += uudecode.o
+COREUTILS-$(CONFIG_UUENCODE)  += uuencode.o
+COREUTILS-$(CONFIG_WATCH)     += watch.o
+COREUTILS-$(CONFIG_WC)        += wc.o
+COREUTILS-$(CONFIG_WHO)       += who.o
+COREUTILS-$(CONFIG_WHOAMI)    += whoami.o
+COREUTILS-$(CONFIG_YES)       += yes.o
+
+COREUTILS-y:=$(sort $(COREUTILS-y))
+
+ifneq ($(strip $(COREUTILS-y)),)
+libraries-y+=$(COREUTILS_DIR)$(COREUTILS_AR)
+endif
+
+COREUTILS_SRC-y:=$(patsubst %.o,$(srcdir)/%.c,$(COREUTILS-y))
+COREUTILS_SRC-a:=$(wildcard $(srcdir)/*.c)
+APPLET_SRC-y+=$(COREUTILS_SRC-y)
+APPLET_SRC-a+=$(COREUTILS_SRC-a)
+
+$(COREUTILS_DIR)$(COREUTILS_AR): $(patsubst %,$(COREUTILS_DIR)%, $(COREUTILS-y))
+	$(do_ar)
+
+$(COREUTILS_DIR)%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/basename.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/basename.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/basename.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,62 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini basename implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/basename.html */
+
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Changes:
+ * 1) Now checks for too many args.  Need at least one and at most two.
+ * 2) Don't check for options, as per SUSv3.
+ * 3) Save some space by using strcmp().  Calling strncmp() here was silly.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "busybox.h"
+
+int basename_main(int argc, char **argv)
+{
+	size_t m, n;
+	char *s;
+
+	if (((unsigned int)(argc-2)) >= 2) {
+		bb_show_usage();
+	}
+
+	s = bb_get_last_path_component(*++argv);
+
+	if (*++argv) {
+		n = strlen(*argv);
+		m = strlen(s);
+		if ((m > n) && ((strcmp)(s+m-n, *argv) == 0)) {
+			s[m-n] = '\0';
+		}
+	}
+
+	puts(s);
+
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cal.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cal.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cal.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,379 @@
+/*
+ * Calendar implementation for busybox
+ *
+ * See original copyright at the end of this file
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+/* BB_AUDIT SUSv3 compliant with -j and -y extensions (from util-linux). */
+/* BB_AUDIT BUG: The output of 'cal -j 1752' is incorrect.  The upstream
+ * BB_AUDIT BUG: version in util-linux seems to be broken as well. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/cal.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Major size reduction... over 50% (>1.5k) on i386.
+ */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "busybox.h"
+
+#ifdef CONFIG_LOCALE_SUPPORT
+#include <locale.h>
+#endif
+
+#define	THURSDAY		4		/* for reformation */
+#define	SATURDAY		6		/* 1 Jan 1 was a Saturday */
+
+#define	FIRST_MISSING_DAY	639787		/* 3 Sep 1752 */
+#define	NUMBER_MISSING_DAYS	11		/* 11 day correction */
+
+#define	MAXDAYS			42		/* max slots in a month array */
+#define	SPACE			-1		/* used in day array */
+
+static const char days_in_month[] = {
+	0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+static const char sep1752[] = {
+	         1,	2,	14,	15,	16,
+	17,	18,	19,	20,	21,	22,	23,
+	24,	25,	26,	27,	28,	29,	30
+};
+
+static int julian;
+
+/* leap year -- account for Gregorian reformation in 1752 */
+#define	leap_year(yr) \
+	((yr) <= 1752 ? !((yr) % 4) : \
+	(!((yr) % 4) && ((yr) % 100)) || !((yr) % 400))
+
+static int is_leap_year(int year)
+{
+	return leap_year(year);
+}
+#undef leap_year
+#define leap_year(yr) is_leap_year(yr)
+
+/* number of centuries since 1700, not inclusive */
+#define	centuries_since_1700(yr) \
+	((yr) > 1700 ? (yr) / 100 - 17 : 0)
+
+/* number of centuries since 1700 whose modulo of 400 is 0 */
+#define	quad_centuries_since_1700(yr) \
+	((yr) > 1600 ? ((yr) - 1600) / 400 : 0)
+
+/* number of leap years between year 1 and this year, not inclusive */
+#define	leap_years_since_year_1(yr) \
+	((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr))
+
+static void center (char *, int, int);
+static void day_array (int, int, int *);
+static void trim_trailing_spaces_and_print (char *);
+
+static void blank_string(char *buf, size_t buflen);
+static char *build_row(char *p, int *dp);
+
+#define	DAY_LEN		3		/* 3 spaces per day */
+#define	J_DAY_LEN	(DAY_LEN + 1)
+#define	WEEK_LEN	20		/* 7 * 3 - one space at the end */
+#define	J_WEEK_LEN	(WEEK_LEN + 7)
+#define	HEAD_SEP	2		/* spaces between day headings */
+
+int cal_main(int argc, char **argv)
+{
+	struct tm *local_time;
+	struct tm zero_tm;
+	time_t now;
+	int month, year, flags, i;
+	char *month_names[12];
+	char day_headings[28];	/* 28 for julian, 21 for nonjulian */
+	char buf[40];
+
+#ifdef CONFIG_LOCALE_SUPPORT
+	setlocale(LC_TIME, "");
+#endif
+
+	flags = bb_getopt_ulflags(argc, argv, "jy");
+
+	julian = flags & 1;
+
+	argv += optind;
+
+	month = 0;
+
+	if ((argc -= optind) > 2) {
+		bb_show_usage();
+	}
+
+	if (!argc) {
+		time(&now);
+		local_time = localtime(&now);
+		year = local_time->tm_year + 1900;
+		if (!(flags & 2)) {
+			month = local_time->tm_mon + 1;
+		}
+	} else {
+		if (argc == 2) {
+			month = bb_xgetularg10_bnd(*argv++, 1, 12);
+		}
+		year = bb_xgetularg10_bnd(*argv, 1, 9999);
+	}
+
+	blank_string(day_headings, sizeof(day_headings) - 7 +  7*julian);
+
+	i = 0;
+	do {
+		zero_tm.tm_mon = i;
+		strftime(buf, sizeof(buf), "%B", &zero_tm);
+		month_names[i] = bb_xstrdup(buf);
+
+		if (i < 7) {
+			zero_tm.tm_wday = i;
+			strftime(buf, sizeof(buf), "%a", &zero_tm);
+			strncpy(day_headings + i * (3+julian) + julian, buf, 2);
+		}
+	} while (++i < 12);
+
+	if (month) {
+		int row, len, days[MAXDAYS];
+		int *dp = days;
+		char lineout[30];
+
+		day_array(month, year, dp);
+		len = sprintf(lineout, "%s %d", month_names[month - 1], year);
+		bb_printf("%*s%s\n%s\n",
+			   ((7*julian + WEEK_LEN) - len) / 2, "",
+			   lineout, day_headings);
+		for (row = 0; row < 6; row++) {
+			build_row(lineout, dp)[0] = '\0';
+			dp += 7;
+			trim_trailing_spaces_and_print(lineout);
+		}
+	} else {
+		int row, which_cal, week_len, days[12][MAXDAYS];
+		int *dp;
+		char lineout[80];
+
+		sprintf(lineout, "%d", year);
+		center(lineout,
+			   (WEEK_LEN * 3 + HEAD_SEP * 2)
+			   + julian * (J_WEEK_LEN * 2 + HEAD_SEP
+						   - (WEEK_LEN * 3 + HEAD_SEP * 2)),
+			   0);
+		puts("\n");		/* two \n's */
+		for (i = 0; i < 12; i++) {
+			day_array(i + 1, year, days[i]);
+		}
+		blank_string(lineout, sizeof(lineout));
+		week_len = WEEK_LEN + julian * (J_WEEK_LEN - WEEK_LEN);
+		for (month = 0; month < 12; month += 3-julian) {
+			center(month_names[month], week_len, HEAD_SEP);
+			if (!julian) {
+				center(month_names[month + 1], week_len, HEAD_SEP);
+			}
+			center(month_names[month + 2 - julian], week_len, 0);
+			bb_printf("\n%s%*s%s", day_headings, HEAD_SEP, "", day_headings);
+			if (!julian) {
+				bb_printf("%*s%s", HEAD_SEP, "", day_headings);
+			}
+			putchar('\n');
+			for (row = 0; row < (6*7); row += 7) {
+				for (which_cal = 0; which_cal < 3-julian; which_cal++) {
+					dp = days[month + which_cal] + row;
+					build_row(lineout + which_cal * (week_len + 2), dp);
+				}
+				/* blank_string took care of nul termination. */
+				trim_trailing_spaces_and_print(lineout);
+			}
+		}
+	}
+
+	bb_fflush_stdout_and_exit(0);
+}
+
+/*
+ * day_array --
+ *	Fill in an array of 42 integers with a calendar.  Assume for a moment
+ *	that you took the (maximum) 6 rows in a calendar and stretched them
+ *	out end to end.  You would have 42 numbers or spaces.  This routine
+ *	builds that array for any month from Jan. 1 through Dec. 9999.
+ */
+static void day_array(int month, int year, int *days)
+{
+	long temp;
+	int i;
+	int j_offset;
+	int day, dw, dm;
+
+	memset(days, SPACE, MAXDAYS * sizeof(int));
+
+	if ((month == 9) && (year == 1752)) {
+		size_t oday = 0;
+		
+		j_offset = julian * 244;
+		do {
+			days[oday+2] = sep1752[oday] + j_offset;
+		} while (++oday < sizeof(sep1752));
+
+		return;
+	}
+
+	/* day_in_year
+	 *	return the 1 based day number within the year
+	 */
+	day = 1;
+	if ((month > 2) && leap_year(year)) {
+		++day;
+	}
+
+	i = month;
+	while (i) {
+		day += days_in_month[--i];
+	}
+
+	/* day_in_week
+	 *	return the 0 based day number for any date from 1 Jan. 1 to
+	 *	31 Dec. 9999.  Assumes the Gregorian reformation eliminates
+	 *	3 Sep. 1752 through 13 Sep. 1752.  Returns Thursday for all
+	 *	missing days.
+	 */
+	dw = THURSDAY;
+	temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1)
+		+ day;
+	if (temp < FIRST_MISSING_DAY) {
+		dw = ((temp - 1 + SATURDAY) % 7);
+	} else if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS)) {
+		dw = (((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7);
+	}
+
+	if (!julian) {
+		day = 1;
+	}
+
+	dm = days_in_month[month];
+	if ((month == 2) && leap_year(year)) {
+		++dm;
+	}
+
+	while (dm) {
+		days[dw++] = day++;
+		--dm;
+	}
+}
+
+static void trim_trailing_spaces_and_print(char *s)
+{
+	char *p = s;
+
+	while (*p) {
+		++p;
+	}
+	while (p > s) {
+		--p;
+		if (!(isspace)(*p)) {	/* We want the function... not the inline. */
+			p[1] = '\0';
+			break;
+		}
+	}
+
+	puts(s);
+}
+
+static void center(char *str, int len, int separate)
+{
+	int n = strlen(str);
+	len -= n;
+	bb_printf("%*s%*s", (len/2) + n, str, (len/2) + (len % 2) + separate, "");
+}
+
+static void blank_string(char *buf, size_t buflen)
+{
+	memset(buf, ' ', buflen);
+	buf[buflen-1] = '\0';
+}
+
+static char *build_row(char *p, int *dp)
+{
+	int col, val, day;
+
+	memset(p, ' ', (julian + DAY_LEN) * 7);
+
+	col = 0;
+	do {
+		if ((day = *dp++) != SPACE) {
+			if (julian) {
+				++p;
+				if (day >= 100) {
+					*p = '0';
+					p[-1] = (day / 100) + '0';
+					day %= 100;
+				}
+			}
+			if ((val = day / 10) > 0) {
+				*p = val + '0';
+			}
+			*++p = day % 10 + '0';
+			p += 2;
+		} else {
+			p += DAY_LEN + julian;
+		}
+	} while (++col < 7);
+
+	return p;
+}
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kim Letkeman.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cat.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cat.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cat.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,40 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * cat implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file License in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/cat.html */
+
+#include "busybox.h"
+#include <unistd.h>
+
+int cat_main(int argc, char **argv)
+{
+	FILE *f;
+	int retval = EXIT_SUCCESS;
+
+	bb_getopt_ulflags(argc, argv, "u");
+
+	argv += optind;
+	if (!*argv) {
+		*--argv = "-";
+	}
+
+	do {
+		if ((f = bb_wfopen_input(*argv)) != NULL) {
+			int r = bb_copyfd_eof(fileno(f), STDOUT_FILENO);
+			bb_fclose_nonstdin(f);
+			if (r >= 0) {
+				continue;
+			}
+		}
+		retval = EXIT_FAILURE;
+	} while (*++argv);
+
+	return retval;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/catv.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/catv.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/catv.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,65 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * cat -v implementation for busybox
+ *
+ * Copyright (C) 2006 Rob Landley <rob at landley.net>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* See "Cat -v considered harmful" at
+ * http://cm.bell-labs.com/cm/cs/doc/84/kp.ps.gz */
+
+#include "busybox.h"
+#include <unistd.h>
+#include <fcntl.h>
+
+int catv_main(int argc, char **argv)
+{
+	int retval = EXIT_SUCCESS, fd, flags;
+
+	flags = bb_getopt_ulflags(argc, argv, "etv");
+	flags ^= 4;
+
+	// Loop through files.
+
+	argv += optind;
+	do {
+		// Read from stdin if there's nothing else to do.
+
+		fd = 0;
+		if (*argv && 0>(fd = bb_xopen(*argv, O_RDONLY))) retval = EXIT_FAILURE;
+		else for(;;) {
+			int i, res;
+
+			res = read(fd, bb_common_bufsiz1, sizeof(bb_common_bufsiz1));
+			if (res < 0) retval = EXIT_FAILURE;
+			if (res <1) break;
+			for (i=0; i<res; i++) {
+				char c=bb_common_bufsiz1[i];
+
+				if (c > 126 && (flags & 4)) {
+					if (c == 127) {
+						printf("^?");
+						continue;
+					} else {
+						printf("M-");
+						c -= 128;
+					}
+				}
+				if (c < 32) {
+					if (c == 10) {
+					   if (flags & 1) putchar('$');
+					} else if (flags & (c==9 ? 2 : 4)) {
+						printf("^%c", c+'@');
+						continue;
+					}
+				}
+				putchar(c);
+			}
+		}
+		if (ENABLE_FEATURE_CLEAN_UP && fd) close(fd);
+	} while (*++argv);
+
+	return retval;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/chgrp.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/chgrp.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/chgrp.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,60 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini chgrp implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 defects - unsupported options -h, -H, -L, and -P. */
+/* BB_AUDIT GNU defects - unsupported options -h, -c, -f, -v, and long options. */
+/* BB_AUDIT Note: gnu chgrp does not support -H, -L, or -P. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/chgrp.html */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+/* Don't use lchown glibc older then 2.1.x */
+#if (__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 1)
+#define lchown	chown
+#endif
+
+static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
+{
+	if (lchown(fileName, statbuf->st_uid, *((long *) junk)) == 0) {
+		return (TRUE);
+	}
+	bb_perror_msg("%s", fileName);	/* Avoid multibyte problems. */
+	return (FALSE);
+}
+
+int chgrp_main(int argc, char **argv)
+{
+	long gid;
+	int recursiveFlag;
+	int retval = EXIT_SUCCESS;
+
+	recursiveFlag = bb_getopt_ulflags(argc, argv, "R");
+
+	if (argc - optind < 2) {
+		bb_show_usage();
+	}
+
+	argv += optind;
+
+	/* Find the selected group */
+	gid = get_ug_id(*argv, bb_xgetgrnam);
+	++argv;
+
+	/* Ok, ready to do the deed now */
+	do {
+		if (! recursive_action (*argv, recursiveFlag, FALSE, FALSE,
+								fileAction, fileAction, &gid)) {
+			retval = EXIT_FAILURE;
+		}
+	} while (*++argv);
+
+	return retval;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/chmod.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/chmod.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/chmod.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,91 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini chmod implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Reworked by (C) 2002 Vladimir Oleynik <dzo at simtreas.ru>
+ *  to correctly parse '-rwxgoa'
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* BB_AUDIT GNU defects - unsupported options -c, -f, -v, and long options. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/chmod.html */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include "busybox.h"
+
+static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
+{
+	if (!bb_parse_mode((char *)junk, &(statbuf->st_mode)))
+		bb_error_msg_and_die( "invalid mode: %s", (char *)junk);
+	if (chmod(fileName, statbuf->st_mode) == 0)
+		return (TRUE);
+	bb_perror_msg("%s", fileName);	/* Avoid multibyte problems. */
+	return (FALSE);
+}
+
+int chmod_main(int ATTRIBUTE_UNUSED argc, char **argv)
+{
+	int retval = EXIT_SUCCESS;
+	int recursiveFlag = FALSE;
+	int count;
+	char *smode;
+	char **p;
+	char *p0;
+	char opt = '-';
+
+	++argv;
+	count = 0;
+
+	for (p = argv  ; *p ; p++) {
+		p0 = p[0];
+		if (p0[0] == opt) {
+			if ((p0[1] == '-') && !p0[2]) {
+				opt = 0;	/* Disable further option processing. */
+				continue;
+			}
+			if (p0[1] == 'R') {
+				char *s = p0 + 2;
+				while (*s == 'R') {
+					++s;
+				}
+				if (*s) {
+					bb_show_usage();
+				}
+				recursiveFlag = TRUE;
+				continue;
+			}
+			if (count) {
+				bb_show_usage();
+			}
+		}
+		argv[count] = p0;
+		++count;
+	}
+
+	argv[count] = NULL;
+
+	if (count < 2) {
+		bb_show_usage();
+	}
+
+	smode = *argv;
+	++argv;
+
+	/* Ok, ready to do the deed now */
+	do {
+		if (! recursive_action (*argv, recursiveFlag, TRUE, FALSE,
+								fileAction,	fileAction, smode)) {
+			retval = EXIT_FAILURE;
+		}
+	} while (*++argv);
+
+	return retval;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/chown.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/chown.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/chown.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,78 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini chown implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 defects - unsupported options -h, -H, -L, and -P. */
+/* BB_AUDIT GNU defects - unsupported options -h, -c, -f, -v, and long options. */
+/* BB_AUDIT Note: gnu chown does not support -H, -L, or -P. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/chown.html */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "busybox.h"
+
+static uid_t uid = -1;
+static gid_t gid = -1;
+
+static int (*chown_func)(const char *, uid_t, gid_t) = chown;
+
+static int fileAction(const char *fileName, struct stat *statbuf,
+		void ATTRIBUTE_UNUSED *junk)
+{
+	if (!chown_func(fileName,
+				(uid == (uid_t)-1) ? statbuf->st_uid : uid,
+				(gid == (gid_t)-1) ? statbuf->st_gid : gid)) {
+		return TRUE;
+	}
+	bb_perror_msg("%s", fileName);	/* A filename could have % in it... */
+	return FALSE;
+}
+
+#define FLAG_R 1
+#define FLAG_h 2
+
+int chown_main(int argc, char **argv)
+{
+	int flags;
+	int retval = EXIT_SUCCESS;
+	char *groupName;
+
+	flags = bb_getopt_ulflags(argc, argv, "Rh");
+
+	if (flags & FLAG_h) chown_func = lchown;
+
+	if (argc - optind < 2) {
+		bb_show_usage();
+	}
+
+	argv += optind;
+
+	/* First, check if there is a group name here */
+	if ((groupName = strchr(*argv, '.')) == NULL) {
+		groupName = strchr(*argv, ':');
+	}
+
+	/* Check for the username and groupname */
+	if (groupName) {
+		*groupName++ = '\0';
+		gid = get_ug_id(groupName, bb_xgetgrnam);
+	}
+	if (--groupName != *argv) uid = get_ug_id(*argv, bb_xgetpwnam);
+	++argv;
+
+	/* Ok, ready to do the deed now */
+	do {
+		if (! recursive_action (*argv, (flags & FLAG_R), FALSE, FALSE,
+								fileAction, fileAction, NULL)) {
+			retval = EXIT_FAILURE;
+		}
+	} while (*++argv);
+
+	return retval;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/chroot.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/chroot.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/chroot.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,41 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini chroot implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include "busybox.h"
+
+int chroot_main(int argc, char **argv)
+{
+	if (argc < 2) {
+		bb_show_usage();
+	}
+
+	++argv;
+	if (chroot(*argv)) {
+		bb_perror_msg_and_die("cannot change root directory to %s", *argv);
+	}
+	bb_xchdir("/");
+
+	++argv;
+	if (argc == 2) {
+		argv -= 2;
+		if (!(*argv = getenv("SHELL"))) {
+			*argv = (char *) DEFAULT_SHELL;
+		}
+		argv[1] = (char *) "-i";
+	}
+
+	execvp(*argv, argv);
+	bb_perror_msg_and_die("cannot execute %s", *argv);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cksum.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cksum.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cksum.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,55 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * cksum - calculate the CRC32 checksum of a file
+ *
+ * Copyright (C) 2006 by Rob Sullivan, with ideas from code by Walter Harms
+ * 
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "busybox.h"
+
+int cksum_main(int argc, char **argv) {
+	
+	uint32_t *crc32_table = bb_crc32_filltable(1);
+
+	FILE *fp;
+	uint32_t crc;
+	long length, filesize;
+	int bytes_read;
+	char *cp;
+	RESERVE_CONFIG_BUFFER(buf, BUFSIZ);
+	int inp_stdin = (argc == optind) ? 1 : 0;
+	
+	do {
+		fp = bb_wfopen_input((inp_stdin) ? bb_msg_standard_input : *++argv);
+			
+		crc = 0;
+		length = 0;
+		
+		while ((bytes_read = fread(buf, 1, BUFSIZ, fp)) > 0) {
+			cp = buf;
+			length += bytes_read;
+			while (bytes_read--)
+				crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ (*cp++)) & 0xffL];
+		}
+		
+		filesize = length;
+		
+		for (; length; length >>= 8)
+			crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ length) & 0xffL];
+		crc ^= 0xffffffffL;
+
+		if (inp_stdin) {
+			printf("%"PRIu32" %li\n", crc, filesize);
+			break;
+		}
+		
+		printf("%"PRIu32" %li %s\n", crc, filesize, *argv);	
+		fclose(fp);
+	} while (*(argv+1));
+	
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cmp.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cmp.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cmp.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,149 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini cmp implementation for busybox
+ *
+ * Copyright (C) 2000,2001 by Matt Kraai <kraai at alumni.carnegiemellon.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 (virtually) compliant -- uses nicer GNU format for -l. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/cmp.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Original version majorly reworked for SUSv3 compliance, bug fixes, and
+ * size optimizations.  Changes include:
+ * 1) Now correctly distinguishes between errors and actual file differences.
+ * 2) Proper handling of '-' args.
+ * 3) Actual error checking of i/o.
+ * 4) Accept SUSv3 -l option.  Note that we use the slightly nicer gnu format
+ *    in the '-l' case.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+static FILE *cmp_xfopen_input(const char *filename)
+{
+	FILE *fp;
+
+	if ((fp = bb_wfopen_input(filename)) != NULL) {
+		return fp;
+	}
+
+	exit(bb_default_error_retval);	/* We already output an error message. */
+}
+
+static const char fmt_eof[] = "cmp: EOF on %s\n";
+static const char fmt_differ[] = "%s %s differ: char %d, line %d\n";
+// This fmt_l_opt uses gnu-isms.  SUSv3 would be "%.0s%.0s%d %o %o\n"
+static const char fmt_l_opt[] = "%.0s%.0s%d %3o %3o\n";
+
+static const char opt_chars[] = "sl";
+
+enum {
+	OPT_s = 1,
+	OPT_l = 2
+};
+
+int cmp_main(int argc, char **argv)
+{
+	FILE *fp1, *fp2, *outfile = stdout;
+	const char *filename1, *filename2;
+	const char *fmt;
+	int c1, c2, char_pos, line_pos;
+	int opt_flags;
+	int exit_val = 0;
+
+	bb_default_error_retval = 2;	/* 1 is returned if files are different. */
+
+	opt_flags = bb_getopt_ulflags(argc, argv, opt_chars);
+
+	if ((opt_flags == 3) || (((unsigned int)(--argc - optind)) > 1)) {
+		bb_show_usage();
+	}
+
+	fp1 = cmp_xfopen_input(filename1 = *(argv += optind));
+
+	filename2 = "-";
+	if (*++argv) {
+		filename2 = *argv;
+	}
+	fp2 = cmp_xfopen_input(filename2);
+
+	if (fp1 == fp2) {			/* Paranioa check... stdin == stdin? */
+		/* Note that we don't bother reading stdin.  Neither does gnu wc.
+		 * But perhaps we should, so that other apps down the chain don't
+		 * get the input.  Consider 'echo hello | (cmp - - && cat -)'.
+		 */
+		return 0;
+	}
+
+	fmt = fmt_differ;
+	if (opt_flags == OPT_l) {
+		fmt = fmt_l_opt;
+	}
+
+	char_pos = 0;
+	line_pos = 1;
+	do {
+		c1 = getc(fp1);
+		c2 = getc(fp2);
+		++char_pos;
+		if (c1 != c2) {			/* Remember -- a read error may have occurred. */
+			exit_val = 1;		/* But assume the files are different for now. */
+			if (c2 == EOF) {
+				/* We know that fp1 isn't at EOF or in an error state.  But to
+				 * save space below, things are setup to expect an EOF in fp1
+				 * if an EOF occurred.  So, swap things around.
+				 */
+				fp1 = fp2;
+				filename1 = filename2;
+				c1 = c2;
+			}
+			if (c1 == EOF) {
+				bb_xferror(fp1, filename1);
+				fmt = fmt_eof;	/* Well, no error, so it must really be EOF. */
+				outfile = stderr;
+				/* There may have been output to stdout (option -l), so
+				 * make sure we fflush before writing to stderr. */
+				bb_xfflush_stdout();
+			}
+			if (opt_flags != OPT_s) {
+				if (opt_flags == OPT_l) {
+					line_pos = c1;	/* line_pos is unused in the -l case. */
+				}
+				bb_fprintf(outfile, fmt, filename1, filename2, char_pos, line_pos, c2);
+				if (opt_flags) {	/* This must be -l since not -s. */
+					/* If we encountered and EOF, the while check will catch it. */
+					continue;
+				}
+			}
+			break;
+		}
+		if (c1 == '\n') {
+			++line_pos;
+		}
+	} while (c1 != EOF);
+
+	bb_xferror(fp1, filename1);
+	bb_xferror(fp2, filename2);
+
+	bb_fflush_stdout_and_exit(exit_val);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/comm.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/comm.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/comm.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,130 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini comm implementation for busybox
+ *
+ * Copyright (C) 2005 by Robert Sullivan <cogito.ergo.cogito at gmail.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "busybox.h"
+
+#define COMM_OPT_1 0x01
+#define COMM_OPT_2 0x02
+#define COMM_OPT_3 0x04
+
+/* These three variables control behaviour if non-zero */
+
+static int only_file_1;
+static int only_file_2;
+static int both;
+
+/* writeline outputs the input given, appropriately aligned according to class */
+static void writeline(char *line, int class)
+{
+	if (class == 0) {
+		if (!only_file_1)
+			return;
+	} else if (class == 1) {
+		if (!only_file_2)
+			return;
+		if (only_file_1)
+			putchar('\t');
+	}
+	else /*if (class == 2)*/ {
+		if (!both)
+			return;
+		if (only_file_1)
+			putchar('\t');
+		if (only_file_2)
+			putchar('\t');
+	}
+	fputs(line, stdout);
+}
+
+/* This is the real core of the program - lines are compared here */
+static void cmp_files(char **infiles)
+{
+#define LINE_LEN 100
+#define BB_EOF_0 0x1
+#define BB_EOF_1 0x2
+	char thisline[2][LINE_LEN];
+	FILE *streams[2];
+	int i;
+
+	for (i = 0; i < 2; ++i) {
+		streams[i] = ((infiles[i][0] == '=' && infiles[i][1]) ? stdin : bb_xfopen(infiles[i], "r"));
+		fgets(thisline[i], LINE_LEN, streams[i]);
+	}
+
+	while (*thisline[0] || *thisline[1]) {
+		int order = 0;
+
+		i = 0;
+		if (feof(streams[0])) i |= BB_EOF_0;
+		if (feof(streams[1])) i |= BB_EOF_1;
+
+		if (!*thisline[0])
+			order = 1;
+		else if (!*thisline[1])
+			order = -1;
+		else {
+			int tl0_len, tl1_len;
+			tl0_len = strlen(thisline[0]);
+			tl1_len = strlen(thisline[1]);
+			order = memcmp(thisline[0], thisline[1], tl0_len < tl1_len ? tl0_len : tl1_len);
+			if (!order)
+				order = tl0_len < tl1_len ? -1 : tl0_len != tl1_len;
+		}
+
+		if (order == 0 && !i)
+			writeline(thisline[1], 2);
+		else if (order > 0 && !(i & BB_EOF_1))
+			writeline(thisline[1], 1);
+		else if (order < 0 && !(i & BB_EOF_0))
+			writeline(thisline[0], 0);
+
+		if (i & BB_EOF_0 & BB_EOF_1) {
+			break;
+
+		} else if (i) {
+			i = (i & BB_EOF_0 ? 1 : 0);
+			while (!feof(streams[i])) {
+				if ((order < 0 && i) || (order > 0 && !i))
+					writeline(thisline[i], i);
+				fgets(thisline[i], LINE_LEN, streams[i]);
+			}
+			break;
+
+		} else {
+			if (order >= 0)
+				fgets(thisline[1], LINE_LEN, streams[1]);
+			if (order <= 0)
+				fgets(thisline[0], LINE_LEN, streams[0]);
+		}
+	}
+
+	fclose(streams[0]);
+	fclose(streams[1]);
+}
+
+int comm_main(int argc, char **argv)
+{
+	unsigned long flags;
+
+	flags = bb_getopt_ulflags(argc, argv, "123");
+
+	if (optind + 2 != argc)
+		bb_show_usage();
+
+	only_file_1 = !(flags & COMM_OPT_1);
+	only_file_2 = !(flags & COMM_OPT_2);
+	both = !(flags & COMM_OPT_3);
+
+	cmp_files(argv + optind);
+	exit(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cp.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cp.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cp.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,110 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini cp implementation for busybox
+ *
+ * Copyright (C) 2000 by Matt Kraai <kraai at alumni.carnegiemellon.edu>
+ *
+ * Licensed under GPL v2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 defects - unsupported options -H, -L, and -P. */
+/* BB_AUDIT GNU defects - only extension options supported are -a and -d.  */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/cp.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Size reduction.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <utime.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "busybox.h"
+#include "libcoreutils/coreutils.h"
+
+int cp_main(int argc, char **argv)
+{
+	struct stat source_stat;
+	struct stat dest_stat;
+	const char *last;
+	const char *dest;
+	int s_flags;
+	int d_flags;
+	int flags;
+	int status = 0;
+
+	flags = bb_getopt_ulflags(argc, argv, "pdRfiarPHL");
+
+	if (flags & 32) {
+		flags |= (FILEUTILS_PRESERVE_STATUS | FILEUTILS_RECUR | FILEUTILS_DEREFERENCE);
+	}
+	if (flags & 64) {
+		/* Make -r a synonym for -R,
+		 * -r was marked as obsolete in SUSv3, but is included for compatibility
+		 */
+		flags |= FILEUTILS_RECUR;
+	}
+	if (flags & 128) {
+		/* Make -P a synonym for -d,
+		 * -d is the GNU option while -P is the POSIX 2003 option
+		 */
+		flags |= FILEUTILS_DEREFERENCE;
+	}
+	/* Default behavior of cp is to dereference, so we don't have to do
+	 * anything special when we are given -L.
+	 * The behavior of -H is *almost* like -L, but not quite, so let's
+	 * just ignore it too for fun.
+	if (flags & 256 || flags & 512) {
+		;
+	}
+	*/
+
+	flags ^= FILEUTILS_DEREFERENCE;		/* The sense of this flag was reversed. */
+
+	if (optind + 2 > argc) {
+		bb_show_usage();
+	}
+
+	last = argv[argc - 1];
+	argv += optind;
+
+	/* If there are only two arguments and...  */
+	if (optind + 2 == argc) {
+		s_flags = cp_mv_stat2(*argv, &source_stat,
+		                      (flags & FILEUTILS_DEREFERENCE) ? stat : lstat);
+		if ((s_flags < 0) || ((d_flags = cp_mv_stat(last, &dest_stat)) < 0)) {
+			exit(EXIT_FAILURE);
+		}
+		/* ...if neither is a directory or...  */
+		if ( !((s_flags | d_flags) & 2) ||
+			/* ...recursing, the 1st is a directory, and the 2nd doesn't exist... */
+			/* ((flags & FILEUTILS_RECUR) && (s_flags & 2) && !d_flags) */
+			/* Simplify the above since FILEUTILS_RECUR >> 1 == 2. */
+			((((flags & FILEUTILS_RECUR) >> 1) & s_flags) && !d_flags)
+		) {
+			/* ...do a simple copy.  */
+			dest = last;
+			goto DO_COPY; /* Note: optind+2==argc implies argv[1]==last below. */
+		}
+	}
+
+	do {
+		dest = concat_path_file(last, bb_get_last_path_component(*argv));
+	DO_COPY:
+		if (copy_file(*argv, dest, flags) < 0) {
+			status = 1;
+		}
+		if (*++argv == last) {
+			break;
+		}
+		free((void *) dest);
+	} while (1);
+
+	exit(status);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cut.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cut.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/cut.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,345 @@
+/* vi: set sw=8 ts=8: */
+/*
+ * cut.c - minimalist version of cut
+ *
+ * Copyright (C) 1999,2000,2001 by Lineo, inc.
+ * Written by Mark Whitley <markw at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include "busybox.h"
+
+
+/* option vars */
+static const char optstring[] = "b:c:f:d:sn";
+#define OPT_BYTE_FLGS    1
+#define OPT_CHAR_FLGS    2
+#define OPT_FIELDS_FLGS  4
+#define OPT_DELIM_FLGS   8
+#define OPT_SUPRESS_FLGS 16
+static char part; /* (b)yte, (c)har, (f)ields */
+static unsigned int supress_non_delimited_lines;
+static char delim = '\t'; /* delimiter, default is tab */
+
+struct cut_list {
+	int startpos;
+	int endpos;
+};
+
+enum {
+	BOL = 0,
+	EOL = INT_MAX,
+	NON_RANGE = -1
+};
+
+static struct cut_list *cut_lists = NULL; /* growable array holding a series of lists */
+static unsigned int nlists = 0; /* number of elements in above list */
+
+
+static int cmpfunc(const void *a, const void *b)
+{
+	struct cut_list *la = (struct cut_list *)a;
+	struct cut_list *lb = (struct cut_list *)b;
+
+	if (la->startpos > lb->startpos)
+		return 1;
+	if (la->startpos < lb->startpos)
+		return -1;
+	return 0;
+}
+
+
+/*
+ * parse_lists() - parses a list and puts values into startpos and endpos.
+ * valid list formats: N, N-, N-M, -M
+ * more than one list can be separated by commas
+ */
+static void parse_lists(char *lists)
+{
+	char *ltok = NULL;
+	char *ntok = NULL;
+	char *junk;
+	int s = 0, e = 0;
+
+	/* take apart the lists, one by one (they are separated with commas */
+	while ((ltok = strsep(&lists, ",")) != NULL) {
+
+		/* it's actually legal to pass an empty list */
+		if (strlen(ltok) == 0)
+			continue;
+
+		/* get the start pos */
+		ntok = strsep(&ltok, "-");
+		if (ntok == NULL) {
+			fprintf(stderr, "Help ntok is null for starting position! What do I do?\n");
+		} else if (strlen(ntok) == 0) {
+			s = BOL;
+		} else {
+			s = strtoul(ntok, &junk, 10);
+			if(*junk != '\0' || s < 0)
+				bb_error_msg_and_die("invalid byte or field list");
+
+			/* account for the fact that arrays are zero based, while the user
+			 * expects the first char on the line to be char # 1 */
+			if (s != 0)
+				s--;
+		}
+
+		/* get the end pos */
+		ntok = strsep(&ltok, "-");
+		if (ntok == NULL) {
+			e = NON_RANGE;
+		} else if (strlen(ntok) == 0) {
+			e = EOL;
+		} else {
+			e = strtoul(ntok, &junk, 10);
+			if(*junk != '\0' || e < 0)
+				bb_error_msg_and_die("invalid byte or field list");
+			/* if the user specified and end position of 0, that means "til the
+			 * end of the line */
+			if (e == 0)
+				e = INT_MAX;
+			e--; /* again, arrays are zero based, lines are 1 based */
+			if (e == s)
+				e = NON_RANGE;
+		}
+
+		/* if there's something left to tokenize, the user past an invalid list */
+		if (ltok)
+			bb_error_msg_and_die("invalid byte or field list");
+
+		/* add the new list */
+		cut_lists = xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists));
+		cut_lists[nlists-1].startpos = s;
+		cut_lists[nlists-1].endpos = e;
+	}
+
+	/* make sure we got some cut positions out of all that */
+	if (nlists == 0)
+		bb_error_msg_and_die("missing list of positions");
+
+	/* now that the lists are parsed, we need to sort them to make life easier
+	 * on us when it comes time to print the chars / fields / lines */
+	qsort(cut_lists, nlists, sizeof(struct cut_list), cmpfunc);
+
+}
+
+
+static void cut_line_by_chars(const char *line)
+{
+	int c, l;
+	/* set up a list so we can keep track of what's been printed */
+	char *printed = xcalloc(strlen(line), sizeof(char));
+
+	/* print the chars specified in each cut list */
+	for (c = 0; c < nlists; c++) {
+		l = cut_lists[c].startpos;
+		while (l < strlen(line)) {
+			if (!printed[l]) {
+				putchar(line[l]);
+				printed[l] = 'X';
+			}
+			l++;
+			if (cut_lists[c].endpos == NON_RANGE || l > cut_lists[c].endpos)
+				break;
+		}
+	}
+	putchar('\n'); /* cuz we were handed a chomped line */
+	free(printed);
+}
+
+
+static void cut_line_by_fields(char *line)
+{
+	int c, f;
+	int ndelim = -1; /* zero-based / one-based problem */
+	int nfields_printed = 0;
+	char *field = NULL;
+	char d[2] = { delim, 0 };
+	char *printed;
+
+	/* test the easy case first: does this line contain any delimiters? */
+	if (strchr(line, delim) == NULL) {
+		if (!supress_non_delimited_lines)
+			puts(line);
+		return;
+	}
+
+	/* set up a list so we can keep track of what's been printed */
+	printed = xcalloc(strlen(line), sizeof(char));
+
+	/* process each list on this line, for as long as we've got a line to process */
+	for (c = 0; c < nlists && line; c++) {
+		f = cut_lists[c].startpos;
+		do {
+
+			/* find the field we're looking for */
+			while (line && ndelim < f) {
+				field = strsep(&line, d);
+				ndelim++;
+			}
+
+			/* we found it, and it hasn't been printed yet */
+			if (field && ndelim == f && !printed[ndelim]) {
+				/* if this isn't our first time through, we need to print the
+				 * delimiter after the last field that was printed */
+				if (nfields_printed > 0)
+					putchar(delim);
+				fputs(field, stdout);
+				printed[ndelim] = 'X';
+				nfields_printed++;
+			}
+
+			f++;
+
+			/* keep going as long as we have a line to work with, this is a
+			 * list, and we're not at the end of that list */
+		} while (line && cut_lists[c].endpos != NON_RANGE && f <= cut_lists[c].endpos);
+	}
+
+	/* if we printed anything at all, we need to finish it with a newline cuz
+	 * we were handed a chomped line */
+	putchar('\n');
+
+	free(printed);
+}
+
+
+static void cut_file_by_lines(const char *line, unsigned int linenum)
+{
+	static int c = 0;
+	static int l = -1;
+
+	/* I can't initialize this above cuz the "initializer isn't
+	 * constant" *sigh* */
+	if (l == -1)
+		l = cut_lists[c].startpos;
+
+	/* get out if we have no more lists to process or if the lines are lower
+	 * than what we're interested in */
+	if (c >= nlists || linenum < l)
+		return;
+
+	/* if the line we're looking for is lower than the one we were passed, it
+	 * means we displayed it already, so move on */
+	while (l < linenum) {
+		l++;
+		/* move on to the next list if we're at the end of this one */
+		if (cut_lists[c].endpos == NON_RANGE || l > cut_lists[c].endpos) {
+			c++;
+			/* get out if there's no more lists to process */
+			if (c >= nlists)
+				return;
+			l = cut_lists[c].startpos;
+			/* get out if the current line is lower than the one we just became
+			 * interested in */
+			if (linenum < l)
+				return;
+		}
+	}
+
+	/* If we made it here, it means we've found the line we're looking for, so print it */
+	puts(line);
+}
+
+
+/*
+ * snippy-snip
+ */
+static void cut_file(FILE *file)
+{
+	char *line = NULL;
+	unsigned int linenum = 0; /* keep these zero-based to be consistent */
+
+	/* go through every line in the file */
+	while ((line = bb_get_chomped_line_from_file(file)) != NULL) {
+
+		/* cut based on chars/bytes XXX: only works when sizeof(char) == byte */
+		if ((part & (OPT_CHAR_FLGS | OPT_BYTE_FLGS)))
+			cut_line_by_chars(line);
+
+		/* cut based on fields */
+		else {
+			if (delim == '\n')
+				cut_file_by_lines(line, linenum);
+			else
+				cut_line_by_fields(line);
+		}
+
+		linenum++;
+		free(line);
+	}
+}
+
+
+int cut_main(int argc, char **argv)
+{
+	unsigned long opt;
+	char *sopt, *sdopt;
+
+	bb_opt_complementally = "b--bcf:c--bcf:f--bcf";
+	opt = bb_getopt_ulflags(argc, argv, optstring, &sopt, &sopt, &sopt, &sdopt);
+	part = opt & (OPT_BYTE_FLGS|OPT_CHAR_FLGS|OPT_FIELDS_FLGS);
+	if(part == 0)
+		bb_error_msg_and_die("you must specify a list of bytes, characters, or fields");
+	if(opt & BB_GETOPT_ERROR)
+		bb_error_msg_and_die("only one type of list may be specified");
+	parse_lists(sopt);
+	if((opt & (OPT_DELIM_FLGS))) {
+		if (strlen(sdopt) > 1) {
+			bb_error_msg_and_die("the delimiter must be a single character");
+		}
+		delim = sdopt[0];
+	}
+	supress_non_delimited_lines = opt & OPT_SUPRESS_FLGS;
+
+	/*  non-field (char or byte) cutting has some special handling */
+	if (part != OPT_FIELDS_FLGS) {
+		if (supress_non_delimited_lines) {
+			bb_error_msg_and_die("suppressing non-delimited lines makes sense"
+					" only when operating on fields");
+		}
+		if (delim != '\t') {
+			bb_error_msg_and_die("a delimiter may be specified only when operating on fields");
+		}
+	}
+
+	/* argv[(optind)..(argc-1)] should be names of file to process. If no
+	 * files were specified or '-' was specified, take input from stdin.
+	 * Otherwise, we process all the files specified. */
+	if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) {
+		cut_file(stdin);
+	}
+	else {
+		int i;
+		FILE *file;
+		for (i = optind; i < argc; i++) {
+			file = bb_wfopen(argv[i], "r");
+			if(file) {
+				cut_file(file);
+				fclose(file);
+			}
+		}
+	}
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/date.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/date.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/date.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,244 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini date implementation for busybox
+ *
+ * by Matthew Grant <grantma at anathoth.gen.nz>
+ *
+ * iso-format handling added by Robert Griebl <griebl at gmx.de>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+*/
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdio.h>
+#include <string.h>
+#include "busybox.h"
+
+/* This 'date' command supports only 2 time setting formats,
+   all the GNU strftime stuff (its in libc, lets use it),
+   setting time using UTC and displaying int, as well as
+   an RFC 822 complient date output for shell scripting
+   mail commands */
+
+/* Input parsing code is always bulky - used heavy duty libc stuff as
+   much as possible, missed out a lot of bounds checking */
+
+/* Default input handling to save surprising some people */
+
+static struct tm *date_conv_time(struct tm *tm_time, const char *t_string)
+{
+	int nr;
+	char *cp;
+
+	nr = sscanf(t_string, "%2d%2d%2d%2d%d", &(tm_time->tm_mon),
+				&(tm_time->tm_mday), &(tm_time->tm_hour), &(tm_time->tm_min),
+				&(tm_time->tm_year));
+
+	if (nr < 4 || nr > 5) {
+		bb_error_msg_and_die(bb_msg_invalid_date, t_string);
+	}
+
+	cp = strchr(t_string, '.');
+	if (cp) {
+		nr = sscanf(cp + 1, "%2d", &(tm_time->tm_sec));
+		if (nr != 1) {
+			bb_error_msg_and_die(bb_msg_invalid_date, t_string);
+		}
+	}
+
+	/* correct for century  - minor Y2K problem here? */
+	if (tm_time->tm_year >= 1900) {
+		tm_time->tm_year -= 1900;
+	}
+	/* adjust date */
+	tm_time->tm_mon -= 1;
+
+	return (tm_time);
+
+}
+
+
+/* The new stuff for LRP */
+
+static struct tm *date_conv_ftime(struct tm *tm_time, const char *t_string)
+{
+	struct tm t;
+
+	/* Parse input and assign appropriately to tm_time */
+
+	if (t = *tm_time, sscanf(t_string, "%d:%d:%d", &t.tm_hour, &t.tm_min,
+						 &t.tm_sec) == 3) {
+		/* no adjustments needed */
+	} else if (t = *tm_time, sscanf(t_string, "%d:%d", &t.tm_hour,
+								&t.tm_min) == 2) {
+		/* no adjustments needed */
+	} else if (t = *tm_time, sscanf(t_string, "%d.%d-%d:%d:%d", &t.tm_mon,
+						&t.tm_mday, &t.tm_hour,
+						&t.tm_min, &t.tm_sec) == 5) {
+		/* Adjust dates from 1-12 to 0-11 */
+		t.tm_mon -= 1;
+	} else if (t = *tm_time, sscanf(t_string, "%d.%d-%d:%d", &t.tm_mon,
+						&t.tm_mday,
+						&t.tm_hour, &t.tm_min) == 4) {
+		/* Adjust dates from 1-12 to 0-11 */
+		t.tm_mon -= 1;
+	} else if (t = *tm_time, sscanf(t_string, "%d.%d.%d-%d:%d:%d", &t.tm_year,
+						&t.tm_mon, &t.tm_mday,
+						&t.tm_hour, &t.tm_min,
+							&t.tm_sec) == 6) {
+		t.tm_year -= 1900;	/* Adjust years */
+		t.tm_mon -= 1;	/* Adjust dates from 1-12 to 0-11 */
+	} else if (t = *tm_time, sscanf(t_string, "%d.%d.%d-%d:%d", &t.tm_year,
+						&t.tm_mon, &t.tm_mday,
+						&t.tm_hour, &t.tm_min) == 5) {
+		t.tm_year -= 1900;	/* Adjust years */
+		t.tm_mon -= 1;	/* Adjust dates from 1-12 to 0-11 */
+	} else {
+		bb_error_msg_and_die(bb_msg_invalid_date, t_string);
+	}
+	*tm_time = t;
+	return (tm_time);
+}
+
+#define DATE_OPT_RFC2822	0x01
+#define DATE_OPT_SET		0x02
+#define DATE_OPT_UTC		0x04
+#define DATE_OPT_DATE		0x08
+#define DATE_OPT_REFERENCE	0x10
+#define DATE_OPT_TIMESPEC	0x20
+#define DATE_OPT_HINT		0x40
+
+int date_main(int argc, char **argv)
+{
+	char *date_str = NULL;
+	char *date_fmt = NULL;
+	int set_time;
+	int utc;
+	time_t tm;
+	unsigned long opt;
+	struct tm tm_time;
+	char *filename = NULL;
+
+	int ifmt = 0;
+	char *isofmt_arg;
+	char *hintfmt_arg;
+
+	bb_opt_complementally = "?:d--s:s--d";
+	opt = bb_getopt_ulflags(argc, argv, "Rs:ud:r:"
+		  		 	USE_FEATURE_DATE_ISOFMT("I::D:"),
+					&date_str, &date_str, &filename
+					USE_FEATURE_DATE_ISOFMT(, &isofmt_arg, &hintfmt_arg));
+	set_time = opt & DATE_OPT_SET;
+	utc = opt & DATE_OPT_UTC;
+	if (utc && putenv("TZ=UTC0") != 0) {
+		bb_error_msg_and_die(bb_msg_memory_exhausted);
+	}
+
+	if(ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_TIMESPEC)) {
+		if (!isofmt_arg) {
+			ifmt = 1;
+		} else {
+			char *isoformats[]={"date","hours","minutes","seconds"};
+			for(ifmt = 4; ifmt;)
+				if(!strcmp(isofmt_arg,isoformats[--ifmt]))
+					break;
+		}
+		if (!ifmt) {
+			bb_show_usage();
+		}
+	}
+
+	/* XXX, date_fmt == NULL from this always */
+	if ((date_fmt == NULL) && (optind < argc) && (argv[optind][0] == '+')) {
+		date_fmt = &argv[optind][1];	/* Skip over the '+' */
+	} else if (date_str == NULL) {
+		set_time = 1;
+		date_str = argv[optind];
+	}
+
+	/* Now we have parsed all the information except the date format
+	   which depends on whether the clock is being set or read */
+
+	if(filename) {
+		struct stat statbuf;
+		xstat(filename,&statbuf);
+		tm=statbuf.st_mtime;
+	} else time(&tm);
+	memcpy(&tm_time, localtime(&tm), sizeof(tm_time));
+	/* Zero out fields - take her back to midnight! */
+	if (date_str != NULL) {
+		tm_time.tm_sec = 0;
+		tm_time.tm_min = 0;
+		tm_time.tm_hour = 0;
+
+		/* Process any date input to UNIX time since 1 Jan 1970 */
+		if (ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_HINT)) {
+			strptime(date_str, hintfmt_arg, &tm_time);
+		} else if (strchr(date_str, ':') != NULL) {
+			date_conv_ftime(&tm_time, date_str);
+		} else {
+			date_conv_time(&tm_time, date_str);
+		}
+
+		/* Correct any day of week and day of year etc. fields */
+		tm_time.tm_isdst = -1;	/* Be sure to recheck dst. */
+		tm = mktime(&tm_time);
+		if (tm < 0) {
+			bb_error_msg_and_die(bb_msg_invalid_date, date_str);
+		}
+		if (utc && putenv("TZ=UTC0") != 0) {
+			bb_error_msg_and_die(bb_msg_memory_exhausted);
+		}
+
+		/* if setting time, set it */
+		if (set_time && stime(&tm) < 0) {
+			bb_perror_msg("cannot set date");
+		}
+	}
+
+	/* Display output */
+
+	/* Deal with format string */
+	if (date_fmt == NULL) {
+		/* Start with the default case */
+		
+		date_fmt = (opt & DATE_OPT_RFC2822 ?
+					(utc ? "%a, %d %b %Y %H:%M:%S GMT" :
+					"%a, %d %b %Y %H:%M:%S %z") :
+					"%a %b %e %H:%M:%S %Z %Y");
+
+		if (ENABLE_FEATURE_DATE_ISOFMT) {
+			if (ifmt == 4)
+				date_fmt = utc ? "%Y-%m-%dT%H:%M:%SZ" : "%Y-%m-%dT%H:%M:%S%z";
+			else if (ifmt == 3)
+				date_fmt = utc ? "%Y-%m-%dT%H:%MZ" : "%Y-%m-%dT%H:%M%z";
+			else if (ifmt == 2) 
+				date_fmt = utc ? "%Y-%m-%dT%HZ" : "%Y-%m-%dT%H%z";
+			else if (ifmt == 1)
+				date_fmt = "%Y-%m-%d";
+		}
+	}
+	
+	if (*date_fmt == '\0') {
+
+		/* With no format string, just print a blank line */
+		
+		*bb_common_bufsiz1=0;
+	} else {
+
+		/* Handle special conversions */
+
+		if (strncmp(date_fmt, "%f", 2) == 0) {
+			date_fmt = "%Y.%m.%d-%H:%M:%S";
+		}
+
+		/* Generate output string */
+		strftime(bb_common_bufsiz1, 200, date_fmt, &tm_time);
+	}
+	puts(bb_common_bufsiz1);
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/dd.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/dd.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/dd.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,232 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini dd implementation for busybox
+ *
+ *
+ * Copyright (C) 2000,2001  Matt Kraai
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <signal.h>  // For FEATURE_DD_SIGNAL_HANDLING
+#include "busybox.h"
+
+static const struct suffix_mult dd_suffixes[] = {
+	{ "c", 1 },
+	{ "w", 2 },
+	{ "b", 512 },
+	{ "kD", 1000 },
+	{ "k", 1024 },
+	{ "MD", 1000000 },
+	{ "M", 1048576 },
+	{ "GD", 1000000000 },
+	{ "G", 1073741824 },
+	{ NULL, 0 }
+};
+
+static size_t out_full;
+static size_t out_part;
+static size_t in_full;
+static size_t in_part;
+
+static void dd_output_status(int cur_signal)
+{
+	fprintf(stderr, "%ld+%ld records in\n%ld+%ld records out\n",
+			(long)in_full, (long)in_part,
+			(long)out_full, (long)out_part);
+}
+
+int dd_main(int argc, char **argv)
+{
+	size_t count = -1, oc = 0, ibs = 512, obs = 512;
+	ssize_t n;
+	off_t seek = 0, skip = 0;
+	int sync_flag = FALSE, noerror = FALSE, trunc_flag = TRUE, twobufs_flag = 0,
+		oflag, ifd, ofd, i;
+	const char *infile = NULL, *outfile = NULL;
+	char *ibuf, *obuf;
+
+	if (ENABLE_FEATURE_DD_SIGNAL_HANDLING)
+	{
+		struct sigaction sa;
+
+		memset(&sa, 0, sizeof(sa));
+		sa.sa_handler = dd_output_status; 
+		sa.sa_flags = SA_RESTART;
+		sigemptyset(&sa.sa_mask);
+		sigaction(SIGUSR1, &sa, 0); 
+	}
+
+	for (i = 1; i < argc; i++) {
+		if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("ibs=", argv[i], 4)) {
+			ibs = bb_xparse_number(argv[i]+4, dd_suffixes);
+			twobufs_flag++;
+		} else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("obs=", argv[i], 4)) {
+			obs = bb_xparse_number(argv[i]+4, dd_suffixes);
+			twobufs_flag++;
+		} else if (!strncmp("bs=", argv[i], 3)) {
+			ibs = obs = bb_xparse_number(argv[i]+3, dd_suffixes);
+		} else if (!strncmp("count=", argv[i], 6))
+			count = bb_xparse_number(argv[i]+6, dd_suffixes);
+		else if (!strncmp("seek=", argv[i], 5))
+			seek = bb_xparse_number(argv[i]+5, dd_suffixes);
+		else if (!strncmp("skip=", argv[i], 5))
+			skip = bb_xparse_number(argv[i]+5, dd_suffixes);
+		else if (!strncmp("if=", argv[i], 3))
+			infile = argv[i]+3;
+		else if (!strncmp("of=", argv[i], 3))
+			outfile = argv[i]+3;
+		else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("conv=", argv[i], 5)) {
+			ibuf = argv[i]+5;
+			while (1) {
+				if (!strncmp("notrunc", ibuf, 7)) {
+					trunc_flag = FALSE;
+					ibuf += 7;
+				} else if (!strncmp("sync", ibuf, 4)) {
+					sync_flag = TRUE;
+					ibuf += 4;
+				} else if (!strncmp("noerror", ibuf, 7)) {
+					noerror = TRUE;
+					ibuf += 7;
+				} else {
+					bb_error_msg_and_die(bb_msg_invalid_arg, argv[i]+5, "conv");
+				}
+				if (ibuf[0] == '\0') break;
+				if (ibuf[0] == ',') ibuf++;
+			}
+		} else
+			bb_show_usage();
+	}
+	ibuf = xmalloc(ibs);
+
+	if (twobufs_flag) obuf = xmalloc(obs);
+	else obuf = ibuf;
+
+	if (infile != NULL) {
+		ifd = bb_xopen(infile, O_RDONLY);
+	} else {
+		ifd = STDIN_FILENO;
+		infile = bb_msg_standard_input;
+	}
+
+	if (outfile != NULL) {
+		oflag = O_WRONLY | O_CREAT;
+
+		if (!seek && trunc_flag) {
+			oflag |= O_TRUNC;
+		}
+
+		ofd = bb_xopen3(outfile, oflag, 0666);
+
+		if (seek && trunc_flag) {
+			if (ftruncate(ofd, seek * obs) < 0) {
+				struct stat st;
+
+				if (fstat (ofd, &st) < 0 || S_ISREG (st.st_mode) ||
+						S_ISDIR (st.st_mode)) {
+					bb_perror_msg_and_die("%s", outfile);
+				}
+			}
+		}
+	} else {
+		ofd = STDOUT_FILENO;
+		outfile = bb_msg_standard_output;
+	}
+
+	if (skip) {
+		if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) {
+			while (skip-- > 0) {
+				n = safe_read(ifd, ibuf, ibs);
+				if (n < 0)
+					bb_perror_msg_and_die("%s", infile);
+				if (n == 0)
+					break;
+			}
+		}
+	}
+
+	if (seek) {
+		if (lseek(ofd, seek * obs, SEEK_CUR) < 0) {
+			bb_perror_msg_and_die("%s", outfile);
+		}
+	}
+
+	while (in_full + in_part != count) {
+		if (noerror) {
+			/* Pre-zero the buffer when doing the noerror thing */
+			memset(ibuf, '\0', ibs);
+		}
+
+		n = safe_read(ifd, ibuf, ibs);
+		if (n == 0) {
+			break;
+		}
+		if (n < 0) {
+			if (noerror) {
+				n = ibs;
+				bb_perror_msg("%s", infile);
+			} else {
+				bb_perror_msg_and_die("%s", infile);
+			}
+		}
+		if ((size_t)n == ibs) {
+			in_full++;
+		} else {
+			in_part++;
+			if (sync_flag) {
+				memset(ibuf + n, '\0', ibs - n);
+				n = ibs;
+			}
+		}
+		if (twobufs_flag) {
+			char *tmp = ibuf;
+			while (n) {
+				size_t d = obs - oc;
+
+				if (d > n) d = n;
+				memcpy(obuf + oc, tmp, d);
+				n -= d;
+				tmp += d;
+				oc += d;
+				if (oc == obs) {
+					if (bb_full_write(ofd, obuf, obs) < 0) {
+						bb_perror_msg_and_die("%s", outfile);
+					}
+					out_full++;
+					oc = 0;
+				}
+			}
+		} else {
+			if ((n = bb_full_write(ofd, ibuf, n)) < 0) {
+				bb_perror_msg_and_die("%s", outfile);
+			}
+			if (n == ibs) out_full++;
+			else out_part++;
+		}
+	}
+	
+	if (ENABLE_FEATURE_DD_IBS_OBS && oc) {
+		if (bb_full_write(ofd, obuf, oc) < 0) {
+			bb_perror_msg_and_die("%s", outfile);
+		}
+		out_part++;
+	}
+	if (close (ifd) < 0) {
+		bb_perror_msg_and_die("%s", infile);
+	}
+
+	if (close (ofd) < 0) {
+		bb_perror_msg_and_die("%s", outfile);
+	}
+
+	dd_output_status(0);
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/df.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/df.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/df.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,149 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini df implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ * based on original code by (I think) Bruce Perens <bruce at pixar.com>.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 _NOT_ compliant -- options -P and -t missing.  Also blocksize. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/df.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Size reduction.  Removed floating point dependency.  Added error checking
+ * on output.  Output stats on 0-sized filesystems if specifically listed on
+ * the command line.  Properly round *-blocks, Used, and Available quantities.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <mntent.h>
+#include <sys/vfs.h>
+#include "busybox.h"
+
+#ifndef CONFIG_FEATURE_HUMAN_READABLE
+static long kscale(long b, long bs)
+{
+	return ( b * (long long) bs + KILOBYTE/2 ) / KILOBYTE;
+}
+#endif
+
+int df_main(int argc, char **argv)
+{
+	long blocks_used;
+	long blocks_percent_used;
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+	unsigned long df_disp_hr = KILOBYTE;
+#endif
+	int status = EXIT_SUCCESS;
+	unsigned long opt;
+	FILE *mount_table;
+	struct mntent *mount_entry;
+	struct statfs s;
+	static const char hdr_1k[] = "1k-blocks"; /* default display is kilobytes */
+	const char *disp_units_hdr = hdr_1k;
+
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+	bb_opt_complementally = "h-km:k-hm:m-hk";
+	opt = bb_getopt_ulflags(argc, argv, "hmk");
+	if(opt & 1) {
+				df_disp_hr = 0;
+				disp_units_hdr = "     Size";
+	}
+	if(opt & 2) {
+				df_disp_hr = MEGABYTE;
+				disp_units_hdr = "1M-blocks";
+	}
+#else
+	opt = bb_getopt_ulflags(argc, argv, "k");
+#endif
+
+	bb_printf("Filesystem%11s%-15sUsed Available Use%% Mounted on\n",
+			  "", disp_units_hdr);
+
+	mount_table = NULL;
+	argv += optind;
+	if (optind >= argc) {
+		if (!(mount_table = setmntent(bb_path_mtab_file, "r"))) {
+			bb_perror_msg_and_die(bb_path_mtab_file);
+		}
+	}
+
+	do {
+		const char *device;
+		const char *mount_point;
+
+		if (mount_table) {
+			if (!(mount_entry = getmntent(mount_table))) {
+				endmntent(mount_table);
+				break;
+			}
+		} else {
+			if (!(mount_point = *argv++)) {
+				break;
+			}
+			if (!(mount_entry = find_mount_point(mount_point, bb_path_mtab_file))) {
+				bb_error_msg("%s: can't find mount point.", mount_point);
+			SET_ERROR:
+				status = EXIT_FAILURE;
+				continue;
+			}
+		}
+
+		device = mount_entry->mnt_fsname;
+		mount_point = mount_entry->mnt_dir;
+
+		if (statfs(mount_point, &s) != 0) {
+			bb_perror_msg("%s", mount_point);
+			goto SET_ERROR;
+		}
+
+		if ((s.f_blocks > 0) || !mount_table){
+			blocks_used = s.f_blocks - s.f_bfree;
+			blocks_percent_used = 0;
+			if (blocks_used + s.f_bavail) {
+				blocks_percent_used = (((long long) blocks_used) * 100
+									   + (blocks_used + s.f_bavail)/2
+									   ) / (blocks_used + s.f_bavail);
+			}
+
+			if (strcmp(device, "rootfs") == 0) {
+				continue;
+			} else if (strcmp(device, "/dev/root") == 0) {
+				/* Adjusts device to be the real root device,
+				* or leaves device alone if it can't find it */
+				if ((device = find_block_device("/")) == NULL) {
+					goto SET_ERROR;
+				}
+			}
+
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+			bb_printf("%-20s %9s ", device,
+					  make_human_readable_str(s.f_blocks, s.f_bsize, df_disp_hr));
+
+			bb_printf("%9s ",
+					  make_human_readable_str( (s.f_blocks - s.f_bfree),
+											  s.f_bsize, df_disp_hr));
+
+			bb_printf("%9s %3ld%% %s\n",
+					  make_human_readable_str(s.f_bavail, s.f_bsize, df_disp_hr),
+					  blocks_percent_used, mount_point);
+#else
+			bb_printf("%-20s %9ld %9ld %9ld %3ld%% %s\n",
+					  device,
+					  kscale(s.f_blocks, s.f_bsize),
+					  kscale(s.f_blocks-s.f_bfree, s.f_bsize),
+					  kscale(s.f_bavail, s.f_bsize),
+					  blocks_percent_used, mount_point);
+#endif
+		}
+
+	} while (1);
+
+	bb_fflush_stdout_and_exit(status);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/diff.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/diff.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/diff.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1274 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini diff implementation for busybox, adapted from OpenBSD diff.
+ *
+ * Copyright (C) 2006 by Robert Sullivan <cogito.ergo.cogito at hotmail.com>
+ * Copyright (c) 2003 Todd C. Miller <Todd.Miller at courtesan.com>
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <time.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <paths.h>
+#include <dirent.h>
+#include "busybox.h"
+
+#define FSIZE_MAX 32768
+
+/*
+ * Output flags
+ */
+#define D_HEADER        1	/* Print a header/footer between files */
+#define D_EMPTY1        2	/* Treat first file as empty (/dev/null) */
+#define D_EMPTY2        4	/* Treat second file as empty (/dev/null) */
+
+/*
+ * Status values for print_status() and diffreg() return values
+ * Guide:
+ * D_SAME - files are the same
+ * D_DIFFER - files differ
+ * D_BINARY - binary files differ
+ * D_COMMON - subdirectory common to both dirs
+ * D_ONLY - file only exists in one dir
+ * D_MISMATCH1 - path1 a dir, path2 a file
+ * D_MISMATCH2 - path1 a file, path2 a dir
+ * D_ERROR - error occurred
+ * D_SKIPPED1 - skipped path1 as it is a special file
+ * D_SKIPPED2 - skipped path2 as it is a special file
+ */
+
+#define D_SAME		0
+#define D_DIFFER	(1<<0)
+#define D_BINARY	(1<<1)
+#define D_COMMON	(1<<2)
+#define D_ONLY		(1<<3)
+#define D_MISMATCH1	(1<<4)
+#define D_MISMATCH2	(1<<5)
+#define D_ERROR		(1<<6)
+#define D_SKIPPED1	(1<<7)
+#define D_SKIPPED2	(1<<8)
+
+/* Command line options */
+static unsigned long cmd_flags;
+
+#define FLAG_a	(1<<0)
+#define FLAG_b	(1<<1)
+#define FLAG_d  (1<<2)
+#define FLAG_i	(1<<3)
+#define FLAG_L	(1<<4)
+#define FLAG_N	(1<<5)
+#define FLAG_q	(1<<6)
+#define FLAG_r	(1<<7)
+#define FLAG_s	(1<<8)
+#define FLAG_S	(1<<9)
+#define FLAG_t	(1<<10)
+#define FLAG_T	(1<<11)
+#define FLAG_U	(1<<12)
+#define	FLAG_w	(1<<13)
+
+int context, status;
+char *start, *label[2];
+struct stat stb1, stb2;
+char **dl;
+int dl_count = 0;
+
+struct cand {
+	int x;
+	int y;
+	int pred;
+};
+
+struct line {
+	int serial;
+	int value;
+} *file[2];
+
+/*
+ * The following struct is used to record change information
+ * doing a "context" or "unified" diff.  (see routine "change" to
+ * understand the highly mnemonic field names)
+ */
+struct context_vec {
+	int a;				/* start line in old file */
+	int b;				/* end line in old file */
+	int c;				/* start line in new file */
+	int d;				/* end line in new file */
+};
+
+static int *J;			/* will be overlaid on class */
+static int *class;		/* will be overlaid on file[0] */
+static int *klist;		/* will be overlaid on file[0] after class */
+static int *member;		/* will be overlaid on file[1] */
+static int clen;
+static int len[2];
+static int pref, suff;	/* length of prefix and suffix */
+static int slen[2];
+static int anychange;
+static long *ixnew;		/* will be overlaid on file[1] */
+static long *ixold;		/* will be overlaid on klist */
+static struct cand *clist;	/* merely a free storage pot for candidates */
+static int clistlen;	/* the length of clist */
+static struct line *sfile[2];	/* shortened by pruning common prefix/suffix */
+static struct context_vec *context_vec_start;
+static struct context_vec *context_vec_end;
+static struct context_vec *context_vec_ptr;
+
+static void print_only(const char *path, size_t dirlen, const char *entry)
+{
+	if (dirlen > 1)
+		dirlen--;
+	printf("Only in %.*s: %s\n", (int) dirlen, path, entry);
+}
+
+static void print_status(int val, char *path1, char *path2, char *entry)
+{
+	const char *const _entry = entry ? entry : "";
+	char *_path1 = entry ? concat_path_file(path1, _entry) : path1;
+	char *_path2 = entry ? concat_path_file(path2, _entry) : path2;
+
+	switch (val) {
+	case D_ONLY:
+		print_only(path1, strlen(path1), entry);
+		break;
+	case D_COMMON:
+		printf("Common subdirectories: %s and %s\n", _path1, _path2);
+		break;
+	case D_BINARY:
+		printf("Binary files %s and %s differ\n", _path1, _path2);
+		break;
+	case D_DIFFER:
+		if (cmd_flags & FLAG_q)
+			printf("Files %s and %s differ\n", _path1, _path2);
+		break;
+	case D_SAME:
+		if (cmd_flags & FLAG_s)
+			printf("Files %s and %s are identical\n", _path1, _path2);
+		break;
+	case D_MISMATCH1:
+		printf("File %s is a directory while file %s is a regular file\n",
+			   _path1, _path2);
+		break;
+	case D_MISMATCH2:
+		printf("File %s is a regular file while file %s is a directory\n",
+			   _path1, _path2);
+		break;
+	case D_SKIPPED1:
+		printf("File %s is not a regular file or directory and was skipped\n",
+			   _path1);
+		break;
+	case D_SKIPPED2:
+		printf("File %s is not a regular file or directory and was skipped\n",
+			   _path2);
+		break;
+	}
+	if (entry) {
+		free(_path1);
+		free(_path2);
+	}
+}
+
+/*
+ * Hash function taken from Robert Sedgewick, Algorithms in C, 3d ed., p 578.
+ */
+static int readhash(FILE * f)
+{
+	int i, t, space;
+	int sum;
+
+	sum = 1;
+	space = 0;
+	if (!(cmd_flags & FLAG_b) && !(cmd_flags & FLAG_w)) {
+		if (FLAG_i)
+			for (i = 0; (t = getc(f)) != '\n'; i++) {
+				if (t == EOF) {
+					if (i == 0)
+						return (0);
+					break;
+				}
+				sum = sum * 127 + t;
+		} else
+			for (i = 0; (t = getc(f)) != '\n'; i++) {
+				if (t == EOF) {
+					if (i == 0)
+						return (0);
+					break;
+				}
+				sum = sum * 127 + t;
+			}
+	} else {
+		for (i = 0;;) {
+			switch (t = getc(f)) {
+			case '\t':
+			case '\r':
+			case '\v':
+			case '\f':
+			case ' ':
+				space++;
+				continue;
+			default:
+				if (space && !(cmd_flags & FLAG_w)) {
+					i++;
+					space = 0;
+				}
+				sum = sum * 127 + t;
+				i++;
+				continue;
+			case EOF:
+				if (i == 0)
+					return (0);
+				/* FALLTHROUGH */
+			case '\n':
+				break;
+			}
+			break;
+		}
+	}
+	/*
+	 * There is a remote possibility that we end up with a zero sum.
+	 * Zero is used as an EOF marker, so return 1 instead.
+	 */
+	return (sum == 0 ? 1 : sum);
+}
+
+
+
+/*
+ * Check to see if the given files differ.
+ * Returns 0 if they are the same, 1 if different, and -1 on error.
+ */
+static int files_differ(FILE * f1, FILE * f2, int flags)
+{
+	char buf1[BUFSIZ], buf2[BUFSIZ];
+	size_t i, j;
+
+	if ((flags & (D_EMPTY1 | D_EMPTY2)) || stb1.st_size != stb2.st_size ||
+		(stb1.st_mode & S_IFMT) != (stb2.st_mode & S_IFMT))
+		return (1);
+	while (1) {
+		i = fread(buf1, 1, sizeof(buf1), f1);
+		j = fread(buf2, 1, sizeof(buf2), f2);
+		if (i != j)
+			return (1);
+		if (i == 0 && j == 0) {
+			if (ferror(f1) || ferror(f2))
+				return (1);
+			return (0);
+		}
+		if (memcmp(buf1, buf2, i) != 0)
+			return (1);
+	}
+}
+
+static void prepare(int i, FILE * fd, off_t filesize)
+{
+	struct line *p;
+	int h;
+	size_t j, sz;
+
+	rewind(fd);
+
+	sz = (filesize <= FSIZE_MAX ? filesize : FSIZE_MAX) / 25;
+	if (sz < 100)
+		sz = 100;
+
+	p = xmalloc((sz + 3) * sizeof(struct line));
+	for (j = 0; (h = readhash(fd));) {
+		if (j == sz) {
+			sz = sz * 3 / 2;
+			p = xrealloc(p, (sz + 3) * sizeof(struct line));
+		}
+		p[++j].value = h;
+	}
+	len[i] = j;
+	file[i] = p;
+}
+
+static void prune(void)
+{
+	int i, j;
+
+	for (pref = 0; pref < len[0] && pref < len[1] &&
+		 file[0][pref + 1].value == file[1][pref + 1].value; pref++);
+	for (suff = 0; suff < len[0] - pref && suff < len[1] - pref &&
+		 file[0][len[0] - suff].value == file[1][len[1] - suff].value;
+		 suff++);
+	for (j = 0; j < 2; j++) {
+		sfile[j] = file[j] + pref;
+		slen[j] = len[j] - pref - suff;
+		for (i = 0; i <= slen[j]; i++)
+			sfile[j][i].serial = i;
+	}
+}
+
+static void equiv(struct line *a, int n, struct line *b, int m, int *c)
+{
+	int i, j;
+
+	i = j = 1;
+	while (i <= n && j <= m) {
+		if (a[i].value < b[j].value)
+			a[i++].value = 0;
+		else if (a[i].value == b[j].value)
+			a[i++].value = j;
+		else
+			j++;
+	}
+	while (i <= n)
+		a[i++].value = 0;
+	b[m + 1].value = 0;
+	j = 0;
+	while (++j <= m) {
+		c[j] = -b[j].serial;
+		while (b[j + 1].value == b[j].value) {
+			j++;
+			c[j] = b[j].serial;
+		}
+	}
+	c[j] = -1;
+}
+
+static int isqrt(int n)
+{
+	int y, x = 1;
+
+	if (n == 0)
+		return (0);
+
+	do {
+		y = x;
+		x = n / x;
+		x += y;
+		x /= 2;
+	} while ((x - y) > 1 || (x - y) < -1);
+
+	return (x);
+}
+
+static int newcand(int x, int y, int pred)
+{
+	struct cand *q;
+
+	if (clen == clistlen) {
+		clistlen = clistlen * 11 / 10;
+		clist = xrealloc(clist, clistlen * sizeof(struct cand));
+	}
+	q = clist + clen;
+	q->x = x;
+	q->y = y;
+	q->pred = pred;
+	return (clen++);
+}
+
+
+static int search(int *c, int k, int y)
+{
+	int i, j, l, t;
+
+	if (clist[c[k]].y < y)	/* quick look for typical case */
+		return (k + 1);
+	i = 0;
+	j = k + 1;
+	while (1) {
+		l = i + j;
+		if ((l >>= 1) <= i)
+			break;
+		t = clist[c[l]].y;
+		if (t > y)
+			j = l;
+		else if (t < y)
+			i = l;
+		else
+			return (l);
+	}
+	return (l + 1);
+}
+
+
+static int stone(int *a, int n, int *b, int *c)
+{
+	int i, k, y, j, l;
+	int oldc, tc, oldl;
+	unsigned int numtries;
+
+#if ENABLE_FEATURE_DIFF_MINIMAL
+	const unsigned int bound =
+		(cmd_flags & FLAG_d) ? UINT_MAX : MAX(256, isqrt(n));
+#else
+	const unsigned int bound = MAX(256, isqrt(n));
+#endif
+	k = 0;
+	c[0] = newcand(0, 0, 0);
+	for (i = 1; i <= n; i++) {
+		j = a[i];
+		if (j == 0)
+			continue;
+		y = -b[j];
+		oldl = 0;
+		oldc = c[0];
+		numtries = 0;
+		do {
+			if (y <= clist[oldc].y)
+				continue;
+			l = search(c, k, y);
+			if (l != oldl + 1)
+				oldc = c[l - 1];
+			if (l <= k) {
+				if (clist[c[l]].y <= y)
+					continue;
+				tc = c[l];
+				c[l] = newcand(i, y, oldc);
+				oldc = tc;
+				oldl = l;
+				numtries++;
+			} else {
+				c[l] = newcand(i, y, oldc);
+				k++;
+				break;
+			}
+		} while ((y = b[++j]) > 0 && numtries < bound);
+	}
+	return (k);
+}
+
+static void unravel(int p)
+{
+	struct cand *q;
+	int i;
+
+	for (i = 0; i <= len[0]; i++)
+		J[i] = i <= pref ? i : i > len[0] - suff ? i + len[1] - len[0] : 0;
+	for (q = clist + p; q->y != 0; q = clist + q->pred)
+		J[q->x + pref] = q->y + pref;
+}
+
+
+static void unsort(struct line *f, int l, int *b)
+{
+	int *a, i;
+
+	a = xmalloc((l + 1) * sizeof(int));
+	for (i = 1; i <= l; i++)
+		a[f[i].serial] = f[i].value;
+	for (i = 1; i <= l; i++)
+		b[i] = a[i];
+	free(a);
+}
+
+static int skipline(FILE * f)
+{
+	int i, c;
+
+	for (i = 1; (c = getc(f)) != '\n' && c != EOF; i++)
+		continue;
+	return (i);
+}
+
+
+/*
+ * Check does double duty:
+ *  1.  ferret out any fortuitous correspondences due
+ *      to confounding by hashing (which result in "jackpot")
+ *  2.  collect random access indexes to the two files
+ */
+static void check(FILE * f1, FILE * f2)
+{
+	int i, j, jackpot, c, d;
+	long ctold, ctnew;
+
+	rewind(f1);
+	rewind(f2);
+	j = 1;
+	ixold[0] = ixnew[0] = 0;
+	jackpot = 0;
+	ctold = ctnew = 0;
+	for (i = 1; i <= len[0]; i++) {
+		if (J[i] == 0) {
+			ixold[i] = ctold += skipline(f1);
+			continue;
+		}
+		while (j < J[i]) {
+			ixnew[j] = ctnew += skipline(f2);
+			j++;
+		}
+		if ((cmd_flags & FLAG_b) || (cmd_flags & FLAG_w)
+			|| (cmd_flags & FLAG_i)) {
+			while (1) {
+				c = getc(f1);
+				d = getc(f2);
+				/*
+				 * GNU diff ignores a missing newline
+				 * in one file if bflag || wflag.
+				 */
+				if (((cmd_flags & FLAG_b) || (cmd_flags & FLAG_w)) &&
+					((c == EOF && d == '\n') || (c == '\n' && d == EOF))) {
+					break;
+				}
+				ctold++;
+				ctnew++;
+				if ((cmd_flags & FLAG_b) && isspace(c) && isspace(d)) {
+					do {
+						if (c == '\n')
+							break;
+						ctold++;
+					} while (isspace(c = getc(f1)));
+					do {
+						if (d == '\n')
+							break;
+						ctnew++;
+					} while (isspace(d = getc(f2)));
+				} else if (cmd_flags & FLAG_w) {
+					while (isspace(c) && c != '\n') {
+						c = getc(f1);
+						ctold++;
+					}
+					while (isspace(d) && d != '\n') {
+						d = getc(f2);
+						ctnew++;
+					}
+				}
+				if (c != d) {
+					jackpot++;
+					J[i] = 0;
+					if (c != '\n' && c != EOF)
+						ctold += skipline(f1);
+					if (d != '\n' && c != EOF)
+						ctnew += skipline(f2);
+					break;
+				}
+				if (c == '\n' || c == EOF)
+					break;
+			}
+		} else {
+			while (1) {
+				ctold++;
+				ctnew++;
+				if ((c = getc(f1)) != (d = getc(f2))) {
+					J[i] = 0;
+					if (c != '\n' && c != EOF)
+						ctold += skipline(f1);
+					if (d != '\n' && c != EOF)
+						ctnew += skipline(f2);
+					break;
+				}
+				if (c == '\n' || c == EOF)
+					break;
+			}
+		}
+		ixold[i] = ctold;
+		ixnew[j] = ctnew;
+		j++;
+	}
+	for (; j <= len[1]; j++)
+		ixnew[j] = ctnew += skipline(f2);
+}
+
+/* shellsort CACM #201 */
+static void sort(struct line *a, int n)
+{
+	struct line *ai, *aim, w;
+	int j, m = 0, k;
+
+	if (n == 0)
+		return;
+	for (j = 1; j <= n; j *= 2)
+		m = 2 * j - 1;
+	for (m /= 2; m != 0; m /= 2) {
+		k = n - m;
+		for (j = 1; j <= k; j++) {
+			for (ai = &a[j]; ai > a; ai -= m) {
+				aim = &ai[m];
+				if (aim < ai)
+					break;	/* wraparound */
+				if (aim->value > ai[0].value ||
+					(aim->value == ai[0].value && aim->serial > ai[0].serial))
+					break;
+				w.value = ai[0].value;
+				ai[0].value = aim->value;
+				aim->value = w.value;
+				w.serial = ai[0].serial;
+				ai[0].serial = aim->serial;
+				aim->serial = w.serial;
+			}
+		}
+	}
+}
+
+
+static void uni_range(int a, int b)
+{
+	if (a < b)
+		printf("%d,%d", a, b - a + 1);
+	else if (a == b)
+		printf("%d", b);
+	else
+		printf("%d,0", b);
+}
+
+static int fetch(long *f, int a, int b, FILE * lb, int ch)
+{
+	int i, j, c, lastc, col, nc;
+
+	if (a > b)
+		return (0);
+	for (i = a; i <= b; i++) {
+		fseek(lb, f[i - 1], SEEK_SET);
+		nc = f[i] - f[i - 1];
+		if (ch != '\0') {
+			putchar(ch);
+			if (cmd_flags & FLAG_T)
+				putchar('\t');
+		}
+		col = 0;
+		for (j = 0, lastc = '\0'; j < nc; j++, lastc = c) {
+			if ((c = getc(lb)) == EOF) {
+				puts("\n\\ No newline at end of file");
+				return (0);
+			}
+			if (c == '\t' && (cmd_flags & FLAG_t)) {
+				do {
+					putchar(' ');
+				} while (++col & 7);
+			} else {
+				putchar(c);
+				col++;
+			}
+		}
+	}
+	return (0);
+}
+
+static int asciifile(FILE * f)
+{
+#if ENABLE_FEATURE_DIFF_BINARY
+	unsigned char buf[BUFSIZ];
+	int i, cnt;
+#endif
+
+	if ((cmd_flags & FLAG_a) || f == NULL)
+		return (1);
+
+#if ENABLE_FEATURE_DIFF_BINARY
+	rewind(f);
+	cnt = fread(buf, 1, sizeof(buf), f);
+	for (i = 0; i < cnt; i++) {
+		if (!isprint(buf[i]) && !isspace(buf[i])) {
+			return (0);
+		}
+	}
+#endif
+	return (1);
+}
+
+/* dump accumulated "unified" diff changes */
+static void dump_unified_vec(FILE * f1, FILE * f2)
+{
+	struct context_vec *cvp = context_vec_start;
+	int lowa, upb, lowc, upd;
+	int a, b, c, d;
+	char ch;
+
+	if (context_vec_start > context_vec_ptr)
+		return;
+
+	b = d = 0;			/* gcc */
+	lowa = MAX(1, cvp->a - context);
+	upb = MIN(len[0], context_vec_ptr->b + context);
+	lowc = MAX(1, cvp->c - context);
+	upd = MIN(len[1], context_vec_ptr->d + context);
+
+	fputs("@@ -", stdout);
+	uni_range(lowa, upb);
+	fputs(" +", stdout);
+	uni_range(lowc, upd);
+	fputs(" @@", stdout);
+	putchar('\n');
+
+	/*
+	 * Output changes in "unified" diff format--the old and new lines
+	 * are printed together.
+	 */
+	for (; cvp <= context_vec_ptr; cvp++) {
+		a = cvp->a;
+		b = cvp->b;
+		c = cvp->c;
+		d = cvp->d;
+
+		/*
+		 * c: both new and old changes
+		 * d: only changes in the old file
+		 * a: only changes in the new file
+		 */
+		if (a <= b && c <= d)
+			ch = 'c';
+		else
+			ch = (a <= b) ? 'd' : 'a';
+#if 0
+		switch (ch) {
+		case 'c':
+			fetch(ixold, lowa, a - 1, f1, ' ');
+			fetch(ixold, a, b, f1, '-');
+			fetch(ixnew, c, d, f2, '+');
+			break;
+		case 'd':
+			fetch(ixold, lowa, a - 1, f1, ' ');
+			fetch(ixold, a, b, f1, '-');
+			break;
+		case 'a':
+			fetch(ixnew, lowc, c - 1, f2, ' ');
+			fetch(ixnew, c, d, f2, '+');
+			break;
+		}
+#else
+		if (ch == 'c' || ch == 'd') {
+			fetch(ixold, lowa, a - 1, f1, ' ');
+			fetch(ixold, a, b, f1, '-');
+		}
+		if (ch == 'a')
+			fetch(ixnew, lowc, c - 1, f2, ' ');
+		if (ch == 'c' || ch == 'a')
+			fetch(ixnew, c, d, f2, '+');
+#endif
+		lowa = b + 1;
+		lowc = d + 1;
+	}
+	fetch(ixnew, d + 1, upd, f2, ' ');
+
+	context_vec_ptr = context_vec_start - 1;
+}
+
+
+static void print_header(const char *file1, const char *file2)
+{
+	if (label[0] != NULL)
+		printf("%s %s\n", "---", label[0]);
+	else
+		printf("%s %s\t%s", "---", file1, ctime(&stb1.st_mtime));
+	if (label[1] != NULL)
+		printf("%s %s\n", "+++", label[1]);
+	else
+		printf("%s %s\t%s", "+++", file2, ctime(&stb2.st_mtime));
+}
+
+
+
+/*
+ * Indicate that there is a difference between lines a and b of the from file
+ * to get to lines c to d of the to file.  If a is greater then b then there
+ * are no lines in the from file involved and this means that there were
+ * lines appended (beginning at b).  If c is greater than d then there are
+ * lines missing from the to file.
+ */
+static void change(char *file1, FILE * f1, char *file2, FILE * f2, int a,
+				   int b, int c, int d)
+{
+	static size_t max_context = 64;
+
+	if (a > b && c > d)
+		return;
+	if (cmd_flags & FLAG_q)
+		return;
+
+	/*
+	 * Allocate change records as needed.
+	 */
+	if (context_vec_ptr == context_vec_end - 1) {
+		ptrdiff_t offset = context_vec_ptr - context_vec_start;
+
+		max_context <<= 1;
+		context_vec_start = xrealloc(context_vec_start,
+									 max_context *
+									 sizeof(struct context_vec));
+		context_vec_end = context_vec_start + max_context;
+		context_vec_ptr = context_vec_start + offset;
+	}
+	if (anychange == 0) {
+		/*
+		 * Print the context/unidiff header first time through.
+		 */
+		print_header(file1, file2);
+		anychange = 1;
+	} else if (a > context_vec_ptr->b + (2 * context) + 1 &&
+			   c > context_vec_ptr->d + (2 * context) + 1) {
+		/*
+		 * If this change is more than 'context' lines from the
+		 * previous change, dump the record and reset it.
+		 */
+		dump_unified_vec(f1, f2);
+	}
+	context_vec_ptr++;
+	context_vec_ptr->a = a;
+	context_vec_ptr->b = b;
+	context_vec_ptr->c = c;
+	context_vec_ptr->d = d;
+	return;
+
+}
+
+
+static void output(char *file1, FILE * f1, char *file2, FILE * f2)
+{
+
+	/* Note that j0 and j1 can't be used as they are defined in math.h.
+	 * This also allows the rather amusing variable 'j00'... */
+	int m, i0, i1, j00, j01;
+
+	rewind(f1);
+	rewind(f2);
+	m = len[0];
+	J[0] = 0;
+	J[m + 1] = len[1] + 1;
+	for (i0 = 1; i0 <= m; i0 = i1 + 1) {
+		while (i0 <= m && J[i0] == J[i0 - 1] + 1)
+			i0++;
+		j00 = J[i0 - 1] + 1;
+		i1 = i0 - 1;
+		while (i1 < m && J[i1 + 1] == 0)
+			i1++;
+		j01 = J[i1 + 1] - 1;
+		J[i1] = j01;
+		change(file1, f1, file2, f2, i0, i1, j00, j01);
+	}
+	if (m == 0) {
+		change(file1, f1, file2, f2, 1, 0, 1, len[1]);
+	}
+	if (anychange != 0) {
+		dump_unified_vec(f1, f2);
+	}
+}
+
+/*
+ *      The following code uses an algorithm due to Harold Stone, 
+ *      which finds a pair of longest identical subsequences in 
+ *      the two files.
+ *
+ *      The major goal is to generate the match vector J.
+ *      J[i] is the index of the line in file1 corresponding
+ *      to line i file0. J[i] = 0 if there is no
+ *      such line in file1.
+ *
+ *      Lines are hashed so as to work in core. All potential
+ *      matches are located by sorting the lines of each file
+ *      on the hash (called ``value''). In particular, this
+ *      collects the equivalence classes in file1 together.
+ *      Subroutine equiv replaces the value of each line in
+ *      file0 by the index of the first element of its
+ *      matching equivalence in (the reordered) file1.
+ *      To save space equiv squeezes file1 into a single
+ *      array member in which the equivalence classes
+ *      are simply concatenated, except that their first
+ *      members are flagged by changing sign.
+ *
+ *      Next the indices that point into member are unsorted into
+ *      array class according to the original order of file0.
+ *
+ *      The cleverness lies in routine stone. This marches
+ *      through the lines of file0, developing a vector klist
+ *      of "k-candidates". At step i a k-candidate is a matched
+ *      pair of lines x,y (x in file0 y in file1) such that
+ *      there is a common subsequence of length k
+ *      between the first i lines of file0 and the first y
+ *      lines of file1, but there is no such subsequence for
+ *      any smaller y. x is the earliest possible mate to y
+ *      that occurs in such a subsequence.
+ *
+ *      Whenever any of the members of the equivalence class of
+ *      lines in file1 matable to a line in file0 has serial number
+ *      less than the y of some k-candidate, that k-candidate
+ *      with the smallest such y is replaced. The new
+ *      k-candidate is chained (via pred) to the current
+ *      k-1 candidate so that the actual subsequence can
+ *      be recovered. When a member has serial number greater
+ *      that the y of all k-candidates, the klist is extended.
+ *      At the end, the longest subsequence is pulled out
+ *      and placed in the array J by unravel
+ *
+ *      With J in hand, the matches there recorded are
+ *      checked against reality to assure that no spurious
+ *      matches have crept in due to hashing. If they have,
+ *      they are broken, and "jackpot" is recorded--a harmless
+ *      matter except that a true match for a spuriously
+ *      mated line may now be unnecessarily reported as a change.
+ *
+ *      Much of the complexity of the program comes simply
+ *      from trying to minimize core utilization and
+ *      maximize the range of doable problems by dynamically
+ *      allocating what is needed and reusing what is not.
+ *      The core requirements for problems larger than somewhat
+ *      are (in words) 2*length(file0) + length(file1) +
+ *      3*(number of k-candidates installed),  typically about
+ *      6n words for files of length n.
+ */
+
+static int diffreg(char *ofile1, char *ofile2, int flags)
+{
+	char *file1 = ofile1;
+	char *file2 = ofile2;
+	FILE *f1 = NULL;
+	FILE *f2 = NULL;
+	int rval = D_SAME;
+	int i;
+
+	anychange = 0;
+	context_vec_ptr = context_vec_start - 1;
+
+	if (S_ISDIR(stb1.st_mode) != S_ISDIR(stb2.st_mode))
+		return (S_ISDIR(stb1.st_mode) ? D_MISMATCH1 : D_MISMATCH2);
+	if (strcmp(file1, "-") == 0 && strcmp(file2, "-") == 0)
+		goto closem;
+
+	if (flags & D_EMPTY1)
+		f1 = bb_xfopen(bb_dev_null, "r");
+	else {
+		if (strcmp(file1, "-") == 0)
+			f1 = stdin;
+		else
+			f1 = bb_xfopen(file1, "r");
+	}
+
+	if (flags & D_EMPTY2)
+		f2 = bb_xfopen(bb_dev_null, "r");
+	else {
+		if (strcmp(file2, "-") == 0)
+			f2 = stdin;
+		else
+			f2 = bb_xfopen(file2, "r");
+	}
+
+	if ((i = files_differ(f1, f2, flags)) == 0)
+		goto closem;
+	else if (i != 1) {	/* 1 == ok */
+		/* error */
+		status |= 2;
+		goto closem;
+	}
+
+	if (!asciifile(f1) || !asciifile(f2)) {
+		rval = D_BINARY;
+		status |= 1;
+		goto closem;
+	}
+
+	prepare(0, f1, stb1.st_size);
+	prepare(1, f2, stb2.st_size);
+	prune();
+	sort(sfile[0], slen[0]);
+	sort(sfile[1], slen[1]);
+
+	member = (int *) file[1];
+	equiv(sfile[0], slen[0], sfile[1], slen[1], member);
+	member = xrealloc(member, (slen[1] + 2) * sizeof(int));
+
+	class = (int *) file[0];
+	unsort(sfile[0], slen[0], class);
+	class = xrealloc(class, (slen[0] + 2) * sizeof(int));
+
+	klist = xmalloc((slen[0] + 2) * sizeof(int));
+	clen = 0;
+	clistlen = 100;
+	clist = xmalloc(clistlen * sizeof(struct cand));
+	i = stone(class, slen[0], member, klist);
+	free(member);
+	free(class);
+
+	J = xrealloc(J, (len[0] + 2) * sizeof(int));
+	unravel(klist[i]);
+	free(clist);
+	free(klist);
+
+	ixold = xrealloc(ixold, (len[0] + 2) * sizeof(long));
+	ixnew = xrealloc(ixnew, (len[1] + 2) * sizeof(long));
+	check(f1, f2);
+	output(file1, f1, file2, f2);
+
+  closem:
+	if (anychange) {
+		status |= 1;
+		if (rval == D_SAME)
+			rval = D_DIFFER;
+	}
+	if (f1 != NULL)
+		fclose(f1);
+	if (f2 != NULL)
+		fclose(f2);
+	if (file1 != ofile1)
+		free(file1);
+	if (file2 != ofile2)
+		free(file2);
+	return (rval);
+}
+
+#if ENABLE_FEATURE_DIFF_DIR
+static void do_diff(char *dir1, char *path1, char *dir2, char *path2)
+{
+
+	int flags = D_HEADER;
+	int val;
+
+	char *fullpath1 = bb_xasprintf("%s/%s", dir1, path1);
+	char *fullpath2 = bb_xasprintf("%s/%s", dir2, path2);
+
+	if (stat(fullpath1, &stb1) != 0) {
+		flags |= D_EMPTY1;
+		memset(&stb1, 0, sizeof(stb1));
+		fullpath1 = bb_xasprintf("%s/%s", dir1, path2);
+	}
+	if (stat(fullpath2, &stb2) != 0) {
+		flags |= D_EMPTY2;
+		memset(&stb2, 0, sizeof(stb2));
+		stb2.st_mode = stb1.st_mode;
+		fullpath2 = bb_xasprintf("%s/%s", dir2, path1);
+	}
+
+	if (stb1.st_mode == 0)
+		stb1.st_mode = stb2.st_mode;
+
+	if (S_ISDIR(stb1.st_mode) && S_ISDIR(stb2.st_mode)) {
+		printf("Common subdirectories: %s and %s\n", fullpath1, fullpath2);
+		return;
+	}
+
+	if (!S_ISREG(stb1.st_mode) && !S_ISDIR(stb1.st_mode))
+		val = D_SKIPPED1;
+	else if (!S_ISREG(stb2.st_mode) && !S_ISDIR(stb2.st_mode))
+		val = D_SKIPPED2;
+	else
+		val = diffreg(fullpath1, fullpath2, flags);
+
+	print_status(val, fullpath1, fullpath2, NULL);
+}
+#endif
+
+#if ENABLE_FEATURE_DIFF_DIR
+static int dir_strcmp(const void *p1, const void *p2)
+{
+	return strcmp(*(char *const *) p1, *(char *const *) p2);
+}
+
+/* This function adds a filename to dl, the directory listing. */
+
+static int add_to_dirlist(const char *filename,
+						  struct stat ATTRIBUTE_UNUSED * sb, void *userdata)
+{
+	dl_count++;
+	dl = xrealloc(dl, dl_count * sizeof(char *));
+	dl[dl_count - 1] = bb_xstrdup(filename);
+	if (cmd_flags & FLAG_r) {
+		int *pp = (int *) userdata;
+		int path_len = *pp + 1;
+
+		dl[dl_count - 1] = &(dl[dl_count - 1])[path_len];
+	}
+	return TRUE;
+}
+
+/* This returns a sorted directory listing. */
+static char **get_dir(char *path)
+{
+
+	int i;
+	char **retval;
+
+	/* If -r has been set, then the recursive_action function will be
+	 * used. Unfortunately, this outputs the root directory along with
+	 * the recursed paths, so use void *userdata to specify the string
+	 * length of the root directory. It can then be removed in
+	 * add_to_dirlist. */
+
+	int path_len = strlen(path);
+	void *userdata = &path_len;
+
+	/* Reset dl_count - there's no need to free dl as bb_xrealloc does
+	 * the job nicely. */
+	dl_count = 0;
+
+	/* Now fill dl with a listing. */
+	if (cmd_flags & FLAG_r)
+		recursive_action(path, TRUE, TRUE, FALSE, add_to_dirlist, NULL,
+						 userdata);
+	else {
+		DIR *dp;
+		struct dirent *ep;
+
+		dp = bb_opendir(path);
+		while ((ep = readdir(dp))) {
+			if ((!strcmp(ep->d_name, "..")) || (!strcmp(ep->d_name, ".")))
+				continue;
+			add_to_dirlist(ep->d_name, NULL, NULL);
+		}
+		closedir(dp);
+	}
+
+	/* Sort dl alphabetically. */
+	qsort(dl, dl_count, sizeof(char *), dir_strcmp);
+
+	/* Copy dl so that we can return it. */
+	retval = xmalloc(dl_count * sizeof(char *));
+	for (i = 0; i < dl_count; i++)
+		retval[i] = bb_xstrdup(dl[i]);
+
+	return retval;
+}
+
+static void diffdir(char *p1, char *p2)
+{
+
+	char **dirlist1, **dirlist2;
+	char *dp1, *dp2;
+	int dirlist1_count, dirlist2_count;
+	int pos;
+
+	/* Check for trailing slashes. */
+
+	if (p1[strlen(p1) - 1] == '/')
+		p1[strlen(p1) - 1] = '\0';
+	if (p2[strlen(p2) - 1] == '/')
+		p2[strlen(p2) - 1] = '\0';
+
+	/* Get directory listings for p1 and p2. */
+
+	dirlist1 = get_dir(p1);
+	dirlist1_count = dl_count;
+	dirlist1[dirlist1_count] = NULL;
+	dirlist2 = get_dir(p2);
+	dirlist2_count = dl_count;
+	dirlist2[dirlist2_count] = NULL;
+
+	/* If -S was set, find the starting point. */
+	if (start) {
+		while (*dirlist1 != NULL && strcmp(*dirlist1, start) < 0)
+			dirlist1++;
+		while (*dirlist2 != NULL && strcmp(*dirlist2, start) < 0)
+			dirlist2++;
+		if ((*dirlist1 == NULL) || (*dirlist2 == NULL))
+			bb_error_msg(bb_msg_invalid_arg, "NULL", "-S");
+	}
+
+	/* Now that both dirlist1 and dirlist2 contain sorted directory
+	 * listings, we can start to go through dirlist1. If both listings
+	 * contain the same file, then do a normal diff. Otherwise, behaviour
+	 * is determined by whether the -N flag is set. */
+	while (*dirlist1 != NULL || *dirlist2 != NULL) {
+		dp1 = *dirlist1;
+		dp2 = *dirlist2;
+		pos = dp1 == NULL ? 1 : dp2 == NULL ? -1 : strcmp(dp1, dp2);
+		if (pos == 0) {
+			do_diff(p1, dp1, p2, dp2);
+			dirlist1++;
+			dirlist2++;
+		} else if (pos < 0) {
+			if (cmd_flags & FLAG_N)
+				do_diff(p1, dp1, p2, NULL);
+			else
+				print_only(p1, strlen(p1) + 1, dp1);
+			dirlist1++;
+		} else {
+			if (cmd_flags & FLAG_N)
+				do_diff(p1, NULL, p2, dp2);
+			else
+				print_only(p2, strlen(p2) + 1, dp2);
+			dirlist2++;
+		}
+	}
+}
+#endif
+
+
+
+int diff_main(int argc, char **argv)
+{
+	int gotstdin = 0;
+
+	char *U_opt;
+	llist_t *L_arg = NULL;
+
+	bb_opt_complementally = "L::";
+	cmd_flags =
+		bb_getopt_ulflags(argc, argv, "abdiL:NqrsS:tTU:wu", &L_arg, &start,
+						  &U_opt);
+
+	if (cmd_flags & FLAG_L) {
+		while (L_arg) {
+			if (label[0] == NULL)
+				label[0] = L_arg->data;
+			else if (label[1] == NULL)
+				label[1] = L_arg->data;
+			else
+				bb_show_usage();
+
+			L_arg = L_arg->link;
+		}
+
+		/* If both label[0] and label[1] were set, they need to be swapped. */
+		if (label[0] && label[1]) {
+			char *tmp;
+
+			tmp = label[1];
+			label[1] = label[0];
+			label[0] = tmp;
+		}
+	}
+
+	context = 3;		/* This is the default number of lines of context. */
+	if (cmd_flags & FLAG_U) {
+		context = bb_xgetlarg(U_opt, 10, 1, INT_MAX);
+	}
+	argc -= optind;
+	argv += optind;
+
+	/*
+	 * Do sanity checks, fill in stb1 and stb2 and call the appropriate
+	 * driver routine.  Both drivers use the contents of stb1 and stb2.
+	 */
+	if (argc < 2) {
+		bb_error_msg("Missing filename");
+		bb_show_usage();
+	}
+	if (strcmp(argv[0], "-") == 0) {
+		fstat(STDIN_FILENO, &stb1);
+		gotstdin = 1;
+	} else
+		xstat(argv[0], &stb1);
+	if (strcmp(argv[1], "-") == 0) {
+		fstat(STDIN_FILENO, &stb2);
+		gotstdin = 1;
+	} else
+		xstat(argv[1], &stb2);
+	if (gotstdin && (S_ISDIR(stb1.st_mode) || S_ISDIR(stb2.st_mode)))
+		bb_error_msg_and_die("Can't compare - to a directory");
+	if (S_ISDIR(stb1.st_mode) && S_ISDIR(stb2.st_mode)) {
+#if ENABLE_FEATURE_DIFF_DIR
+		diffdir(argv[0], argv[1]);
+#else
+		bb_error_msg_and_die("Directory comparison not supported");
+#endif
+	} else {
+		if (S_ISDIR(stb1.st_mode)) {
+			argv[0] = concat_path_file(argv[0], argv[1]);
+			xstat(argv[0], &stb1);
+		}
+		if (S_ISDIR(stb2.st_mode)) {
+			argv[1] = concat_path_file(argv[1], argv[0]);
+			xstat(argv[1], &stb2);
+		}
+		print_status(diffreg(argv[0], argv[1], 0), argv[0], argv[1], NULL);
+	}
+	exit(status);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/dirname.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/dirname.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/dirname.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,39 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini dirname implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/dirname.html */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+int dirname_main(int argc, char **argv)
+{
+	if (argc != 2) {
+		bb_show_usage();
+	}
+
+	puts(dirname(argv[1]));
+
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/dos2unix.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/dos2unix.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/dos2unix.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,119 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * dos2unix for BusyBox
+ *
+ * dos2unix '\n' convertor 0.5.0
+ * based on Unix2Dos 0.9.0 by Peter Hanecak (made 19.2.1997)
+ * Copyright 1997,.. by Peter Hanecak <hanecak at megaloman.sk>.
+ * All rights reserved.
+ *
+ * dos2unix filters reading input from stdin and writing output to stdout.
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+*/
+
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include "busybox.h"
+
+enum ConvType {
+	CT_UNIX2DOS = 1,
+	CT_DOS2UNIX
+} ConvType;
+
+/* if fn is NULL then input is stdin and output is stdout */
+static int convert(char *fn)
+{
+	FILE *in, *out;
+	int i;
+
+	if (fn != NULL) {
+		in = bb_xfopen(fn, "rw");
+		/*
+		   The file is then created with mode read/write and
+		   permissions 0666 for glibc 2.0.6 and earlier or
+		   0600  for glibc  2.0.7 and  later.
+		 */
+		snprintf(bb_common_bufsiz1, sizeof(bb_common_bufsiz1), "%sXXXXXX", fn);
+		/*
+		   sizeof bb_common_bufsiz1 is 4096, so it should be big enough to
+		   hold the full path.  However if the output is truncated the
+		   subsequent call to mkstemp would fail.
+		 */
+		if ((i = mkstemp(&bb_common_bufsiz1[0])) == -1
+			|| chmod(bb_common_bufsiz1, 0600) == -1) {
+			bb_perror_nomsg_and_die();
+		}
+		out = fdopen(i, "w+");
+		if (!out) {
+			close(i);
+			remove(bb_common_bufsiz1);
+		}
+	} else {
+		in = stdin;
+		out = stdout;
+	}
+
+	while ((i = fgetc(in)) != EOF) {
+		if (i == '\r')
+			continue;
+		if (i == '\n') {
+			if (ConvType == CT_UNIX2DOS)
+				fputc('\r', out);
+			fputc('\n', out);
+			continue;
+		}
+		fputc(i, out);
+	}
+
+	if (fn != NULL) {
+		if (fclose(in) < 0 || fclose(out) < 0) {
+			bb_perror_nomsg();
+			remove(bb_common_bufsiz1);
+			return -2;
+		}
+		/* Assume they are both on the same filesystem (which
+		 * should be true since we put them into the same directory
+		 * so we _should_ be ok, but you never know... */
+		if (rename(bb_common_bufsiz1, fn) < 0) {
+			bb_perror_msg("cannot rename '%s' as '%s'", bb_common_bufsiz1, fn);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+int dos2unix_main(int argc, char *argv[])
+{
+	int o;
+
+	/* See if we are supposed to be doing dos2unix or unix2dos */
+	if (bb_applet_name[0] == 'd') {
+		ConvType = CT_DOS2UNIX;	/*2 */
+	} else {
+		ConvType = CT_UNIX2DOS;	/*1 */
+	}
+	/* -u and -d are mutally exclusive */
+	bb_opt_complementally = "?:u--d:d--u";
+	/* process parameters */
+	/* -u convert to unix */
+	/* -d convert to dos  */
+	o = bb_getopt_ulflags(argc, argv, "du");
+
+	/* Do the conversion requested by an argument else do the default
+	 * conversion depending on our name.  */
+	if (o)
+		ConvType = o;
+
+	if (optind < argc) {
+		while (optind < argc)
+			if ((o = convert(argv[optind++])) < 0)
+				break;
+	} else
+		o = convert(NULL);
+
+	return o;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/du.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/du.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/du.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,255 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini du implementation for busybox
+ *
+ * Copyright (C) 1999,2000,2001 by Lineo, inc. and John Beppu
+ * Copyright (C) 1999,2000,2001 by John Beppu <beppu at codepoet.org>
+ * Copyright (C) 2002  Edward Betts <edward at debian.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 compliant (unless default blocksize set to 1k) */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/du.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Mostly rewritten for SUSv3 compliance and to fix bugs/defects.
+ * 1) Added support for SUSv3 -a, -H, -L, gnu -c, and (busybox) -d options.
+ *    The -d option allows setting of max depth (similar to gnu --max-depth).
+ * 2) Fixed incorrect size calculations for links and directories, especially
+ *    when errors occurred.  Calculates sizes should now match gnu du output.
+ * 3) Added error checking of output.
+ * 4) Fixed busybox bug #1284 involving long overflow with human_readable.
+ */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include "busybox.h"
+
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+# ifdef CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
+static unsigned long disp_hr = KILOBYTE;
+# else
+static unsigned long disp_hr = 512;
+# endif
+#elif defined CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
+static unsigned int disp_k = 1;
+#else
+static unsigned int disp_k;	/* bss inits to 0 */
+#endif
+
+static int max_print_depth = INT_MAX;
+static nlink_t count_hardlinks = 1;
+
+static int status
+#if EXIT_SUCCESS == 0
+	= EXIT_SUCCESS
+#endif
+	;
+static int print_files;
+static int slink_depth;
+static int du_depth;
+static int one_file_system;
+static dev_t dir_dev;
+
+
+static void print(long size, char *filename)
+{
+	/* TODO - May not want to defer error checking here. */
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+	bb_printf("%s\t%s\n", make_human_readable_str(size, 512, disp_hr),
+		   filename);
+#else
+	if (disp_k) {
+		size++;
+		size >>= 1;
+	}
+	bb_printf("%ld\t%s\n", size, filename);
+#endif
+}
+
+/* tiny recursive du */
+static long du(char *filename)
+{
+	struct stat statbuf;
+	long sum;
+
+	if ((lstat(filename, &statbuf)) != 0) {
+		bb_perror_msg("%s", filename);
+		status = EXIT_FAILURE;
+		return 0;
+	}
+
+	if (one_file_system) {
+		if (du_depth == 0) {
+			dir_dev = statbuf.st_dev;
+		} else if (dir_dev != statbuf.st_dev) {
+			return 0;
+		}
+	}
+
+	sum = statbuf.st_blocks;
+
+	if (S_ISLNK(statbuf.st_mode)) {
+		if (slink_depth > du_depth) {	/* -H or -L */
+			if ((stat(filename, &statbuf)) != 0) {
+				bb_perror_msg("%s", filename);
+				status = EXIT_FAILURE;
+				return 0;
+			}
+			sum = statbuf.st_blocks;
+			if (slink_depth == 1) {
+				slink_depth = INT_MAX;	/* Convert -H to -L. */
+			}
+		}
+	}
+
+	if (statbuf.st_nlink > count_hardlinks) {
+		/* Add files/directories with links only once */
+		if (is_in_ino_dev_hashtable(&statbuf, NULL)) {
+			return 0;
+		}
+		add_to_ino_dev_hashtable(&statbuf, NULL);
+	}
+
+	if (S_ISDIR(statbuf.st_mode)) {
+		DIR *dir;
+		struct dirent *entry;
+		char *newfile;
+
+		dir = bb_opendir(filename);
+		if (!dir) {
+			status = EXIT_FAILURE;
+			return sum;
+		}
+
+		newfile = last_char_is(filename, '/');
+		if (newfile)
+			*newfile = '\0';
+
+		while ((entry = readdir(dir))) {
+			char *name = entry->d_name;
+
+			newfile = concat_subpath_file(filename, name);
+			if(newfile == NULL)
+				continue;
+			++du_depth;
+			sum += du(newfile);
+			--du_depth;
+			free(newfile);
+		}
+		closedir(dir);
+	} else if (du_depth > print_files) {
+		return sum;
+	}
+	if (du_depth <= max_print_depth) {
+		print(sum, filename);
+	}
+	return sum;
+}
+
+int du_main(int argc, char **argv)
+{
+	long total;
+	int slink_depth_save;
+	int print_final_total;
+	char *smax_print_depth;
+	unsigned long opt;
+
+#ifdef CONFIG_FEATURE_DU_DEFUALT_BLOCKSIZE_1K
+	if (getenv("POSIXLY_CORRECT")) {	/* TODO - a new libbb function? */
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+		disp_hr = 512;
+#else
+		disp_k = 0;
+#endif
+	}
+#endif
+
+	/* Note: SUSv3 specifies that -a and -s options can not be used together
+	 * in strictly conforming applications.  However, it also says that some
+	 * du implementations may produce output when -a and -s are used together.
+	 * gnu du exits with an error code in this case.  We choose to simply
+	 * ignore -a.  This is consistent with -s being equivalent to -d 0.
+	 */
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+	bb_opt_complementally = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s";
+	opt = bb_getopt_ulflags(argc, argv, "aHkLsx" "d:" "lc" "hm", &smax_print_depth);
+	if((opt & (1 << 9))) {
+		/* -h opt */
+		disp_hr = 0;
+	}
+	if((opt & (1 << 10))) {
+		/* -m opt */
+		disp_hr = MEGABYTE;
+	}
+	if((opt & (1 << 2))) {
+		/* -k opt */
+			disp_hr = KILOBYTE;
+	}
+#else
+	bb_opt_complementally = "H-L:L-H:s-d:d-s";
+	opt = bb_getopt_ulflags(argc, argv, "aHkLsx" "d:" "lc", &smax_print_depth);
+#if !defined CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
+	if((opt & (1 << 2))) {
+		/* -k opt */
+			disp_k = 1;
+	}
+#endif
+#endif
+	if((opt & (1 << 0))) {
+		/* -a opt */
+		print_files = INT_MAX;
+	}
+	if((opt & (1 << 1))) {
+		/* -H opt */
+		slink_depth = 1;
+	}
+	if((opt & (1 << 3))) {
+		/* -L opt */
+			slink_depth = INT_MAX;
+	}
+	if((opt & (1 << 4))) {
+		/* -s opt */
+			max_print_depth = 0;
+		}
+	one_file_system = opt & (1 << 5); /* -x opt */
+	if((opt & (1 << 6))) {
+		/* -d opt */
+		max_print_depth = bb_xgetularg10_bnd(smax_print_depth, 0, INT_MAX);
+	}
+	if((opt & (1 << 7))) {
+		/* -l opt */
+		count_hardlinks = INT_MAX;
+	}
+	print_final_total = opt & (1 << 8); /* -c opt */
+
+	/* go through remaining args (if any) */
+	argv += optind;
+	if (optind >= argc) {
+		*--argv = ".";
+		if (slink_depth == 1) {
+			slink_depth = 0;
+		}
+	}
+
+	slink_depth_save = slink_depth;
+	total = 0;
+	do {
+		total += du(*argv);
+		slink_depth = slink_depth_save;
+	} while (*++argv);
+#ifdef CONFIG_FEATURE_CLEAN_UP
+	reset_ino_dev_hashtable();
+#endif
+
+	if (print_final_total) {
+		print(total, "total");
+	}
+
+	bb_fflush_stdout_and_exit(status);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/echo.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/echo.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/echo.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,158 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * echo implementation for busybox
+ *
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * Original copyright notice is retained at the end of this file.
+ */
+
+/* BB_AUDIT SUSv3 compliant -- unless configured as fancy echo. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/echo.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Because of behavioral differences, implemented configurable SUSv3
+ * or 'fancy' gnu-ish behaviors.  Also, reduced size and fixed bugs.
+ * 1) In handling '\c' escape, the previous version only suppressed the
+ *     trailing newline.  SUSv3 specifies _no_ output after '\c'.
+ * 2) SUSv3 specifies that octal escapes are of the form \0{#{#{#}}}.
+ *    The previous version version did not allow 4-digit octals.
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+int bb_echo(int ATTRIBUTE_UNUSED argc, char **argv)
+{
+#ifndef CONFIG_FEATURE_FANCY_ECHO
+#define eflag '\\'
+	++argv;
+#else
+	const char *p;
+	int nflag = 1;
+	int eflag = 0;
+
+	while (*++argv && (**argv == '-')) {
+		/* If it appears that we are handling options, then make sure
+		 * that all of the options specified are actually valid.
+		 * Otherwise, the string should just be echoed.
+		 */
+
+		if (!*(p = *argv + 1)) {	/* A single '-', so echo it. */
+			goto just_echo;
+		}
+
+		do {
+			if (strrchr("neE", *p) == 0) {
+				goto just_echo;
+			}
+		} while (*++p);
+
+		/* All of the options in this arg are valid, so handle them. */
+		p = *argv + 1;
+		do {
+			if (*p == 'n') {
+				nflag = 0;
+			} else if (*p == 'e') {
+				eflag = '\\';
+			} else {
+				eflag = 0;
+			}
+		} while (*++p);
+	}
+
+just_echo:
+#endif
+	while (*argv) {
+		register int c;
+
+		while ((c = *(*argv)++)) {
+			if (c == eflag) {	/* Check for escape seq. */
+				if (**argv == 'c') {
+					/* '\c' means cancel newline and
+					 * ignore all subsequent chars. */
+					return 0;
+				}
+#ifndef CONFIG_FEATURE_FANCY_ECHO
+				/* SUSv3 specifies that octal escapes must begin with '0'. */
+				if (((unsigned int)(**argv - '1')) >= 7)
+#endif
+				{
+					/* Since SUSv3 mandates a first digit of 0, 4-digit octals
+					* of the form \0### are accepted. */
+					if ((**argv == '0') && (((unsigned int)(argv[0][1] - '0')) < 8)) {
+						(*argv)++;
+					}
+					/* bb_process_escape_sequence can handle nul correctly */
+					c = bb_process_escape_sequence((const char **) argv);
+				}
+			}
+			putchar(c);
+		}
+
+		if (*++argv) {
+			putchar(' ');
+		}
+	}
+
+#ifdef CONFIG_FEATURE_FANCY_ECHO
+	if (nflag) {
+		putchar('\n');
+	}
+#else
+	putchar('\n');
+#endif
+	return 0;
+}
+
+int echo_main(int argc, char** argv)
+{
+	(void)bb_echo(argc, argv);
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
+ *		ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
+ *
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)echo.c	8.1 (Berkeley) 5/31/93
+ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/env.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/env.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/env.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,146 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * env implementation for busybox
+ *
+ * Copyright (c) 1988, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Original copyright notice is retained at the end of this file.
+ *
+ * Modified for BusyBox by Erik Andersen <andersen at codepoet.org>
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/env.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Fixed bug involving exit return codes if execvp fails.  Also added
+ * output error checking.
+ */
+
+/*
+ * Modified by Vladimir Oleynik <dzo at simtreas.ru> (C) 2003
+ * - correct "-" option usage
+ * - multiple "-u unsetenv" support
+ * - GNU long option support
+ * - use bb_default_error_retval
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <getopt.h> /* struct option */
+#include "busybox.h"
+
+#if ENABLE_FEATURE_ENV_LONG_OPTIONS
+static const struct option env_long_options[] = {
+	{ "ignore-environment", 0, NULL, 'i' },
+	{ "unset", 1, NULL, 'u' },
+	{ 0, 0, 0, 0 }
+};
+#endif
+
+int env_main(int argc, char** argv)
+{
+	static char *cleanenv[1] = { NULL };
+
+	char **ep, *p;
+	unsigned long opt;
+	llist_t *unset_env = NULL;
+	extern char **environ;
+
+	bb_opt_complementally = "u::";
+#if ENABLE_FEATURE_ENV_LONG_OPTIONS
+	bb_applet_long_options = env_long_options;
+#endif
+
+	opt = bb_getopt_ulflags(argc, argv, "+iu:", &unset_env);
+
+	argv += optind;
+	if (*argv && (argv[0][0] == '-') && !argv[0][1]) {
+		opt |= 1;
+		++argv;
+	}
+
+	if(opt & 1)
+		environ = cleanenv;
+	else if(opt & 2) {
+		while(unset_env) {
+			unsetenv(unset_env->data);
+			unset_env = unset_env->link;
+		}
+	}
+
+	while (*argv && ((p = strchr(*argv, '=')) != NULL)) {
+		if (putenv(*argv) < 0) {
+			bb_perror_msg_and_die("putenv");
+		}
+		++argv;
+	}
+
+	if (*argv) {
+		execvp(*argv, argv);
+		/* SUSv3-mandated exit codes. */
+		bb_default_error_retval = (errno == ENOENT) ? 127 : 126;
+		bb_perror_msg_and_die("%s", *argv);
+	}
+
+	for (ep = environ; *ep; ep++) {
+		puts(*ep);
+	}
+
+	bb_fflush_stdout_and_exit(0);
+}
+
+/*
+ * Copyright (c) 1988, 1993, 1994
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
+ *		ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
+ *
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/expr.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/expr.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/expr.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,538 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini expr implementation for busybox
+ *
+ * based on GNU expr Mike Parker.
+ * Copyright (C) 86, 1991-1997, 1999 Free Software Foundation, Inc.
+ *
+ * Busybox modifications
+ * Copyright (c) 2000  Edward Betts <edward at debian.org>.
+ * Copyright (C) 2003-2005  Vladimir Oleynik <dzo at simtreas.ru>
+ *  - reduced 464 bytes.
+ *  - 64 math support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* This program evaluates expressions.  Each token (operator, operand,
+ * parenthesis) of the expression must be a separate argument.  The
+ * parser used is a reasonably general one, though any incarnation of
+ * it is language-specific.  It is especially nice for expressions.
+ *
+ * No parse tree is needed; a new node is evaluated immediately.
+ * One function can handle multiple operators all of equal precedence,
+ * provided they all associate ((x op x) op x). */
+
+/* no getopt needed */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <regex.h>
+#include <sys/types.h>
+#include <errno.h>
+#include "busybox.h"
+
+
+/* The kinds of value we can have.  */
+enum valtype {
+	integer,
+	string
+};
+typedef enum valtype TYPE;
+
+#if ENABLE_EXPR_MATH_SUPPORT_64
+typedef int64_t arith_t;
+#define PF_REZ      "ll"
+#define PF_REZ_TYPE (long long)
+#define STRTOL(s, e, b) strtoll(s, e, b)
+#else
+typedef long arith_t;
+#define PF_REZ      "l"
+#define PF_REZ_TYPE (long)
+#define STRTOL(s, e, b) strtol(s, e, b)
+#endif
+
+/* A value is.... */
+struct valinfo {
+	TYPE type;                      /* Which kind. */
+	union {                         /* The value itself. */
+		arith_t i;
+		char *s;
+	} u;
+};
+typedef struct valinfo VALUE;
+
+/* The arguments given to the program, minus the program name.  */
+static char **args;
+
+static VALUE *docolon (VALUE *sv, VALUE *pv);
+static VALUE *eval (void);
+static VALUE *int_value (arith_t i);
+static VALUE *str_value (char *s);
+static int nextarg (char *str);
+static int null (VALUE *v);
+static int toarith (VALUE *v);
+static void freev (VALUE *v);
+static void tostring (VALUE *v);
+
+int expr_main (int argc, char **argv)
+{
+	VALUE *v;
+
+	if (argc == 1) {
+		bb_error_msg_and_die("too few arguments");
+	}
+
+	args = argv + 1;
+
+	v = eval ();
+	if (*args)
+		bb_error_msg_and_die ("syntax error");
+
+	if (v->type == integer)
+		printf ("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i);
+	else
+		puts (v->u.s);
+
+	exit (null (v));
+}
+
+/* Return a VALUE for I.  */
+
+static VALUE *int_value (arith_t i)
+{
+	VALUE *v;
+
+	v = xmalloc (sizeof(VALUE));
+	v->type = integer;
+	v->u.i = i;
+	return v;
+}
+
+/* Return a VALUE for S.  */
+
+static VALUE *str_value (char *s)
+{
+	VALUE *v;
+
+	v = xmalloc (sizeof(VALUE));
+	v->type = string;
+	v->u.s = bb_xstrdup (s);
+	return v;
+}
+
+/* Free VALUE V, including structure components.  */
+
+static void freev (VALUE *v)
+{
+	if (v->type == string)
+		free (v->u.s);
+	free (v);
+}
+
+/* Return nonzero if V is a null-string or zero-number.  */
+
+static int null (VALUE *v)
+{
+	switch (v->type) {
+		case integer:
+			return v->u.i == 0;
+		default: /* string: */
+			return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0;
+	}
+}
+
+/* Coerce V to a string value (can't fail).  */
+
+static void tostring (VALUE *v)
+{
+	if (v->type == integer) {
+		v->u.s = bb_xasprintf ("%" PF_REZ "d", PF_REZ_TYPE v->u.i);
+		v->type = string;
+	}
+}
+
+/* Coerce V to an integer value.  Return 1 on success, 0 on failure.  */
+
+static int toarith (VALUE *v)
+{
+	if(v->type == string) {
+		arith_t i;
+		char *e;
+
+		/* Don't interpret the empty string as an integer.  */
+		/* Currently does not worry about overflow or int/long differences. */
+		i = STRTOL(v->u.s, &e, 10);
+		if ((v->u.s == e) || *e)
+			return 0;
+		free (v->u.s);
+		v->u.i = i;
+		v->type = integer;
+	}
+	return 1;
+}
+
+/* Return nonzero if the next token matches STR exactly.
+   STR must not be NULL.  */
+
+static int
+nextarg (char *str)
+{
+	if (*args == NULL)
+		return 0;
+	return strcmp (*args, str) == 0;
+}
+
+/* The comparison operator handling functions.  */
+
+static int cmp_common (VALUE *l, VALUE *r, int op)
+{
+	int cmpval;
+
+	if (l->type == string || r->type == string) {
+		tostring (l);
+		tostring (r);
+		cmpval = strcmp (l->u.s, r->u.s);
+	}
+	else
+		cmpval = l->u.i - r->u.i;
+	switch(op) {
+		case '<':
+			return cmpval < 0;
+		case ('L'+'E'):
+			return cmpval <= 0;
+		case '=':
+			return cmpval == 0;
+		case '!':
+			return cmpval != 0;
+		case '>':
+			return cmpval > 0;
+		default: /* >= */
+			return cmpval >= 0;
+	}
+}
+
+/* The arithmetic operator handling functions.  */
+
+static arith_t arithmetic_common (VALUE *l, VALUE *r, int op)
+{
+  arith_t li, ri;
+
+  if (!toarith (l) || !toarith (r))
+    bb_error_msg_and_die ("non-numeric argument");
+  li = l->u.i;
+  ri = r->u.i;
+  if((op == '/' || op == '%') && ri == 0)
+    bb_error_msg_and_die ( "division by zero");
+  switch(op) {
+	case '+':
+		return li + ri;
+	case '-':
+		return li - ri;
+	case '*':
+		return li * ri;
+	case '/':
+		return li / ri;
+	default:
+		return li % ri;
+  }
+}
+
+/* Do the : operator.
+   SV is the VALUE for the lhs (the string),
+   PV is the VALUE for the rhs (the pattern).  */
+
+static VALUE *docolon (VALUE *sv, VALUE *pv)
+{
+	VALUE *v;
+	regex_t re_buffer;
+	const int NMATCH = 2;
+	regmatch_t re_regs[NMATCH];
+
+	tostring (sv);
+	tostring (pv);
+
+	if (pv->u.s[0] == '^') {
+		fprintf (stderr, "\
+warning: unportable BRE: `%s': using `^' as the first character\n\
+of a basic regular expression is not portable; it is being ignored",
+		pv->u.s);
+	}
+
+	memset (&re_buffer, 0, sizeof (re_buffer));
+	memset (re_regs, 0, sizeof (*re_regs));
+	if( regcomp (&re_buffer, pv->u.s, 0) != 0 )
+		bb_error_msg_and_die("Invalid regular expression");
+
+	/* expr uses an anchored pattern match, so check that there was a
+	 * match and that the match starts at offset 0. */
+	if (regexec (&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH &&
+			re_regs[0].rm_so == 0) {
+		/* Were \(...\) used? */
+		if (re_buffer.re_nsub > 0) {
+			sv->u.s[re_regs[1].rm_eo] = '\0';
+			v = str_value (sv->u.s + re_regs[1].rm_so);
+		}
+		else
+			v = int_value (re_regs[0].rm_eo);
+	}
+	else {
+		/* Match failed -- return the right kind of null.  */
+		if (re_buffer.re_nsub > 0)
+			v = str_value ("");
+		else
+			v = int_value (0);
+	}
+	return v;
+}
+
+/* Handle bare operands and ( expr ) syntax.  */
+
+static VALUE *eval7 (void)
+{
+	VALUE *v;
+
+	if (!*args)
+		bb_error_msg_and_die ( "syntax error");
+
+	if (nextarg ("(")) {
+		args++;
+		v = eval ();
+		if (!nextarg (")"))
+			bb_error_msg_and_die ( "syntax error");
+			args++;
+			return v;
+		}
+
+	if (nextarg (")"))
+		bb_error_msg_and_die ( "syntax error");
+
+	return str_value (*args++);
+}
+
+/* Handle match, substr, index, length, and quote keywords.  */
+
+static VALUE *eval6 (void)
+{
+	VALUE *l, *r, *v, *i1, *i2;
+
+	if (nextarg ("quote")) {
+		args++;
+		if (!*args)
+			bb_error_msg_and_die ( "syntax error");
+		return str_value (*args++);
+	}
+	else if (nextarg ("length")) {
+		args++;
+		r = eval6 ();
+		tostring (r);
+		v = int_value (strlen (r->u.s));
+		freev (r);
+		return v;
+	}
+	else if (nextarg ("match")) {
+		args++;
+		l = eval6 ();
+		r = eval6 ();
+		v = docolon (l, r);
+		freev (l);
+		freev (r);
+		return v;
+	}
+	else if (nextarg ("index")) {
+		args++;
+		l = eval6 ();
+		r = eval6 ();
+		tostring (l);
+		tostring (r);
+		v = int_value (strcspn (l->u.s, r->u.s) + 1);
+		if (v->u.i == (arith_t) strlen (l->u.s) + 1)
+			v->u.i = 0;
+		freev (l);
+		freev (r);
+		return v;
+	}
+	else if (nextarg ("substr")) {
+		args++;
+		l = eval6 ();
+		i1 = eval6 ();
+		i2 = eval6 ();
+		tostring (l);
+		if (!toarith (i1) || !toarith (i2)
+			|| i1->u.i > (arith_t) strlen (l->u.s)
+			|| i1->u.i <= 0 || i2->u.i <= 0)
+		v = str_value ("");
+		else {
+			v = xmalloc (sizeof(VALUE));
+			v->type = string;
+			v->u.s = bb_xstrndup(l->u.s + i1->u.i - 1, i2->u.i);
+		}
+		freev (l);
+		freev (i1);
+		freev (i2);
+		return v;
+	}
+	else
+		return eval7 ();
+}
+
+/* Handle : operator (pattern matching).
+   Calls docolon to do the real work.  */
+
+static VALUE *eval5 (void)
+{
+	VALUE *l, *r, *v;
+
+	l = eval6 ();
+	while (nextarg (":")) {
+		args++;
+		r = eval6 ();
+		v = docolon (l, r);
+		freev (l);
+		freev (r);
+		l = v;
+	}
+	return l;
+}
+
+/* Handle *, /, % operators.  */
+
+static VALUE *eval4 (void)
+{
+	VALUE *l, *r;
+	int op;
+	arith_t val;
+
+	l = eval5 ();
+	while (1) {
+		if (nextarg ("*"))
+			op = '*';
+		else if (nextarg ("/"))
+			op = '/';
+		else if (nextarg ("%"))
+			op = '%';
+		else
+			return l;
+		args++;
+		r = eval5 ();
+		val = arithmetic_common (l, r, op);
+		freev (l);
+		freev (r);
+		l = int_value (val);
+	}
+}
+
+/* Handle +, - operators.  */
+
+static VALUE *eval3 (void)
+{
+	VALUE *l, *r;
+	int op;
+	arith_t val;
+
+	l = eval4 ();
+	while (1) {
+		if (nextarg ("+"))
+			op = '+';
+		else if (nextarg ("-"))
+			op = '-';
+		else
+			return l;
+		args++;
+		r = eval4 ();
+		val = arithmetic_common (l, r, op);
+		freev (l);
+		freev (r);
+		l = int_value (val);
+	}
+}
+
+/* Handle comparisons.  */
+
+static VALUE *eval2 (void)
+{
+	VALUE *l, *r;
+	int op;
+	arith_t val;
+
+	l = eval3 ();
+	while (1) {
+		if (nextarg ("<"))
+			op = '<';
+		else if (nextarg ("<="))
+			op = 'L'+'E';
+		else if (nextarg ("=") || nextarg ("=="))
+			op = '=';
+		else if (nextarg ("!="))
+			op = '!';
+		else if (nextarg (">="))
+			op = 'G'+'E';
+		else if (nextarg (">"))
+			op = '>';
+		else
+			return l;
+		args++;
+		r = eval3 ();
+		toarith (l);
+		toarith (r);
+		val = cmp_common (l, r, op);
+		freev (l);
+		freev (r);
+		l = int_value (val);
+	}
+}
+
+/* Handle &.  */
+
+static VALUE *eval1 (void)
+{
+	VALUE *l, *r;
+
+	l = eval2 ();
+	while (nextarg ("&")) {
+		args++;
+		r = eval2 ();
+		if (null (l) || null (r)) {
+			freev (l);
+			freev (r);
+			l = int_value (0);
+		}
+		else
+			freev (r);
+	}
+	return l;
+}
+
+/* Handle |.  */
+
+static VALUE *eval (void)
+{
+	VALUE *l, *r;
+
+	l = eval1 ();
+	while (nextarg ("|")) {
+		args++;
+		r = eval1 ();
+		if (null (l)) {
+			freev (l);
+			l = r;
+		}
+		else
+			freev (r);
+	}
+	return l;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/false.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/false.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/false.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,19 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini false implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/false.html */
+
+#include <stdlib.h>
+#include "busybox.h"
+
+int false_main(int ATTRIBUTE_UNUSED argc, char ATTRIBUTE_UNUSED **argv)
+{
+	return EXIT_FAILURE;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/fold.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/fold.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/fold.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,161 @@
+/* fold -- wrap each input line to fit in specified width.
+
+   Written by David MacKenzie, djm at gnu.ai.mit.edu.
+   Copyright (C) 91, 1995-2002 Free Software Foundation, Inc.
+
+   Modified for busybox based on coreutils v 5.0
+   Copyright (C) 2003 Glenn McGrath <bug1 at iinet.net.au>
+
+   Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+*/
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "busybox.h"
+
+static unsigned long flags;
+#define FLAG_COUNT_BYTES	1
+#define FLAG_BREAK_SPACES	2
+#define FLAG_WIDTH			4
+
+/* Assuming the current column is COLUMN, return the column that
+   printing C will move the cursor to.
+   The first column is 0. */
+
+static int adjust_column(int column, char c)
+{
+	if (!(flags & FLAG_COUNT_BYTES)) {
+		if (c == '\b') {
+			if (column > 0)
+				column--;
+		} else if (c == '\r')
+			column = 0;
+		else if (c == '\t')
+			column = column + 8 - column % 8;
+		else			/* if (isprint (c)) */
+			column++;
+	} else
+		column++;
+	return column;
+}
+
+int fold_main(int argc, char **argv)
+{
+	char *w_opt;
+	int width = 80;
+	int i;
+	int errs = 0;
+
+	if(!ENABLE_DEBUG_YANK_SUSv2) {
+		/* Turn any numeric options into -w options.  */
+		for (i = 1; i < argc; i++) {
+			char const *a = argv[i];
+
+			if (*a++ == '-') {
+				if (*a == '-' && !a[1])
+					break;
+				if (isdigit(*a)) {
+					argv[i] = bb_xasprintf("-w%s", a);
+				}
+			}
+		}
+	}
+
+	flags = bb_getopt_ulflags(argc, argv, "bsw:", &w_opt);
+	if (flags & FLAG_WIDTH)
+		width = bb_xgetlarg(w_opt, 10, 1, 10000);
+
+	argv += optind;
+	if (!*argv) {
+		*--argv = "-";
+	}
+
+	do {
+		FILE *istream = bb_wfopen_input(*argv);
+		int c;
+		int column = 0;		/* Screen column where next char will go. */
+		int offset_out = 0;	/* Index in `line_out' for next char. */
+		static char *line_out = NULL;
+		static int allocated_out = 0;
+
+		if (istream == NULL) {
+			errs |= EXIT_FAILURE;
+			continue;
+		}
+
+		while ((c = getc(istream)) != EOF) {
+			if (offset_out + 1 >= allocated_out) {
+				allocated_out += 1024;
+				line_out = xrealloc(line_out, allocated_out);
+			}
+
+			if (c == '\n') {
+				line_out[offset_out++] = c;
+				fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
+				column = offset_out = 0;
+				continue;
+			}
+
+rescan:
+			column = adjust_column(column, c);
+
+			if (column > width) {
+				/* This character would make the line too long.
+				   Print the line plus a newline, and make this character
+				   start the next line. */
+				if (flags & FLAG_BREAK_SPACES) {
+					/* Look for the last blank. */
+					int logical_end;
+
+					for (logical_end = offset_out - 1; logical_end >= 0; logical_end--) {
+						if (isblank(line_out[logical_end])) {
+							break;
+						}
+					}
+					if (logical_end >= 0) {
+						/* Found a blank.  Don't output the part after it. */
+						logical_end++;
+						fwrite(line_out, sizeof(char), (size_t) logical_end, stdout);
+						putchar('\n');
+						/* Move the remainder to the beginning of the next line.
+						   The areas being copied here might overlap. */
+						memmove(line_out, line_out + logical_end, offset_out - logical_end);
+						offset_out -= logical_end;
+						for (column = i = 0; i < offset_out; i++) {
+							column = adjust_column(column, line_out[i]);
+						}
+						goto rescan;
+					}
+				} else {
+					if (offset_out == 0) {
+						line_out[offset_out++] = c;
+						continue;
+					}
+				}
+				line_out[offset_out++] = '\n';
+				fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
+				column = offset_out = 0;
+				goto rescan;
+			}
+
+			line_out[offset_out++] = c;
+		}
+
+		if (offset_out) {
+			fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
+		}
+
+		if (ferror(istream) || bb_fclose_nonstdin(istream)) {
+			bb_perror_msg("%s", *argv);	/* Avoid multibyte problems. */
+			errs |= EXIT_FAILURE;
+		}
+	} while (*++argv);
+
+	bb_fflush_stdout_and_exit(errs);
+}
+/* vi: set sw=4 ts=4: */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/head.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/head.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/head.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,146 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * head implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* BB_AUDIT GNU compatible -c, -q, and -v options in 'fancy' configuration. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/head.html */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <ctype.h>
+#include <unistd.h>
+#include "busybox.h"
+
+static const char head_opts[] =
+	"n:"
+#if ENABLE_FEATURE_FANCY_HEAD
+	"c:qv"
+#endif
+	;
+
+#if ENABLE_FEATURE_FANCY_HEAD
+static const struct suffix_mult head_suffixes[] = {
+	{ "b", 512 },
+	{ "k", 1024 },
+	{ "m", 1024*1024 },
+	{ NULL, 0 }
+};
+#endif
+                                        
+static const char header_fmt_str[] = "\n==> %s <==\n";
+
+int head_main(int argc, char **argv)
+{
+	unsigned long count = 10;
+	unsigned long i;
+#if ENABLE_FEATURE_FANCY_HEAD
+	int count_bytes = 0;
+	int header_threshhold = 1;
+#endif
+
+	FILE *fp;
+	const char *fmt;
+	char *p;
+	int opt;
+	int c;
+	int retval = EXIT_SUCCESS;
+
+#if !ENABLE_DEBUG_YANK_SUSv2 || ENABLE_FEATURE_FANCY_HEAD
+	/* Allow legacy syntax of an initial numeric option without -n. */
+	if ((argc > 1) && (argv[1][0] == '-')
+		/* && (isdigit)(argv[1][1]) */
+		&& (((unsigned int)(argv[1][1] - '0')) <= 9)
+	) {
+		--argc;
+		++argv;
+		p = (*argv) + 1;
+		goto GET_COUNT;
+	}
+#endif
+
+	/* No size benefit in converting this to bb_getopt_ulflags */
+	while ((opt = getopt(argc, argv, head_opts)) > 0) {
+		switch(opt) {
+#if ENABLE_FEATURE_FANCY_HEAD
+			case 'q':
+				header_threshhold = INT_MAX;
+				break;
+			case 'v':
+				header_threshhold = -1;
+				break;
+			case 'c':
+				count_bytes = 1;
+				/* fall through */
+#endif
+			case 'n':
+				p = optarg;
+#if !ENABLE_DEBUG_YANK_SUSv2 || ENABLE_FEATURE_FANCY_HEAD
+			GET_COUNT:
+#endif
+
+#if !ENABLE_FEATURE_FANCY_HEAD
+				count = bb_xgetularg10(p);
+#else
+				count = bb_xgetularg_bnd_sfx(p, 10, 
+								0, ULONG_MAX, 
+								head_suffixes);
+#endif
+				break;
+			default:
+				bb_show_usage();
+		}
+	}
+
+	argv += optind;
+	if (!*argv) {
+		*--argv = "-";
+	}
+
+	fmt = header_fmt_str + 1;
+#if ENABLE_FEATURE_FANCY_HEAD
+	if (argc - optind <= header_threshhold) {
+		header_threshhold = 0;
+	}
+#else
+	if (argc <= optind + 1) {
+		fmt += 11;
+	}
+	/* Now define some things here to avoid #ifdefs in the code below.
+	 * These should optimize out of the if conditions below. */
+#define header_threshhold   1
+#define count_bytes         0
+#endif
+
+	do {
+		if ((fp = bb_wfopen_input(*argv)) != NULL) {
+			if (fp == stdin) {
+				*argv = (char *) bb_msg_standard_input;
+			}
+			if (header_threshhold) {
+				bb_printf(fmt, *argv);
+			}
+			i = count;
+			while (i && ((c = getc(fp)) != EOF)) {
+				if (count_bytes || (c == '\n')) {
+					--i;
+				}
+				putchar(c);
+			}
+			if (bb_fclose_nonstdin(fp)) {
+				bb_perror_msg("%s", *argv);	/* Avoid multibyte problems. */
+				retval = EXIT_FAILURE;
+			}
+			bb_xferror_stdout();
+		}
+		fmt = header_fmt_str;
+	} while (*++argv);
+
+	bb_fflush_stdout_and_exit(retval);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/hostid.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/hostid.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/hostid.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,25 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini hostid implementation for busybox
+ *
+ * Copyright (C) 2000  Edward Betts <edward at debian.org>.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+int hostid_main(int argc, char ATTRIBUTE_UNUSED **argv)
+{
+	if (argc > 1) {
+		bb_show_usage();
+	}
+
+	bb_printf("%lx\n", gethostid());
+
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/id.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/id.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/id.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,112 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini id implementation for busybox
+ *
+ * Copyright (C) 2000 by Randolph Chung <tausq at debian.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 _NOT_ compliant -- option -G is not currently supported. */
+/* Hacked by Tito Ragusa (C) 2004 to handle usernames of whatever length and to
+ * be more similar to GNU id.
+ */
+
+#include "busybox.h"
+#include "pwd_.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#ifdef CONFIG_SELINUX
+#include <selinux/selinux.h>          /* for is_selinux_enabled() */
+#endif
+
+#define PRINT_REAL        1
+#define NAME_NOT_NUMBER   2
+#define JUST_USER         4
+#define JUST_GROUP        8
+
+static short printf_full(unsigned int id, const char *arg, const char prefix)
+{
+	const char *fmt = "%cid=%u";
+	short status=EXIT_FAILURE;
+
+	if(arg) {
+		fmt = "%cid=%u(%s)";
+		status=EXIT_SUCCESS;
+	}
+	bb_printf(fmt, prefix, id, arg);
+	return status;
+}
+
+int id_main(int argc, char **argv)
+{
+	struct passwd *p;
+	uid_t uid;
+	gid_t gid;
+	unsigned long flags;
+	short status;
+
+	/* Don't allow -n -r -nr -ug -rug -nug -rnug */
+	/* Don't allow more than one username */
+	bb_opt_complementally = "?1:?:u--g:g--u:r?ug:n?ug";
+	flags = bb_getopt_ulflags(argc, argv, "rnug");
+
+	/* This values could be overwritten later */
+	uid = geteuid();
+	gid = getegid();
+	if (flags & PRINT_REAL) {
+		uid = getuid();
+		gid = getgid();
+	}
+
+	if(argv[optind]) {
+		p=getpwnam(argv[optind]);
+		/* bb_xgetpwnam is needed because it exits on failure */
+		uid = bb_xgetpwnam(argv[optind]);
+		gid = p->pw_gid;
+		/* in this case PRINT_REAL is the same */
+	}
+
+	if(flags & (JUST_GROUP | JUST_USER)) {
+		/* JUST_GROUP and JUST_USER are mutually exclusive */
+		if(flags & NAME_NOT_NUMBER) {
+			/* bb_getpwuid and bb_getgrgid exit on failure so puts cannot segfault */
+			puts((flags & JUST_USER) ? bb_getpwuid(NULL, uid, -1 ) : bb_getgrgid(NULL, gid, -1 ));
+		} else {
+			bb_printf("%u\n",(flags & JUST_USER) ? uid : gid);
+		}
+		/* exit */
+		bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+	}
+
+	/* Print full info like GNU id */
+	/* bb_getpwuid doesn't exit on failure here */
+	status=printf_full(uid, bb_getpwuid(NULL, uid, 0), 'u');
+	putchar(' ');
+	/* bb_getgrgid doesn't exit on failure here */
+	status|=printf_full(gid, bb_getgrgid(NULL, gid, 0), 'g');
+
+#ifdef CONFIG_SELINUX
+	if ( is_selinux_enabled() ) {
+			security_context_t mysid;
+			char context[80];
+			int len = sizeof(context);
+
+			getcon(&mysid);
+			context[0] = '\0';
+			if (mysid) {
+					len = strlen(mysid)+1;
+					safe_strncpy(context, mysid, len);
+					freecon(mysid);
+			}else{
+					safe_strncpy(context, "unknown",8);
+			}
+		bb_printf(" context=%s", context);
+	}
+#endif
+
+	putchar('\n');
+	bb_fflush_stdout_and_exit(status);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/install.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/install.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/install.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,149 @@
+/*
+ *  Copyright (C) 2003 by Glenn McGrath <bug1 at iinet.net.au>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * TODO: -d option, need a way of recursively making directories and changing
+ *           owner/group, will probably modify bb_make_directory(...)
+ */
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h> /* struct option */
+
+#include "busybox.h"
+#include "libcoreutils/coreutils.h"
+
+#define INSTALL_OPT_CMD	1
+#define INSTALL_OPT_DIRECTORY	2
+#define INSTALL_OPT_PRESERVE_TIME	4
+#define INSTALL_OPT_STRIP	8
+#define INSTALL_OPT_GROUP  16
+#define INSTALL_OPT_MODE  32
+#define INSTALL_OPT_OWNER  64
+
+#if ENABLE_FEATURE_INSTALL_LONG_OPTIONS
+static const struct option install_long_options[] = {
+	{ "directory",	0,	NULL,	'd' },
+	{ "preserve-timestamps",	0,	NULL,	'p' },
+	{ "strip",	0,	NULL,	's' },
+	{ "group",	0,	NULL,	'g' },
+	{ "mode",	0,	NULL,	'm' },
+	{ "owner",	0,	NULL,	'o' },
+	{ 0,	0,	0,	0 }
+};
+#endif
+
+int install_main(int argc, char **argv)
+{
+	mode_t mode;
+	uid_t uid;
+	gid_t gid;
+	char *gid_str = "-1";
+	char *uid_str = "-1";
+	char *mode_str = "0755";
+	int copy_flags = FILEUTILS_DEREFERENCE | FILEUTILS_FORCE;
+	int ret = EXIT_SUCCESS, flags, i, isdir;
+
+#if ENABLE_FEATURE_INSTALL_LONG_OPTIONS
+	bb_applet_long_options = install_long_options;
+#endif
+	bb_opt_complementally = "?:s--d:d--s";
+	/* -c exists for backwards compatibility, its needed */
+	flags = bb_getopt_ulflags(argc, argv, "cdpsg:m:o:", &gid_str, &mode_str, &uid_str);	/* 'a' must be 2nd */
+
+	/* preserve access and modification time, this is GNU behaviour, BSD only preserves modification time */
+	if (flags & INSTALL_OPT_PRESERVE_TIME) {
+		copy_flags |= FILEUTILS_PRESERVE_STATUS;
+	}
+	bb_parse_mode(mode_str, &mode);
+	gid = get_ug_id(gid_str, bb_xgetgrnam);
+	uid = get_ug_id(uid_str, bb_xgetpwnam);
+	umask(0);
+
+	/* Create directories
+	 * dont use bb_make_directory() as it cant change uid or gid
+	 * perhaps bb_make_directory() should be improved.
+	 */
+	if (flags & INSTALL_OPT_DIRECTORY) {
+		for (argv += optind; *argv; argv++) {
+			char *old_argv_ptr = *argv + 1;
+			char *argv_ptr;
+			do {
+				argv_ptr = strchr(old_argv_ptr, '/');
+				old_argv_ptr = argv_ptr;
+				if (argv_ptr) {
+					*argv_ptr = '\0';
+					old_argv_ptr++;
+				}
+				if (mkdir(*argv, mode) == -1) {
+					if (errno != EEXIST) {
+						bb_perror_msg("coulnt create %s", *argv);
+						ret = EXIT_FAILURE;
+						break;
+					}
+				}
+				else if (lchown(*argv, uid, gid) == -1) {
+					bb_perror_msg("cannot change ownership of %s", *argv);
+					ret = EXIT_FAILURE;
+					break;
+				}
+				if (argv_ptr) {
+					*argv_ptr = '/';
+				}
+			} while (old_argv_ptr);
+		}
+		return(ret);
+	}
+
+	{
+		struct stat statbuf;
+		isdir = lstat(argv[argc - 1], &statbuf)<0
+					? 0 : S_ISDIR(statbuf.st_mode);
+	}
+	for (i = optind; i < argc - 1; i++) {
+		char *dest;
+
+		dest = argv[argc - 1];
+		if (isdir) dest = concat_path_file(argv[argc - 1], basename(argv[i]));
+		ret |= copy_file(argv[i], dest, copy_flags);
+
+		/* Set the file mode */
+		if (chmod(dest, mode) == -1) {
+			bb_perror_msg("cannot change permissions of %s", dest);
+			ret = EXIT_FAILURE;
+		}
+
+		/* Set the user and group id */
+		if (lchown(dest, uid, gid) == -1) {
+			bb_perror_msg("cannot change ownership of %s", dest);
+			ret = EXIT_FAILURE;
+		}
+		if (flags & INSTALL_OPT_STRIP) {
+			if (execlp("strip", "strip", dest, NULL) == -1) {
+				bb_error_msg("strip failed");
+				ret = EXIT_FAILURE;
+			}
+		}
+		if(ENABLE_FEATURE_CLEAN_UP && isdir) free(dest);
+	}
+
+	return(ret);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/length.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/length.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/length.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,19 @@
+/* vi: set sw=4 ts=4: */
+
+/* BB_AUDIT SUSv3 N/A -- Apparently a busybox (obsolete?) extension. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "busybox.h"
+
+int length_main(int argc, char **argv)
+{
+	if ((argc != 2) ||  (**(++argv) == '-')) {
+	    bb_show_usage();
+	}
+
+	bb_printf("%lu\n", (unsigned long)strlen(*argv));
+
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,37 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+ifndef top_srcdir
+top_srcdir=../..
+endif
+ifndef top_builddir
+top_builddir=../..
+endif
+srcdir=$(top_srcdir)/coreutils/libcoreutils
+LIBCOREUTILS_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include $(srcdir)/Makefile.in
+
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,39 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+
+LIBCOREUTILS_AR:=libcoreutils.a
+ifndef $(LIBCOREUTILS_DIR)
+LIBCOREUTILS_DIR:=$(top_builddir)/coreutils/libcoreutils
+endif
+srcdir=$(top_srcdir)/coreutils/libcoreutils
+
+LIBCOREUTILS_ALL_SRC:= cp_mv_stat.c getopt_mk_fifo_nod.c
+
+LIBCOREUTILS-y:=
+LIBCOREUTILS-$(CONFIG_MKFIFO)	+= getopt_mk_fifo_nod.o
+LIBCOREUTILS-$(CONFIG_MKNOD)	+= getopt_mk_fifo_nod.o
+LIBCOREUTILS-$(CONFIG_INSTALL)	+= cp_mv_stat.o
+LIBCOREUTILS-$(CONFIG_CP)	+= cp_mv_stat.o
+LIBCOREUTILS-$(CONFIG_MV)	+= cp_mv_stat.o
+
+LIBCOREUTILS-y:=$(sort $(LIBCOREUTILS-y))
+
+LIBCOREUTILS_SRC-y:=$(patsubst %,$(srcdir)/%,$(subst .o,.c,$(LIBCOREUTILS-y)))
+LIBCOREUTILS_SRC-a:=$(wildcard $(srcdir)/*.c)
+LIBRARY_SRC-y+=$(LIBCOREUTILS_SRC-y)
+LIBRARY_SRC-a+=$(LIBCOREUTILS_SRC-a)
+
+ifneq ($(strip $(LIBCOREUTILS-y)),)
+libraries-y+=$(LIBCOREUTILS_DIR)/$(LIBCOREUTILS_AR)
+endif
+
+LIBCOREUTILS_OBJS=$(patsubst %,$(LIBCOREUTILS_DIR)/%, $(LIBCOREUTILS-y))
+
+$(LIBCOREUTILS_DIR)/$(LIBCOREUTILS_AR): $(patsubst %,$(LIBCOREUTILS_DIR)/%,$(LIBCOREUTILS-y))
+	$(do_ar)
+
+$(LIBCOREUTILS_DIR)/%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/coreutils.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/coreutils.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/coreutils.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,15 @@
+/*
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#ifndef COREUTILS_H
+#define COREUTILS_H		1
+
+typedef int (*stat_func)(const char *fn, struct stat *ps);
+
+extern int cp_mv_stat2(const char *fn, struct stat *fn_stat, stat_func sf);
+extern int cp_mv_stat(const char *fn, struct stat *fn_stat);
+
+extern mode_t getopt_mk_fifo_nod(int argc, char **argv);
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/cp_mv_stat.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/cp_mv_stat.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/cp_mv_stat.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,45 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * coreutils utility routine
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <errno.h>
+#include <sys/stat.h>
+#include "libbb.h"
+#include "coreutils.h"
+
+int cp_mv_stat2(const char *fn, struct stat *fn_stat, stat_func sf)
+{
+	if (sf(fn, fn_stat) < 0) {
+		if (errno != ENOENT) {
+			bb_perror_msg("unable to stat `%s'", fn);
+			return -1;
+		}
+		return 0;
+	} else if (S_ISDIR(fn_stat->st_mode)) {
+		return 3;
+	}
+	return 1;
+}
+
+int cp_mv_stat(const char *fn, struct stat *fn_stat)
+{
+	return cp_mv_stat2(fn, fn_stat, stat);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/getopt_mk_fifo_nod.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/getopt_mk_fifo_nod.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/libcoreutils/getopt_mk_fifo_nod.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,40 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * coreutils utility routine
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "libbb.h"
+#include "coreutils.h"
+
+mode_t getopt_mk_fifo_nod(int argc, char **argv)
+{
+	mode_t mode = 0666;
+	char *smode = NULL;
+
+	bb_getopt_ulflags(argc, argv, "m:", &smode);
+	if(smode) {
+		if (bb_parse_mode(smode, &mode))
+			umask(0);
+	}
+	return mode;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/ln.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/ln.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/ln.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,118 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini ln implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* BB_AUDIT GNU options missing: -d, -F, -i, and -v. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/ln.html */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include "busybox.h"
+
+#define LN_SYMLINK          1
+#define LN_FORCE            2
+#define LN_NODEREFERENCE    4
+#define LN_BACKUP           8
+#define LN_SUFFIX           16
+
+int ln_main(int argc, char **argv)
+{
+	int status = EXIT_SUCCESS;
+	int flag;
+	char *last;
+	char *src_name;
+	char *src;
+	char *suffix = "~";
+	struct stat statbuf;
+	int (*link_func)(const char *, const char *);
+
+	flag = bb_getopt_ulflags(argc, argv, "sfnbS:", &suffix);
+
+	if (argc == optind) {
+		bb_show_usage();
+	}
+
+	last = argv[argc - 1];
+	argv += optind;
+
+	if (argc == optind + 1) {
+		*--argv = last;
+		last = bb_get_last_path_component(bb_xstrdup(last));
+	}
+
+	do {
+		src_name = NULL;
+		src = last;
+
+		if (is_directory(src,
+						 (flag & LN_NODEREFERENCE) ^ LN_NODEREFERENCE,
+						 NULL)) {
+			src_name = bb_xstrdup(*argv);
+			src = concat_path_file(src, bb_get_last_path_component(src_name));
+			free(src_name);
+			src_name = src;
+		}
+		if (!(flag & LN_SYMLINK) && stat(*argv, &statbuf)) {
+			bb_perror_msg("%s", *argv);
+			status = EXIT_FAILURE;
+			free(src_name);
+			continue;
+		}
+
+		if (flag & LN_BACKUP) {
+				char *backup;
+				backup = bb_xasprintf("%s%s", src, suffix);
+				if (rename(src, backup) < 0 && errno != ENOENT) {
+						bb_perror_msg("%s", src);
+						status = EXIT_FAILURE;
+						free(backup);
+						continue;
+				}
+				free(backup);
+				/*
+				 * When the source and dest are both hard links to the same
+				 * inode, a rename may succeed even though nothing happened.
+				 * Therefore, always unlink().
+				 */
+				unlink(src);
+		} else if (flag & LN_FORCE) {
+			unlink(src);
+		}
+
+		link_func = link;
+		if (flag & LN_SYMLINK) {
+			link_func = symlink;
+		}
+
+		if (link_func(*argv, src) != 0) {
+			bb_perror_msg("%s", src);
+			status = EXIT_FAILURE;
+		}
+
+		free(src_name);
+
+	} while ((++argv)[1]);
+
+	return status;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/logname.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/logname.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/logname.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,42 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini logname implementation for busybox
+ *
+ * Copyright (C) 2000  Edward Betts <edward at debian.org>.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/logname.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * SUSv3 specifies the string used is that returned from getlogin().
+ * The previous implementation used getpwuid() for geteuid(), which
+ * is _not_ the same.  Erik apparently made this change almost 3 years
+ * ago to avoid failing when no utmp was available.  However, the
+ * correct course of action wrt SUSv3 for a failing getlogin() is
+ * a diagnostic message and an error return.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+int logname_main(int argc, char ATTRIBUTE_UNUSED **argv)
+{
+	const char *p;
+
+	if (argc > 1) {
+		bb_show_usage();
+	}
+
+	if ((p = getlogin()) != NULL) {
+		puts(p);
+		bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+	}
+
+	bb_perror_msg_and_die("getlogin");
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/ls.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/ls.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/ls.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1084 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * tiny-ls.c version 0.1.0: A minimalist 'ls'
+ * Copyright (C) 1996 Brian Candler <B.Candler at pobox.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/*
+ * To achieve a small memory footprint, this version of 'ls' doesn't do any
+ * file sorting, and only has the most essential command line switches
+ * (i.e., the ones I couldn't live without :-) All features which involve
+ * linking in substantial chunks of libc can be disabled.
+ *
+ * Although I don't really want to add new features to this program to
+ * keep it small, I *am* interested to receive bug fixes and ways to make
+ * it more portable.
+ *
+ * KNOWN BUGS:
+ * 1. ls -l of a directory doesn't give "total <blocks>" header
+ * 2. ls of a symlink to a directory doesn't list directory contents
+ * 3. hidden files can make column width too large
+ *
+ * NON-OPTIMAL BEHAVIOUR:
+ * 1. autowidth reads directories twice
+ * 2. if you do a short directory listing without filetype characters
+ *    appended, there's no need to stat each one
+ * PORTABILITY:
+ * 1. requires lstat (BSD) - how do you do it without?
+ */
+
+enum {
+	TERMINAL_WIDTH = 80,	/* use 79 if terminal has linefold bug */
+	COLUMN_GAP = 2,		/* includes the file type char */
+};
+
+/************************************************************************/
+
+#include "busybox.h"
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <getopt.h> /* struct option */
+#include <sys/ioctl.h>
+#include <sys/sysmacros.h>     /* major() and minor() */
+#include <time.h>
+
+/* what is the overall style of the listing */
+#define STYLE_COLUMNS   (1U<<21)	/* fill columns */
+#define STYLE_LONG      (2U<<21)	/* one record per line, extended info */
+#define STYLE_SINGLE    (3U<<21)	/* one record per line */
+
+#define STYLE_MASK                 STYLE_SINGLE
+#define STYLE_ONE_RECORD_FLAG      STYLE_LONG
+
+/* 51306 lrwxrwxrwx  1 root     root         2 May 11 01:43 /bin/view -> vi* */
+/* what file information will be listed */
+#define LIST_INO	(1U<<0)
+#define LIST_BLOCKS	(1U<<1)
+#define LIST_MODEBITS	(1U<<2)
+#define LIST_NLINKS	(1U<<3)
+#define LIST_ID_NAME	(1U<<4)
+#define LIST_ID_NUMERIC	(1U<<5)
+#define LIST_CONTEXT	(1U<<6)
+#define LIST_SIZE	(1U<<7)
+#define LIST_DEV	(1U<<8)
+#define LIST_DATE_TIME	(1U<<9)
+#define LIST_FULLTIME	(1U<<10)
+#define LIST_FILENAME	(1U<<11)
+#define LIST_SYMLINK	(1U<<12)
+#define LIST_FILETYPE	(1U<<13)
+#define LIST_EXEC	(1U<<14)
+
+#define LIST_MASK       ((LIST_EXEC << 1) - 1)
+
+/* what files will be displayed */
+#define DISP_DIRNAME	(1U<<15)	/* 2 or more items? label directories */
+#define DISP_HIDDEN	(1U<<16)	/* show filenames starting with .  */
+#define DISP_DOT	(1U<<17)	/* show . and .. */
+#define DISP_NOLIST	(1U<<18)	/* show directory as itself, not contents */
+#define DISP_RECURSIVE	(1U<<19)	/* show directory and everything below it */
+#define DISP_ROWS	(1U<<20)	/* print across rows */
+
+#define DISP_MASK       (((DISP_ROWS << 1) - 1) & ~(DISP_DIRNAME - 1))
+
+// CONFIG_FEATURE_LS_SORTFILES
+/* how will the files be sorted */
+#define SORT_ORDER_FORWARD   0		/* sort in reverse order */
+#define SORT_ORDER_REVERSE   (1U<<27)	/* sort in reverse order */
+
+#define SORT_NAME      0		/* sort by file name */
+#define SORT_SIZE      (1U<<28)		/* sort by file size */
+#define SORT_ATIME     (2U<<28)		/* sort by last access time */
+#define SORT_CTIME     (3U<<28)		/* sort by last change time */
+#define SORT_MTIME     (4U<<28)		/* sort by last modification time */
+#define SORT_VERSION   (5U<<28)		/* sort by version */
+#define SORT_EXT       (6U<<28)		/* sort by file name extension */
+#define SORT_DIR       (7U<<28)		/* sort by file or directory */
+
+#define SORT_MASK      (7U<<28)
+
+/* which of the three times will be used */
+#define TIME_CHANGE    ((1U<<23) * ENABLE_FEATURE_LS_TIMESTAMPS)
+#define TIME_ACCESS    ((1U<<24) * ENABLE_FEATURE_LS_TIMESTAMPS)
+#define TIME_MASK      ((3U<<23) * ENABLE_FEATURE_LS_TIMESTAMPS)
+
+#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
+#define FOLLOW_LINKS   (1U<<25)
+#endif
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+#define LS_DISP_HR     (1U<<26)
+#endif
+
+#define LIST_SHORT	(LIST_FILENAME)
+#define LIST_ISHORT	(LIST_INO | LIST_FILENAME)
+#define LIST_LONG	(LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \
+						LIST_DATE_TIME | LIST_FILENAME | LIST_SYMLINK)
+#define LIST_ILONG	(LIST_INO | LIST_LONG)
+
+#define SPLIT_DIR      1
+#define SPLIT_FILE     0
+#define SPLIT_SUBDIR   2
+
+#define TYPEINDEX(mode) (((mode) >> 12) & 0x0f)
+#define TYPECHAR(mode)  ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)])
+
+#if defined(CONFIG_FEATURE_LS_FILETYPES) || defined(CONFIG_FEATURE_LS_COLOR)
+# define APPCHAR(mode)   ("\0|\0\0/\0\0\0\0\0@\0=\0\0\0" [TYPEINDEX(mode)])
+#endif
+
+/* colored LS support by JaWi, janwillem.janssen at lxtreme.nl */
+#ifdef CONFIG_FEATURE_LS_COLOR
+
+static int show_color = 0;
+
+/* long option entry used only for --color, which has no short option
+ * equivalent.  */
+static const struct option ls_color_opt[] =
+{
+	{"color", optional_argument, NULL, 1},
+	{NULL, 0, NULL, 0}
+};
+
+#define COLOR(mode)	("\000\043\043\043\042\000\043\043"\
+			 "\000\000\044\000\043\000\000\040" [TYPEINDEX(mode)])
+#define ATTR(mode)	("\00\00\01\00\01\00\01\00"\
+			 "\00\00\01\00\01\00\00\01" [TYPEINDEX(mode)])
+#endif
+
+/*
+ * a directory entry and its stat info are stored here
+ */
+struct dnode {			/* the basic node */
+	char *name;		/* the dir entry name */
+	char *fullname;		/* the dir entry name */
+	int   allocated;
+	struct stat dstat;	/* the file stat info */
+#ifdef CONFIG_SELINUX
+	security_context_t sid;
+#endif
+	struct dnode *next;	/* point at the next node */
+};
+typedef struct dnode dnode_t;
+
+static struct dnode **list_dir(const char *);
+static struct dnode **dnalloc(int);
+static int list_single(struct dnode *);
+
+static unsigned int all_fmt;
+
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+static int terminal_width = TERMINAL_WIDTH;
+static unsigned short tabstops = COLUMN_GAP;
+#else
+#define tabstops COLUMN_GAP
+#define terminal_width TERMINAL_WIDTH
+#endif
+
+static int status = EXIT_SUCCESS;
+
+static struct dnode *my_stat(char *fullname, char *name)
+{
+	struct stat dstat;
+	struct dnode *cur;
+#ifdef CONFIG_SELINUX
+	security_context_t sid=NULL;
+#endif
+
+#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
+	if (all_fmt & FOLLOW_LINKS) {
+#ifdef CONFIG_SELINUX
+		if (is_selinux_enabled())  {
+			 getfilecon(fullname,&sid);
+		}
+#endif
+		if (stat(fullname, &dstat)) {
+			bb_perror_msg("%s", fullname);
+			status = EXIT_FAILURE;
+			return 0;
+		}
+	} else
+#endif
+	{
+#ifdef CONFIG_SELINUX
+	        if  (is_selinux_enabled())  {
+		  lgetfilecon(fullname,&sid);
+		}
+#endif
+		if (lstat(fullname, &dstat)) {
+			bb_perror_msg("%s", fullname);
+			status = EXIT_FAILURE;
+			return 0;
+		}
+	}
+
+	cur = (struct dnode *) xmalloc(sizeof(struct dnode));
+	cur->fullname = fullname;
+	cur->name = name;
+	cur->dstat = dstat;
+#ifdef CONFIG_SELINUX
+	cur->sid = sid;
+#endif
+	return cur;
+}
+
+/*----------------------------------------------------------------------*/
+#ifdef CONFIG_FEATURE_LS_COLOR
+static char fgcolor(mode_t mode)
+{
+	/* Check wheter the file is existing (if so, color it red!) */
+	if (errno == ENOENT) {
+		return '\037';
+	}
+	if (S_ISREG(mode) && (mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+		return COLOR(0xF000);	/* File is executable ... */
+	return COLOR(mode);
+}
+
+/*----------------------------------------------------------------------*/
+static char bgcolor(mode_t mode)
+{
+	if (S_ISREG(mode) && (mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+		return ATTR(0xF000);	/* File is executable ... */
+	return ATTR(mode);
+}
+#endif
+
+/*----------------------------------------------------------------------*/
+#if defined(CONFIG_FEATURE_LS_FILETYPES) || defined(CONFIG_FEATURE_LS_COLOR)
+static char append_char(mode_t mode)
+{
+	if (!(all_fmt & LIST_FILETYPE))
+		return '\0';
+	if (S_ISDIR(mode))
+		return '/';
+	if (!(all_fmt & LIST_EXEC))
+		return '\0';
+	if (S_ISREG(mode) && (mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+		return '*';
+	return APPCHAR(mode);
+}
+#endif
+
+/*----------------------------------------------------------------------*/
+
+#define countdirs(A,B) count_dirs((A), (B), 1)
+#define countsubdirs(A,B) count_dirs((A), (B), 0)
+
+static int count_dirs(struct dnode **dn, int nfiles, int notsubdirs)
+{
+	int i, dirs;
+
+	if (dn == NULL || nfiles < 1)
+		return (0);
+	dirs = 0;
+	for (i = 0; i < nfiles; i++) {
+		if (S_ISDIR(dn[i]->dstat.st_mode)
+			&& (notsubdirs ||
+			((dn[i]->name[0] != '.') || (dn[i]->name[1]
+						&& ((dn[i]->name[1] != '.')
+						|| dn[i]->name[2])))))
+			dirs++;
+	}
+	return (dirs);
+}
+
+static int countfiles(struct dnode **dnp)
+{
+	int nfiles;
+	struct dnode *cur;
+
+	if (dnp == NULL)
+		return (0);
+	nfiles = 0;
+	for (cur = dnp[0]; cur->next != NULL; cur = cur->next)
+		nfiles++;
+	nfiles++;
+	return (nfiles);
+}
+
+/* get memory to hold an array of pointers */
+static struct dnode **dnalloc(int num)
+{
+	struct dnode **p;
+
+	if (num < 1)
+		return (NULL);
+
+	p = (struct dnode **) xcalloc((size_t) num, (size_t) (sizeof(struct dnode *)));
+	return (p);
+}
+
+#ifdef CONFIG_FEATURE_LS_RECURSIVE
+static void dfree(struct dnode **dnp, int nfiles)
+{
+	int i;
+
+	if (dnp == NULL)
+		return;
+
+	for (i = 0; i < nfiles; i++) {
+		struct dnode *cur = dnp[i];
+		if(cur->allocated)
+			free(cur->fullname);	/* free the filename */
+		free(cur);		/* free the dnode */
+	}
+	free(dnp);			/* free the array holding the dnode pointers */
+}
+#else
+#define dfree(...)
+#endif
+
+static struct dnode **splitdnarray(struct dnode **dn, int nfiles, int which)
+{
+	int dncnt, i, d;
+	struct dnode **dnp;
+
+	if (dn == NULL || nfiles < 1)
+		return (NULL);
+
+	/* count how many dirs and regular files there are */
+	if (which == SPLIT_SUBDIR)
+		dncnt = countsubdirs(dn, nfiles);
+	else {
+		dncnt = countdirs(dn, nfiles);	/* assume we are looking for dirs */
+		if (which == SPLIT_FILE)
+			dncnt = nfiles - dncnt;	/* looking for files */
+	}
+
+	/* allocate a file array and a dir array */
+	dnp = dnalloc(dncnt);
+
+	/* copy the entrys into the file or dir array */
+	for (d = i = 0; i < nfiles; i++) {
+		if (S_ISDIR(dn[i]->dstat.st_mode)) {
+			if (which & (SPLIT_DIR|SPLIT_SUBDIR)) {
+				if ((which & SPLIT_DIR)
+					|| ((dn[i]->name[0] != '.')
+						|| (dn[i]->name[1]
+							&& ((dn[i]->name[1] != '.')
+								|| dn[i]->name[2])))) {
+									dnp[d++] = dn[i];
+								}
+			}
+		} else if (!(which & (SPLIT_DIR|SPLIT_SUBDIR))) {
+			dnp[d++] = dn[i];
+		}
+	}
+	return (dnp);
+}
+
+/*----------------------------------------------------------------------*/
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+static int sortcmp(const void *a, const void *b)
+{
+	struct dnode *d1 = *(struct dnode **)a;
+	struct dnode *d2 = *(struct dnode **)b;
+	unsigned int sort_opts = all_fmt & SORT_MASK;
+	int dif;
+
+	dif = 0;			/* assume SORT_NAME */
+	if (sort_opts == SORT_SIZE) {
+		dif = (int) (d2->dstat.st_size - d1->dstat.st_size);
+	} else if (sort_opts == SORT_ATIME) {
+		dif = (int) (d2->dstat.st_atime - d1->dstat.st_atime);
+	} else if (sort_opts == SORT_CTIME) {
+		dif = (int) (d2->dstat.st_ctime - d1->dstat.st_ctime);
+	} else if (sort_opts == SORT_MTIME) {
+		dif = (int) (d2->dstat.st_mtime - d1->dstat.st_mtime);
+	} else if (sort_opts == SORT_DIR) {
+		dif = S_ISDIR(d2->dstat.st_mode) - S_ISDIR(d1->dstat.st_mode);
+		/* } else if (sort_opts == SORT_VERSION) { */
+		/* } else if (sort_opts == SORT_EXT) { */
+	}
+
+	if (dif == 0) {
+		/* sort by name- may be a tie_breaker for time or size cmp */
+		if (ENABLE_LOCALE_SUPPORT) dif = strcoll(d1->name, d2->name);
+		else dif = strcmp(d1->name, d2->name);
+	}
+
+	if (all_fmt & SORT_ORDER_REVERSE) {
+		dif = -dif;
+	}
+	return (dif);
+}
+
+/*----------------------------------------------------------------------*/
+static void dnsort(struct dnode **dn, int size)
+{
+	qsort(dn, size, sizeof *dn, sortcmp);
+}
+#else
+#define sortcmp(a, b) 0
+#define dnsort(dn, size)
+#endif
+
+
+/*----------------------------------------------------------------------*/
+static void showfiles(struct dnode **dn, int nfiles)
+{
+	int i, ncols, nrows, row, nc;
+	int column = 0;
+	int nexttab = 0;
+	int column_width = 0; /* for STYLE_LONG and STYLE_SINGLE not used */
+
+	if (dn == NULL || nfiles < 1)
+		return;
+
+	if (all_fmt & STYLE_ONE_RECORD_FLAG) {
+		ncols = 1;
+	} else {
+		/* find the longest file name-  use that as the column width */
+		for (i = 0; i < nfiles; i++) {
+			int len = strlen(dn[i]->name) +
+#ifdef CONFIG_SELINUX
+			((all_fmt & LIST_CONTEXT) ? 33 : 0) +
+#endif
+			((all_fmt & LIST_INO) ? 8 : 0) +
+			((all_fmt & LIST_BLOCKS) ? 5 : 0);
+			if (column_width < len)
+				column_width = len;
+		}
+		column_width += tabstops;
+		ncols = (int) (terminal_width / column_width);
+	}
+
+	if (ncols > 1) {
+		nrows = nfiles / ncols;
+		if ((nrows * ncols) < nfiles)
+			nrows++;                /* round up fractionals */
+	} else {
+		nrows = nfiles;
+		ncols = 1;
+	}
+
+	for (row = 0; row < nrows; row++) {
+		for (nc = 0; nc < ncols; nc++) {
+			/* reach into the array based on the column and row */
+			i = (nc * nrows) + row;	/* assume display by column */
+			if (all_fmt & DISP_ROWS)
+				i = (row * ncols) + nc;	/* display across row */
+			if (i < nfiles) {
+				if (column > 0) {
+					nexttab -= column;
+					while (nexttab--) {
+						putchar(' ');
+						column++;
+					}
+			}
+				nexttab = column + column_width;
+				column += list_single(dn[i]);
+		}
+		}
+		putchar('\n');
+		column = 0;
+	}
+}
+
+/*----------------------------------------------------------------------*/
+static void showdirs(struct dnode **dn, int ndirs, int first)
+{
+	int i, nfiles;
+	struct dnode **subdnp;
+	int dndirs;
+	struct dnode **dnd;
+
+	if (dn == NULL || ndirs < 1)
+		return;
+
+	for (i = 0; i < ndirs; i++) {
+		if (all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) {
+			if (!first)
+				printf("\n");
+			first = 0;
+			printf("%s:\n", dn[i]->fullname);
+		}
+		subdnp = list_dir(dn[i]->fullname);
+		nfiles = countfiles(subdnp);
+		if (nfiles > 0) {
+			/* list all files at this level */
+			if (ENABLE_FEATURE_LS_SORTFILES) dnsort(subdnp, nfiles);
+			showfiles(subdnp, nfiles);
+			if (ENABLE_FEATURE_LS_RECURSIVE) {
+				if (all_fmt & DISP_RECURSIVE) {
+					/* recursive- list the sub-dirs */
+					dnd = splitdnarray(subdnp, nfiles, SPLIT_SUBDIR);
+					dndirs = countsubdirs(subdnp, nfiles);
+					if (dndirs > 0) {
+						if (ENABLE_FEATURE_LS_SORTFILES) dnsort(dnd, dndirs);
+						showdirs(dnd, dndirs, 0);
+						/* free the array of dnode pointers to the dirs */
+						free(dnd);
+					}
+				}
+				/* free the dnodes and the fullname mem */
+				dfree(subdnp, nfiles);
+			}
+		}
+	}
+}
+
+/*----------------------------------------------------------------------*/
+static struct dnode **list_dir(const char *path)
+{
+	struct dnode *dn, *cur, **dnp;
+	struct dirent *entry;
+	DIR *dir;
+	int i, nfiles;
+
+	if (path == NULL)
+		return (NULL);
+
+	dn = NULL;
+	nfiles = 0;
+	dir = bb_opendir(path);
+	if (dir == NULL) {
+		status = EXIT_FAILURE;
+		return (NULL);	/* could not open the dir */
+	}
+	while ((entry = readdir(dir)) != NULL) {
+		char *fullname;
+
+		/* are we going to list the file- it may be . or .. or a hidden file */
+		if (entry->d_name[0] == '.') {
+			if ((entry->d_name[1] == 0 || (
+				entry->d_name[1] == '.'
+				&& entry->d_name[2] == 0))
+					&& !(all_fmt & DISP_DOT))
+			continue;
+			if (!(all_fmt & DISP_HIDDEN))
+			continue;
+		}
+		fullname = concat_path_file(path, entry->d_name);
+		cur = my_stat(fullname, strrchr(fullname, '/') + 1);
+		if (!cur)
+			continue;
+		cur->allocated = 1;
+		cur->next = dn;
+		dn = cur;
+		nfiles++;
+	}
+	closedir(dir);
+
+	/* now that we know how many files there are
+	   ** allocate memory for an array to hold dnode pointers
+	 */
+	if (dn == NULL)
+		return (NULL);
+	dnp = dnalloc(nfiles);
+	for (i = 0, cur = dn; i < nfiles; i++) {
+		dnp[i] = cur;	/* save pointer to node in array */
+		cur = cur->next;
+	}
+
+	return (dnp);
+}
+
+/*----------------------------------------------------------------------*/
+static int list_single(struct dnode *dn)
+{
+	int i, column = 0;
+
+#ifdef CONFIG_FEATURE_LS_USERNAME
+	char scratch[16];
+#endif
+#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
+	char *filetime;
+	time_t ttime, age;
+#endif
+#if defined(CONFIG_FEATURE_LS_FILETYPES) || defined (CONFIG_FEATURE_LS_COLOR)
+	struct stat info;
+	char append;
+#endif
+
+	if (dn->fullname == NULL)
+		return (0);
+
+#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
+	ttime = dn->dstat.st_mtime;	/* the default time */
+	if (all_fmt & TIME_ACCESS)
+		ttime = dn->dstat.st_atime;
+	if (all_fmt & TIME_CHANGE)
+		ttime = dn->dstat.st_ctime;
+	filetime = ctime(&ttime);
+#endif
+#ifdef CONFIG_FEATURE_LS_FILETYPES
+	append = append_char(dn->dstat.st_mode);
+#endif
+
+	for (i = 0; i <= 31; i++) {
+		switch (all_fmt & (1 << i)) {
+		case LIST_INO:
+			column += printf("%7ld ", (long int) dn->dstat.st_ino);
+			break;
+		case LIST_BLOCKS:
+#if _FILE_OFFSET_BITS == 64
+			column += printf("%4lld ", (long long)dn->dstat.st_blocks >> 1);
+#else
+			column += printf("%4ld ", dn->dstat.st_blocks >> 1);
+#endif
+			break;
+		case LIST_MODEBITS:
+			column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode));
+			break;
+		case LIST_NLINKS:
+			column += printf("%4ld ", (long) dn->dstat.st_nlink);
+			break;
+		case LIST_ID_NAME:
+#ifdef CONFIG_FEATURE_LS_USERNAME
+			bb_getpwuid(scratch, dn->dstat.st_uid, sizeof(scratch));
+			printf("%-8.8s ", scratch);
+			bb_getgrgid(scratch, dn->dstat.st_gid, sizeof(scratch));
+			printf("%-8.8s", scratch);
+			column += 17;
+			break;
+#endif
+		case LIST_ID_NUMERIC:
+			column += printf("%-8d %-8d", dn->dstat.st_uid, dn->dstat.st_gid);
+			break;
+		case LIST_SIZE:
+		case LIST_DEV:
+			if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) {
+				column += printf("%4d, %3d ", (int) major(dn->dstat.st_rdev),
+					   (int) minor(dn->dstat.st_rdev));
+			} else {
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+				if (all_fmt & LS_DISP_HR) {
+					column += printf("%9s ",
+							make_human_readable_str(dn->dstat.st_size, 1, 0));
+				} else
+#endif
+				{
+#if _FILE_OFFSET_BITS == 64
+					column += printf("%9lld ", (long long) dn->dstat.st_size);
+#else
+					column += printf("%9ld ", dn->dstat.st_size);
+#endif
+				}
+			}
+			break;
+#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
+		case LIST_FULLTIME:
+			printf("%24.24s ", filetime);
+			column += 25;
+			break;
+		case LIST_DATE_TIME:
+			if ((all_fmt & LIST_FULLTIME) == 0) {
+				age = time(NULL) - ttime;
+				printf("%6.6s ", filetime + 4);
+				if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) {
+					/* hh:mm if less than 6 months old */
+					printf("%5.5s ", filetime + 11);
+				} else {
+					printf(" %4.4s ", filetime + 20);
+				}
+				column += 13;
+			}
+			break;
+#endif
+#ifdef CONFIG_SELINUX
+		case LIST_CONTEXT:
+			{
+				char context[80];
+				int len = 0;
+
+				if (dn->sid) {
+				  /*  I assume sid initilized with NULL  */
+				  len = strlen(dn->sid)+1;
+				  safe_strncpy(context, dn->sid, len);
+				  freecon(dn->sid);
+				}else {
+				  safe_strncpy(context, "unknown", 8);
+				}
+				printf("%-32s ", context);
+				column += MAX(33, len);
+			}
+			break;
+#endif
+		case LIST_FILENAME:
+#ifdef CONFIG_FEATURE_LS_COLOR
+			errno = 0;
+			if (show_color && !lstat(dn->fullname, &info)) {
+				printf("\033[%d;%dm", bgcolor(info.st_mode),
+					   fgcolor(info.st_mode));
+			}
+#endif
+			column += printf("%s", dn->name);
+#ifdef CONFIG_FEATURE_LS_COLOR
+			if (show_color) {
+				printf("\033[0m");
+			}
+#endif
+			break;
+		case LIST_SYMLINK:
+			if (S_ISLNK(dn->dstat.st_mode)) {
+				char *lpath = xreadlink(dn->fullname);
+
+				if (lpath) {
+					printf(" -> ");
+#if defined(CONFIG_FEATURE_LS_FILETYPES) || defined (CONFIG_FEATURE_LS_COLOR)
+					if (!stat(dn->fullname, &info)) {
+						append = append_char(info.st_mode);
+					}
+#endif
+#ifdef CONFIG_FEATURE_LS_COLOR
+					if (show_color) {
+						errno = 0;
+						printf("\033[%d;%dm", bgcolor(info.st_mode),
+							   fgcolor(info.st_mode));
+					}
+#endif
+					column += printf("%s", lpath) + 4;
+#ifdef CONFIG_FEATURE_LS_COLOR
+					if (show_color) {
+						printf("\033[0m");
+					}
+#endif
+					free(lpath);
+				}
+			}
+			break;
+#ifdef CONFIG_FEATURE_LS_FILETYPES
+		case LIST_FILETYPE:
+			if (append != '\0') {
+				printf("%1c", append);
+				column++;
+			}
+			break;
+#endif
+		}
+	}
+
+	return column;
+}
+
+/*----------------------------------------------------------------------*/
+
+/* "[-]Cadil1", POSIX mandated options, busybox always supports */
+/* "[-]gnsx", POSIX non-mandated options, busybox always supports */
+/* "[-]Ak" GNU options, busybox always supports */
+/* "[-]FLRctur", POSIX mandated options, busybox optionally supports */
+/* "[-]p", POSIX non-mandated options, busybox optionally supports */
+/* "[-]SXvThw", GNU options, busybox optionally supports */
+/* "[-]K", SELinux mandated options, busybox optionally supports */
+/* "[-]e", I think we made this one up */
+
+#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
+# define LS_STR_TIMESTAMPS	"cetu"
+#else
+# define LS_STR_TIMESTAMPS	""
+#endif
+
+#ifdef CONFIG_FEATURE_LS_FILETYPES
+# define LS_STR_FILETYPES	"Fp"
+#else
+# define LS_STR_FILETYPES	""
+#endif
+
+#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
+# define LS_STR_FOLLOW_LINKS	"L"
+#else
+# define LS_STR_FOLLOW_LINKS	""
+#endif
+
+#ifdef CONFIG_FEATURE_LS_RECURSIVE
+# define LS_STR_RECURSIVE	"R"
+#else
+# define LS_STR_RECURSIVE	""
+#endif
+
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+# define LS_STR_HUMAN_READABLE	"h"
+#else
+# define LS_STR_HUMAN_READABLE	""
+#endif
+
+#ifdef CONFIG_SELINUX
+# define LS_STR_SELINUX	"K"
+#else
+# define LS_STR_SELINUX	""
+#endif
+
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+# define LS_STR_AUTOWIDTH	"T:w:"
+#else
+# define LS_STR_AUTOWIDTH	""
+#endif
+
+static const char ls_options[]="Cadil1gnsxAk" \
+	LS_STR_TIMESTAMPS \
+	USE_FEATURE_LS_SORTFILES("SXrv") \
+	LS_STR_FILETYPES \
+	LS_STR_FOLLOW_LINKS \
+	LS_STR_RECURSIVE \
+	LS_STR_HUMAN_READABLE \
+	LS_STR_SELINUX \
+	LS_STR_AUTOWIDTH;
+
+#define LIST_MASK_TRIGGER	0
+#define STYLE_MASK_TRIGGER	STYLE_MASK
+#define SORT_MASK_TRIGGER	SORT_MASK
+#define DISP_MASK_TRIGGER	DISP_ROWS
+
+static const unsigned opt_flags[] = {
+	LIST_SHORT | STYLE_COLUMNS,	/* C */
+	DISP_HIDDEN | DISP_DOT,		/* a */
+	DISP_NOLIST,				/* d */
+	LIST_INO,					/* i */
+	LIST_LONG | STYLE_LONG,		/* l - remember LS_DISP_HR in mask! */
+	LIST_SHORT | STYLE_SINGLE,	/* 1 */
+	0,							/* g - ingored */
+	LIST_ID_NUMERIC,			/* n */
+	LIST_BLOCKS,				/* s */
+	DISP_ROWS,					/* x */
+	DISP_HIDDEN,				/* A */
+#ifdef CONFIG_SELINUX
+	LIST_CONTEXT,				/* k */
+#else
+	0,							/* k - ingored */
+#endif
+#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
+	TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME),	/* c */
+	LIST_FULLTIME,				/* e */
+	ENABLE_FEATURE_LS_SORTFILES * SORT_MTIME,	/* t */
+	TIME_ACCESS | (ENABLE_FEATURE_LS_SORTFILES * SORT_ATIME),	/* u */
+#endif
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+	SORT_SIZE,					/* S */
+	SORT_EXT,					/* X */
+	SORT_ORDER_REVERSE,			/* r */
+	SORT_VERSION,				/* v */
+#endif
+#ifdef CONFIG_FEATURE_LS_FILETYPES
+	LIST_FILETYPE | LIST_EXEC,	/* F */
+	LIST_FILETYPE,				/* p */
+#endif
+#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
+	FOLLOW_LINKS,				/* L */
+#endif
+#ifdef CONFIG_FEATURE_LS_RECURSIVE
+	DISP_RECURSIVE,				/* R */
+#endif
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+	LS_DISP_HR,					/* h */
+#endif
+#ifdef CONFIG_SELINUX
+	LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */
+#endif
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+       0, 0,                    /* T, w - ignored */
+#endif
+	(1U<<31)
+};
+
+
+/*----------------------------------------------------------------------*/
+
+int ls_main(int argc, char **argv)
+{
+	struct dnode **dnd;
+	struct dnode **dnf;
+	struct dnode **dnp;
+	struct dnode *dn;
+	struct dnode *cur;
+	long opt;
+	int nfiles = 0;
+	int dnfiles;
+	int dndirs;
+	int oi;
+	int ac;
+	int i;
+	char **av;
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+	char *tabstops_str = NULL;
+	char *terminal_width_str = NULL;
+#endif
+#ifdef CONFIG_FEATURE_LS_COLOR
+	char *color_opt;
+#endif
+
+	all_fmt = LIST_SHORT |
+		(ENABLE_FEATURE_LS_SORTFILES * (SORT_NAME | SORT_ORDER_FORWARD));
+
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+	/* Obtain the terminal width.  */
+	get_terminal_width_height(STDOUT_FILENO, &terminal_width, NULL);
+	/* Go one less... */
+	terminal_width--;
+#endif
+
+#ifdef CONFIG_FEATURE_LS_COLOR
+	bb_applet_long_options = ls_color_opt;
+#endif
+
+	/* process options */
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+	opt = bb_getopt_ulflags(argc, argv, ls_options, &tabstops_str, &terminal_width_str
+#ifdef CONFIG_FEATURE_LS_COLOR
+		, &color_opt
+#endif
+		);
+	if (tabstops_str) {
+		tabstops = atoi(tabstops_str);
+	}
+	if (terminal_width_str) {
+		terminal_width = atoi(terminal_width_str);
+	}
+#else
+	opt = bb_getopt_ulflags(argc, argv, ls_options
+#ifdef CONFIG_FEATURE_LS_COLOR
+		, &color_opt
+#endif
+		);
+#endif
+	for (i = 0; opt_flags[i] != (1U<<31); i++) {
+		if (opt & (1 << i)) {
+			unsigned int flags = opt_flags[i];
+
+			if (flags & LIST_MASK_TRIGGER) {
+				all_fmt &= ~LIST_MASK;
+			}
+			if (flags & STYLE_MASK_TRIGGER) {
+				all_fmt &= ~STYLE_MASK;
+			}
+			if (ENABLE_FEATURE_LS_SORTFILES && (flags & SORT_MASK_TRIGGER)) {
+				all_fmt &= ~SORT_MASK;
+			}
+			if (flags & DISP_MASK_TRIGGER) {
+				all_fmt &= ~DISP_MASK;
+			}
+			if (flags & TIME_MASK) {
+				all_fmt &= ~TIME_MASK;
+			}
+			if (flags & LIST_CONTEXT) {
+				all_fmt |= STYLE_SINGLE;
+			}
+#ifdef CONFIG_FEATURE_HUMAN_READABLE
+			if (opt == 'l') {
+				all_fmt &= ~LS_DISP_HR;
+			}
+#endif
+			all_fmt |= flags;
+		}
+	}
+
+#ifdef CONFIG_FEATURE_LS_COLOR
+	{
+		/* find color bit value - last position for short getopt */
+
+#if CONFIG_FEATURE_LS_COLOR_IS_DEFAULT
+		char *p;
+
+		if ((p = getenv ("LS_COLORS")) != NULL &&
+			(*p == '\0' || (strcmp(p, "none") == 0))) {
+			;
+		} else if (isatty(STDOUT_FILENO)) {
+			show_color = 1;
+		}
+#endif
+
+		if((opt & (1 << i))) {  /* next flag after short options */
+			if (color_opt == NULL || strcmp("always", color_opt) == 0)
+				show_color = 1;
+			else if (color_opt != NULL && strcmp("never", color_opt) == 0)
+				show_color = 0;
+			else if (color_opt != NULL && strcmp("auto", color_opt) == 0 && isatty(STDOUT_FILENO))
+				show_color = 1;
+		}
+	}
+#endif
+
+	/* sort out which command line options take precedence */
+#ifdef CONFIG_FEATURE_LS_RECURSIVE
+	if (all_fmt & DISP_NOLIST)
+		all_fmt &= ~DISP_RECURSIVE;	/* no recurse if listing only dir */
+#endif
+	if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) {
+		if (all_fmt & TIME_CHANGE)
+			all_fmt = (all_fmt & ~SORT_MASK) | SORT_CTIME;
+		if (all_fmt & TIME_ACCESS)
+			all_fmt = (all_fmt & ~SORT_MASK) | SORT_ATIME;
+	}
+	if ((all_fmt & STYLE_MASK) != STYLE_LONG) /* only for long list */
+		all_fmt &= ~(LIST_ID_NUMERIC|LIST_FULLTIME|LIST_ID_NAME|LIST_ID_NUMERIC);
+#ifdef CONFIG_FEATURE_LS_USERNAME
+	if ((all_fmt & STYLE_MASK) == STYLE_LONG && (all_fmt & LIST_ID_NUMERIC))
+		all_fmt &= ~LIST_ID_NAME;	/* don't list names if numeric uid */
+#endif
+
+	/* choose a display format */
+	if (!(all_fmt & STYLE_MASK))
+		all_fmt |= (isatty(STDOUT_FILENO) ? STYLE_COLUMNS : STYLE_SINGLE);
+
+	/*
+	 * when there are no cmd line args we have to supply a default "." arg.
+	 * we will create a second argv array, "av" that will hold either
+	 * our created "." arg, or the real cmd line args.  The av array
+	 * just holds the pointers- we don't move the date the pointers
+	 * point to.
+	 */
+	ac = argc - optind;	/* how many cmd line args are left */
+	if (ac < 1) {
+		static const char * const dotdir[] = { "." };
+
+		av = (char **) dotdir;
+		ac = 1;
+	} else {
+		av = argv + optind;
+	}
+
+	/* now, everything is in the av array */
+	if (ac > 1)
+		all_fmt |= DISP_DIRNAME;	/* 2 or more items? label directories */
+
+	/* stuff the command line file names into an dnode array */
+	dn = NULL;
+	for (oi = 0; oi < ac; oi++) {
+		cur = my_stat(av[oi], av[oi]);
+		if (!cur)
+			continue;
+		cur->allocated = 0;
+		cur->next = dn;
+		dn = cur;
+		nfiles++;
+	}
+
+	/* now that we know how many files there are
+	   ** allocate memory for an array to hold dnode pointers
+	 */
+	dnp = dnalloc(nfiles);
+	for (i = 0, cur = dn; i < nfiles; i++) {
+		dnp[i] = cur;	/* save pointer to node in array */
+		cur = cur->next;
+	}
+
+	if (all_fmt & DISP_NOLIST) {
+		if (ENABLE_FEATURE_LS_SORTFILES) dnsort(dnp, nfiles);
+		if (nfiles > 0)
+			showfiles(dnp, nfiles);
+	} else {
+		dnd = splitdnarray(dnp, nfiles, SPLIT_DIR);
+		dnf = splitdnarray(dnp, nfiles, SPLIT_FILE);
+		dndirs = countdirs(dnp, nfiles);
+		dnfiles = nfiles - dndirs;
+		if (dnfiles > 0) {
+			if (ENABLE_FEATURE_LS_SORTFILES) dnsort(dnf, dnfiles);
+			showfiles(dnf, dnfiles);
+			if (ENABLE_FEATURE_CLEAN_UP)
+				free(dnf);
+		}
+		if (dndirs > 0) {
+			if (ENABLE_FEATURE_LS_SORTFILES) dnsort(dnd, dndirs);
+			showdirs(dnd, dndirs, dnfiles == 0);
+			if (ENABLE_FEATURE_CLEAN_UP)
+				free(dnd);
+		}
+	}
+	if (ENABLE_FEATURE_CLEAN_UP)
+		dfree(dnp, nfiles);
+	return (status);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/md5_sha1_sum.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/md5_sha1_sum.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/md5_sha1_sum.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,201 @@
+/* vi: set sw=4 ts=4: */
+/*
+ *  Copyright (C) 2003 Glenn L. McGrath
+ *  Copyright (C) 2003-2004 Erik Andersen
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "busybox.h"
+
+typedef enum { HASH_SHA1, HASH_MD5 } hash_algo_t;
+
+#define FLAG_SILENT	1
+#define FLAG_CHECK	2
+#define FLAG_WARN	4
+
+/* This might be useful elsewhere */
+static unsigned char *hash_bin_to_hex(unsigned char *hash_value,
+									  unsigned char hash_length)
+{
+	int x, len, max;
+	unsigned char *hex_value;
+
+	max = (hash_length * 2) + 2;
+	hex_value = xmalloc(max);
+	for (x = len = 0; x < hash_length; x++) {
+		len += snprintf((char*)(hex_value + len), max - len, "%02x", hash_value[x]);
+	}
+	return (hex_value);
+}
+
+static uint8_t *hash_file(const char *filename, hash_algo_t hash_algo)
+{
+	int src_fd, hash_len, count;
+	union _ctx_ {
+		sha1_ctx_t sha1;
+		md5_ctx_t md5;
+	} context;
+	uint8_t *hash_value = NULL;
+	RESERVE_CONFIG_UBUFFER(in_buf, 4096);
+	void (*update)(const void*, size_t, void*);
+	void (*final)(void*, void*);
+
+	if (strcmp(filename, "-") == 0) {
+		src_fd = STDIN_FILENO;
+	} else if(0 > (src_fd = open(filename, O_RDONLY))) {
+		bb_perror_msg("%s", filename);
+		return NULL;
+	}
+
+	/* figure specific hash algorithims */
+	if (ENABLE_MD5SUM && hash_algo==HASH_MD5) {
+		md5_begin(&context.md5);
+		update = (void (*)(const void*, size_t, void*))md5_hash;
+		final = (void (*)(void*, void*))md5_end;
+		hash_len = 16;
+	} else if (ENABLE_SHA1SUM && hash_algo==HASH_SHA1) {
+		sha1_begin(&context.sha1);
+		update = (void (*)(const void*, size_t, void*))sha1_hash;
+		final = (void (*)(void*, void*))sha1_end;
+		hash_len = 20;
+	} else {
+		bb_error_msg_and_die("algorithm not supported");
+	}
+
+	while (0 < (count = read(src_fd, in_buf, 4096))) {
+		update(in_buf, count, &context);
+	}
+
+	if (count == 0) {
+		final(in_buf, &context);
+		hash_value = hash_bin_to_hex(in_buf, hash_len);
+	}
+
+	RELEASE_CONFIG_BUFFER(in_buf);
+
+	if (src_fd != STDIN_FILENO) {
+		close(src_fd);
+	}
+
+	return hash_value;
+}
+
+/* This could become a common function for md5 as well, by using md5_stream */
+static int hash_files(int argc, char **argv, hash_algo_t hash_algo)
+{
+	int return_value = EXIT_SUCCESS;
+	uint8_t *hash_value;
+	unsigned int flags;
+
+	if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK)
+		flags = bb_getopt_ulflags(argc, argv, "scw");
+
+	if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK && !(flags & FLAG_CHECK)) {
+		if (flags & FLAG_SILENT) {
+			bb_error_msg_and_die
+				("the -s option is meaningful only when verifying checksums");
+		} else if (flags & FLAG_WARN) {
+			bb_error_msg_and_die
+				("the -w option is meaningful only when verifying checksums");
+		}
+	}
+
+	if (argc == optind) {
+		argv[argc++] = "-";
+	}
+
+	if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK && flags & FLAG_CHECK) {
+		FILE *pre_computed_stream;
+		int count_total = 0;
+		int count_failed = 0;
+		char *file_ptr = argv[optind];
+		char *line;
+
+		if (optind + 1 != argc) {
+			bb_error_msg_and_die
+				("only one argument may be specified when using -c");
+		}
+
+		if (strcmp(file_ptr, "-") == 0) {
+			pre_computed_stream = stdin;
+		} else {
+			pre_computed_stream = bb_xfopen(file_ptr, "r");
+		}
+
+		while ((line = bb_get_chomped_line_from_file(pre_computed_stream)) != NULL) {
+			char *filename_ptr;
+
+			count_total++;
+			filename_ptr = strstr(line, "  ");
+			if (filename_ptr == NULL) {
+				if (flags & FLAG_WARN) {
+					bb_error_msg("Invalid format");
+				}
+				count_failed++;
+				return_value = EXIT_FAILURE;
+				free(line);
+				continue;
+			}
+			*filename_ptr = '\0';
+			filename_ptr += 2;
+
+			hash_value = hash_file(filename_ptr, hash_algo);
+
+			if (hash_value && (strcmp((char*)hash_value, line) == 0)) {
+				if (!(flags & FLAG_SILENT))
+					printf("%s: OK\n", filename_ptr);
+			} else {
+				if (!(flags & FLAG_SILENT))
+					printf("%s: FAILED\n", filename_ptr);
+				count_failed++;
+				return_value = EXIT_FAILURE;
+			}
+			/* possible free(NULL) */
+			free(hash_value);
+			free(line);
+		}
+		if (count_failed && !(flags & FLAG_SILENT)) {
+			bb_error_msg("WARNING: %d of %d computed checksums did NOT match",
+						 count_failed, count_total);
+		}
+		if (bb_fclose_nonstdin(pre_computed_stream) == EOF) {
+			bb_perror_msg_and_die("Couldnt close file %s", file_ptr);
+		}
+	} else {
+		while (optind < argc) {
+			char *file_ptr = argv[optind++];
+
+			hash_value = hash_file(file_ptr, hash_algo);
+			if (hash_value == NULL) {
+				return_value = EXIT_FAILURE;
+			} else {
+				printf("%s  %s\n", hash_value, file_ptr);
+				free(hash_value);
+			}
+		}
+	}
+	return (return_value);
+}
+
+#ifdef CONFIG_MD5SUM
+int md5sum_main(int argc, char **argv)
+{
+	return (hash_files(argc, argv, HASH_MD5));
+}
+#endif
+
+#ifdef CONFIG_SHA1SUM
+int sha1sum_main(int argc, char **argv)
+{
+	return (hash_files(argc, argv, HASH_SHA1));
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/mkdir.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/mkdir.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/mkdir.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,79 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini mkdir implementation for busybox
+ *
+ * Copyright (C) 2001 Matt Kraai <kraai at alumni.carnegiemellon.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/mkdir.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Fixed broken permission setting when -p was used; especially in
+ * conjunction with -m.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h> /* struct option */
+#include "busybox.h"
+
+#if ENABLE_FEATURE_MKDIR_LONG_OPTIONS
+static const struct option mkdir_long_options[] = {
+	{ "mode", 1, NULL, 'm' },
+	{ "parents", 0, NULL, 'p' },
+	{ 0, 0, 0, 0 }
+};
+#endif
+
+int mkdir_main (int argc, char **argv)
+{
+	mode_t mode = (mode_t)(-1);
+	int status = EXIT_SUCCESS;
+	int flags = 0;
+	unsigned long opt;
+	char *smode;
+
+#if ENABLE_FEATURE_MKDIR_LONG_OPTIONS
+	bb_applet_long_options = mkdir_long_options;
+#endif
+	opt = bb_getopt_ulflags(argc, argv, "m:p", &smode);
+	if(opt & 1) {
+			mode = 0777;
+		if (!bb_parse_mode (smode, &mode)) {
+			bb_error_msg_and_die ("invalid mode `%s'", smode);
+		}
+	}
+	if(opt & 2)
+		flags |= FILEUTILS_RECUR;
+
+	if (optind == argc) {
+		bb_show_usage();
+	}
+
+	argv += optind;
+
+	do {
+		if (bb_make_directory(*argv, mode, flags)) {
+			status = EXIT_FAILURE;
+		}
+	} while (*++argv);
+
+	return status;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/mkfifo.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/mkfifo.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/mkfifo.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,51 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * mkfifo implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/mkfifo.html */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "busybox.h"
+#include "libcoreutils/coreutils.h"
+
+int mkfifo_main(int argc, char **argv)
+{
+	mode_t mode;
+	int retval = EXIT_SUCCESS;
+
+	mode = getopt_mk_fifo_nod(argc, argv);
+
+	if (!*(argv += optind)) {
+		bb_show_usage();
+	}
+
+	do {
+		if (mkfifo(*argv, mode) < 0) {
+			bb_perror_msg("%s", *argv);	/* Avoid multibyte problems. */
+			retval = EXIT_FAILURE;
+		}
+	} while (*++argv);
+
+	return retval;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/mknod.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/mknod.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/mknod.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,66 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * mknod implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>  // For makedev
+#include <unistd.h>
+#include "busybox.h"
+#include "libcoreutils/coreutils.h"
+
+static const char modes_chars[] = { 'p', 'c', 'u', 'b', 0, 1, 1, 2 };
+static const mode_t modes_cubp[] = { S_IFIFO, S_IFCHR, S_IFBLK };
+
+int mknod_main(int argc, char **argv)
+{
+	mode_t mode;
+	dev_t dev;
+	const char *name;
+
+	mode = getopt_mk_fifo_nod(argc, argv);
+	argv += optind;
+	argc -= optind;
+
+	if ((argc >= 2) && ((name = strchr(modes_chars, argv[1][0])) != NULL)) {
+		mode |= modes_cubp[(int)(name[4])];
+
+		dev = 0;
+		if ((*name != 'p') && ((argc -= 2) == 2)) {
+			/* Autodetect what the system supports; thexe macros should
+			 * optimize out to two constants. */
+			dev = makedev(bb_xgetularg10_bnd(argv[2], 0, major(UINT_MAX)),
+						  bb_xgetularg10_bnd(argv[3], 0, minor(UINT_MAX)));
+		}
+
+		if (argc == 2) {
+			name = *argv;
+			if (mknod(name, mode, dev) == 0) {
+				return EXIT_SUCCESS;
+			}
+			bb_perror_msg_and_die("%s", name);
+		}
+	}
+	bb_show_usage();
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/mv.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/mv.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/mv.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,143 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini mv implementation for busybox
+ *
+ * Copyright (C) 2000 by Matt Kraai <kraai at alumni.carnegiemellon.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Size reduction and improved error checking.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <getopt.h> /* struct option */
+#include "busybox.h"
+#include "libcoreutils/coreutils.h"
+
+#if ENABLE_FEATURE_MV_LONG_OPTIONS
+static const struct option mv_long_options[] = {
+	{ "interactive", 0, NULL, 'i' },
+	{ "force", 0, NULL, 'f' },
+	{ 0, 0, 0, 0 }
+};
+#endif
+
+#define OPT_FILEUTILS_FORCE       1
+#define OPT_FILEUTILS_INTERACTIVE 2
+
+static const char fmt[] = "cannot overwrite %sdirectory with %sdirectory";
+
+int mv_main(int argc, char **argv)
+{
+	struct stat dest_stat;
+	const char *last;
+	const char *dest;
+	unsigned long flags;
+	int dest_exists;
+	int status = 0;
+
+#if ENABLE_FEATURE_MV_LONG_OPTIONS
+	bb_applet_long_options = mv_long_options;
+#endif
+	bb_opt_complementally = "f-i:i-f";
+	flags = bb_getopt_ulflags(argc, argv, "fi");
+	if (optind + 2 > argc) {
+		bb_show_usage();
+	}
+
+	last = argv[argc - 1];
+	argv += optind;
+
+	if (optind + 2 == argc) {
+		if ((dest_exists = cp_mv_stat(last, &dest_stat)) < 0) {
+			return 1;
+		}
+
+		if (!(dest_exists & 2)) {
+			dest = last;
+			goto DO_MOVE;
+		}
+	}
+
+	do {
+		dest = concat_path_file(last, bb_get_last_path_component(*argv));
+
+		if ((dest_exists = cp_mv_stat(dest, &dest_stat)) < 0) {
+			goto RET_1;
+		}
+
+DO_MOVE:
+
+		if (dest_exists && !(flags & OPT_FILEUTILS_FORCE) &&
+			((access(dest, W_OK) < 0 && isatty(0)) ||
+			(flags & OPT_FILEUTILS_INTERACTIVE))) {
+			if (fprintf(stderr, "mv: overwrite `%s'? ", dest) < 0) {
+				goto RET_1;	/* Ouch! fprintf failed! */
+			}
+			if (!bb_ask_confirmation()) {
+				goto RET_0;
+			}
+		}
+		if (rename(*argv, dest) < 0) {
+			struct stat source_stat;
+			int source_exists;
+
+			if (errno != EXDEV ||
+				(source_exists = cp_mv_stat(*argv, &source_stat)) < 1) {
+				bb_perror_msg("unable to rename `%s'", *argv);
+			} else {
+				if (dest_exists) {
+					if (dest_exists == 3) {
+						if (source_exists != 3) {
+							bb_error_msg(fmt, "", "non-");
+							goto RET_1;
+						}
+					} else {
+						if (source_exists == 3) {
+							bb_error_msg(fmt, "non-", "");
+							goto RET_1;
+						}
+					}
+					if (unlink(dest) < 0) {
+						bb_perror_msg("cannot remove `%s'", dest);
+						goto RET_1;
+					}
+				}
+				if ((copy_file(*argv, dest,
+					FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS) >= 0) &&
+					(remove_file(*argv, FILEUTILS_RECUR | FILEUTILS_FORCE) >= 0)) {
+					goto RET_0;
+				}
+			}
+RET_1:
+			status = 1;
+		}
+RET_0:
+		if (dest != last) {
+			free((void *) dest);
+		}
+	} while (*++argv != last);
+
+	return (status);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/nice.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/nice.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/nice.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,85 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * nice implementation for busybox
+ *
+ * Copyright (C) 2005  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/resource.h>
+#include "busybox.h"
+
+static inline int int_add_no_wrap(int a, int b)
+{
+	int s = a + b;
+
+	if (b < 0) {
+		if (s > a) s = INT_MIN;
+	} else {
+		if (s < a) s = INT_MAX;
+	}
+
+	return s;
+}
+
+int nice_main(int argc, char **argv)
+{
+	static const char Xetpriority_msg[] = "cannot %cet priority";
+
+	int old_priority, adjustment;
+
+	errno = 0;			 /* Needed for getpriority error detection. */
+	old_priority = getpriority(PRIO_PROCESS, 0);
+	if (errno) {
+		bb_perror_msg_and_die(Xetpriority_msg, 'g');
+	}
+
+	if (!*++argv) {	/* No args, so (GNU) output current nice value. */
+		bb_printf("%d\n", old_priority);
+		bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+	}
+
+	adjustment = 10;			/* Set default adjustment. */
+
+	if ((argv[0][0] == '-') && (argv[0][1] == 'n') && !argv[0][2]) { /* "-n" */
+		if (argc < 4) {			/* Missing priority and/or utility! */
+			bb_show_usage();
+		}
+		adjustment = bb_xgetlarg(argv[1], 10, INT_MIN, INT_MAX);
+		argv += 2;
+	}
+
+	{  /* Set our priority.  Handle integer wrapping for old + adjust. */
+		int new_priority = int_add_no_wrap(old_priority, adjustment);
+
+		if (setpriority(PRIO_PROCESS, 0, new_priority) < 0) {
+			bb_perror_msg_and_die(Xetpriority_msg, 's');
+		}
+	}
+
+	execvp(*argv, argv);		/* Now exec the desired program. */
+
+	/* The exec failed... */
+	bb_default_error_retval = (errno == ENOENT) ? 127 : 126; /* SUSv3 */
+	bb_perror_msg_and_die("%s", *argv);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/nohup.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/nohup.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/nohup.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,60 @@
+/* vi:set ts=4: */
+/* nohup - invoke a utility immune to hangups.
+ * 
+ * Busybox version based on nohup specification at
+ * http://www.opengroup.org/onlinepubs/007904975/utilities/nohup.html
+ * 
+ * Copyright 2006 Rob Landley <rob at landley.net>
+ * 
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include "busybox.h"
+
+int nohup_main(int argc, char *argv[])
+{
+	int temp, nullfd;
+	char *nohupout = "nohup.out", *home = NULL;
+
+	// I have no idea why the standard cares about this.
+
+	bb_default_error_retval = 127;
+
+	if (argc<2) bb_show_usage();
+
+	nullfd = bb_xopen(bb_dev_null, O_WRONLY|O_APPEND);
+	// If stdin is a tty, detach from it.
+
+	if (isatty(0)) dup2(nullfd, 0);
+
+	// Redirect stdout to nohup.out, either in "." or in "$HOME".
+
+	if (isatty(1)) {
+		close(1);
+		if (open(nohupout, O_CREAT|O_WRONLY|O_APPEND, S_IRUSR|S_IWUSR) < 0) {
+			home = getenv("HOME");
+			if (home) {
+				home = concat_path_file(home, nohupout);
+				bb_xopen3(nohupout, O_CREAT|O_WRONLY|O_APPEND, S_IRUSR|S_IWUSR);
+			}
+		}
+	} else dup2(nullfd, 1);
+
+	// If we have a tty on strderr, announce filename and redirect to stdout.
+	// Else redirect to /dev/null.
+
+	temp = isatty(2);
+	if (temp) fdprintf(2,"Writing to %s\n", home ? home : nohupout);
+	dup2(temp ? 1 : nullfd, 2);
+	close(nullfd);
+	signal (SIGHUP, SIG_IGN);
+
+	// Exec our new program.
+
+	execvp(argv[1],argv+1);
+	if (ENABLE_FEATURE_CLEAN_UP) free(home);
+	bb_error_msg_and_die("exec %s",argv[1]);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/od.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/od.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/od.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,231 @@
+/*
+ * od implementation for busybox
+ * Based on code from util-linux v 2.11l
+ *
+ * Copyright (c) 1990
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Original copyright notice is retained at the end of this file.
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include "busybox.h"
+#include "dump.h"
+
+#define isdecdigit(c) (isdigit)(c)
+#define ishexdigit(c) (isxdigit)(c)
+
+static void
+odoffset(int argc, char ***argvp)
+{
+	register char *num, *p;
+	int base;
+	char *end;
+
+	/*
+	 * The offset syntax of od(1) was genuinely bizarre.  First, if
+	 * it started with a plus it had to be an offset.  Otherwise, if
+	 * there were at least two arguments, a number or lower-case 'x'
+	 * followed by a number makes it an offset.  By default it was
+	 * octal; if it started with 'x' or '0x' it was hex.  If it ended
+	 * in a '.', it was decimal.  If a 'b' or 'B' was appended, it
+	 * multiplied the number by 512 or 1024 byte units.  There was
+	 * no way to assign a block count to a hex offset.
+	 *
+	 * We assumes it's a file if the offset is bad.
+	 */
+	p = **argvp;
+
+	if (!p) {
+		/* hey someone is probably piping to us ... */
+		return;
+	}
+
+	if ((*p != '+')
+		&& (argc < 2
+			|| (!isdecdigit(p[0])
+				&& ((p[0] != 'x') || !ishexdigit(p[1])))))
+		return;
+
+	base = 0;
+	/*
+	 * bb_dump_skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
+	 * set base.
+	 */
+	if (p[0] == '+')
+		++p;
+	if (p[0] == 'x' && ishexdigit(p[1])) {
+		++p;
+		base = 16;
+	} else if (p[0] == '0' && p[1] == 'x') {
+		p += 2;
+		base = 16;
+	}
+
+	/* bb_dump_skip over the number */
+	if (base == 16)
+		for (num = p; ishexdigit(*p); ++p);
+	else
+		for (num = p; isdecdigit(*p); ++p);
+
+	/* check for no number */
+	if (num == p)
+		return;
+
+	/* if terminates with a '.', base is decimal */
+	if (*p == '.') {
+		if (base)
+			return;
+		base = 10;
+	}
+
+	bb_dump_skip = strtol(num, &end, base ? base : 8);
+
+	/* if end isn't the same as p, we got a non-octal digit */
+	if (end != p)
+		bb_dump_skip = 0;
+	else {
+		if (*p) {
+			if (*p == 'b') {
+				bb_dump_skip *= 512;
+				++p;
+			} else if (*p == 'B') {
+				bb_dump_skip *= 1024;
+				++p;
+			}
+		}
+		if (*p)
+			bb_dump_skip = 0;
+		else {
+			++*argvp;
+			/*
+			 * If the offset uses a non-octal base, the base of
+			 * the offset is changed as well.  This isn't pretty,
+			 * but it's easy.
+			 */
+#define	TYPE_OFFSET	7
+			{
+				char x_or_d;
+				if (base == 16) {
+					x_or_d = 'x';
+					goto DO_X_OR_D;
+				}
+				if (base == 10) {
+					x_or_d = 'd';
+				DO_X_OR_D:
+					bb_dump_fshead->nextfu->fmt[TYPE_OFFSET]
+						= bb_dump_fshead->nextfs->nextfu->fmt[TYPE_OFFSET]
+						= x_or_d;
+				}
+			}
+		}
+	}
+}
+
+static const char * const add_strings[] = {
+	"16/1 \"%3_u \" \"\\n\"",				/* a */
+	"8/2 \" %06o \" \"\\n\"",				/* B, o */
+	"16/1 \"%03o \" \"\\n\"",				/* b */
+	"16/1 \"%3_c \" \"\\n\"",				/* c */
+	"8/2 \"  %05u \" \"\\n\"",				/* d */
+	"4/4 \"     %010u \" \"\\n\"",			/* D */
+	"2/8 \"          %21.14e \" \"\\n\"",	/* e (undocumented in od), F */
+	"4/4 \" %14.7e \" \"\\n\"",				/* f */
+	"4/4 \"       %08x \" \"\\n\"",			/* H, X */
+	"8/2 \"   %04x \" \"\\n\"",				/* h, x */
+	"4/4 \"    %11d \" \"\\n\"",			/* I, L, l */
+	"8/2 \" %6d \" \"\\n\"",				/* i */
+	"4/4 \"    %011o \" \"\\n\"",			/* O */
+};
+
+static const char od_opts[] = "aBbcDdeFfHhIiLlOoXxv";
+
+static const char od_o2si[] = {
+	0, 1, 2, 3, 5,
+	4, 6, 6, 7, 8,
+	9, 0xa, 0xb, 0xa, 0xa,
+	0xb, 1, 8, 9,
+};
+
+int od_main(int argc, char **argv)
+{
+	int ch;
+	int first = 1;
+	char *p;
+	bb_dump_vflag = FIRST;
+	bb_dump_length = -1;
+
+	while ((ch = getopt(argc, argv, od_opts)) > 0) {
+		if (ch == 'v') {
+			bb_dump_vflag = ALL;
+		} else if (((p = strchr(od_opts, ch)) != NULL) && (*p != '\0')) {
+			if (first) {
+				first = 0;
+				bb_dump_add("\"%07.7_Ao\n\"");
+				bb_dump_add("\"%07.7_ao  \"");
+			} else {
+				bb_dump_add("\"         \"");
+			}
+			bb_dump_add(add_strings[(int)od_o2si[(p-od_opts)]]);
+		} else {	/* P, p, s, w, or other unhandled */
+			bb_show_usage();
+		}
+	}
+	if (!bb_dump_fshead) {
+		bb_dump_add("\"%07.7_Ao\n\"");
+		bb_dump_add("\"%07.7_ao  \" 8/2 \"%06o \" \"\\n\"");
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	odoffset(argc, &argv);
+
+	return(bb_dump_dump(argv));
+}
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/printenv.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/printenv.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/printenv.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,53 @@
+/*
+ * printenv implementation for busybox
+ *
+ * Copyright (C) 2005 by Erik Andersen <andersen at codepoet.org>
+ * Copyright (C) 2005 by Mike Frysinger <vapier at gentoo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+int printenv_main(int argc, char **argv)
+{
+	extern char **environ;
+	int e = 0;
+
+	/* no variables specified, show whole env */
+	if (argc == 1)
+		while (environ[e])
+			puts(environ[e++]);
+
+	/* search for specified variables and print them out if found */
+	else {
+		int i;
+		size_t l;
+		char *arg, *env;
+
+		for (i=1; (arg = argv[i]); ++i)
+			for (; (env = environ[e]); ++e) {
+				l = strlen(arg);
+				if (!strncmp(env, arg, l) && env[l] == '=')
+					puts(env + l + 1);
+			}
+	}
+
+	bb_fflush_stdout_and_exit(0);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/printf.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/printf.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/printf.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,312 @@
+/* vi: set sw=4 ts=4: */
+/* printf - format and print data
+
+   Copyright 1999 Dave Cinege
+   Portions copyright (C) 1990-1996 Free Software Foundation, Inc.
+
+   Licensed under GPL v2 or later, see file LICENSE in this tarball for details.
+*/
+
+/* Usage: printf format [argument...]
+
+   A front end to the printf function that lets it be used from the shell.
+
+   Backslash escapes:
+
+   \" = double quote
+   \\ = backslash
+   \a = alert (bell)
+   \b = backspace
+   \c = produce no further output
+   \f = form feed
+   \n = new line
+   \r = carriage return
+   \t = horizontal tab
+   \v = vertical tab
+   \0ooo = octal number (ooo is 0 to 3 digits)
+   \xhhh = hexadecimal number (hhh is 1 to 3 digits)
+
+   Additional directive:
+
+   %b = print an argument string, interpreting backslash escapes
+
+   The `format' argument is re-used as many times as necessary
+   to convert all of the given arguments.
+
+   David MacKenzie <djm at gnu.ai.mit.edu> */
+
+
+//   19990508 Busy Boxed! Dave Cinege
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <assert.h>
+#include "busybox.h"
+
+static int print_formatted (char *format, int argc, char **argv);
+static void print_direc (char *start, size_t length,
+			int field_width, int precision, char *argument);
+
+typedef int (*converter)(char *arg, void *result);
+static void multiconvert(char *arg, void *result, converter convert)
+{
+	char s[16];
+	if (*arg == '"' || *arg == '\'') {
+		sprintf(s,"%d",(unsigned)*(++arg));
+		arg=s;
+	}
+	if(convert(arg,result)) fprintf(stderr, "%s", arg);
+}
+
+static unsigned long xstrtoul(char *arg)
+{
+	unsigned long result;
+
+	multiconvert(arg,&result, (converter)safe_strtoul);
+	return result;
+}
+
+static long xstrtol(char *arg)
+{
+	long result;
+	multiconvert(arg, &result, (converter)safe_strtol);
+	return result;
+}
+
+static double xstrtod(char *arg)
+{
+	double result;
+	multiconvert(arg, &result, (converter)safe_strtod);
+	return result;
+}
+
+static void print_esc_string(char *str)
+{
+	for (; *str; str++) {
+		if (*str == '\\') {
+			str++;
+			putchar(bb_process_escape_sequence((const char **)&str));
+		} else {
+			putchar(*str);
+		}
+
+	}
+}
+
+int printf_main(int argc, char **argv)
+{
+	char *format;
+	int args_used;
+
+	if (argc <= 1 || **(argv + 1) == '-') {
+		bb_show_usage();
+	}
+
+	format = argv[1];
+	argc -= 2;
+	argv += 2;
+
+	do {
+		args_used = print_formatted(format, argc, argv);
+		argc -= args_used;
+		argv += args_used;
+	}
+	while (args_used > 0 && argc > 0);
+
+/*
+  if (argc > 0)
+    fprintf(stderr, "excess args ignored");
+*/
+
+	return EXIT_SUCCESS;
+}
+
+/* Print the text in FORMAT, using ARGV (with ARGC elements) for
+   arguments to any `%' directives.
+   Return the number of elements of ARGV used.  */
+
+static int print_formatted(char *format, int argc, char **argv)
+{
+	int save_argc = argc;		/* Preserve original value.  */
+	char *f;					/* Pointer into `format'.  */
+	char *direc_start;			/* Start of % directive.  */
+	size_t direc_length;		/* Length of % directive.  */
+	int field_width;			/* Arg to first '*', or -1 if none.  */
+	int precision;				/* Arg to second '*', or -1 if none.  */
+
+	for (f = format; *f; ++f) {
+		switch (*f) {
+		case '%':
+			direc_start = f++;
+			direc_length = 1;
+			field_width = precision = -1;
+			if (*f == '%') {
+				putchar('%');
+				break;
+			}
+			if (*f == 'b') {
+				if (argc > 0) {
+					print_esc_string(*argv);
+					++argv;
+					--argc;
+				}
+				break;
+			}
+			if (strchr("-+ #", *f)) {
+				++f;
+				++direc_length;
+			}
+			if (*f == '*') {
+				++f;
+				++direc_length;
+				if (argc > 0) {
+					field_width = xstrtoul(*argv);
+					++argv;
+					--argc;
+				} else
+					field_width = 0;
+			} else
+				while (isdigit(*f)) {
+					++f;
+					++direc_length;
+				}
+			if (*f == '.') {
+				++f;
+				++direc_length;
+				if (*f == '*') {
+					++f;
+					++direc_length;
+					if (argc > 0) {
+						precision = xstrtoul(*argv);
+						++argv;
+						--argc;
+					} else
+						precision = 0;
+				} else
+					while (isdigit(*f)) {
+						++f;
+						++direc_length;
+					}
+			}
+			if (*f == 'l' || *f == 'L' || *f == 'h') {
+				++f;
+				++direc_length;
+			}
+			/*
+			   if (!strchr ("diouxXfeEgGcs", *f))
+			   fprintf(stderr, "%%%c: invalid directive", *f);
+			 */
+			++direc_length;
+			if (argc > 0) {
+				print_direc(direc_start, direc_length, field_width,
+							precision, *argv);
+				++argv;
+				--argc;
+			} else
+				print_direc(direc_start, direc_length, field_width,
+							precision, "");
+			break;
+
+		case '\\':
+			if (*++f == 'c')
+				exit(0);
+			putchar(bb_process_escape_sequence((const char **)&f));
+			f--;
+			break;
+
+		default:
+			putchar(*f);
+		}
+	}
+
+	return save_argc - argc;
+}
+
+static void
+print_direc(char *start, size_t length, int field_width, int precision,
+			char *argument)
+{
+	char *p;					/* Null-terminated copy of % directive. */
+
+	p = xmalloc((unsigned) (length + 1));
+	strncpy(p, start, length);
+	p[length] = 0;
+
+	switch (p[length - 1]) {
+	case 'd':
+	case 'i':
+		if (field_width < 0) {
+			if (precision < 0)
+				printf(p, xstrtol(argument));
+			else
+				printf(p, precision, xstrtol(argument));
+		} else {
+			if (precision < 0)
+				printf(p, field_width, xstrtol(argument));
+			else
+				printf(p, field_width, precision, xstrtol(argument));
+		}
+		break;
+
+	case 'o':
+	case 'u':
+	case 'x':
+	case 'X':
+		if (field_width < 0) {
+			if (precision < 0)
+				printf(p, xstrtoul(argument));
+			else
+				printf(p, precision, xstrtoul(argument));
+		} else {
+			if (precision < 0)
+				printf(p, field_width, xstrtoul(argument));
+			else
+				printf(p, field_width, precision, xstrtoul(argument));
+		}
+		break;
+
+	case 'f':
+	case 'e':
+	case 'E':
+	case 'g':
+	case 'G':
+		if (field_width < 0) {
+			if (precision < 0)
+				printf(p, xstrtod(argument));
+			else
+				printf(p, precision, xstrtod(argument));
+		} else {
+			if (precision < 0)
+				printf(p, field_width, xstrtod(argument));
+			else
+				printf(p, field_width, precision, xstrtod(argument));
+		}
+		break;
+
+	case 'c':
+		printf(p, *argument);
+		break;
+
+	case 's':
+		if (field_width < 0) {
+			if (precision < 0)
+				printf(p, argument);
+			else
+				printf(p, precision, argument);
+		} else {
+			if (precision < 0)
+				printf(p, field_width, argument);
+			else
+				printf(p, field_width, precision, argument);
+		}
+		break;
+	}
+
+	free(p);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/pwd.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/pwd.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/pwd.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,37 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini pwd implementation for busybox
+ *
+ * Copyright (C) 1995, 1996 by Bruce Perens <bruce at pixar.com>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+int pwd_main(int argc, char **argv)
+{
+	char *buf;
+
+	if ((buf = xgetcwd(NULL)) != NULL) {
+		puts(buf);
+		bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+	}
+
+	return EXIT_FAILURE;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/realpath.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/realpath.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/realpath.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,48 @@
+/* vi: set sw=4 ts=4: */
+
+/* BB_AUDIT SUSv3 N/A -- Apparently a busybox extension. */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Now does proper error checking on output and returns a failure exit code
+ * if one or more paths can not be resolved.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <limits.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+int realpath_main(int argc, char **argv)
+{
+	int retval = EXIT_SUCCESS;
+
+#if PATH_MAX > (BUFSIZ+1)
+	RESERVE_CONFIG_BUFFER(resolved_path, PATH_MAX);
+# define resolved_path_MUST_FREE 1
+#else
+#define resolved_path bb_common_bufsiz1
+# define resolved_path_MUST_FREE 0
+#endif
+
+	if (--argc == 0) {
+		bb_show_usage();
+	}
+
+	do {
+		argv++;
+		if (realpath(*argv, resolved_path) != NULL) {
+			puts(resolved_path);
+		} else {
+			retval = EXIT_FAILURE;
+			bb_perror_msg("%s", *argv);
+		}
+	} while (--argc);
+
+#if ENABLE_FEATURE_CLEAN_UP && resolved_path_MUST_FREE
+	RELEASE_CONFIG_BUFFER(resolved_path);
+#endif
+
+	bb_fflush_stdout_and_exit(retval);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/rm.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/rm.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/rm.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,66 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini rm implementation for busybox
+ *
+ * Copyright (C) 2001 Matt Kraai <kraai at alumni.carnegiemellon.edu>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/rm.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Size reduction.
+ */
+
+#include <unistd.h>
+#include "busybox.h"
+
+int rm_main(int argc, char **argv)
+{
+	int status = 0;
+	int flags = 0;
+	unsigned long opt;
+
+	bb_opt_complementally = "f-i:i-f";
+	opt = bb_getopt_ulflags(argc, argv, "fiRr");
+	if(opt & 1)
+				flags |= FILEUTILS_FORCE;
+	if(opt & 2)
+		flags |= FILEUTILS_INTERACTIVE;
+	if(opt & 12)
+		flags |= FILEUTILS_RECUR;
+
+	if (*(argv += optind) != NULL) {
+		do {
+			const char *base = bb_get_last_path_component(*argv);
+
+			if ((base[0] == '.') && (!base[1] || ((base[1] == '.') && !base[2]))) {
+				bb_error_msg("cannot remove `.' or `..'");
+			} else if (remove_file(*argv, flags) >= 0) {
+				continue;
+			}
+			status = 1;
+		} while (*++argv);
+	} else if (!(flags & FILEUTILS_FORCE)) {
+		bb_show_usage();
+	}
+
+	return status;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/rmdir.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/rmdir.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/rmdir.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,73 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * rmdir implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/rmdir.html */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <libgen.h>
+#include "busybox.h"
+
+int rmdir_main(int argc, char **argv)
+{
+	int status = EXIT_SUCCESS;
+	int flags;
+	int do_dot;
+	char *path;
+
+	flags = bb_getopt_ulflags(argc, argv, "p");
+
+	argv += optind;
+
+	if (!*argv) {
+		bb_show_usage();
+	}
+
+	do {
+		path = *argv;
+
+		/* Record if the first char was a '.' so we can use dirname later. */
+		do_dot = (*path == '.');
+
+		do {
+			if (rmdir(path) < 0) {
+				bb_perror_msg("`%s'", path);	/* Match gnu rmdir msg. */
+				status = EXIT_FAILURE;
+			} else if (flags) {
+				/* Note: path was not empty or null since rmdir succeeded. */
+				path = dirname(path);
+				/* Path is now just the parent component.  Note that dirname
+				 * returns "." if there are no parents.  We must distinguish
+				 * this from the case of the original path starting with '.'.
+		 */
+				if (do_dot || (*path != '.') || path[1]) {
+					continue;
+				}
+			}
+			break;
+		} while (1);
+
+	} while (*++argv);
+
+	return status;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/seq.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/seq.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/seq.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,40 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * seq implementation for busybox
+ *
+ * Copyright (C) 2004, Glenn McGrath
+ *
+ * Licensed under the GPL v2, see the file LICENSE in this tarball.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+int seq_main(int argc, char **argv)
+{
+	double last, first, increment, i;
+	
+	first = increment = 1;
+	switch (argc) {
+		case 4:
+			increment=atof(argv[2]);
+		case 3:
+			first=atof(argv[1]);
+		case 2:
+			last=atof(argv[argc -1]);
+			break;
+		default:
+			bb_show_usage();
+	}
+
+	/* You should note that this is pos-5.0.91 semantics, -- FK. */
+	for (i = first;
+         (increment > 0 && i <= last) || (increment < 0 && i >=last);
+		 i += increment)
+	{
+		printf("%g\n", i);
+	}
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/sleep.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/sleep.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/sleep.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,86 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * sleep implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* BB_AUDIT GNU issues -- fancy version matches except args must be ints. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/sleep.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Rewritten to do proper arg and error checking.
+ * Also, added a 'fancy' configuration to accept multiple args with
+ * time suffixes for seconds, minutes, hours, and days.
+ */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <unistd.h>
+#include "busybox.h"
+
+#ifdef CONFIG_FEATURE_FANCY_SLEEP
+static const struct suffix_mult sleep_suffixes[] = {
+	{ "s", 1 },
+	{ "m", 60 },
+	{ "h", 60*60 },
+	{ "d", 24*60*60 },
+	{ NULL, 0 }
+};
+#endif
+
+int sleep_main(int argc, char **argv)
+{
+	unsigned int duration;
+
+#ifdef CONFIG_FEATURE_FANCY_SLEEP
+
+	if (argc < 2) {
+		bb_show_usage();
+	}
+
+	++argv;
+	duration = 0;
+	do {
+		duration += bb_xgetularg_bnd_sfx(*argv, 10,
+										 0, UINT_MAX-duration,
+										 sleep_suffixes);
+	} while (*++argv);
+
+#else  /* CONFIG_FEATURE_FANCY_SLEEP */
+
+	if (argc != 2) {
+		bb_show_usage();
+	}
+
+#if UINT_MAX == ULONG_MAX
+	duration = bb_xgetularg10(argv[1]);
+#else
+	duration = bb_xgetularg10_bnd(argv[1], 0, UINT_MAX);
+#endif
+
+#endif /* CONFIG_FEATURE_FANCY_SLEEP */
+
+	if (sleep(duration)) {
+		bb_perror_nomsg_and_die();
+	}
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/sort.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/sort.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/sort.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,330 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * SuS3 compliant sort implementation for busybox
+ *
+ * Copyright (C) 2004 by Rob Landley <rob at landley.net>
+ *
+ * MAINTAINER: Rob Landley <rob at landley.net>
+ * 
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * See SuS3 sort standard at:
+ * http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html
+ */
+
+#include <ctype.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include "busybox.h"
+
+static int global_flags;
+
+/*
+	sort [-m][-o output][-bdfinru][-t char][-k keydef]... [file...]
+	sort -c [-bdfinru][-t char][-k keydef][file]
+*/
+
+/* These are sort types */
+#define FLAG_n			1		/* Numeric sort */
+#define FLAG_g			2		/* Sort using strtod() */
+#define FLAG_M			4		/* Sort date */
+/* ucsz apply to root level only, not keys.  b at root level implies bb */
+#define FLAG_u			8		/* Unique */
+#define FLAG_c			16		/* Check: no output, exit(!ordered) */
+#define FLAG_s			32		/* Stable sort, no ascii fallback at end */
+#define FLAG_z			64		/* Input is null terminated, not \n */
+/* These can be applied to search keys, the previous four can't */
+#define FLAG_b			128		/* Ignore leading blanks */
+#define FLAG_r			256		/* Reverse */
+#define FLAG_d			512		/* Ignore !(isalnum()|isspace()) */
+#define FLAG_f			1024	/* Force uppercase */
+#define FLAG_i			2048	/* Ignore !isprint() */
+#define FLAG_bb			32768	/* Ignore trailing blanks  */
+
+
+#ifdef CONFIG_FEATURE_SORT_BIG
+static char key_separator;
+
+static struct sort_key
+{
+	struct sort_key *next_key;	/* linked list */
+	unsigned short range[4];	/* start word, start char, end word, end char */
+	int flags;
+} *key_list;
+
+static char *get_key(char *str, struct sort_key *key, int flags)
+{
+	int start=0,end,len,i,j;
+
+	/* Special case whole string, so we don't have to make a copy */
+	if(key->range[0]==1 && !key->range[1] && !key->range[2] && !key->range[3]
+		&& !(flags&(FLAG_b&FLAG_d&FLAG_f&FLAG_i&FLAG_bb))) return str;
+	/* Find start of key on first pass, end on second pass*/
+	len=strlen(str);
+
+	for(j=0;j<2;j++) {
+		if(!key->range[2*j]) end=len;
+		/* Loop through fields */
+		else {
+			end=0;
+			for(i=1;i<key->range[2*j]+j;i++) {
+				/* Skip leading blanks or first separator */
+				if(str[end]) {
+					if(!key_separator && isspace(str[end]))
+						while(isspace(str[end])) end++;
+				}
+				/* Skip body of key */
+				for(;str[end];end++) {
+					if(key_separator) {
+						if(str[end]==key_separator) break;
+					} else if(isspace(str[end])) break;
+				}
+			}
+		}
+		if(!j) start=end;
+	}
+	/* Key with explicit separator starts after separator */
+	if(key_separator && str[start]==key_separator) start++;
+	/* Strip leading whitespace if necessary */
+	if(flags&FLAG_b) while(isspace(str[start])) start++;
+	/* Strip trailing whitespace if necessary */
+	if(flags&FLAG_bb) while(end>start && isspace(str[end-1])) end--;
+	/* Handle offsets on start and end */
+	if(key->range[3]) {
+		end+=key->range[3]-1;
+		if(end>len) end=len;
+	}
+	if(key->range[1]) {
+		start+=key->range[1]-1;
+		if(start>len) start=len;
+	}
+	/* Make the copy */
+	if(end<start) end=start;
+	str=bb_xstrndup(str+start,end-start);
+	/* Handle -d */
+	if(flags&FLAG_d) {
+		for(start=end=0;str[end];end++)
+			if(isspace(str[end]) || isalnum(str[end])) str[start++]=str[end];
+		str[start]=0;
+	}
+	/* Handle -i */
+	if(flags&FLAG_i) {
+		for(start=end=0;str[end];end++)
+			if(isprint(str[end])) str[start++]=str[end];
+		str[start]=0;
+	}
+	/* Handle -f */
+	if(flags*FLAG_f) for(i=0;str[i];i++) str[i]=toupper(str[i]);
+
+	return str;
+}
+
+static struct sort_key *add_key(void)
+{
+	struct sort_key **pkey=&key_list;
+	while(*pkey) pkey=&((*pkey)->next_key);
+	return *pkey=xcalloc(1,sizeof(struct sort_key));
+}
+
+#define GET_LINE(fp) (global_flags&FLAG_z) ? bb_get_chunk_from_file(fp,NULL) \
+										   : bb_get_chomped_line_from_file(fp)
+#else
+#define GET_LINE(fp)		bb_get_chomped_line_from_file(fp)
+#endif
+
+/* Iterate through keys list and perform comparisons */
+static int compare_keys(const void *xarg, const void *yarg)
+{
+	int flags=global_flags,retval=0;
+	char *x,*y;
+
+#ifdef CONFIG_FEATURE_SORT_BIG
+	struct sort_key *key;
+
+	for(key=key_list;!retval && key;key=key->next_key) {
+		flags=(key->flags) ? key->flags : global_flags;
+		/* Chop out and modify key chunks, handling -dfib */
+		x=get_key(*(char **)xarg,key,flags);
+		y=get_key(*(char **)yarg,key,flags);
+#else
+	/* This curly bracket serves no purpose but to match the nesting
+	   level of the for() loop we're not using */
+	{
+		x=*(char **)xarg;
+		y=*(char **)yarg;
+#endif
+		/* Perform actual comparison */
+		switch(flags&7) {
+			default:
+				bb_error_msg_and_die("Unknown sort type.");
+				break;
+			/* Ascii sort */
+			case 0:
+				retval=strcmp(x,y);
+				break;
+#ifdef CONFIG_FEATURE_SORT_BIG
+			case FLAG_g:
+			{
+				char *xx,*yy;
+				double dx=strtod(x,&xx), dy=strtod(y,&yy);
+				/* not numbers < NaN < -infinity < numbers < +infinity) */
+				if(x==xx) retval=(y==yy ? 0 : -1);
+				else if(y==yy) retval=1;
+				/* Check for isnan */
+				else if(dx != dx) retval = (dy != dy) ? 0 : -1;
+				else if(dy != dy) retval = 1;
+				/* Check for infinity.  Could underflow, but it avoids libm. */
+				else if(1.0/dx == 0.0) {
+					if(dx<0) retval=((1.0/dy == 0.0 && dy<0) ? 0 : -1);
+					else retval=((1.0/dy == 0.0 && dy>0) ? 0 : 1);
+				} else if(1.0/dy == 0.0) retval=dy<0 ? 1 : -1;
+				else retval=dx>dy ? 1 : (dx<dy ? -1 : 0);
+				break;
+			}
+			case FLAG_M:
+			{
+				struct tm thyme;
+				int dx;
+				char *xx,*yy;
+
+				xx=strptime(x,"%b",&thyme);
+				dx=thyme.tm_mon;
+				yy=strptime(y,"%b",&thyme);
+				if(!xx) retval=(!yy ? 0 : -1);
+				else if(!yy) retval=1;
+				else retval=(dx==thyme.tm_mon ? 0 : dx-thyme.tm_mon);
+				break;
+			}
+			/* Full floating point version of -n */
+			case FLAG_n:
+			{
+				double dx=atof(x),dy=atof(y);
+				retval=dx>dy ? 1 : (dx<dy ? -1 : 0);
+				break;
+			}
+		}
+		/* Free key copies. */
+		if(x!=*(char **)xarg) free(x);
+		if(y!=*(char **)yarg) free(y);
+		if(retval) break;
+#else
+			/* Integer version of -n for tiny systems */
+			case FLAG_n:
+				retval=atoi(x)-atoi(y);
+				break;
+		}
+#endif
+	}
+	/* Perform fallback sort if necessary */
+	if(!retval && !(global_flags&FLAG_s))
+			retval=strcmp(*(char **)xarg, *(char **)yarg);
+//dprintf(2,"reverse=%d\n",flags&FLAG_r);
+	return ((flags&FLAG_r)?-1:1)*retval;
+}
+
+int sort_main(int argc, char **argv)
+{
+	FILE *fp,*outfile=NULL;
+	int linecount=0,i,flag;
+	char *line,**lines=NULL,*optlist="ngMucszbrdfimS:T:o:k:t:";
+	int c;
+
+	bb_default_error_retval = 2;
+	/* Parse command line options */
+	while((c=getopt(argc,argv,optlist))>0) {
+		line=strchr(optlist,c);
+		if(!line) bb_show_usage();
+		switch(*line) {
+#ifdef CONFIG_FEATURE_SORT_BIG
+			case 'o':
+				if(outfile) bb_error_msg_and_die("Too many -o.");
+				outfile=bb_xfopen(optarg,"w");
+				break;
+			case 't':
+				if(key_separator || optarg[1])
+					bb_error_msg_and_die("Too many -t.");
+				key_separator=*optarg;
+				break;
+			/* parse sort key */
+			case 'k':
+			{
+				struct sort_key *key=add_key();
+				char *temp, *temp2;
+
+				temp=optarg;
+				for(i=0;*temp;) {
+					/* Start of range */
+					key->range[2*i]=(unsigned short)strtol(temp,&temp,10);
+					if(*temp=='.')
+						key->range[(2*i)+1]=(unsigned short)strtol(temp+1,&temp,10);
+					for(;*temp;temp++) {
+						if(*temp==',' && !i++) {
+							temp++;
+							break;
+						} /* no else needed: fall through to syntax error
+							 because comma isn't in optlist */
+						temp2=strchr(optlist,*temp);
+						flag=(1<<(temp2-optlist));
+						if(!temp2 || (flag>FLAG_M && flag<FLAG_b))
+							bb_error_msg_and_die("Unknown key option.");
+						/* b after , means strip _trailing_ space */
+						if(i && flag==FLAG_b) flag=FLAG_bb;
+						key->flags|=flag;
+					}
+				}
+				break;
+			}
+#endif
+			default:
+				global_flags|=(1<<(line-optlist));
+				/* global b strips leading and trailing spaces */
+				if(global_flags&FLAG_b) global_flags|=FLAG_bb;
+				break;
+		}
+	}
+	/* Open input files and read data */
+	for(i=argv[optind] ? optind : optind-1;argv[i];i++) {
+		if(i<optind || (*argv[i]=='-' && !argv[i][1])) fp=stdin;
+		else fp=bb_xfopen(argv[i],"r");
+		for(;;) {
+			line=GET_LINE(fp);
+			if(!line) break;
+			if(!(linecount&63))
+				lines=xrealloc(lines, sizeof(char *)*(linecount+64));
+			lines[linecount++]=line;
+		}
+		fclose(fp);
+	}
+#ifdef CONFIG_FEATURE_SORT_BIG
+	/* if no key, perform alphabetic sort */
+    if(!key_list) add_key()->range[0]=1;
+	/* handle -c */
+	if(global_flags&FLAG_c) {
+		int j=(global_flags&FLAG_u) ? -1 : 0;
+		for(i=1;i<linecount;i++)
+			if(compare_keys(&lines[i-1],&lines[i])>j) {
+				fprintf(stderr,"Check line %d\n",i);
+				return 1;
+			}
+		return 0;
+	}
+#endif
+	/* Perform the actual sort */
+	qsort(lines,linecount,sizeof(char *),compare_keys);
+	/* handle -u */
+	if(global_flags&FLAG_u) {
+		for(flag=0,i=1;i<linecount;i++) {
+			if(!compare_keys(&lines[flag],&lines[i])) free(lines[i]);
+			else lines[++flag]=lines[i];
+		}
+		if(linecount) linecount=flag+1;
+	}
+	/* Print it */
+	if(!outfile) outfile=stdout;
+	for(i=0;i<linecount;i++) fprintf(outfile,"%s\n",lines[i]);
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/stat.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/stat.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/stat.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,544 @@
+/* vi:set ts=4:*/
+/*
+ * stat -- display file or file system status
+ *
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation.
+ * Copyright (C) 2005 by Erik Andersen <andersen at codepoet.org>
+ * Copyright (C) 2005 by Mike Frysinger <vapier at gentoo.org>
+ *
+ * Written by Michael Meskes
+ * Taken from coreutils and turned into a busybox applet by Mike Frysinger
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/vfs.h>
+#include <time.h>
+#include <getopt.h> /* optind */
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/statvfs.h>
+#include <string.h>
+#include "busybox.h"
+
+/* vars to control behavior */
+#define OPT_TERSE 2
+#define OPT_DEREFERENCE 4
+static long flags;
+
+static char const *file_type(struct stat const *st)
+{
+	/* See POSIX 1003.1-2001 XCU Table 4-8 lines 17093-17107
+	 * for some of these formats.
+	 * To keep diagnostics grammatical in English, the
+	 * returned string must start with a consonant.
+	 */
+	if (S_ISREG(st->st_mode))  return st->st_size == 0 ? "regular empty file" : "regular file";
+	if (S_ISDIR(st->st_mode))  return "directory";
+	if (S_ISBLK(st->st_mode))  return "block special file";
+	if (S_ISCHR(st->st_mode))  return "character special file";
+	if (S_ISFIFO(st->st_mode)) return "fifo";
+	if (S_ISLNK(st->st_mode))  return "symbolic link";
+	if (S_ISSOCK(st->st_mode)) return "socket";
+	if (S_TYPEISMQ(st))        return "message queue";
+	if (S_TYPEISSEM(st))       return "semaphore";
+	if (S_TYPEISSHM(st))       return "shared memory object";
+#ifdef S_TYPEISTMO
+	if (S_TYPEISTMO(st))       return "typed memory object";
+#endif
+	return "weird file";
+}
+
+static char const *human_time(time_t t)
+{
+	static char *str;
+	str = ctime(&t);
+	str[strlen(str)-1] = '\0';
+	return str;
+}
+
+/* Return the type of the specified file system.
+ * Some systems have statfvs.f_basetype[FSTYPSZ]. (AIX, HP-UX, and Solaris)
+ * Others have statfs.f_fstypename[MFSNAMELEN]. (NetBSD 1.5.2)
+ * Still others have neither and have to get by with f_type (Linux).
+ */
+static char const *human_fstype(long f_type)
+{
+	int i;
+	static const struct types {
+		long type;
+		const char *fs;
+	} humantypes[] = {
+		{ 0xADFF,     "affs" },
+		{ 0x1Cd1,     "devpts" },
+		{ 0x137D,     "ext" },
+		{ 0xEF51,     "ext2" },
+		{ 0xEF53,     "ext2/ext3" },
+		{ 0x3153464a, "jfs" },
+		{ 0x58465342, "xfs" },
+		{ 0xF995E849, "hpfs" },
+		{ 0x9660,     "isofs" },
+		{ 0x4000,     "isofs" },
+		{ 0x4004,     "isofs" },
+		{ 0x137F,     "minix" },
+		{ 0x138F,     "minix (30 char.)" },
+		{ 0x2468,     "minix v2" },
+		{ 0x2478,     "minix v2 (30 char.)" },
+		{ 0x4d44,     "msdos" },
+		{ 0x4006,     "fat" },
+		{ 0x564c,     "novell" },
+		{ 0x6969,     "nfs" },
+		{ 0x9fa0,     "proc" },
+		{ 0x517B,     "smb" },
+		{ 0x012FF7B4, "xenix" },
+		{ 0x012FF7B5, "sysv4" },
+		{ 0x012FF7B6, "sysv2" },
+		{ 0x012FF7B7, "coh" },
+		{ 0x00011954, "ufs" },
+		{ 0x012FD16D, "xia" },
+		{ 0x5346544e, "ntfs" },
+		{ 0x1021994,  "tmpfs" },
+		{ 0x52654973, "reiserfs" },
+		{ 0x28cd3d45, "cramfs" },
+		{ 0x7275,     "romfs" },
+		{ 0x858458f6, "romfs" },
+		{ 0x73717368, "squashfs" },
+		{ 0x62656572, "sysfs" },
+		{ 0, "UNKNOWN" }
+	};
+	for (i=0; humantypes[i].type; ++i)
+		if (humantypes[i].type == f_type)
+			break;
+	return humantypes[i].fs;
+}
+
+#ifdef CONFIG_FEATURE_STAT_FORMAT
+/* print statfs info */
+static void print_statfs(char *pformat, size_t buf_len, char m,
+			 char const *filename, void const *data)
+{
+	struct statfs const *statfsbuf = data;
+
+	switch (m) {
+	case 'n':
+		strncat(pformat, "s", buf_len);
+		printf(pformat, filename);
+		break;
+	case 'i':
+		strncat(pformat, "Lx", buf_len);
+		printf(pformat, statfsbuf->f_fsid);
+		break;
+	case 'l':
+		strncat(pformat, "lu", buf_len);
+		printf(pformat, statfsbuf->f_namelen);
+		break;
+	case 't':
+		strncat(pformat, "lx", buf_len);
+		printf(pformat, (unsigned long int) (statfsbuf->f_type));  /* no equiv. */
+		break;
+	case 'T':
+		strncat(pformat, "s", buf_len);
+		printf(pformat, human_fstype(statfsbuf->f_type));
+		break;
+	case 'b':
+		strncat(pformat, "jd", buf_len);
+		printf(pformat, (intmax_t) (statfsbuf->f_blocks));
+		break;
+	case 'f':
+		strncat(pformat, "jd", buf_len);
+		printf(pformat, (intmax_t) (statfsbuf->f_bfree));
+		break;
+	case 'a':
+		strncat(pformat, "jd", buf_len);
+		printf(pformat, (intmax_t) (statfsbuf->f_bavail));
+		break;
+	case 'S':
+	case 's':
+		strncat(pformat, "lu", buf_len);
+		printf(pformat, (unsigned long int) (statfsbuf->f_bsize));
+		break;
+	case 'c':
+		strncat(pformat, "jd", buf_len);
+		printf(pformat, (intmax_t) (statfsbuf->f_files));
+		break;
+	case 'd':
+		strncat(pformat, "jd", buf_len);
+		printf(pformat, (intmax_t) (statfsbuf->f_ffree));
+		break;
+	default:
+		strncat(pformat, "c", buf_len);
+		printf(pformat, m);
+		break;
+	}
+}
+
+/* print stat info */
+static void print_stat(char *pformat, size_t buf_len, char m,
+		       char const *filename, void const *data)
+{
+#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+	struct stat *statbuf = (struct stat *) data;
+	struct passwd *pw_ent;
+	struct group *gw_ent;
+
+	switch (m) {
+	case 'n':
+		strncat(pformat, "s", buf_len);
+		printf(pformat, filename);
+		break;
+	case 'N':
+		strncat(pformat, "s", buf_len);
+		if (S_ISLNK(statbuf->st_mode)) {
+			char *linkname = xreadlink(filename);
+			if (linkname == NULL) {
+				bb_perror_msg("cannot read symbolic link '%s'", filename);
+				return;
+			}
+			/*printf("\"%s\" -> \"%s\"", filename, linkname); */
+			printf(pformat, filename);
+			printf(" -> ");
+			printf(pformat, linkname);
+		} else {
+			printf(pformat, filename);
+		}
+		break;
+	case 'd':
+		strncat(pformat, "ju", buf_len);
+		printf(pformat, (uintmax_t) statbuf->st_dev);
+		break;
+	case 'D':
+		strncat(pformat, "jx", buf_len);
+		printf(pformat, (uintmax_t) statbuf->st_dev);
+		break;
+	case 'i':
+		strncat(pformat, "ju", buf_len);
+		printf(pformat, (uintmax_t) statbuf->st_ino);
+		break;
+	case 'a':
+		strncat(pformat, "lo", buf_len);
+		printf(pformat, (unsigned long int) (statbuf->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)));
+		break;
+	case 'A':
+		strncat(pformat, "s", buf_len);
+		printf(pformat, bb_mode_string(statbuf->st_mode));
+		break;
+	case 'f':
+		strncat(pformat, "lx", buf_len);
+		printf(pformat, (unsigned long int) statbuf->st_mode);
+		break;
+	case 'F':
+		strncat(pformat, "s", buf_len);
+		printf(pformat, file_type(statbuf));
+		break;
+	case 'h':
+		strncat(pformat, "lu", buf_len);
+		printf(pformat, (unsigned long int) statbuf->st_nlink);
+		break;
+	case 'u':
+		strncat(pformat, "lu", buf_len);
+		printf(pformat, (unsigned long int) statbuf->st_uid);
+		break;
+	case 'U':
+		strncat(pformat, "s", buf_len);
+		setpwent();
+		pw_ent = getpwuid(statbuf->st_uid);
+		printf(pformat, (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN");
+		break;
+	case 'g':
+		strncat(pformat, "lu", buf_len);
+		printf(pformat, (unsigned long int) statbuf->st_gid);
+		break;
+	case 'G':
+		strncat(pformat, "s", buf_len);
+		setgrent();
+		gw_ent = getgrgid(statbuf->st_gid);
+		printf(pformat, (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN");
+		break;
+	case 't':
+		strncat(pformat, "lx", buf_len);
+		printf(pformat, (unsigned long int) major(statbuf->st_rdev));
+		break;
+	case 'T':
+		strncat(pformat, "lx", buf_len);
+		printf(pformat, (unsigned long int) minor(statbuf->st_rdev));
+		break;
+	case 's':
+		strncat(pformat, "ju", buf_len);
+		printf(pformat, (uintmax_t) (statbuf->st_size));
+		break;
+	case 'B':
+		strncat(pformat, "lu", buf_len);
+		printf(pformat, (unsigned long int) 512); //ST_NBLOCKSIZE
+		break;
+	case 'b':
+		strncat(pformat, "ju", buf_len);
+		printf(pformat, (uintmax_t) statbuf->st_blocks);
+		break;
+	case 'o':
+		strncat(pformat, "lu", buf_len);
+		printf(pformat, (unsigned long int) statbuf->st_blksize);
+		break;
+	case 'x':
+		strncat(pformat, "s", buf_len);
+		printf(pformat, human_time(statbuf->st_atime));
+		break;
+	case 'X':
+		strncat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu", buf_len);
+		printf(pformat, (unsigned long int) statbuf->st_atime);
+		break;
+	case 'y':
+		strncat(pformat, "s", buf_len);
+		printf(pformat, human_time(statbuf->st_mtime));
+		break;
+	case 'Y':
+		strncat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu", buf_len);
+		printf(pformat, (unsigned long int) statbuf->st_mtime);
+		break;
+	case 'z':
+		strncat(pformat, "s", buf_len);
+		printf(pformat, human_time(statbuf->st_ctime));
+		break;
+	case 'Z':
+		strncat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu", buf_len);
+		printf(pformat, (unsigned long int) statbuf->st_ctime);
+		break;
+	default:
+		strncat(pformat, "c", buf_len);
+		printf(pformat, m);
+		break;
+	}
+}
+
+static void print_it(char const *masterformat, char const *filename,
+		     void (*print_func) (char *, size_t, char, char const *, void const *),
+		     void const *data)
+{
+	char *b;
+
+	/* create a working copy of the format string */
+	char *format = bb_xstrdup(masterformat);
+
+	/* Add 2 to accommodate our conversion of the stat `%s' format string
+	 * to the printf `%llu' one.  */
+	size_t n_alloc = strlen(format) + 2 + 1;
+	char *dest = xmalloc(n_alloc);
+
+	b = format;
+	while (b) {
+		char *p = strchr(b, '%');
+		if (p != NULL) {
+			size_t len;
+			*p++ = '\0';
+			fputs(b, stdout);
+
+			len = strspn(p, "#-+.I 0123456789");
+			dest[0] = '%';
+			memcpy(dest + 1, p, len);
+			dest[1 + len] = 0;
+			p += len;
+
+			b = p + 1;
+			switch (*p) {
+				case '\0':
+					b = NULL;
+					/* fall through */
+				case '%':
+					putchar('%');
+					break;
+				default:
+					print_func(dest, n_alloc, *p, filename, data);
+					break;
+			}
+
+		} else {
+			fputs(b, stdout);
+			b = NULL;
+		}
+	}
+
+	free(format);
+	free(dest);
+}
+#endif
+
+/* Stat the file system and print what we find.  */
+static int do_statfs(char const *filename, char const *format)
+{
+	struct statfs statfsbuf;
+
+	if (statfs(filename, &statfsbuf) != 0) {
+		bb_perror_msg("cannot read file system information for '%s'", filename);
+		return 0;
+	}
+
+#ifdef CONFIG_FEATURE_STAT_FORMAT
+	if (format == NULL)
+		format = (flags & OPT_TERSE
+			? "%n %i %l %t %s %b %f %a %c %d\n"
+			: "  File: \"%n\"\n"
+			  "    ID: %-8i Namelen: %-7l Type: %T\n"
+			  "Block size: %-10s\n"
+			  "Blocks: Total: %-10b Free: %-10f Available: %a\n"
+			  "Inodes: Total: %-10c Free: %d\n");
+	print_it(format, filename, print_statfs, &statfsbuf);
+#else
+
+	format = (flags & OPT_TERSE
+		? "%s %llx %lu "
+		: "  File: \"%s\"\n"
+		  "    ID: %-8Lx Namelen: %-7lu ");
+	printf(format,
+	       filename,
+	       statfsbuf.f_fsid,
+	       statfsbuf.f_namelen);
+
+	if (flags & OPT_TERSE)
+		printf("%lx ", (unsigned long int) (statfsbuf.f_type));
+	else
+		printf("Type: %s\n", human_fstype(statfsbuf.f_type));
+
+	format = (flags & OPT_TERSE
+		? "%lu %ld %ld %ld %ld %ld\n"
+		: "Block size: %-10lu\n"
+		  "Blocks: Total: %-10jd Free: %-10jd Available: %jd\n"
+		  "Inodes: Total: %-10jd Free: %jd\n");
+	printf(format,
+	       (unsigned long int) (statfsbuf.f_bsize),
+	       (intmax_t) (statfsbuf.f_blocks),
+	       (intmax_t) (statfsbuf.f_bfree),
+	       (intmax_t) (statfsbuf.f_bavail),
+	       (intmax_t) (statfsbuf.f_files),
+	       (intmax_t) (statfsbuf.f_ffree));
+#endif
+
+	return 1;
+}
+
+/* stat the file and print what we find */
+static int do_stat(char const *filename, char const *format)
+{
+	struct stat statbuf;
+
+	if ((flags & OPT_DEREFERENCE ? stat : lstat) (filename, &statbuf) != 0) {
+		bb_perror_msg("cannot stat '%s'", filename);
+		return 0;
+	}
+
+#ifdef CONFIG_FEATURE_STAT_FORMAT
+	if (format == NULL) {
+		if (flags & OPT_TERSE) {
+			format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o\n";
+		} else {
+			if (S_ISBLK(statbuf.st_mode) || S_ISCHR(statbuf.st_mode)) {
+				format =
+					"  File: \"%N\"\n"
+					"  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
+					"Device: %Dh/%dd\tInode: %-10i  Links: %-5h"
+					" Device type: %t,%T\n"
+					"Access: (%04a/%10.10A)  Uid: (%5u/%8U)   Gid: (%5g/%8G)\n"
+					"Access: %x\n" "Modify: %y\n" "Change: %z\n";
+			} else {
+				format =
+					"  File: \"%N\"\n"
+					"  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
+					"Device: %Dh/%dd\tInode: %-10i  Links: %h\n"
+					"Access: (%04a/%10.10A)  Uid: (%5u/%8U)   Gid: (%5g/%8G)\n"
+					"Access: %x\n" "Modify: %y\n" "Change: %z\n";
+			}
+		}
+	}
+	print_it(format, filename, print_stat, &statbuf);
+#else
+	if (flags & OPT_TERSE) {
+		printf("%s %ju %ju %lx %lu %lu %jx %ju %lu %lx %lx %lu %lu %lu %lu\n",
+		       filename,
+		       (uintmax_t) (statbuf.st_size),
+		       (uintmax_t) statbuf.st_blocks,
+		       (unsigned long int) statbuf.st_mode,
+		       (unsigned long int) statbuf.st_uid,
+		       (unsigned long int) statbuf.st_gid,
+		       (uintmax_t) statbuf.st_dev,
+		       (uintmax_t) statbuf.st_ino,
+		       (unsigned long int) statbuf.st_nlink,
+		       (unsigned long int) major(statbuf.st_rdev),
+		       (unsigned long int) minor(statbuf.st_rdev),
+		       (unsigned long int) statbuf.st_atime,
+		       (unsigned long int) statbuf.st_mtime,
+		       (unsigned long int) statbuf.st_ctime,
+		       (unsigned long int) statbuf.st_blksize
+		);
+	} else {
+		char *linkname = NULL;
+
+		struct passwd *pw_ent;
+		struct group *gw_ent;
+		setgrent();
+		gw_ent = getgrgid(statbuf.st_gid);
+		setpwent();
+		pw_ent = getpwuid(statbuf.st_uid);
+
+		if (S_ISLNK(statbuf.st_mode))
+			linkname = xreadlink(filename);
+		if (linkname)
+			printf("  File: \"%s\" -> \"%s\"\n", filename, linkname);
+		else
+			printf("  File: \"%s\"\n", filename);
+
+		printf("  Size: %-10ju\tBlocks: %-10ju IO Block: %-6lu %s\n"
+		       "Device: %jxh/%jud\tInode: %-10ju  Links: %-5lu",
+		       (uintmax_t) (statbuf.st_size),
+		       (uintmax_t) statbuf.st_blocks,
+		       (unsigned long int) statbuf.st_blksize,
+		       file_type(&statbuf),
+		       (uintmax_t) statbuf.st_dev,
+		       (uintmax_t) statbuf.st_dev,
+		       (uintmax_t) statbuf.st_ino,
+		       (unsigned long int) statbuf.st_nlink);
+		if (S_ISBLK(statbuf.st_mode) || S_ISCHR(statbuf.st_mode))
+			printf(" Device type: %lx,%lx\n",
+			       (unsigned long int) major(statbuf.st_rdev),
+			       (unsigned long int) minor(statbuf.st_rdev));
+		else
+			putchar('\n');
+		printf("Access: (%04lo/%10.10s)  Uid: (%5lu/%8s)   Gid: (%5lu/%8s)\n"
+		       "Access: %s\n" "Modify: %s\n" "Change: %s\n",
+		       (unsigned long int) (statbuf.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)),
+		       bb_mode_string(statbuf.st_mode),
+		       (unsigned long int) statbuf.st_uid,
+		       (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN",
+		       (unsigned long int) statbuf.st_gid,
+		       (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN",
+		       human_time(statbuf.st_atime),
+		       human_time(statbuf.st_mtime),
+		       human_time(statbuf.st_ctime));
+	}
+#endif
+	return 1;
+}
+
+int stat_main(int argc, char **argv)
+{
+	int i;
+	char *format = NULL;
+	int ok = 1;
+	int (*statfunc)(char const *, char const *) = do_stat;
+
+	flags = bb_getopt_ulflags(argc, argv, "ftL"
+	USE_FEATURE_STAT_FORMAT("c:", &format)
+	);
+
+	if (flags & 1)                /* -f */
+		statfunc = do_statfs;
+	if (argc == optind)           /* files */
+		bb_show_usage();
+
+	for (i = optind; i < argc; ++i)
+		ok &= statfunc(argv[i], format);
+
+	return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/stty.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/stty.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/stty.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1307 @@
+/* vi: set sw=4 ts=4: */
+/* stty -- change and print terminal line settings
+   Copyright (C) 1990-1999 Free Software Foundation, Inc.
+
+   Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+*/
+/* Usage: stty [-ag] [-F device] [setting...]
+
+   Options:
+   -a Write all current settings to stdout in human-readable form.
+   -g Write all current settings to stdout in stty-readable form.
+   -F Open and use the specified device instead of stdin
+
+   If no args are given, write to stdout the baud rate and settings that
+   have been changed from their defaults.  Mode reading and changes
+   are done on the specified device, or stdin if none was specified.
+
+   David MacKenzie <djm at gnu.ai.mit.edu>
+
+   Special for busybox ported by Vladimir Oleynik <dzo at simtreas.ru> 2001
+
+   */
+
+//#define TEST
+
+#include "busybox.h"
+#include <stddef.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include <sys/param.h>
+#include <unistd.h>
+
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <fcntl.h>
+
+#define STREQ(a, b) (strcmp ((a), (b)) == 0)
+
+
+#ifndef _POSIX_VDISABLE
+# define _POSIX_VDISABLE ((unsigned char) 0)
+#endif
+
+#define Control(c) ((c) & 0x1f)
+/* Canonical values for control characters. */
+#ifndef CINTR
+# define CINTR Control ('c')
+#endif
+#ifndef CQUIT
+# define CQUIT 28
+#endif
+#ifndef CERASE
+# define CERASE 127
+#endif
+#ifndef CKILL
+# define CKILL Control ('u')
+#endif
+#ifndef CEOF
+# define CEOF Control ('d')
+#endif
+#ifndef CEOL
+# define CEOL _POSIX_VDISABLE
+#endif
+#ifndef CSTART
+# define CSTART Control ('q')
+#endif
+#ifndef CSTOP
+# define CSTOP Control ('s')
+#endif
+#ifndef CSUSP
+# define CSUSP Control ('z')
+#endif
+#if defined(VEOL2) && !defined(CEOL2)
+# define CEOL2 _POSIX_VDISABLE
+#endif
+/* ISC renamed swtch to susp for termios, but we'll accept either name.  */
+#if defined(VSUSP) && !defined(VSWTCH)
+# define VSWTCH VSUSP
+# define CSWTCH CSUSP
+#endif
+#if defined(VSWTCH) && !defined(CSWTCH)
+# define CSWTCH _POSIX_VDISABLE
+#endif
+
+/* SunOS 5.3 loses (^Z doesn't work) if `swtch' is the same as `susp'.
+   So the default is to disable `swtch.'  */
+#if defined (__sparc__) && defined (__svr4__)
+# undef CSWTCH
+# define CSWTCH _POSIX_VDISABLE
+#endif
+
+#if defined(VWERSE) && !defined (VWERASE)       /* AIX-3.2.5 */
+# define VWERASE VWERSE
+#endif
+#if defined(VDSUSP) && !defined (CDSUSP)
+# define CDSUSP Control ('y')
+#endif
+#if !defined(VREPRINT) && defined(VRPRNT)       /* Irix 4.0.5 */
+# define VREPRINT VRPRNT
+#endif
+#if defined(VREPRINT) && !defined(CRPRNT)
+# define CRPRNT Control ('r')
+#endif
+#if defined(VWERASE) && !defined(CWERASE)
+# define CWERASE Control ('w')
+#endif
+#if defined(VLNEXT) && !defined(CLNEXT)
+# define CLNEXT Control ('v')
+#endif
+#if defined(VDISCARD) && !defined(VFLUSHO)
+# define VFLUSHO VDISCARD
+#endif
+#if defined(VFLUSH) && !defined(VFLUSHO)        /* Ultrix 4.2 */
+# define VFLUSHO VFLUSH
+#endif
+#if defined(CTLECH) && !defined(ECHOCTL)        /* Ultrix 4.3 */
+# define ECHOCTL CTLECH
+#endif
+#if defined(TCTLECH) && !defined(ECHOCTL)       /* Ultrix 4.2 */
+# define ECHOCTL TCTLECH
+#endif
+#if defined(CRTKIL) && !defined(ECHOKE)         /* Ultrix 4.2 and 4.3 */
+# define ECHOKE CRTKIL
+#endif
+#if defined(VFLUSHO) && !defined(CFLUSHO)
+# define CFLUSHO Control ('o')
+#endif
+#if defined(VSTATUS) && !defined(CSTATUS)
+# define CSTATUS Control ('t')
+#endif
+
+/* Which speeds to set.  */
+enum speed_setting {
+	input_speed, output_speed, both_speeds
+};
+
+/* Which member(s) of `struct termios' a mode uses.  */
+enum mode_type {
+	/* Do NOT change the order or values, as mode_type_flag()
+	 * depends on them. */
+	control, input, output, local, combination
+};
+
+
+static const char evenp     [] = "evenp";
+static const char raw       [] = "raw";
+static const char stty_min  [] = "min";
+static const char stty_time [] = "time";
+static const char stty_swtch[] = "swtch";
+static const char stty_eol  [] = "eol";
+static const char stty_eof  [] = "eof";
+static const char parity    [] = "parity";
+static const char stty_oddp [] = "oddp";
+static const char stty_nl   [] = "nl";
+static const char stty_ek   [] = "ek";
+static const char stty_sane [] = "sane";
+static const char cbreak    [] = "cbreak";
+static const char stty_pass8[] = "pass8";
+static const char litout    [] = "litout";
+static const char cooked    [] = "cooked";
+static const char decctlq   [] = "decctlq";
+static const char stty_tabs [] = "tabs";
+static const char stty_lcase[] = "lcase";
+static const char stty_LCASE[] = "LCASE";
+static const char stty_crt  [] = "crt";
+static const char stty_dec  [] = "dec";
+
+
+/* Flags for `struct mode_info'. */
+#define SANE_SET 1              /* Set in `sane' mode.                  */
+#define SANE_UNSET 2            /* Unset in `sane' mode.                */
+#define REV 4                   /* Can be turned off by prepending `-'. */
+#define OMIT 8                  /* Don't display value.                 */
+
+/* Each mode.  */
+struct mode_info {
+	const char *name;       /* Name given on command line.           */
+	/* enum mode_type type; */
+	char type;              /* Which structure element to change.    */
+	char flags;             /* Setting and display options.          */
+	unsigned short mask;     /* Other bits to turn off for this mode. */
+	unsigned long bits;     /* Bits to set for this mode.            */
+};
+
+#define MI_ENTRY(N,T,F,B,M) { N, T, F, M, B }
+
+static const struct  mode_info mode_info[] = {
+	MI_ENTRY("parenb",   control,     REV,               PARENB,     0 ),
+	MI_ENTRY("parodd",   control,     REV,               PARODD,     0 ),
+	MI_ENTRY("cs5",      control,     0,                 CS5,     CSIZE),
+	MI_ENTRY("cs6",      control,     0,                 CS6,     CSIZE),
+	MI_ENTRY("cs7",      control,     0,                 CS7,     CSIZE),
+	MI_ENTRY("cs8",      control,     0,                 CS8,     CSIZE),
+	MI_ENTRY("hupcl",    control,     REV,               HUPCL,      0 ),
+	MI_ENTRY("hup",      control,     REV        | OMIT, HUPCL,      0 ),
+	MI_ENTRY("cstopb",   control,     REV,               CSTOPB,     0 ),
+	MI_ENTRY("cread",    control,     SANE_SET   | REV,  CREAD,      0 ),
+	MI_ENTRY("clocal",   control,     REV,               CLOCAL,     0 ),
+#ifdef CRTSCTS
+	MI_ENTRY("crtscts",  control,     REV,               CRTSCTS,    0 ),
+#endif
+	MI_ENTRY("ignbrk",   input,       SANE_UNSET | REV,  IGNBRK,     0 ),
+	MI_ENTRY("brkint",   input,       SANE_SET   | REV,  BRKINT,     0 ),
+	MI_ENTRY("ignpar",   input,       REV,               IGNPAR,     0 ),
+	MI_ENTRY("parmrk",   input,       REV,               PARMRK,     0 ),
+	MI_ENTRY("inpck",    input,       REV,               INPCK,      0 ),
+	MI_ENTRY("istrip",   input,       REV,               ISTRIP,     0 ),
+	MI_ENTRY("inlcr",    input,       SANE_UNSET | REV,  INLCR,      0 ),
+	MI_ENTRY("igncr",    input,       SANE_UNSET | REV,  IGNCR,      0 ),
+	MI_ENTRY("icrnl",    input,       SANE_SET   | REV,  ICRNL,      0 ),
+	MI_ENTRY("ixon",     input,       REV,               IXON,       0 ),
+	MI_ENTRY("ixoff",    input,       SANE_UNSET | REV,  IXOFF,      0 ),
+	MI_ENTRY("tandem",   input,       REV        | OMIT, IXOFF,      0 ),
+#ifdef IUCLC
+	MI_ENTRY("iuclc",    input,       SANE_UNSET | REV,  IUCLC,      0 ),
+#endif
+#ifdef IXANY
+	MI_ENTRY("ixany",    input,       SANE_UNSET | REV,  IXANY,      0 ),
+#endif
+#ifdef IMAXBEL
+	MI_ENTRY("imaxbel",  input,       SANE_SET   | REV,  IMAXBEL,    0 ),
+#endif
+	MI_ENTRY("opost",    output,      SANE_SET   | REV,  OPOST,      0 ),
+#ifdef OLCUC
+	MI_ENTRY("olcuc",    output,      SANE_UNSET | REV,  OLCUC,      0 ),
+#endif
+#ifdef OCRNL
+	MI_ENTRY("ocrnl",    output,      SANE_UNSET | REV,  OCRNL,      0 ),
+#endif
+#ifdef ONLCR
+	MI_ENTRY("onlcr",    output,      SANE_SET   | REV,  ONLCR,      0 ),
+#endif
+#ifdef ONOCR
+	MI_ENTRY("onocr",    output,      SANE_UNSET | REV,  ONOCR,      0 ),
+#endif
+#ifdef ONLRET
+	MI_ENTRY("onlret",   output,      SANE_UNSET | REV,  ONLRET,     0 ),
+#endif
+#ifdef OFILL
+	MI_ENTRY("ofill",    output,      SANE_UNSET | REV,  OFILL,      0 ),
+#endif
+#ifdef OFDEL
+	MI_ENTRY("ofdel",    output,      SANE_UNSET | REV,  OFDEL,      0 ),
+#endif
+#ifdef NLDLY
+	MI_ENTRY("nl1",      output,      SANE_UNSET,        NL1,     NLDLY),
+	MI_ENTRY("nl0",      output,      SANE_SET,          NL0,     NLDLY),
+#endif
+#ifdef CRDLY
+	MI_ENTRY("cr3",      output,      SANE_UNSET,        CR3,     CRDLY),
+	MI_ENTRY("cr2",      output,      SANE_UNSET,        CR2,     CRDLY),
+	MI_ENTRY("cr1",      output,      SANE_UNSET,        CR1,     CRDLY),
+	MI_ENTRY("cr0",      output,      SANE_SET,          CR0,     CRDLY),
+#endif
+
+#ifdef TABDLY
+	MI_ENTRY("tab3",     output,      SANE_UNSET,        TAB3,   TABDLY),
+	MI_ENTRY("tab2",     output,      SANE_UNSET,        TAB2,   TABDLY),
+	MI_ENTRY("tab1",     output,      SANE_UNSET,        TAB1,   TABDLY),
+	MI_ENTRY("tab0",     output,      SANE_SET,          TAB0,   TABDLY),
+#else
+# ifdef OXTABS
+	MI_ENTRY("tab3",     output,      SANE_UNSET,        OXTABS,     0 ),
+# endif
+#endif
+
+#ifdef BSDLY
+	MI_ENTRY("bs1",      output,      SANE_UNSET,        BS1,     BSDLY),
+	MI_ENTRY("bs0",      output,      SANE_SET,          BS0,     BSDLY),
+#endif
+#ifdef VTDLY
+	MI_ENTRY("vt1",      output,      SANE_UNSET,        VT1,     VTDLY),
+	MI_ENTRY("vt0",      output,      SANE_SET,          VT0,     VTDLY),
+#endif
+#ifdef FFDLY
+	MI_ENTRY("ff1",      output,      SANE_UNSET,        FF1,     FFDLY),
+	MI_ENTRY("ff0",      output,      SANE_SET,          FF0,     FFDLY),
+#endif
+	MI_ENTRY("isig",     local,       SANE_SET   | REV,  ISIG,       0 ),
+	MI_ENTRY("icanon",   local,       SANE_SET   | REV,  ICANON,     0 ),
+#ifdef IEXTEN
+	MI_ENTRY("iexten",   local,       SANE_SET   | REV,  IEXTEN,     0 ),
+#endif
+	MI_ENTRY("echo",     local,       SANE_SET   | REV,  ECHO,       0 ),
+	MI_ENTRY("echoe",    local,       SANE_SET   | REV,  ECHOE,      0 ),
+	MI_ENTRY("crterase", local,       REV        | OMIT, ECHOE,      0 ),
+	MI_ENTRY("echok",    local,       SANE_SET   | REV,  ECHOK,      0 ),
+	MI_ENTRY("echonl",   local,       SANE_UNSET | REV,  ECHONL,     0 ),
+	MI_ENTRY("noflsh",   local,       SANE_UNSET | REV,  NOFLSH,     0 ),
+#ifdef XCASE
+	MI_ENTRY("xcase",    local,       SANE_UNSET | REV,  XCASE,      0 ),
+#endif
+#ifdef TOSTOP
+	MI_ENTRY("tostop",   local,       SANE_UNSET | REV,  TOSTOP,     0 ),
+#endif
+#ifdef ECHOPRT
+	MI_ENTRY("echoprt",  local,       SANE_UNSET | REV,  ECHOPRT,    0 ),
+	MI_ENTRY("prterase", local,       REV | OMIT,        ECHOPRT,    0 ),
+#endif
+#ifdef ECHOCTL
+	MI_ENTRY("echoctl",  local,       SANE_SET   | REV,  ECHOCTL,    0 ),
+	MI_ENTRY("ctlecho",  local,       REV        | OMIT, ECHOCTL,    0 ),
+#endif
+#ifdef ECHOKE
+	MI_ENTRY("echoke",   local,       SANE_SET   | REV,  ECHOKE,     0 ),
+	MI_ENTRY("crtkill",  local,       REV        | OMIT, ECHOKE,     0 ),
+#endif
+	MI_ENTRY(evenp,      combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(parity,     combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(stty_oddp,  combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(stty_nl,    combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(stty_ek,    combination, OMIT,              0,          0 ),
+	MI_ENTRY(stty_sane,  combination, OMIT,              0,          0 ),
+	MI_ENTRY(cooked,     combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(raw,        combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(stty_pass8, combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(litout,     combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(cbreak,     combination, REV        | OMIT, 0,          0 ),
+#ifdef IXANY
+	MI_ENTRY(decctlq,    combination, REV        | OMIT, 0,          0 ),
+#endif
+#if defined (TABDLY) || defined (OXTABS)
+	MI_ENTRY(stty_tabs,  combination, REV        | OMIT, 0,          0 ),
+#endif
+#if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
+	MI_ENTRY(stty_lcase, combination, REV        | OMIT, 0,          0 ),
+	MI_ENTRY(stty_LCASE, combination, REV        | OMIT, 0,          0 ),
+#endif
+	MI_ENTRY(stty_crt,   combination, OMIT,              0,          0 ),
+	MI_ENTRY(stty_dec,   combination, OMIT,              0,          0 ),
+};
+
+enum {
+	NUM_mode_info =
+	(sizeof(mode_info) / sizeof(struct mode_info))
+};
+
+/* Control character settings.  */
+struct control_info {
+	const char *name;                       /* Name given on command line.  */
+	unsigned char saneval;          /* Value to set for `stty sane'.  */
+	unsigned char offset;                           /* Offset in c_cc.  */
+};
+
+/* Control characters. */
+
+static const struct  control_info control_info[] = {
+	{"intr",     CINTR,   VINTR},
+	{"quit",     CQUIT,   VQUIT},
+	{"erase",    CERASE,  VERASE},
+	{"kill",     CKILL,   VKILL},
+	{stty_eof,   CEOF,    VEOF},
+	{stty_eol,   CEOL,    VEOL},
+#ifdef VEOL2
+	{"eol2",     CEOL2,   VEOL2},
+#endif
+#ifdef VSWTCH
+	{stty_swtch, CSWTCH,  VSWTCH},
+#endif
+	{"start",    CSTART,  VSTART},
+	{"stop",     CSTOP,   VSTOP},
+	{"susp",     CSUSP,   VSUSP},
+#ifdef VDSUSP
+	{"dsusp",    CDSUSP,  VDSUSP},
+#endif
+#ifdef VREPRINT
+	{"rprnt",    CRPRNT,  VREPRINT},
+#endif
+#ifdef VWERASE
+	{"werase",   CWERASE, VWERASE},
+#endif
+#ifdef VLNEXT
+	{"lnext",    CLNEXT,  VLNEXT},
+#endif
+#ifdef VFLUSHO
+	{"flush",    CFLUSHO, VFLUSHO},
+#endif
+#ifdef VSTATUS
+	{"status",   CSTATUS, VSTATUS},
+#endif
+	/* These must be last because of the display routines. */
+	{stty_min,   1,       VMIN},
+	{stty_time,  0,       VTIME},
+};
+
+enum {
+	NUM_control_info =
+	(sizeof(control_info) / sizeof(struct control_info))
+};
+
+#define EMT(t) ((enum mode_type)(t))
+
+static const char *  visible(unsigned int ch);
+static int           recover_mode(char *arg, struct termios *mode);
+static int           screen_columns(void);
+static int           set_mode(const struct mode_info *info,
+					int reversed, struct termios *mode);
+static speed_t       string_to_baud(const char *arg);
+static tcflag_t*     mode_type_flag(enum mode_type type, struct termios *mode);
+static void          display_all(struct termios *mode);
+static void          display_changed(struct termios *mode);
+static void          display_recoverable(struct termios *mode);
+static void          display_speed(struct termios *mode, int fancy);
+static void          display_window_size(int fancy);
+static void          sane_mode(struct termios *mode);
+static void          set_control_char(const struct control_info *info,
+					const char *arg, struct termios *mode);
+static void          set_speed(enum speed_setting type,
+					const char *arg, struct termios *mode);
+static void          set_window_size(int rows, int cols);
+
+static const char *device_name;
+
+static ATTRIBUTE_NORETURN void perror_on_device(const char *fmt)
+{
+	bb_perror_msg_and_die(fmt, device_name);
+}
+
+
+/* The width of the screen, for output wrapping. */
+static int max_col;
+
+/* Current position, to know when to wrap. */
+static int current_col;
+
+/* Print format string MESSAGE and optional args.
+   Wrap to next line first if it won't fit.
+   Print a space first unless MESSAGE will start a new line. */
+
+static void wrapf(const char *message, ...)
+{
+	va_list args;
+	char buf[1024];                 /* Plenty long for our needs. */
+	int buflen;
+
+	va_start(args, message);
+	vsprintf(buf, message, args);
+	va_end(args);
+	buflen = strlen(buf);
+	if (current_col + (current_col > 0) + buflen >= max_col) {
+		putchar('\n');
+		current_col = 0;
+	}
+	if (current_col > 0) {
+		putchar(' ');
+		current_col++;
+	}
+	fputs(buf, stdout);
+	current_col += buflen;
+}
+
+static const struct suffix_mult stty_suffixes[] = {
+	{"b",  512 },
+	{"k",  1024},
+	{"B",  1024},
+	{NULL, 0   }
+};
+
+#ifndef TEST
+int stty_main(int argc, char **argv)
+#else
+int main(int argc, char **argv)
+#endif
+{
+	struct termios mode;
+	void (*output_func)(struct termios *);
+	int    optc;
+	int    require_set_attr;
+	int    speed_was_set;
+	int    verbose_output;
+	int    recoverable_output;
+	int    k;
+	int    noargs = 1;
+	char * file_name = NULL;
+
+	output_func = display_changed;
+	verbose_output = 0;
+	recoverable_output = 0;
+
+	/* Don't print error messages for unrecognized options.  */
+	opterr = 0;
+
+	while ((optc = getopt(argc, argv, "agF:")) != -1) {
+		switch (optc) {
+		case 'a':
+			verbose_output = 1;
+			output_func = display_all;
+			break;
+
+		case 'g':
+			recoverable_output = 1;
+			output_func = display_recoverable;
+			break;
+
+		case 'F':
+			if (file_name)
+				bb_error_msg_and_die("only one device may be specified");
+			file_name = optarg;
+			break;
+
+		default:                /* unrecognized option */
+			noargs = 0;
+			break;
+		}
+
+		if (noargs == 0)
+			break;
+	}
+
+	if (optind < argc)
+		noargs = 0;
+
+	/* Specifying both -a and -g gets an error.  */
+	if (verbose_output & recoverable_output)
+		bb_error_msg_and_die ("verbose and stty-readable output styles are mutually exclusive");
+
+	/* Specifying any other arguments with -a or -g gets an error.  */
+	if (~noargs & (verbose_output | recoverable_output))
+		bb_error_msg_and_die ("modes may not be set when specifying an output style");
+
+	/* FIXME: it'd be better not to open the file until we've verified
+	   that all arguments are valid.  Otherwise, we could end up doing
+	   only some of the requested operations and then failing, probably
+	   leaving things in an undesirable state.  */
+
+	if (file_name) {
+		int fdflags;
+
+		device_name = file_name;
+		fclose(stdin);
+		bb_xopen(device_name, O_RDONLY | O_NONBLOCK);
+		if ((fdflags = fcntl(STDIN_FILENO, F_GETFL)) == -1
+			|| fcntl(STDIN_FILENO, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
+			perror_on_device("%s: couldn't reset non-blocking mode");
+	} else {
+		device_name = bb_msg_standard_input;
+	}
+
+	/* Initialize to all zeroes so there is no risk memcmp will report a
+	   spurious difference in an uninitialized portion of the structure.  */
+	memset(&mode, 0, sizeof(mode));
+	if (tcgetattr(STDIN_FILENO, &mode))
+		perror_on_device("%s");
+
+	if (verbose_output | recoverable_output | noargs) {
+		max_col = screen_columns();
+		current_col = 0;
+		output_func(&mode);
+		return EXIT_SUCCESS;
+	}
+
+	speed_was_set = 0;
+	require_set_attr = 0;
+	k = 0;
+	while (++k < argc) {
+		int match_found = 0;
+		int reversed = 0;
+		int i;
+
+		if (argv[k][0] == '-') {
+			char *find_dev_opt;
+
+			++argv[k];
+
+     /* Handle "-a", "-ag", "-aF/dev/foo", "-aF /dev/foo", etc.
+	Find the options that have been parsed.  This is really
+	gross, but it's needed because stty SETTINGS look like options to
+	getopt(), so we need to work around things in a really horrible
+	way.  If any new options are ever added to stty, the short option
+	MUST NOT be a letter which is the first letter of one of the
+	possible stty settings.
+     */
+			find_dev_opt = strchr(argv[k], 'F'); /* find -*F* */
+			if(find_dev_opt) {
+				if(find_dev_opt[1]==0)  /* -*F   /dev/foo */
+					k++;            /* skip  /dev/foo */
+				continue;   /* else -*F/dev/foo - no skip */
+			}
+			if(argv[k][0]=='a' || argv[k][0]=='g')
+				continue;
+			/* Is not options - is reverse params */
+			reversed = 1;
+		}
+		for (i = 0; i < NUM_mode_info; ++i)
+			if (STREQ(argv[k], mode_info[i].name)) {
+				match_found = set_mode(&mode_info[i], reversed, &mode);
+				require_set_attr = 1;
+				break;
+			}
+
+		if (match_found == 0 && reversed)
+			bb_error_msg_and_die("invalid argument `%s'", --argv[k]);
+
+		if (match_found == 0)
+			for (i = 0; i < NUM_control_info; ++i)
+				if (STREQ(argv[k], control_info[i].name)) {
+					if (k == argc - 1)
+					    bb_error_msg_and_die(bb_msg_requires_arg, argv[k]);
+					match_found = 1;
+					++k;
+					set_control_char(&control_info[i], argv[k], &mode);
+					require_set_attr = 1;
+					break;
+				}
+
+		if (match_found == 0) {
+			if (STREQ(argv[k], "ispeed")) {
+				if (k == argc - 1)
+				    bb_error_msg_and_die(bb_msg_requires_arg, argv[k]);
+				++k;
+				set_speed(input_speed, argv[k], &mode);
+				speed_was_set = 1;
+				require_set_attr = 1;
+			} else if (STREQ(argv[k], "ospeed")) {
+				if (k == argc - 1)
+				    bb_error_msg_and_die(bb_msg_requires_arg, argv[k]);
+				++k;
+				set_speed(output_speed, argv[k], &mode);
+				speed_was_set = 1;
+				require_set_attr = 1;
+			}
+#ifdef TIOCGWINSZ
+			else if (STREQ(argv[k], "rows")) {
+				if (k == argc - 1)
+				    bb_error_msg_and_die(bb_msg_requires_arg, argv[k]);
+				++k;
+				set_window_size((int) bb_xparse_number(argv[k], stty_suffixes),
+								-1);
+			} else if (STREQ(argv[k], "cols") || STREQ(argv[k], "columns")) {
+				if (k == argc - 1)
+				    bb_error_msg_and_die(bb_msg_requires_arg, argv[k]);
+				++k;
+				set_window_size(-1,
+						(int) bb_xparse_number(argv[k], stty_suffixes));
+			} else if (STREQ(argv[k], "size")) {
+				max_col = screen_columns();
+				current_col = 0;
+				display_window_size(0);
+			}
+#endif
+#ifdef HAVE_C_LINE
+			else if (STREQ(argv[k], "line")) {
+				if (k == argc - 1)
+					bb_error_msg_and_die(bb_msg_requires_arg, argv[k]);
+				++k;
+				mode.c_line = bb_xparse_number(argv[k], stty_suffixes);
+				require_set_attr = 1;
+			}
+#endif
+			else if (STREQ(argv[k], "speed")) {
+				max_col = screen_columns();
+				display_speed(&mode, 0);
+			} else if (recover_mode(argv[k], &mode) == 1)
+				require_set_attr = 1;
+			else if (string_to_baud(argv[k]) != (speed_t) - 1) {
+				set_speed(both_speeds, argv[k], &mode);
+				speed_was_set = 1;
+				require_set_attr = 1;
+			} else
+				bb_error_msg_and_die("invalid argument `%s'", argv[k]);
+		}
+	}
+
+	if (require_set_attr) {
+		struct termios new_mode;
+
+		if (tcsetattr(STDIN_FILENO, TCSADRAIN, &mode))
+			perror_on_device("%s");
+
+		/* POSIX (according to Zlotnick's book) tcsetattr returns zero if
+		   it performs *any* of the requested operations.  This means it
+		   can report `success' when it has actually failed to perform
+		   some proper subset of the requested operations.  To detect
+		   this partial failure, get the current terminal attributes and
+		   compare them to the requested ones.  */
+
+		/* Initialize to all zeroes so there is no risk memcmp will report a
+		   spurious difference in an uninitialized portion of the structure.  */
+		memset(&new_mode, 0, sizeof(new_mode));
+		if (tcgetattr(STDIN_FILENO, &new_mode))
+			perror_on_device("%s");
+
+		/* Normally, one shouldn't use memcmp to compare structures that
+		   may have `holes' containing uninitialized data, but we have been
+		   careful to initialize the storage of these two variables to all
+		   zeroes.  One might think it more efficient simply to compare the
+		   modified fields, but that would require enumerating those fields --
+		   and not all systems have the same fields in this structure.  */
+
+		if (memcmp(&mode, &new_mode, sizeof(mode)) != 0) {
+#ifdef CIBAUD
+			/* SunOS 4.1.3 (at least) has the problem that after this sequence,
+			   tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2);
+			   sometimes (m1 != m2).  The only difference is in the four bits
+			   of the c_cflag field corresponding to the baud rate.  To save
+			   Sun users a little confusion, don't report an error if this
+			   happens.  But suppress the error only if we haven't tried to
+			   set the baud rate explicitly -- otherwise we'd never give an
+			   error for a true failure to set the baud rate.  */
+
+			new_mode.c_cflag &= (~CIBAUD);
+			if (speed_was_set || memcmp(&mode, &new_mode, sizeof(mode)) != 0)
+#endif
+				perror_on_device ("%s: unable to perform all requested operations");
+		}
+	}
+
+	return EXIT_SUCCESS;
+}
+
+/* Return 0 if not applied because not reversible; otherwise return 1.  */
+
+static int
+set_mode(const struct mode_info *info, int reversed, struct termios *mode)
+{
+	tcflag_t *bitsp;
+
+	if (reversed && (info->flags & REV) == 0)
+		return 0;
+
+	bitsp = mode_type_flag(EMT(info->type), mode);
+
+	if (bitsp == NULL) {
+		/* Combination mode. */
+		if (info->name == evenp || info->name == parity) {
+			if (reversed)
+				mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
+			else
+				mode->c_cflag =
+					(mode->c_cflag & ~PARODD & ~CSIZE) | PARENB | CS7;
+		} else if (info->name == stty_oddp) {
+			if (reversed)
+				mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
+			else
+				mode->c_cflag =
+					(mode->c_cflag & ~CSIZE) | CS7 | PARODD | PARENB;
+		} else if (info->name == stty_nl) {
+			if (reversed) {
+				mode->c_iflag = (mode->c_iflag | ICRNL) & ~INLCR & ~IGNCR;
+				mode->c_oflag = (mode->c_oflag
+#ifdef ONLCR
+								 | ONLCR
+#endif
+					)
+#ifdef OCRNL
+					& ~OCRNL
+#endif
+#ifdef ONLRET
+					& ~ONLRET
+#endif
+					;
+			} else {
+				mode->c_iflag = mode->c_iflag & ~ICRNL;
+#ifdef ONLCR
+				mode->c_oflag = mode->c_oflag & ~ONLCR;
+#endif
+			}
+		} else if (info->name == stty_ek) {
+			mode->c_cc[VERASE] = CERASE;
+			mode->c_cc[VKILL] = CKILL;
+		} else if (info->name == stty_sane)
+			sane_mode(mode);
+		else if (info->name == cbreak) {
+			if (reversed)
+				mode->c_lflag |= ICANON;
+			else
+				mode->c_lflag &= ~ICANON;
+		} else if (info->name == stty_pass8) {
+			if (reversed) {
+				mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
+				mode->c_iflag |= ISTRIP;
+			} else {
+				mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
+				mode->c_iflag &= ~ISTRIP;
+			}
+		} else if (info->name == litout) {
+			if (reversed) {
+				mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
+				mode->c_iflag |= ISTRIP;
+				mode->c_oflag |= OPOST;
+			} else {
+				mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
+				mode->c_iflag &= ~ISTRIP;
+				mode->c_oflag &= ~OPOST;
+			}
+		} else if (info->name == raw || info->name == cooked) {
+			if ((info->name[0] == 'r' && reversed)
+				|| (info->name[0] == 'c' && !reversed)) {
+				/* Cooked mode. */
+				mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;
+				mode->c_oflag |= OPOST;
+				mode->c_lflag |= ISIG | ICANON;
+#if VMIN == VEOF
+				mode->c_cc[VEOF] = CEOF;
+#endif
+#if VTIME == VEOL
+				mode->c_cc[VEOL] = CEOL;
+#endif
+			} else {
+				/* Raw mode. */
+				mode->c_iflag = 0;
+				mode->c_oflag &= ~OPOST;
+				mode->c_lflag &= ~(ISIG | ICANON
+#ifdef XCASE
+								   | XCASE
+#endif
+					);
+				mode->c_cc[VMIN] = 1;
+				mode->c_cc[VTIME] = 0;
+			}
+		}
+#ifdef IXANY
+		else if (info->name == decctlq) {
+			if (reversed)
+				mode->c_iflag |= IXANY;
+			else
+				mode->c_iflag &= ~IXANY;
+		}
+#endif
+#ifdef TABDLY
+		else if (info->name == stty_tabs) {
+			if (reversed)
+				mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB3;
+			else
+				mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB0;
+		}
+#else
+# ifdef OXTABS
+		else if (info->name == stty_tabs) {
+			if (reversed)
+				mode->c_oflag = mode->c_oflag | OXTABS;
+			else
+				mode->c_oflag = mode->c_oflag & ~OXTABS;
+		}
+# endif
+#endif
+#if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
+		else if (info->name == stty_lcase || info->name == stty_LCASE) {
+			if (reversed) {
+				mode->c_lflag &= ~XCASE;
+				mode->c_iflag &= ~IUCLC;
+				mode->c_oflag &= ~OLCUC;
+			} else {
+				mode->c_lflag |= XCASE;
+				mode->c_iflag |= IUCLC;
+				mode->c_oflag |= OLCUC;
+			}
+		}
+#endif
+		else if (info->name == stty_crt)
+			mode->c_lflag |= ECHOE
+#ifdef ECHOCTL
+				| ECHOCTL
+#endif
+#ifdef ECHOKE
+				| ECHOKE
+#endif
+				;
+		else if (info->name == stty_dec) {
+			mode->c_cc[VINTR] = 3;  /* ^C */
+			mode->c_cc[VERASE] = 127;       /* DEL */
+			mode->c_cc[VKILL] = 21; /* ^U */
+			mode->c_lflag |= ECHOE
+#ifdef ECHOCTL
+				| ECHOCTL
+#endif
+#ifdef ECHOKE
+				| ECHOKE
+#endif
+				;
+#ifdef IXANY
+			mode->c_iflag &= ~IXANY;
+#endif
+		}
+	} else if (reversed)
+		*bitsp = *bitsp & ~((unsigned long)info->mask) & ~info->bits;
+	else
+		*bitsp = (*bitsp & ~((unsigned long)info->mask)) | info->bits;
+
+	return 1;
+}
+
+static void
+set_control_char(const struct control_info *info, const char *arg,
+				 struct termios *mode)
+{
+	unsigned char value;
+
+	if (info->name == stty_min || info->name == stty_time)
+		value = bb_xparse_number(arg, stty_suffixes);
+	else if (arg[0] == '\0' || arg[1] == '\0')
+		value = arg[0];
+	else if (STREQ(arg, "^-") || STREQ(arg, "undef"))
+		value = _POSIX_VDISABLE;
+	else if (arg[0] == '^' && arg[1] != '\0') {     /* Ignore any trailing junk. */
+		if (arg[1] == '?')
+			value = 127;
+		else
+			value = arg[1] & ~0140; /* Non-letters get weird results. */
+	} else
+		value = bb_xparse_number(arg, stty_suffixes);
+	mode->c_cc[info->offset] = value;
+}
+
+static void
+set_speed(enum speed_setting type, const char *arg, struct termios *mode)
+{
+	speed_t baud;
+
+	baud = string_to_baud(arg);
+
+	if (type != output_speed) {     /* either input or both */
+		cfsetispeed(mode, baud);
+	}
+	if (type != input_speed) {      /* either output or both */
+		cfsetospeed(mode, baud);
+	}
+}
+
+#ifdef TIOCGWINSZ
+
+static int get_win_size(int fd, struct winsize *win)
+{
+	int err = ioctl(fd, TIOCGWINSZ, (char *) win);
+
+	return err;
+}
+
+static void
+set_window_size(int rows, int cols)
+{
+	struct winsize win;
+
+	if (get_win_size(STDIN_FILENO, &win)) {
+		if (errno != EINVAL)
+			perror_on_device("%s");
+		memset(&win, 0, sizeof(win));
+	}
+
+	if (rows >= 0)
+		win.ws_row = rows;
+	if (cols >= 0)
+		win.ws_col = cols;
+
+# ifdef TIOCSSIZE
+	/* Alexander Dupuy <dupuy at cs.columbia.edu> wrote:
+	   The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
+	   This comment from sys/ttold.h describes Sun's twisted logic - a better
+	   test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
+	   At any rate, the problem is gone in Solaris 2.x. */
+
+	if (win.ws_row == 0 || win.ws_col == 0) {
+		struct ttysize ttysz;
+
+		ttysz.ts_lines = win.ws_row;
+		ttysz.ts_cols = win.ws_col;
+
+		win.ws_row = win.ws_col = 1;
+
+		if ((ioctl(STDIN_FILENO, TIOCSWINSZ, (char *) &win) != 0)
+			|| (ioctl(STDIN_FILENO, TIOCSSIZE, (char *) &ttysz) != 0)) {
+			perror_on_device("%s");
+		}
+		return;
+	}
+# endif
+
+	if (ioctl(STDIN_FILENO, TIOCSWINSZ, (char *) &win))
+		perror_on_device("%s");
+}
+
+static void display_window_size(int fancy)
+{
+	const char *fmt_str = "%s" "\0" "%s: no size information for this device";
+	struct winsize win;
+
+	if (get_win_size(STDIN_FILENO, &win)) {
+		if ((errno != EINVAL) || ((fmt_str += 2), !fancy)) {
+			perror_on_device(fmt_str);
+		}
+	} else {
+		wrapf(fancy ? "rows %d; columns %d;" : "%d %d\n",
+			  win.ws_row, win.ws_col);
+		if (!fancy)
+			current_col = 0;
+	}
+}
+#endif
+
+static int screen_columns(void)
+{
+	int columns;
+	const char *s;
+
+#ifdef TIOCGWINSZ
+	struct winsize win;
+
+	/* With Solaris 2.[123], this ioctl fails and errno is set to
+	   EINVAL for telnet (but not rlogin) sessions.
+	   On ISC 3.0, it fails for the console and the serial port
+	   (but it works for ptys).
+	   It can also fail on any system when stdout isn't a tty.
+	   In case of any failure, just use the default.  */
+	if (get_win_size(STDOUT_FILENO, &win) == 0 && win.ws_col > 0)
+		return win.ws_col;
+#endif
+
+	columns = 80;
+	if ((s = getenv("COLUMNS"))) {
+		columns = atoi(s);
+	}
+	return columns;
+}
+
+static tcflag_t *mode_type_flag(enum mode_type type, struct termios *mode)
+{
+	static const unsigned char tcflag_offsets[] = {
+		offsetof(struct termios, c_cflag), /* control */
+		offsetof(struct termios, c_iflag), /* input */
+		offsetof(struct termios, c_oflag), /* output */
+		offsetof(struct termios, c_lflag) /* local */
+	};
+
+	if (((unsigned int) type) <= local) {
+		return (tcflag_t *)(((char *) mode) + tcflag_offsets[(int)type]);
+	}
+	return NULL;
+}
+
+static void display_changed(struct termios *mode)
+{
+	int i;
+	int empty_line;
+	tcflag_t *bitsp;
+	unsigned long mask;
+	enum mode_type prev_type = control;
+
+	display_speed(mode, 1);
+#ifdef HAVE_C_LINE
+	wrapf("line = %d;", mode->c_line);
+#endif
+	putchar('\n');
+	current_col = 0;
+
+	empty_line = 1;
+	for (i = 0; control_info[i].name != stty_min; ++i) {
+		if (mode->c_cc[control_info[i].offset] == control_info[i].saneval)
+			continue;
+		/* If swtch is the same as susp, don't print both.  */
+#if VSWTCH == VSUSP
+		if (control_info[i].name == stty_swtch)
+			continue;
+#endif
+		/* If eof uses the same slot as min, only print whichever applies.  */
+#if VEOF == VMIN
+		if ((mode->c_lflag & ICANON) == 0
+			&& (control_info[i].name == stty_eof
+				|| control_info[i].name == stty_eol)) continue;
+#endif
+
+		empty_line = 0;
+		wrapf("%s = %s;", control_info[i].name,
+			  visible(mode->c_cc[control_info[i].offset]));
+	}
+	if ((mode->c_lflag & ICANON) == 0) {
+		wrapf("min = %d; time = %d;\n", (int) mode->c_cc[VMIN],
+			  (int) mode->c_cc[VTIME]);
+	} else if (empty_line == 0)
+		putchar('\n');
+	current_col = 0;
+
+	empty_line = 1;
+	for (i = 0; i < NUM_mode_info; ++i) {
+		if (mode_info[i].flags & OMIT)
+			continue;
+		if (EMT(mode_info[i].type) != prev_type) {
+			if (empty_line == 0) {
+				putchar('\n');
+				current_col = 0;
+				empty_line = 1;
+			}
+			prev_type = EMT(mode_info[i].type);
+		}
+
+		bitsp = mode_type_flag(EMT(mode_info[i].type), mode);
+		mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
+		if ((*bitsp & mask) == mode_info[i].bits) {
+			if (mode_info[i].flags & SANE_UNSET) {
+				wrapf("%s", mode_info[i].name);
+				empty_line = 0;
+			}
+		}
+			else if ((mode_info[i].flags & (SANE_SET | REV)) ==
+					 (SANE_SET | REV)) {
+			wrapf("-%s", mode_info[i].name);
+			empty_line = 0;
+		}
+	}
+	if (empty_line == 0)
+		putchar('\n');
+	current_col = 0;
+}
+
+static void
+display_all(struct termios *mode)
+{
+	int i;
+	tcflag_t *bitsp;
+	unsigned long mask;
+	enum mode_type prev_type = control;
+
+	display_speed(mode, 1);
+#ifdef TIOCGWINSZ
+	display_window_size(1);
+#endif
+#ifdef HAVE_C_LINE
+	wrapf("line = %d;", mode->c_line);
+#endif
+	putchar('\n');
+	current_col = 0;
+
+	for (i = 0; control_info[i].name != stty_min; ++i) {
+		/* If swtch is the same as susp, don't print both.  */
+#if VSWTCH == VSUSP
+		if (control_info[i].name == stty_swtch)
+			continue;
+#endif
+		/* If eof uses the same slot as min, only print whichever applies.  */
+#if VEOF == VMIN
+		if ((mode->c_lflag & ICANON) == 0
+			&& (control_info[i].name == stty_eof
+				|| control_info[i].name == stty_eol)) continue;
+#endif
+		wrapf("%s = %s;", control_info[i].name,
+			  visible(mode->c_cc[control_info[i].offset]));
+	}
+#if VEOF == VMIN
+	if ((mode->c_lflag & ICANON) == 0)
+#endif
+		wrapf("min = %d; time = %d;", mode->c_cc[VMIN], mode->c_cc[VTIME]);
+	if (current_col != 0)
+		putchar('\n');
+	current_col = 0;
+
+	for (i = 0; i < NUM_mode_info; ++i) {
+		if (mode_info[i].flags & OMIT)
+			continue;
+		if (EMT(mode_info[i].type) != prev_type) {
+			putchar('\n');
+			current_col = 0;
+			prev_type = EMT(mode_info[i].type);
+		}
+
+		bitsp = mode_type_flag(EMT(mode_info[i].type), mode);
+		mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
+		if ((*bitsp & mask) == mode_info[i].bits)
+			wrapf("%s", mode_info[i].name);
+		else if (mode_info[i].flags & REV)
+			wrapf("-%s", mode_info[i].name);
+	}
+	putchar('\n');
+	current_col = 0;
+}
+
+static void display_speed(struct termios *mode, int fancy)
+{
+	unsigned long ispeed, ospeed;
+	const char *fmt_str =
+		"%lu %lu\n\0"        "ispeed %lu baud; ospeed %lu baud;\0"
+		"%lu\n\0" "\0\0\0\0" "speed %lu baud;";
+
+	ospeed = ispeed = cfgetispeed(mode);
+	if (ispeed == 0 || ispeed == (ospeed = cfgetospeed(mode))) {
+		ispeed = ospeed;                /* in case ispeed was 0 */
+		fmt_str += 43;
+	}
+	if (fancy) {
+		fmt_str += 9;
+	}
+	wrapf(fmt_str, tty_baud_to_value(ispeed), tty_baud_to_value(ospeed));
+	if (!fancy)
+		current_col = 0;
+}
+
+static void display_recoverable(struct termios *mode)
+{
+	int i;
+
+	printf("%lx:%lx:%lx:%lx",
+		   (unsigned long) mode->c_iflag, (unsigned long) mode->c_oflag,
+		   (unsigned long) mode->c_cflag, (unsigned long) mode->c_lflag);
+	for (i = 0; i < NCCS; ++i)
+		printf(":%x", (unsigned int) mode->c_cc[i]);
+	putchar('\n');
+}
+
+static int recover_mode(char *arg, struct termios *mode)
+{
+	int i, n;
+	unsigned int chr;
+	unsigned long iflag, oflag, cflag, lflag;
+
+	/* Scan into temporaries since it is too much trouble to figure out
+	   the right format for `tcflag_t'.  */
+	if (sscanf(arg, "%lx:%lx:%lx:%lx%n",
+			   &iflag, &oflag, &cflag, &lflag, &n) != 4)
+		return 0;
+	mode->c_iflag = iflag;
+	mode->c_oflag = oflag;
+	mode->c_cflag = cflag;
+	mode->c_lflag = lflag;
+	arg += n;
+	for (i = 0; i < NCCS; ++i) {
+		if (sscanf(arg, ":%x%n", &chr, &n) != 1)
+			return 0;
+		mode->c_cc[i] = chr;
+		arg += n;
+	}
+
+	/* Fail if there are too many fields.  */
+	if (*arg != '\0')
+		return 0;
+
+	return 1;
+}
+
+static speed_t string_to_baud(const char *arg)
+{
+	return tty_value_to_baud(bb_xparse_number(arg, 0));
+}
+
+static void sane_mode(struct termios *mode)
+{
+	int i;
+	tcflag_t *bitsp;
+
+	for (i = 0; i < NUM_control_info; ++i) {
+#if VMIN == VEOF
+		if (control_info[i].name == stty_min)
+			break;
+#endif
+		mode->c_cc[control_info[i].offset] = control_info[i].saneval;
+	}
+
+	for (i = 0; i < NUM_mode_info; ++i) {
+		if (mode_info[i].flags & SANE_SET) {
+			bitsp = mode_type_flag(EMT(mode_info[i].type), mode);
+			*bitsp = (*bitsp & ~((unsigned long)mode_info[i].mask))
+				| mode_info[i].bits;
+		} else if (mode_info[i].flags & SANE_UNSET) {
+			bitsp = mode_type_flag(EMT(mode_info[i].type), mode);
+			*bitsp = *bitsp & ~((unsigned long)mode_info[i].mask)
+				& ~mode_info[i].bits;
+		}
+	}
+}
+
+/* Return a string that is the printable representation of character CH.  */
+/* Adapted from `cat' by Torbjorn Granlund.  */
+
+static const char *visible(unsigned int ch)
+{
+	static char buf[10];
+	char *bpout = buf;
+
+	if (ch == _POSIX_VDISABLE) {
+		return "<undef>";
+	}
+
+	if (ch >= 128) {
+		ch -= 128;
+		*bpout++ = 'M';
+		*bpout++ = '-';
+	}
+
+	if (ch < 32) {
+		*bpout++ = '^';
+		*bpout++ = ch + 64;
+	} else if (ch < 127) {
+		*bpout++ = ch;
+	} else {
+		*bpout++ = '^';
+		*bpout++ = '?';
+	}
+
+	*bpout = '\0';
+	return (const char *) buf;
+}
+
+#ifdef TEST
+
+const char *bb_applet_name = "stty";
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/sum.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/sum.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/sum.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,161 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * sum -- checksum and count the blocks in a file
+ *     Like BSD sum or SysV sum -r, except like SysV sum if -s option is given.
+ *
+ * Copyright (C) 86, 89, 91, 1995-2002, 2004 Free Software Foundation, Inc.
+ * Copyright (C) 2005 by Erik Andersen <andersen at codepoet.org>
+ * Copyright (C) 2005 by Mike Frysinger <vapier at gentoo.org>
+ *
+ * Written by Kayvan Aghaiepour and David MacKenzie
+ * Taken from coreutils and turned into a busybox applet by Mike Frysinger
+ *
+ * Licensed under the GPL v2, see the file LICENSE in this tarball.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "busybox.h"
+
+/* 1 if any of the files read were the standard input */
+static int have_read_stdin;
+
+/* make a little more readable and avoid using strcmp for just 2 bytes */
+#define IS_STDIN(s) (s[0] == '-' && s[1] == '\0')
+
+/* Calculate and print the rotated checksum and the size in 1K blocks
+   of file FILE, or of the standard input if FILE is "-".
+   If PRINT_NAME is >1, print FILE next to the checksum and size.
+   The checksum varies depending on sizeof (int).
+   Return 1 if successful.  */
+static int bsd_sum_file(const char *file, int print_name)
+{
+	FILE *fp;
+	int checksum = 0;          /* The checksum mod 2^16. */
+	uintmax_t total_bytes = 0; /* The number of bytes. */
+	int ch;                    /* Each character read. */
+
+	if (IS_STDIN(file)) {
+		fp = stdin;
+		have_read_stdin = 1;
+	} else {
+		fp = bb_wfopen(file, "r");
+		if (fp == NULL)
+			return 0;
+	}
+
+	while ((ch = getc(fp)) != EOF) {
+		++total_bytes;
+		checksum = (checksum >> 1) + ((checksum & 1) << 15);
+		checksum += ch;
+		checksum &= 0xffff;             /* Keep it within bounds. */
+	}
+
+	if (ferror(fp)) {
+		bb_perror_msg(file);
+		bb_fclose_nonstdin(fp);
+		return 0;
+	}
+
+	if (bb_fclose_nonstdin(fp) == EOF) {
+		bb_perror_msg(file);
+		return 0;
+	}
+
+	printf("%05d %5ju ", checksum, (total_bytes+1023)/1024);
+	if (print_name > 1)
+		puts(file);
+	else
+		printf("\n");
+
+	return 1;
+}
+
+/* Calculate and print the checksum and the size in 512-byte blocks
+   of file FILE, or of the standard input if FILE is "-".
+   If PRINT_NAME is >0, print FILE next to the checksum and size.
+   Return 1 if successful.  */
+#define MY_BUF_SIZE 8192
+static int sysv_sum_file(const char *file, int print_name)
+{
+	RESERVE_CONFIG_BUFFER(buf, MY_BUF_SIZE);
+	int fd;
+	uintmax_t total_bytes = 0;
+
+	/* The sum of all the input bytes, modulo (UINT_MAX + 1).  */
+	unsigned int s = 0;
+
+	if (IS_STDIN(file)) {
+		fd = 0;
+		have_read_stdin = 1;
+	} else {
+		fd = open(file, O_RDONLY);
+		if (fd == -1)
+			goto release_and_ret;
+	}
+
+	while (1) {
+		size_t bytes_read = safe_read(fd, buf, MY_BUF_SIZE);
+
+		if (bytes_read == 0)
+			break;
+
+		if (bytes_read == -1) {
+release_and_ret:
+			bb_perror_msg(file);
+			RELEASE_CONFIG_BUFFER(buf);
+			if (!IS_STDIN(file))
+				close(fd);
+			return 0;
+		}
+
+		total_bytes += bytes_read;
+		while (bytes_read--)
+			s += buf[bytes_read];
+	}
+
+	if (!IS_STDIN(file) && close(fd) == -1)
+		goto release_and_ret;
+	else
+		RELEASE_CONFIG_BUFFER(buf);
+
+	{
+		int r = (s & 0xffff) + ((s & 0xffffffff) >> 16);
+		s = (r & 0xffff) + (r >> 16);
+
+		printf("%d %ju ", s, (total_bytes+511)/512);
+	}
+	puts(print_name ? file : "");
+
+	return 1;
+}
+
+int sum_main(int argc, char **argv)
+{
+	int flags;
+	int ok;
+	int (*sum_func)(const char *, int) = bsd_sum_file;
+
+	/* give the bsd func priority over sysv func */
+	flags = bb_getopt_ulflags(argc, argv, "sr");
+	if (flags & 1)
+		sum_func = sysv_sum_file;
+	if (flags & 2)
+		sum_func = bsd_sum_file;
+
+	have_read_stdin = 0;
+	if ((argc - optind) == 0)
+		ok = sum_func("-", 0);
+	else
+		for (ok = 1; optind < argc; optind++)
+			ok &= sum_func(argv[optind], 1);
+
+	if (have_read_stdin && fclose(stdin) == EOF)
+		bb_perror_msg_and_die("-");
+
+	exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/sync.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/sync.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/sync.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,36 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini sync implementation for busybox
+ *
+ * Copyright (C) 1995, 1996 by Bruce Perens <bruce at pixar.com>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+int sync_main(int argc, char **argv)
+{
+	bb_warn_ignoring_args(argc - 1);
+
+	sync();
+
+	return(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/tail.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/tail.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/tail.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,323 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini tail implementation for busybox
+ *
+ * Copyright (C) 2001 by Matt Kraai <kraai at alumni.carnegiemellon.edu>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 compliant (need fancy for -c) */
+/* BB_AUDIT GNU compatible -c, -q, and -v options in 'fancy' configuration. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/tail.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Pretty much rewritten to fix numerous bugs and reduce realloc() calls.
+ * Bugs fixed (although I may have forgotten one or two... it was pretty bad)
+ * 1) mixing printf/write without fflush()ing stdout
+ * 2) no check that any open files are present
+ * 3) optstring had -q taking an arg
+ * 4) no error checking on write in some cases, and a warning even then
+ * 5) q and s interaction bug
+ * 6) no check for lseek error
+ * 7) lseek attempted when count==0 even if arg was +0 (from top)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "busybox.h"
+
+static const struct suffix_mult tail_suffixes[] = {
+	{ "b", 512 },
+	{ "k", 1024 },
+	{ "m", 1048576 },
+	{ NULL, 0 }
+};
+
+static int status;
+
+static void tail_xprint_header(const char *fmt, const char *filename)
+{
+	/* If we get an output error, there is really no sense in continuing. */
+	if (dprintf(STDOUT_FILENO, fmt, filename) < 0) {
+		bb_perror_nomsg_and_die();
+	}
+}
+
+/* len should probably be size_t */
+static void tail_xbb_full_write(const char *buf, size_t len)
+{
+	/* If we get a write error, there is really no sense in continuing. */
+	if (bb_full_write(STDOUT_FILENO, buf, len) < 0) {
+		bb_perror_nomsg_and_die();
+	}
+}
+
+static ssize_t tail_read(int fd, char *buf, size_t count)
+{
+	ssize_t r;
+	off_t current,end;
+	struct stat sbuf;
+
+	end = current = lseek(fd, 0, SEEK_CUR);
+	if (!fstat(fd, &sbuf))
+		end = sbuf.st_size;
+	lseek(fd, end < current ? 0 : current, SEEK_SET);
+	if ((r = safe_read(fd, buf, count)) < 0) {
+		bb_perror_msg(bb_msg_read_error);
+		status = EXIT_FAILURE;
+	}
+
+	return r;
+}
+
+static const char tail_opts[] =
+	"fn:c:"
+#if ENABLE_FEATURE_FANCY_TAIL
+	"qs:v"
+#endif
+	;
+
+static const char header_fmt[] = "\n==> %s <==\n";
+
+int tail_main(int argc, char **argv)
+{
+	long count = 10;
+	unsigned int sleep_period = 1;
+	int from_top = 0;
+	int follow = 0;
+	int header_threshhold = 1;
+	int count_bytes = 0;
+
+	char *tailbuf;
+	size_t tailbufsize;
+	int taillen = 0;
+	int newline = 0;
+
+	int *fds, nfiles, nread, nwrite, seen, i, opt;
+	char *s, *buf;
+	const char *fmt;
+
+#if !ENABLE_DEBUG_YANK_SUSv2 || ENABLE_FEATURE_FANCY_TAIL
+	/* Allow legacy syntax of an initial numeric option without -n. */
+	if (argc >=2 && ((argv[1][0] == '+') || ((argv[1][0] == '-')
+			/* && (isdigit)(argv[1][1]) */
+			&& (((unsigned int)(argv[1][1] - '0')) <= 9))))
+	{
+		optind = 2;
+		optarg = argv[1];
+		goto GET_COUNT;
+	}
+#endif
+
+	while ((opt = getopt(argc, argv, tail_opts)) > 0) {
+		switch (opt) {
+			case 'f':
+				follow = 1;
+				break;
+			case 'c':
+				count_bytes = 1;
+				/* FALLS THROUGH */
+			case 'n':
+#if !ENABLE_DEBUG_YANK_SUSv2 || ENABLE_FEATURE_FANCY_TAIL
+			GET_COUNT:
+#endif
+				count = bb_xgetlarg10_sfx(optarg, tail_suffixes);
+				/* Note: Leading whitespace is an error trapped above. */
+				if (*optarg == '+') {
+					from_top = 1;
+				} else {
+					from_top = 0;
+				}
+				if (count < 0) {
+					count = -count;
+				}
+				break;
+#if ENABLE_FEATURE_FANCY_TAIL
+			case 'q':
+				header_threshhold = INT_MAX;
+				break;
+			case 's':
+				sleep_period =bb_xgetularg10_bnd(optarg, 0, UINT_MAX);
+				break;
+			case 'v':
+				header_threshhold = 0;
+				break;
+#endif
+			default:
+				bb_show_usage();
+		}
+	}
+
+	/* open all the files */
+	fds = (int *)xmalloc(sizeof(int) * (argc - optind + 1));
+
+	argv += optind;
+	nfiles = i = 0;
+
+	if ((argc -= optind) == 0) {
+		struct stat statbuf;
+
+		if (!fstat(STDIN_FILENO, &statbuf) && S_ISFIFO(statbuf.st_mode)) {
+			follow = 0;
+		}
+		/* --argv; */
+		*argv = (char *) bb_msg_standard_input;
+		goto DO_STDIN;
+	}
+
+	do {
+		if ((argv[i][0] == '-') && !argv[i][1]) {
+		DO_STDIN:
+			fds[nfiles] = STDIN_FILENO;
+		} else if ((fds[nfiles] = open(argv[i], O_RDONLY)) < 0) {
+			bb_perror_msg("%s", argv[i]);
+			status = EXIT_FAILURE;
+			continue;
+		}
+		argv[nfiles] = argv[i];
+		++nfiles;
+	} while (++i < argc);
+
+	if (!nfiles) {
+		bb_error_msg_and_die("no files");
+	}
+
+	tailbufsize = BUFSIZ;
+
+	/* tail the files */
+	if (from_top < count_bytes) {	/* Each is 0 or 1, so true iff 0 < 1. */
+		/* Hence, !from_top && count_bytes */
+		if (tailbufsize < count) {
+			tailbufsize = count + BUFSIZ;
+		}
+	}
+
+	buf = tailbuf = xmalloc(tailbufsize);
+
+	fmt = header_fmt + 1;	/* Skip header leading newline on first output. */
+	i = 0;
+	do {
+		/* Be careful.  It would be possible to optimize the count-bytes
+		 * case if the file is seekable.  If you do though, remember that
+		 * starting file position may not be the beginning of the file.
+		 * Beware of backing up too far.  See example in wc.c.
+		 */
+		if ((!(count|from_top)) && (lseek(fds[i], 0, SEEK_END) >= 0)) {
+			continue;
+		}
+
+		if (nfiles > header_threshhold) {
+			tail_xprint_header(fmt, argv[i]);
+			fmt = header_fmt;
+		}
+
+		buf = tailbuf;
+		taillen = 0;
+		seen = 1;
+		newline = 0;
+
+		while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) {
+			if (from_top) {
+				nwrite = nread;
+				if (seen < count) {
+					if (count_bytes) {
+						nwrite -= (count - seen);
+						seen = count;
+					} else {
+						s = buf;
+						do {
+							--nwrite;
+							if ((*s++ == '\n') && (++seen == count)) {
+								break;
+							}
+						} while (nwrite);
+					}
+				}
+				tail_xbb_full_write(buf + nread - nwrite, nwrite);
+			} else if (count) {
+				if (count_bytes) {
+					taillen += nread;
+					if (taillen > count) {
+						memmove(tailbuf, tailbuf + taillen - count, count);
+						taillen = count;
+					}
+				} else {
+					int k = nread;
+					int nbuf = 0;
+
+					while (k) {
+						--k;
+						if (buf[k] == '\n') {
+							++nbuf;
+						}
+					}
+
+					if (newline + nbuf < count) {
+						newline += nbuf;
+						taillen += nread;
+
+					} else {
+						int extra = 0;
+						if (buf[nread-1] != '\n') {
+							extra = 1;
+						}
+
+						k = newline + nbuf + extra - count;
+						s = tailbuf;
+						while (k) {
+							if (*s == '\n') {
+								--k;
+							}
+							++s;
+						}
+
+						taillen += nread - (s - tailbuf);
+						memmove(tailbuf, s, taillen);
+						newline = count - extra;
+					}
+					if (tailbufsize < taillen + BUFSIZ) {
+						tailbufsize = taillen + BUFSIZ;
+						tailbuf = xrealloc(tailbuf, tailbufsize);
+					}
+				}
+				buf = tailbuf + taillen;
+			}
+		}
+
+		if (!from_top) {
+			tail_xbb_full_write(tailbuf, taillen);
+		}
+
+		taillen = 0;
+	} while (++i < nfiles);
+
+	buf = xrealloc(tailbuf, BUFSIZ);
+
+	fmt = NULL;
+
+	while (follow) {
+		sleep(sleep_period);
+		i = 0;
+		do {
+			if (nfiles > header_threshhold) {
+				fmt = header_fmt;
+			}
+			while ((nread = tail_read(fds[i], buf, sizeof(buf))) > 0) {
+				if (fmt) {
+					tail_xprint_header(fmt, argv[i]);
+					fmt = NULL;
+				}
+				tail_xbb_full_write(buf, nread);
+			}
+		} while (++i < nfiles);
+	}
+
+	return status;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/tee.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/tee.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/tee.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,116 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * tee implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/tee.html */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include "busybox.h"
+
+int tee_main(int argc, char **argv)
+{
+	const char *mode = "w\0a";
+	FILE **files;
+	FILE **p;
+	char **filenames;
+	int flags;
+	int retval = EXIT_SUCCESS;
+#ifdef CONFIG_FEATURE_TEE_USE_BLOCK_IO
+	ssize_t c;
+# define buf bb_common_bufsiz1
+#else
+	int c;
+#endif
+
+	flags = bb_getopt_ulflags(argc, argv, "ia");	/* 'a' must be 2nd */
+
+	mode += (flags & 2);	/* Since 'a' is the 2nd option... */
+
+	if (flags & 1) {
+		signal(SIGINT, SIG_IGN);	/* TODO - switch to sigaction.*/
+	}
+
+	/* gnu tee ignores SIGPIPE in case one of the output files is a pipe
+	 * that doesn't consume all its input.  Good idea... */
+	signal(SIGPIPE, SIG_IGN);		/* TODO - switch to sigaction.*/
+
+	/* Allocate an array of FILE *'s, with one extra for a sentinal. */
+	p = files = (FILE **)xmalloc(sizeof(FILE *) * (argc - optind + 2));
+	*p = stdout;
+	argv += optind - 1;
+	filenames = argv - 1;
+	*filenames = (char *) bb_msg_standard_input;	/* for later */
+	goto GOT_NEW_FILE;
+
+	do {
+		if ((*p = bb_wfopen(*argv, mode)) == NULL) {
+			retval = EXIT_FAILURE;
+			continue;
+		}
+		filenames[(int)(p - files)] = *argv;
+	GOT_NEW_FILE:
+		setbuf(*p, NULL);	/* tee must not buffer output. */
+		++p;
+	} while (*++argv);
+
+	*p = NULL;				/* Store the sentinal value. */
+
+#ifdef CONFIG_FEATURE_TEE_USE_BLOCK_IO
+	while ((c = safe_read(STDIN_FILENO, buf, BUFSIZ)) > 0) {
+		for (p=files ; *p ; p++) {
+			fwrite(buf, 1, c, *p);
+		}
+	}
+
+	if (c < 0) {			/* Make sure read errors are signaled. */
+		retval = EXIT_FAILURE;
+	}
+
+#else
+	setvbuf(stdout, NULL, _IONBF, 0);
+	while ((c = getchar()) != EOF) {
+		for (p=files ; *p ; p++) {
+			putc(c, *p);
+		}
+	}
+#endif
+
+	/* Now we need to check for i/o errors on stdin and the various
+	 * output files.  Since we know that the first entry in the output
+	 * file table is stdout, we can save one "if ferror" test by
+	 * setting the first entry to stdin and checking stdout error
+	 * status with bb_fflush_stdout_and_exit()... although fflush()ing
+	 * is unnecessary here. */
+
+	p = files;
+	*p = stdin;
+	do {		/* Now check for (input and) output errors. */
+		/* Checking ferror should be sufficient, but we may want to fclose.
+		 * If we do, remember not to close stdin! */
+		bb_xferror(*p, filenames[(int)(p - files)]);
+	} while (*++p);
+
+	bb_fflush_stdout_and_exit(retval);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/test.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/test.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/test.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,581 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * test implementation for busybox
+ *
+ * Copyright (c) by a whole pile of folks:
+ *
+ *     test(1); version 7-like  --  author Erik Baalbergen
+ *     modified by Eric Gisin to be used as built-in.
+ *     modified by Arnold Robbins to add SVR3 compatibility
+ *     (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket).
+ *     modified by J.T. Conklin for NetBSD.
+ *     modified by Herbert Xu to be used as built-in in ash.
+ *     modified by Erik Andersen <andersen at codepoet.org> to be used
+ *     in busybox.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * Original copyright notice states:
+ *     "This program is in the Public Domain."
+ */
+
+#include "busybox.h"
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <setjmp.h>
+
+/* test(1) accepts the following grammar:
+	oexpr	::= aexpr | aexpr "-o" oexpr ;
+	aexpr	::= nexpr | nexpr "-a" aexpr ;
+	nexpr	::= primary | "!" primary
+	primary ::= unary-operator operand
+		| operand binary-operator operand
+		| operand
+		| "(" oexpr ")"
+		;
+	unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"|
+		"-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S";
+
+	binary-operator ::= "="|"=="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
+			"-nt"|"-ot"|"-ef";
+	operand ::= <any legal UNIX file name>
+*/
+
+enum token {
+	EOI,
+	FILRD,
+	FILWR,
+	FILEX,
+	FILEXIST,
+	FILREG,
+	FILDIR,
+	FILCDEV,
+	FILBDEV,
+	FILFIFO,
+	FILSOCK,
+	FILSYM,
+	FILGZ,
+	FILTT,
+	FILSUID,
+	FILSGID,
+	FILSTCK,
+	FILNT,
+	FILOT,
+	FILEQ,
+	FILUID,
+	FILGID,
+	STREZ,
+	STRNZ,
+	STREQ,
+	STRNE,
+	STRLT,
+	STRGT,
+	INTEQ,
+	INTNE,
+	INTGE,
+	INTGT,
+	INTLE,
+	INTLT,
+	UNOT,
+	BAND,
+	BOR,
+	LPAREN,
+	RPAREN,
+	OPERAND
+};
+
+enum token_types {
+	UNOP,
+	BINOP,
+	BUNOP,
+	BBINOP,
+	PAREN
+};
+
+static const struct t_op {
+	const char *op_text;
+	short op_num, op_type;
+} ops[] = {
+	{
+	"-r", FILRD, UNOP}, {
+	"-w", FILWR, UNOP}, {
+	"-x", FILEX, UNOP}, {
+	"-e", FILEXIST, UNOP}, {
+	"-f", FILREG, UNOP}, {
+	"-d", FILDIR, UNOP}, {
+	"-c", FILCDEV, UNOP}, {
+	"-b", FILBDEV, UNOP}, {
+	"-p", FILFIFO, UNOP}, {
+	"-u", FILSUID, UNOP}, {
+	"-g", FILSGID, UNOP}, {
+	"-k", FILSTCK, UNOP}, {
+	"-s", FILGZ, UNOP}, {
+	"-t", FILTT, UNOP}, {
+	"-z", STREZ, UNOP}, {
+	"-n", STRNZ, UNOP}, {
+	"-h", FILSYM, UNOP},    /* for backwards compat */
+	{
+	"-O", FILUID, UNOP}, {
+	"-G", FILGID, UNOP}, {
+	"-L", FILSYM, UNOP}, {
+	"-S", FILSOCK, UNOP}, {
+	"=", STREQ, BINOP}, {
+	"==", STREQ, BINOP}, {
+	"!=", STRNE, BINOP}, {
+	"<", STRLT, BINOP}, {
+	">", STRGT, BINOP}, {
+	"-eq", INTEQ, BINOP}, {
+	"-ne", INTNE, BINOP}, {
+	"-ge", INTGE, BINOP}, {
+	"-gt", INTGT, BINOP}, {
+	"-le", INTLE, BINOP}, {
+	"-lt", INTLT, BINOP}, {
+	"-nt", FILNT, BINOP}, {
+	"-ot", FILOT, BINOP}, {
+	"-ef", FILEQ, BINOP}, {
+	"!", UNOT, BUNOP}, {
+	"-a", BAND, BBINOP}, {
+	"-o", BOR, BBINOP}, {
+	"(", LPAREN, PAREN}, {
+	")", RPAREN, PAREN}, {
+	0, 0, 0}
+};
+
+#ifdef CONFIG_FEATURE_TEST_64
+typedef int64_t arith_t;
+#else
+typedef int arith_t;
+#endif
+
+static char **t_wp;
+static struct t_op const *t_wp_op;
+static gid_t *group_array = NULL;
+static int ngroups;
+
+static enum token t_lex(char *s);
+static arith_t oexpr(enum token n);
+static arith_t aexpr(enum token n);
+static arith_t nexpr(enum token n);
+static int binop(void);
+static arith_t primary(enum token n);
+static int filstat(char *nm, enum token mode);
+static arith_t getn(const char *s);
+static int newerf(const char *f1, const char *f2);
+static int olderf(const char *f1, const char *f2);
+static int equalf(const char *f1, const char *f2);
+static int test_eaccess(char *path, int mode);
+static int is_a_group_member(gid_t gid);
+static void initialize_group_array(void);
+
+static jmp_buf leaving;
+
+int bb_test(int argc, char **argv)
+{
+	int res;
+
+	if (strcmp(argv[0], "[") == 0) {
+		if (strcmp(argv[--argc], "]")) {
+			bb_error_msg("missing ]");
+			return 2;
+		}
+		argv[argc] = NULL;
+	} else if (strcmp(argv[0], "[[") == 0) {
+		if (strcmp(argv[--argc], "]]")) {
+			bb_error_msg("missing ]]");
+			return 2;
+		}
+		argv[argc] = NULL;
+	}
+
+	res = setjmp(leaving);
+	if (res)
+		return res;
+
+	/* resetting ngroups is probably unnecessary.  it will
+	 * force a new call to getgroups(), which prevents using
+	 * group data fetched during a previous call.  but the
+	 * only way the group data could be stale is if there's
+	 * been an intervening call to setgroups(), and this
+	 * isn't likely in the case of a shell.  paranoia
+	 * prevails...
+	 */
+	 ngroups = 0;
+
+	/* Implement special cases from POSIX.2, section 4.62.4 */
+	switch (argc) {
+	case 1:
+		return 1;
+	case 2:
+		return *argv[1] == '\0';
+	case 3:
+		if (argv[1][0] == '!' && argv[1][1] == '\0') {
+			return *argv[2] != '\0';
+		}
+		break;
+	case 4:
+		if (argv[1][0] != '!' || argv[1][1] != '\0') {
+			if (t_lex(argv[2]), t_wp_op && t_wp_op->op_type == BINOP) {
+				t_wp = &argv[1];
+				return binop() == 0;
+			}
+		}
+		break;
+	case 5:
+		if (argv[1][0] == '!' && argv[1][1] == '\0') {
+			if (t_lex(argv[3]), t_wp_op && t_wp_op->op_type == BINOP) {
+				t_wp = &argv[2];
+				return binop() != 0;
+			}
+		}
+		break;
+	}
+
+	t_wp = &argv[1];
+	res = !oexpr(t_lex(*t_wp));
+
+	if (*t_wp != NULL && *++t_wp != NULL) {
+		bb_error_msg("%s: unknown operand", *t_wp);
+		return 2;
+	}
+	return res;
+}
+
+static void syntax(const char *op, const char *msg)
+{
+	if (op && *op) {
+		bb_error_msg("%s: %s", op, msg);
+	} else {
+		bb_error_msg("%s", msg);
+	}
+	longjmp(leaving, 2);
+}
+
+static arith_t oexpr(enum token n)
+{
+	arith_t res;
+
+	res = aexpr(n);
+	if (t_lex(*++t_wp) == BOR) {
+		return oexpr(t_lex(*++t_wp)) || res;
+	}
+	t_wp--;
+	return res;
+}
+
+static arith_t aexpr(enum token n)
+{
+	arith_t res;
+
+	res = nexpr(n);
+	if (t_lex(*++t_wp) == BAND)
+		return aexpr(t_lex(*++t_wp)) && res;
+	t_wp--;
+	return res;
+}
+
+static arith_t nexpr(enum token n)
+{
+	if (n == UNOT)
+		return !nexpr(t_lex(*++t_wp));
+	return primary(n);
+}
+
+static arith_t primary(enum token n)
+{
+	arith_t res;
+
+	if (n == EOI) {
+		syntax(NULL, "argument expected");
+	}
+	if (n == LPAREN) {
+		res = oexpr(t_lex(*++t_wp));
+		if (t_lex(*++t_wp) != RPAREN)
+			syntax(NULL, "closing paren expected");
+		return res;
+	}
+	if (t_wp_op && t_wp_op->op_type == UNOP) {
+		/* unary expression */
+		if (*++t_wp == NULL)
+			syntax(t_wp_op->op_text, "argument expected");
+		switch (n) {
+		case STREZ:
+			return strlen(*t_wp) == 0;
+		case STRNZ:
+			return strlen(*t_wp) != 0;
+		case FILTT:
+			return isatty(getn(*t_wp));
+		default:
+			return filstat(*t_wp, n);
+		}
+	}
+
+	if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) {
+		return binop();
+	}
+
+	return strlen(*t_wp) > 0;
+}
+
+static int binop(void)
+{
+	const char *opnd1, *opnd2;
+	struct t_op const *op;
+
+	opnd1 = *t_wp;
+	(void) t_lex(*++t_wp);
+	op = t_wp_op;
+
+	if ((opnd2 = *++t_wp) == (char *) 0)
+		syntax(op->op_text, "argument expected");
+
+	switch (op->op_num) {
+	case STREQ:
+		return strcmp(opnd1, opnd2) == 0;
+	case STRNE:
+		return strcmp(opnd1, opnd2) != 0;
+	case STRLT:
+		return strcmp(opnd1, opnd2) < 0;
+	case STRGT:
+		return strcmp(opnd1, opnd2) > 0;
+	case INTEQ:
+		return getn(opnd1) == getn(opnd2);
+	case INTNE:
+		return getn(opnd1) != getn(opnd2);
+	case INTGE:
+		return getn(opnd1) >= getn(opnd2);
+	case INTGT:
+		return getn(opnd1) > getn(opnd2);
+	case INTLE:
+		return getn(opnd1) <= getn(opnd2);
+	case INTLT:
+		return getn(opnd1) < getn(opnd2);
+	case FILNT:
+		return newerf(opnd1, opnd2);
+	case FILOT:
+		return olderf(opnd1, opnd2);
+	case FILEQ:
+		return equalf(opnd1, opnd2);
+	}
+	/* NOTREACHED */
+	return 1;
+}
+
+static int filstat(char *nm, enum token mode)
+{
+	struct stat s;
+	unsigned int i;
+
+	if (mode == FILSYM) {
+#ifdef S_IFLNK
+		if (lstat(nm, &s) == 0) {
+			i = S_IFLNK;
+			goto filetype;
+		}
+#endif
+		return 0;
+	}
+
+	if (stat(nm, &s) != 0)
+		return 0;
+
+	switch (mode) {
+	case FILRD:
+		return test_eaccess(nm, R_OK) == 0;
+	case FILWR:
+		return test_eaccess(nm, W_OK) == 0;
+	case FILEX:
+		return test_eaccess(nm, X_OK) == 0;
+	case FILEXIST:
+		return 1;
+	case FILREG:
+		i = S_IFREG;
+		goto filetype;
+	case FILDIR:
+		i = S_IFDIR;
+		goto filetype;
+	case FILCDEV:
+		i = S_IFCHR;
+		goto filetype;
+	case FILBDEV:
+		i = S_IFBLK;
+		goto filetype;
+	case FILFIFO:
+#ifdef S_IFIFO
+		i = S_IFIFO;
+		goto filetype;
+#else
+		return 0;
+#endif
+	case FILSOCK:
+#ifdef S_IFSOCK
+		i = S_IFSOCK;
+		goto filetype;
+#else
+		return 0;
+#endif
+	case FILSUID:
+		i = S_ISUID;
+		goto filebit;
+	case FILSGID:
+		i = S_ISGID;
+		goto filebit;
+	case FILSTCK:
+		i = S_ISVTX;
+		goto filebit;
+	case FILGZ:
+		return s.st_size > 0L;
+	case FILUID:
+		return s.st_uid == geteuid();
+	case FILGID:
+		return s.st_gid == getegid();
+	default:
+		return 1;
+	}
+
+  filetype:
+	return ((s.st_mode & S_IFMT) == i);
+
+  filebit:
+	return ((s.st_mode & i) != 0);
+}
+
+static enum token t_lex(char *s)
+{
+	struct t_op const *op = ops;
+
+	if (s == 0) {
+		t_wp_op = (struct t_op *) 0;
+		return EOI;
+	}
+	while (op->op_text) {
+		if (strcmp(s, op->op_text) == 0) {
+			t_wp_op = op;
+			return op->op_num;
+		}
+		op++;
+	}
+	t_wp_op = (struct t_op *) 0;
+	return OPERAND;
+}
+
+/* atoi with error detection */
+static arith_t getn(const char *s)
+{
+	char *p;
+#ifdef CONFIG_FEATURE_TEST_64
+	long long r;
+#else
+	long r;
+#endif
+
+	errno = 0;
+#ifdef CONFIG_FEATURE_TEST_64
+	r = strtoll(s, &p, 10);
+#else
+	r = strtol(s, &p, 10);
+#endif
+
+	if (errno != 0)
+		syntax(s, "out of range");
+
+	if (*(skip_whitespace(p)))
+		syntax(s, "bad number");
+
+	return r;
+}
+
+static int newerf(const char *f1, const char *f2)
+{
+	struct stat b1, b2;
+
+	return (stat(f1, &b1) == 0 &&
+			stat(f2, &b2) == 0 && b1.st_mtime > b2.st_mtime);
+}
+
+static int olderf(const char *f1, const char *f2)
+{
+	struct stat b1, b2;
+
+	return (stat(f1, &b1) == 0 &&
+			stat(f2, &b2) == 0 && b1.st_mtime < b2.st_mtime);
+}
+
+static int equalf(const char *f1, const char *f2)
+{
+	struct stat b1, b2;
+
+	return (stat(f1, &b1) == 0 &&
+			stat(f2, &b2) == 0 &&
+			b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino);
+}
+
+/* Do the same thing access(2) does, but use the effective uid and gid,
+   and don't make the mistake of telling root that any file is
+   executable. */
+static int test_eaccess(char *path, int mode)
+{
+	struct stat st;
+	unsigned int euid = geteuid();
+
+	if (stat(path, &st) < 0)
+		return (-1);
+
+	if (euid == 0) {
+		/* Root can read or write any file. */
+		if (mode != X_OK)
+			return (0);
+
+		/* Root can execute any file that has any one of the execute
+		   bits set. */
+		if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
+			return (0);
+	}
+
+	if (st.st_uid == euid)  /* owner */
+		mode <<= 6;
+	else if (is_a_group_member(st.st_gid))
+		mode <<= 3;
+
+	if (st.st_mode & mode)
+		return (0);
+
+	return (-1);
+}
+
+static void initialize_group_array(void)
+{
+	ngroups = getgroups(0, NULL);
+	group_array = xrealloc(group_array, ngroups * sizeof(gid_t));
+	getgroups(ngroups, group_array);
+}
+
+/* Return non-zero if GID is one that we have in our groups list. */
+static int is_a_group_member(gid_t gid)
+{
+	register int i;
+
+	/* Short-circuit if possible, maybe saving a call to getgroups(). */
+	if (gid == getgid() || gid == getegid())
+		return (1);
+
+	if (ngroups == 0)
+		initialize_group_array();
+
+	/* Search through the list looking for GID. */
+	for (i = 0; i < ngroups; i++)
+		if (gid == group_array[i])
+			return (1);
+
+	return (0);
+}
+
+
+/* applet entry point */
+
+int test_main(int argc, char **argv)
+{
+	exit(bb_test(argc, argv));
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/touch.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/touch.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/touch.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,76 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini touch implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 _NOT_ compliant -- options -a, -m, -r, -t not supported. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/touch.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Previous version called open() and then utime().  While this will be
+ * be necessary to implement -r and -t, it currently only makes things bigger.
+ * Also, exiting on a failure was a bug.  All args should be processed.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <utime.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+int touch_main(int argc, char **argv)
+{
+	int fd;
+	int flags;
+	int status = EXIT_SUCCESS;
+
+	flags = bb_getopt_ulflags(argc, argv, "c");
+
+	argv += optind;
+
+	if (!*argv) {
+		bb_show_usage();
+	}
+
+	do {
+		if (utime(*argv, NULL)) {
+			if (errno == ENOENT) {	/* no such file*/
+				if (flags & 1) {	/* Creation is disabled, so ignore. */
+					continue;
+				}
+				/* Try to create the file. */
+				fd = open(*argv, O_RDWR | O_CREAT,
+						  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
+						  );
+				if ((fd >= 0) && !close(fd)) {
+					continue;
+				}
+			}
+			status = EXIT_FAILURE;
+			bb_perror_msg("%s", *argv);
+		}
+	} while (*++argv);
+
+	return status;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/tr.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/tr.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/tr.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,253 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini tr implementation for busybox
+ *
+ ** Copyright (c) 1987,1997, Prentice Hall   All rights reserved.
+ *
+ * The name of Prentice Hall may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * Copyright (c) Michiel Huisjes
+ *
+ * This version of tr is adapted from Minix tr and was modified
+ * by Erik Andersen <andersen at codepoet.org> to be used in busybox.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+
+// Even with -funsigned-char, gcc still complains about char as an array index.
+
+#define GCC4_IS_STUPID int
+
+#define ASCII 0377
+
+/* some "globals" shared across this file */
+static char com_fl, del_fl, sq_fl;
+/* these last are pointers to static buffers declared in tr_main */
+static char *poutput, *pvector, *pinvec, *poutvec;
+
+static void convert(void)
+{
+	int read_chars = 0, in_index = 0, out_index = 0, c, coded, last = -1;
+
+	for (;;) {
+		// If we're out of input, flush output and read more input.
+
+		if (in_index == read_chars) {
+			if (out_index) {
+				if (write(1, (char *) poutput, out_index) != out_index)
+					bb_error_msg_and_die(bb_msg_write_error);
+				out_index = 0;
+			}
+
+			if ((read_chars = read(0, bb_common_bufsiz1, BUFSIZ)) <= 0) {
+				if (write(1, (char *) poutput, out_index) != out_index)
+					bb_error_msg(bb_msg_write_error);
+				exit(0);
+			}
+			in_index = 0;
+		}
+		c = bb_common_bufsiz1[in_index++];
+		coded = pvector[c];
+		if (del_fl && pinvec[c])
+			continue;
+		if (sq_fl && last == coded && (pinvec[c] || poutvec[coded]))
+			continue;
+		poutput[out_index++] = last = coded;
+	}
+
+	/* NOTREACHED */
+}
+
+static void map(char *string1, unsigned int string1_len,
+		char *string2, unsigned int string2_len)
+{
+	char last = '0';
+	unsigned int i, j;
+
+	for (j = 0, i = 0; i < string1_len; i++) {
+		if (string2_len <= j)
+			pvector[(GCC4_IS_STUPID)string1[i]] = last;
+		else
+			pvector[(GCC4_IS_STUPID)string1[i]] = last = string2[j++];
+	}
+}
+
+/* supported constructs:
+ *   Ranges,  e.g.,  [0-9]  ==>  0123456789
+ *   Escapes, e.g.,  \a     ==>  Control-G
+ *	 Character classes, e.g. [:upper:] ==> A ... Z
+ */
+static unsigned int expand(const char *arg, char *buffer)
+{
+	char *buffer_start = buffer;
+	int i, ac;
+
+	while (*arg) {
+		if (*arg == '\\') {
+			arg++;
+			*buffer++ = bb_process_escape_sequence(&arg);
+		} else if (*(arg+1) == '-') {
+			ac = *(arg+2);
+			if(ac == 0) {
+				*buffer++ = *arg++;
+				continue;
+			}
+			i = *arg;
+			while (i <= ac)
+				*buffer++ = i++;
+			arg += 3; /* Skip the assumed a-z */
+		} else if (*arg == '[') {
+			arg++;
+			i = *arg++;
+			if (ENABLE_FEATURE_TR_CLASSES && i == ':') {
+				if (strncmp(arg, "alpha", 5) == 0) {
+					for (i = 'A'; i <= 'Z'; i++)
+						*buffer++ = i;
+					for (i = 'a'; i <= 'z'; i++)
+						*buffer++ = i;
+				}
+				else if (strncmp(arg, "alnum", 5) == 0) {
+					for (i = '0'; i <= '9'; i++)
+						*buffer++ = i;
+					for (i = 'A'; i <= 'Z'; i++)
+						*buffer++ = i;
+					for (i = 'a'; i <= 'z'; i++)
+						*buffer++ = i;
+				}
+				else if (strncmp(arg, "digit", 5) == 0)
+					for (i = '0'; i <= '9'; i++)
+						*buffer++ = i;
+				else if (strncmp(arg, "lower", 5) == 0)
+					for (i = 'a'; i <= 'z'; i++)
+						*buffer++ = i;
+				else if (strncmp(arg, "upper", 5) == 0)
+					for (i = 'A'; i <= 'Z'; i++)
+						*buffer++ = i;
+				else if (strncmp(arg, "space", 5) == 0) {
+				    const char s[] = "\t\n\v\f\r ";
+					strcat((char*)buffer, s);
+					buffer += sizeof(s) - 1;
+				}
+				else if (strncmp(arg, "blank", 5) == 0) {
+					*buffer++ = '\t';
+					*buffer++ = ' ';
+				}
+				/* gcc gives a warning if braces aren't used here */
+				else if (strncmp(arg, "punct", 5) == 0) {
+					for (i = 0; i <= ASCII; i++)
+						if (isprint(i) && (!isalnum(i)) && (!isspace(i)))
+							*buffer++ = i;
+				}
+				else if (strncmp(arg, "cntrl", 5) == 0) {
+					for (i = 0; i <= ASCII; i++)
+						if (iscntrl(i))
+							*buffer++ = i;
+				}
+				else {
+					*buffer++ = '[';
+					*buffer++ = ':';
+					continue;
+				}
+				break;
+			}
+			if (ENABLE_FEATURE_TR_EQUIV && i == '=') {
+				*buffer++ = *arg;
+				/* skip the closing =] */
+				arg += 3;
+				continue;
+			}
+			if (*arg++ != '-') {
+				*buffer++ = '[';
+				arg -= 2;
+				continue;
+			}
+			ac = *arg++;
+			while (i <= ac)
+				*buffer++ = i++;
+			arg++;				/* Skip the assumed ']' */
+		} else
+			*buffer++ = *arg++;
+	}
+
+	return (buffer - buffer_start);
+}
+
+static int complement(char *buffer, int buffer_len)
+{
+	register short i, j, ix;
+	char conv[ASCII + 2];
+
+	ix = 0;
+	for (i = 0; i <= ASCII; i++) {
+		for (j = 0; j < buffer_len; j++)
+			if (buffer[j] == i)
+				break;
+		if (j == buffer_len)
+			conv[ix++] = i & ASCII;
+	}
+	memcpy(buffer, conv, ix);
+	return ix;
+}
+
+int tr_main(int argc, char **argv)
+{
+	register unsigned char *ptr;
+	int output_length=0, input_length;
+	int idx = 1;
+	int i;
+	RESERVE_CONFIG_BUFFER(output, BUFSIZ);
+	RESERVE_CONFIG_BUFFER(vector, ASCII+1);
+	RESERVE_CONFIG_BUFFER(invec,  ASCII+1);
+	RESERVE_CONFIG_BUFFER(outvec, ASCII+1);
+
+	/* ... but make them available globally */
+	poutput = output;
+	pvector = vector;
+	pinvec  = invec;
+	poutvec = outvec;
+
+	if (argc > 1 && argv[idx][0] == '-') {
+		for (ptr = (unsigned char *) &argv[idx][1]; *ptr; ptr++) {
+			switch (*ptr) {
+			case 'c':
+				com_fl = TRUE;
+				break;
+			case 'd':
+				del_fl = TRUE;
+				break;
+			case 's':
+				sq_fl = TRUE;
+				break;
+			default:
+				bb_show_usage();
+			}
+		}
+		idx++;
+	}
+	for (i = 0; i <= ASCII; i++) {
+		vector[i] = i;
+		invec[i] = outvec[i] = FALSE;
+	}
+
+	if (argv[idx] != NULL) {
+		input_length = expand(argv[idx++], bb_common_bufsiz1);
+		if (com_fl)
+			input_length = complement(bb_common_bufsiz1, input_length);
+		if (argv[idx] != NULL) {
+			if (*argv[idx] == '\0')
+				bb_error_msg_and_die("STRING2 cannot be empty");
+			output_length = expand(argv[idx], output);
+			map(bb_common_bufsiz1, input_length, output, output_length);
+		}
+		for (i = 0; i < input_length; i++)
+			invec[(GCC4_IS_STUPID)bb_common_bufsiz1[i]] = TRUE;
+		for (i = 0; i < output_length; i++)
+			outvec[(GCC4_IS_STUPID)output[i]] = TRUE;
+	}
+	convert();
+	return (0);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/true.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/true.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/true.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,32 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini true implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/true.html */
+
+#include <stdlib.h>
+#include "busybox.h"
+
+int true_main(int argc, char **argv)
+{
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/tty.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/tty.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/tty.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,58 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * tty implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/tty.html */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+int tty_main(int argc, char **argv)
+{
+	const char *s;
+	int silent;		/* Note: No longer relevant in SUSv3. */
+	int retval;
+
+	bb_default_error_retval = 2;	/* SUSv3 requires > 1 for error. */
+
+	silent = bb_getopt_ulflags(argc, argv, "s");
+
+	/* gnu tty outputs a warning that it is ignoring all args. */
+	bb_warn_ignoring_args(argc - optind);
+
+	retval = 0;
+
+	if ((s = ttyname(0)) == NULL) {
+	/* According to SUSv3, ttyname can on fail with EBADF or ENOTTY.
+	 * We know the file descriptor is good, so failure means not a tty. */
+		s = "not a tty";
+		retval = 1;
+	}
+
+	if (!silent) {
+		puts(s);
+	}
+
+	bb_fflush_stdout_and_exit(retval);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/uname.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/uname.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/uname.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,118 @@
+/* vi: set sw=4 ts=4: */
+/* uname -- print system information
+   Copyright (C) 1989-1999 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/uname.html */
+
+/* Option		Example
+
+   -s, --sysname	SunOS
+   -n, --nodename	rocky8
+   -r, --release	4.0
+   -v, --version
+   -m, --machine	sun
+   -a, --all		SunOS rocky8 4.0  sun
+
+   The default behavior is equivalent to `-s'.
+
+   David MacKenzie <djm at gnu.ai.mit.edu> */
+
+/* Busyboxed by Erik Andersen */
+
+/* Further size reductions by Glenn McGrath and Manuel Novoa III. */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Now does proper error checking on i/o.  Plus some further space savings.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include "busybox.h"
+
+typedef struct {
+	struct utsname name;
+	char processor[8];			/* for "unknown" */
+} uname_info_t;
+
+static const char options[] = "snrvmpa";
+static const unsigned short int utsname_offset[] = {
+	offsetof(uname_info_t,name.sysname),
+	offsetof(uname_info_t,name.nodename),
+	offsetof(uname_info_t,name.release),
+	offsetof(uname_info_t,name.version),
+	offsetof(uname_info_t,name.machine),
+	offsetof(uname_info_t,processor)
+};
+
+int uname_main(int argc, char **argv)
+{
+	uname_info_t uname_info;
+#if defined(__sparc__) && defined(__linux__)
+	char *fake_sparc = getenv("FAKE_SPARC");
+#endif
+	const unsigned short int *delta;
+	char toprint;
+
+	toprint = bb_getopt_ulflags(argc, argv, options);
+
+	if (argc != optind) {
+		bb_show_usage();
+	}
+
+	if (toprint & (1 << 6)) {
+		toprint = 0x3f;
+	}
+
+	if (toprint == 0) {
+		toprint = 1;			/* sysname */
+	}
+
+	if (uname(&uname_info.name) == -1) {
+		bb_error_msg_and_die("cannot get system name");
+	}
+
+#if defined(__sparc__) && defined(__linux__)
+	if ((fake_sparc != NULL)
+		&& ((fake_sparc[0] == 'y')
+			|| (fake_sparc[0] == 'Y'))) {
+		strcpy(uname_info.name.machine, "sparc");
+	}
+#endif
+
+	strcpy(uname_info.processor, "unknown");
+
+	delta=utsname_offset;
+	do {
+		if (toprint & 1) {
+			bb_printf(((char *)(&uname_info)) + *delta);
+			if (toprint > 1) {
+				putchar(' ');
+			}
+		}
+		++delta;
+	} while (toprint >>= 1);
+	putchar('\n');
+
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/uniq.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/uniq.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/uniq.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,106 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * uniq implementation for busybox
+ *
+ * Copyright (C) 2005  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/uniq.html */
+
+#include "busybox.h"
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+
+static const char uniq_opts[] = "f:s:" "cdu\0\1\2\4";
+
+static FILE *xgetoptfile_uniq_s(char **argv, int read0write2)
+{
+	const char *n;
+
+	if ((n = *argv) != NULL) {
+		if ((*n != '-') || n[1]) {
+			return bb_xfopen(n, "r\0w" + read0write2);
+		}
+	}
+	return (read0write2) ? stdout : stdin;
+}
+
+int uniq_main(int argc, char **argv)
+{
+	FILE *in, *out;
+	unsigned long dups, skip_fields, skip_chars, i, uniq_flags;
+	const char *s0, *e0, *s1, *e1, *input_filename;
+	int opt;
+
+	uniq_flags = skip_fields = skip_chars = 0;
+
+	while ((opt = getopt(argc, argv, uniq_opts)) > 0) {
+		if ((opt == 'f') || (opt == 's')) {
+			int t = bb_xgetularg10(optarg);
+			if (opt == 'f') {
+				skip_fields = t;
+			} else {
+				skip_chars = t;
+			}
+		} else if ((s0 = strchr(uniq_opts, opt)) != NULL) {
+			uniq_flags |= s0[4];
+		} else {
+			bb_show_usage();
+		}
+	}
+
+	input_filename = *(argv += optind);
+
+	in = xgetoptfile_uniq_s(argv, 0);
+	if (*argv) {
+		++argv;
+	}
+	out = xgetoptfile_uniq_s(argv, 2);
+	if (*argv && argv[1]) {
+		bb_show_usage();
+	}
+
+	s1 = e1 = NULL;				/* prime the pump */
+
+	do {
+		s0 = s1;
+		e0 = e1;
+		dups = 0;
+
+		/* gnu uniq ignores newlines */
+		while ((s1 = bb_get_chomped_line_from_file(in)) != NULL) {
+			e1 = s1;
+			for (i=skip_fields ; i ; i--) {
+				e1 = skip_whitespace(e1);
+				while (*e1 && !isspace(*e1)) {
+					++e1;
+				}
+			}
+			for (i = skip_chars ; *e1 && i ; i--) {
+				++e1;
+			}
+
+			if (!s0 || strcmp(e0, e1)) {
+				break;
+			}
+
+			++dups;		 /* Note: Testing for overflow seems excessive. */
+		}
+
+		if (s0) {
+			if (!(uniq_flags & (2 << !!dups))) {
+				bb_fprintf(out, "\0%d " + (uniq_flags & 1), dups + 1);
+				bb_fprintf(out, "%s\n", s0);
+			}
+			free((void *)s0);
+		}
+	} while (s1);
+
+	bb_xferror(in, input_filename);
+
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/usleep.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/usleep.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/usleep.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,41 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * usleep implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 N/A -- Apparently a busybox extension. */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <unistd.h>
+#include "busybox.h"
+
+int usleep_main(int argc, char **argv)
+{
+	if (argc != 2) {
+		bb_show_usage();
+	}
+
+	if (usleep(bb_xgetularg10_bnd(argv[1], 0, UINT_MAX))) {
+		bb_perror_nomsg_and_die();
+	}
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/uudecode.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/uudecode.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/uudecode.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,189 @@
+/*
+ *  Copyright 2003, Glenn McGrath <bug1 at iinet.net.au>
+ *
+ *  Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ *  Based on specification from
+ *  http://www.opengroup.org/onlinepubs/007904975/utilities/uuencode.html
+ *
+ *  Bugs: the spec doesn't mention anything about "`\n`\n" prior to the
+ *        "end" line
+ */
+
+
+#include <stdio.h>
+#include <errno.h>
+#include <getopt.h> /* optind */
+#include <string.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+static int read_stduu(FILE *src_stream, FILE *dst_stream)
+{
+	char *line;
+
+	while ((line = bb_get_chomped_line_from_file(src_stream)) != NULL) {
+		int length;
+		char *line_ptr = line;
+
+		if (strcmp(line, "end") == 0) {
+			return(EXIT_SUCCESS);
+		}
+		length = ((*line_ptr - 0x20) & 0x3f)* 4 / 3;
+
+		if (length <= 0) {
+			/* Ignore the "`\n" line, why is it even in the encode file ? */
+			continue;
+		}
+		if (length > 60) {
+			bb_error_msg_and_die("Line too long");
+		}
+
+		line_ptr++;
+		/* Tolerate an overly long line to acomadate a possible exta '`' */
+		if (strlen(line_ptr) < (size_t)length) {
+			bb_error_msg_and_die("Short file");
+		}
+
+		while (length > 0) {
+			/* Merge four 6 bit chars to three 8 bit chars */
+			fputc(((line_ptr[0] - 0x20) & 077) << 2 | ((line_ptr[1] - 0x20) & 077) >> 4, dst_stream);
+			line_ptr++;
+			length--;
+			if (length == 0) {
+				break;
+			}
+
+			fputc(((line_ptr[0] - 0x20) & 077) << 4 | ((line_ptr[1] - 0x20) & 077) >> 2, dst_stream);
+			line_ptr++;
+			length--;
+			if (length == 0) {
+				break;
+			}
+
+			fputc(((line_ptr[0] - 0x20) & 077) << 6 | ((line_ptr[1] - 0x20) & 077), dst_stream);
+			line_ptr += 2;
+			length -= 2;
+		}
+		free(line);
+	}
+	bb_error_msg_and_die("Short file");
+}
+
+static int read_base64(FILE *src_stream, FILE *dst_stream)
+{
+	static const char base64_table[] =
+		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n";
+	char term_count = 0;
+
+	while (1) {
+		char translated[4];
+		int count = 0;
+
+		while (count < 4) {
+			char *table_ptr;
+			int ch;
+
+			/* Get next _valid_ character */
+			do {
+				ch = fgetc(src_stream);
+				if (ch == EOF) {
+					bb_error_msg_and_die("Short file");
+				}
+			} while ((table_ptr = strchr(base64_table, ch)) == NULL);
+
+			/* Convert encoded charcter to decimal */
+			ch = table_ptr - base64_table;
+
+			if (*table_ptr == '=') {
+				if (term_count == 0) {
+					translated[count] = 0;
+					break;
+				}
+				term_count++;
+			}
+			else if (*table_ptr == '\n') {
+				/* Check for terminating line */
+				if (term_count == 5) {
+					return(EXIT_SUCCESS);
+				}
+				term_count = 1;
+				continue;
+			} else {
+				translated[count] = ch;
+				count++;
+				term_count = 0;
+			}
+		}
+
+		/* Merge 6 bit chars to 8 bit */
+	    fputc(translated[0] << 2 | translated[1] >> 4, dst_stream);
+		if (count > 2) {
+			fputc(translated[1] << 4 | translated[2] >> 2, dst_stream);
+		}
+		if (count > 3) {
+			fputc(translated[2] << 6 | translated[3], dst_stream);
+		}
+	}
+}
+
+int uudecode_main(int argc, char **argv)
+{
+	int (*decode_fn_ptr) (FILE * src, FILE * dst);
+	FILE *src_stream;
+	char *outname = NULL;
+	char *line;
+	int opt;
+
+	opt = bb_getopt_ulflags(argc, argv, "o:", &outname);
+
+	if (optind == argc) {
+		src_stream = stdin;
+	} else if (optind + 1 == argc) {
+		src_stream = bb_xfopen(argv[optind], "r");
+	} else {
+		bb_show_usage();
+	}
+
+	/* Search for the start of the encoding */
+	while ((line = bb_get_chomped_line_from_file(src_stream)) != NULL) {
+		char *line_ptr = NULL;
+
+		if (line == NULL) {
+			break;
+		} else if (strncmp(line, "begin-base64 ", 13) == 0) {
+			line_ptr = line + 13;
+			decode_fn_ptr = read_base64;
+		} else if (strncmp(line, "begin ", 6) == 0) {
+			line_ptr = line + 6;
+			decode_fn_ptr = read_stduu;
+		}
+
+		if (line_ptr) {
+			FILE *dst_stream;
+			int mode;
+			int ret;
+
+			mode = strtoul(line_ptr, NULL, 8);
+			if (outname == NULL) {
+				outname = strchr(line_ptr, ' ');
+				if ((outname == NULL) || (*outname == '\0')) {
+					break;
+				}
+				outname++;
+			}
+			if (strcmp(outname, "-") == 0) {
+				dst_stream = stdout;
+			} else {
+				dst_stream = bb_xfopen(outname, "w");
+				chmod(outname, mode & (S_IRWXU | S_IRWXG | S_IRWXO));
+			}
+			free(line);
+			ret = decode_fn_ptr(src_stream, dst_stream);
+			bb_fclose_nonstdin(src_stream);
+			return(ret);
+		}
+		free(line);
+	}
+	bb_error_msg_and_die("No `begin' line");
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/uuencode.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/uuencode.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/uuencode.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,146 @@
+/* vi: set sw=4 ts=4: */
+/*
+ *  Copyright (C) 2000 by Glenn McGrath
+ *
+ *  based on the function base64_encode from http.c in wget v1.6
+ *  Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "busybox.h"
+
+/* Conversion table.  for base 64 */
+static const char tbl_base64[65] = {
+	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+	'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+	'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+	'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+	'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+	'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+	'w', 'x', 'y', 'z', '0', '1', '2', '3',
+	'4', '5', '6', '7', '8', '9', '+', '/',
+	'=' /* termination character */
+};
+
+static const char tbl_std[65] = {
+	'`', '!', '"', '#', '$', '%', '&', '\'',
+	'(', ')', '*', '+', ',', '-', '.', '/',
+	'0', '1', '2', '3', '4', '5', '6', '7',
+	'8', '9', ':', ';', '<', '=', '>', '?',
+	'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+	'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+	'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+	'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
+	'`' /* termination character */
+};
+
+/*
+ * Encode the string S of length LENGTH to base64 format and place it
+ * to STORE.  STORE will be 0-terminated, and must point to a writable
+ * buffer of at least 1+BASE64_LENGTH(length) bytes.
+ * where BASE64_LENGTH(len) = (4 * ((LENGTH + 2) / 3))
+ */
+static void uuencode (const unsigned char *s, char *store, const int length, const char *tbl)
+{
+	int i;
+	char *p = store;
+
+	/* Transform the 3x8 bits to 4x6 bits, as required by base64.  */
+	for (i = 0; i < length; i += 3) {
+		*p++ = tbl[s[0] >> 2];
+		*p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
+		*p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
+		*p++ = tbl[s[2] & 0x3f];
+		s += 3;
+	}
+	/* Pad the result if necessary...  */
+	if (i == length + 1) {
+		*(p - 1) = tbl[64];
+	}
+	else if (i == length + 2) {
+		*(p - 1) = *(p - 2) = tbl[64];
+	}
+	/* ...and zero-terminate it.  */
+	*p = '\0';
+}
+
+#define SRC_BUF_SIZE	45  // This *MUST* be a multiple of 3
+#define DST_BUF_SIZE    4 * ((SRC_BUF_SIZE + 2) / 3)
+int uuencode_main(int argc, char **argv)
+{
+	const size_t src_buf_size = SRC_BUF_SIZE;
+	const size_t dst_buf_size = DST_BUF_SIZE;
+	size_t write_size = dst_buf_size;
+	struct stat stat_buf;
+	FILE *src_stream = stdin;
+	const char *tbl;
+	size_t size;
+	mode_t mode;
+	RESERVE_CONFIG_BUFFER(src_buf, SRC_BUF_SIZE + 1);
+	RESERVE_CONFIG_BUFFER(dst_buf, DST_BUF_SIZE + 1);
+
+	tbl = tbl_std;
+	if (bb_getopt_ulflags(argc, argv, "m") & 1) {
+		tbl = tbl_base64;
+	}
+
+	switch (argc - optind) {
+		case 2:
+			src_stream = bb_xfopen(argv[optind], "r");
+			xstat(argv[optind], &stat_buf);
+			mode = stat_buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+			if (src_stream == stdout) {
+				puts("NULL");
+			}
+			break;
+		case 1:
+			mode = 0666 & ~umask(0666);
+			break;
+		default:
+			bb_show_usage();
+	}
+
+	bb_printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]);
+
+	while ((size = fread(src_buf, 1, src_buf_size, src_stream)) > 0) {
+		if (size != src_buf_size) {
+			/* write_size is always 60 until the last line */
+			write_size=(4 * ((size + 2) / 3));
+			/* pad with 0s so we can just encode extra bits */
+			memset(&src_buf[size], 0, src_buf_size - size);
+		}
+		/* Encode the buffer we just read in */
+		uuencode((unsigned char*)src_buf, dst_buf, size, tbl);
+
+		putchar('\n');
+		if (tbl == tbl_std) {
+			putchar(tbl[size]);
+		}
+		if (fwrite(dst_buf, 1, write_size, stdout) != write_size) {
+			bb_perror_msg_and_die(bb_msg_write_error);
+		}
+	}
+	bb_printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n");
+
+	bb_xferror(src_stream, "source");	/* TODO - Fix this! */
+
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/watch.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/watch.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/watch.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,68 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini watch implementation for busybox
+ *
+ * Copyright (C) 2001 by Michael Habermann <mhabermann at gmx.de>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 N/A */
+/* BB_AUDIT GNU defects -- only option -n is supported. */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Removed dependency on date_main(), added proper error checking, and
+ * reduced size.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <time.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include "busybox.h"
+
+int watch_main(int argc, char **argv)
+{
+	int width, len;
+	unsigned period = 2;
+	char **watched_argv, *header;
+
+	if (argc < 2) bb_show_usage();
+
+	get_terminal_width_height(1, &width, 0);
+	header = xzalloc(width--);
+
+	/* don't use getopt, because it permutes the arguments */
+	++argv;
+	if ((argc > 3) && !strcmp(*argv, "-n")) {
+		period = bb_xgetularg10_bnd(argv[1], 1, UINT_MAX);
+		argv += 2;
+	}
+	watched_argv = argv;
+
+	/* create header */
+
+	len = snprintf(header, width, "Every %ds:", period);
+	while (*argv && len<width)
+		snprintf(header+len, width-len, " %s", *(argv++));
+
+	while (1) {
+		char *thyme;
+		time_t t;
+
+		time(&t);
+		thyme = ctime(&t);
+		len = strlen(thyme);
+		if (len < width) header[width-len] = 0;
+		
+		printf("\033[H\033[J%s %s\n", header, thyme);
+
+		waitpid(bb_xspawn(watched_argv),0,0);
+		sleep(period);
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/wc.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/wc.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/wc.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,227 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * wc implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 _NOT_ compliant -- option -m is not currently supported. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/wc.html */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Rewritten to fix a number of problems and do some size optimizations.
+ * Problems in the previous busybox implementation (besides bloat) included:
+ *  1) broken 'wc -c' optimization (read note below)
+ *  2) broken handling of '-' args
+ *  3) no checking of ferror on EOF returns
+ *  4) isprint() wasn't considered when word counting.
+ *
+ * TODO:
+ *
+ * When locale support is enabled, count multibyte chars in the '-m' case.
+ *
+ * NOTES:
+ *
+ * The previous busybox wc attempted an optimization using stat for the
+ * case of counting chars only.  I omitted that because it was broken.
+ * It didn't take into account the possibility of input coming from a
+ * pipe, or input from a file with file pointer not at the beginning.
+ *
+ * To implement such a speed optimization correctly, not only do you
+ * need the size, but also the file position.  Note also that the
+ * file position may be past the end of file.  Consider the example
+ * (adapted from example in gnu wc.c)
+ *
+ *      echo hello > /tmp/testfile &&
+ *      (dd ibs=1k skip=1 count=0 &> /dev/null ; wc -c) < /tmp/testfile
+ *
+ * for which 'wc -c' should output '0'.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "busybox.h"
+
+#ifdef CONFIG_LOCALE_SUPPORT
+#include <locale.h>
+#include <ctype.h>
+#define isspace_given_isprint(c) isspace(c)
+#else
+#undef isspace
+#undef isprint
+#define isspace(c) ((((c) == ' ') || (((unsigned int)((c) - 9)) <= (13 - 9))))
+#define isprint(c) (((unsigned int)((c) - 0x20)) <= (0x7e - 0x20))
+#define isspace_given_isprint(c) ((c) == ' ')
+#endif
+
+enum {
+	WC_LINES	= 0,
+	WC_WORDS	= 1,
+	WC_CHARS	= 2,
+	WC_LENGTH	= 3
+};
+
+/* Note: If this changes, remember to change the initialization of
+ *       'name' in wc_main.  It needs to point to the terminating nul. */
+static const char wc_opts[] = "lwcL";	/* READ THE WARNING ABOVE! */
+
+enum {
+	OP_INC_LINE	= 1, /* OP_INC_LINE must be 1. */
+	OP_SPACE	= 2,
+	OP_NEWLINE	= 4,
+	OP_TAB		= 8,
+	OP_NUL		= 16,
+};
+
+/* Note: If fmt_str changes, the offsets to 's' in the OUTPUT section
+ *       will need to be updated. */
+static const char fmt_str[] = " %7u\0 %s\n";
+static const char total_str[] = "total";
+
+int wc_main(int argc, char **argv)
+{
+	FILE *fp;
+	const char *s;
+	unsigned int *pcounts;
+	unsigned int counts[4];
+	unsigned int totals[4];
+	unsigned int linepos;
+	unsigned int u;
+	int num_files = 0;
+	int c;
+	char status = EXIT_SUCCESS;
+	char in_word;
+	char print_type;
+
+	print_type = bb_getopt_ulflags(argc, argv, wc_opts);
+
+	if (print_type == 0) {
+		print_type = (1 << WC_LINES) | (1 << WC_WORDS) | (1 << WC_CHARS);
+	}
+
+	argv += optind;
+	if (!*argv) {
+		*--argv = (char *) bb_msg_standard_input;
+	}
+
+	memset(totals, 0, sizeof(totals));
+
+	pcounts = counts;
+
+	do {
+		++num_files;
+		if (!(fp = bb_wfopen_input(*argv))) {
+			status = EXIT_FAILURE;
+			continue;
+		}
+
+		memset(counts, 0, sizeof(counts));
+		linepos = 0;
+		in_word = 0;
+
+		do {
+			++counts[WC_CHARS];
+			c = getc(fp);
+			if (isprint(c)) {
+				++linepos;
+				if (!isspace_given_isprint(c)) {
+					in_word = 1;
+					continue;
+				}
+			} else if (((unsigned int)(c - 9)) <= 4) {
+				/* \t  9
+				 * \n 10
+				 * \v 11
+				 * \f 12
+				 * \r 13
+				 */
+				if (c == '\t') {
+					linepos = (linepos | 7) + 1;
+				} else {			/* '\n', '\r', '\f', or '\v' */
+				DO_EOF:
+					if (linepos > counts[WC_LENGTH]) {
+						counts[WC_LENGTH] = linepos;
+					}
+					if (c == '\n') {
+						++counts[WC_LINES];
+					}
+					if (c != '\v') {
+						linepos = 0;
+					}
+				}
+			} else if (c == EOF) {
+				if (ferror(fp)) {
+					bb_perror_msg("%s", *argv);
+					status = EXIT_FAILURE;
+				}
+				--counts[WC_CHARS];
+				goto DO_EOF;		/* Treat an EOF as '\r'. */
+			} else {
+				continue;
+			}
+
+			counts[WC_WORDS] += in_word;
+			in_word = 0;
+			if (c == EOF) {
+				break;
+			}
+		} while (1);
+
+		if (totals[WC_LENGTH] < counts[WC_LENGTH]) {
+			totals[WC_LENGTH] = counts[WC_LENGTH];
+		}
+		totals[WC_LENGTH] -= counts[WC_LENGTH];
+
+		bb_fclose_nonstdin(fp);
+
+	OUTPUT:
+		s = fmt_str + 1;			/* Skip the leading space on 1st pass. */
+		u = 0;
+		do {
+			if (print_type & (1 << u)) {
+				bb_printf(s, pcounts[u]);
+				s = fmt_str;		/* Ok... restore the leading space. */
+			}
+			totals[u] += pcounts[u];
+		} while (++u < 4);
+
+		s += 8;						/* Set the format to the empty string. */
+
+		if (*argv != bb_msg_standard_input) {
+			s -= 3;					/* We have a name, so do %s conversion. */
+		}
+		bb_printf(s, *argv);
+
+	} while (*++argv);
+
+	/* If more than one file was processed, we want the totals.  To save some
+	 * space, we set the pcounts ptr to the totals array.  This has the side
+	 * effect of trashing the totals array after outputting it, but that's
+	 * irrelavent since we no longer need it. */
+	if (num_files > 1) {
+		num_files = 0;				/* Make sure we don't get here again. */
+		*--argv = (char *) total_str;
+		pcounts = totals;
+		goto OUTPUT;
+	}
+
+	bb_fflush_stdout_and_exit(status);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/who.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/who.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/who.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,64 @@
+/* vi: set sw=4 ts=4: */
+/*----------------------------------------------------------------------
+ * Mini who is used to display user name, login time,
+ * idle time and host name.
+ *
+ * Author: Da Chen  <dchen at ayrnetworks.com>
+ *
+ * This is a free document; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation:
+ *    http://www.gnu.org/copyleft/gpl.html
+ *
+ * Copyright (c) 2002 AYR Networks, Inc.
+ *----------------------------------------------------------------------
+ */
+
+#include "busybox.h"
+#include <utmp.h>
+#include <time.h>
+
+static const char * idle_string (time_t t)
+{
+	static char str[6];
+	
+	time_t s = time(NULL) - t;
+
+	if (s < 60)
+		return ".";
+	if (s < (24 * 60 * 60)) {
+		sprintf (str, "%02d:%02d",
+				(int) (s / (60 * 60)),
+				(int) ((s % (60 * 60)) / 60));
+		return str;
+	}
+	return "old";
+}
+
+int who_main(int argc, char **argv)
+{
+	struct utmp *ut;
+	struct stat st;
+	char *name;
+	
+	if (argc > 1) {
+		bb_show_usage();
+	}
+	
+	setutent();
+	printf("USER       TTY      IDLE      TIME           HOST\n");
+	while ((ut = getutent()) != NULL) {
+		if (ut->ut_user[0] && ut->ut_type == USER_PROCESS) {
+			time_t thyme = ut->ut_tv.tv_sec;
+
+			/* ut->ut_line is device name of tty - "/dev/" */
+			name = concat_path_file("/dev", ut->ut_line);
+			printf("%-10s %-8s %-8s  %-12.12s   %s\n", ut->ut_user, ut->ut_line,
+									(stat(name, &st)) ?  "?" : idle_string(st.st_atime),
+									ctime(&thyme) + 4, ut->ut_host);
+			if (ENABLE_FEATURE_CLEAN_UP) free(name);
+		}
+	}
+	if (ENABLE_FEATURE_CLEAN_UP) endutent();
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/whoami.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/whoami.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/whoami.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,38 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini whoami implementation for busybox
+ *
+ * Copyright (C) 2000  Edward Betts <edward at debian.org>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+int whoami_main(int argc, char **argv)
+{
+	if (argc > 1)
+		bb_show_usage();
+
+	puts(bb_getpwuid(NULL, geteuid(), -1));
+	/* exits on error */
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/yes.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/yes.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/coreutils/yes.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,56 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * yes implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
+
+/* Mar 16, 2003      Manuel Novoa III   (mjn3 at codepoet.org)
+ *
+ * Size reductions and removed redundant applet name prefix from error messages.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+int yes_main(int argc, char **argv)
+{
+	static const char fmt_str[] = " %s";
+	const char *fmt;
+	char **first_arg;
+
+	*argv = "y";
+	if (argc != 1) {
+		++argv;
+	}
+
+	first_arg = argv;
+	do {
+		fmt = fmt_str + 1;
+		do {
+			bb_printf(fmt, *argv);
+			fmt = fmt_str;
+		} while (*++argv);
+		argv = first_arg;
+	} while (putchar('\n') != EOF);
+
+	bb_perror_nomsg_and_die();
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,88 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Debian Utilities"
+
+config CONFIG_MKTEMP
+	bool "mktemp"
+	default n
+	help
+	  mktemp is used to create unique temporary files
+
+config CONFIG_PIPE_PROGRESS
+	bool "pipe_progress"
+	default n
+	help
+	  Display a dot to indicate pipe activity.
+
+config CONFIG_READLINK
+	bool "readlink"
+	default n
+	help
+	  This program reads a symbolic link and returns the name
+	  of the file it points to
+
+config CONFIG_FEATURE_READLINK_FOLLOW
+	bool "Enable canonicalization by following all symlinks (-f)"
+	default n
+	depends on CONFIG_READLINK
+	help
+	  Enable the readlink option (-f).
+
+config CONFIG_RUN_PARTS
+	bool "run-parts"
+	default n
+	help
+	  run-parts is a utility designed to run all the scripts in a directory.
+
+	  It is useful to set up a directory like cron.daily, where you need to
+	  execute all the scripts in that directory.
+
+	  In this implementation of run-parts some features (such as report mode)
+	  are not implemented.
+
+	  Unless you know that run-parts is used in some of your scripts
+	  you can safely say N here.
+
+config CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS
+	bool "Enable long options"
+	default n
+	depends on CONFIG_RUN_PARTS && CONFIG_GETOPT_LONG
+	help
+	  Support long options for the run-parts applet.
+
+config CONFIG_START_STOP_DAEMON
+	bool "start-stop-daemon"
+	default y
+	help
+	  start-stop-daemon is used to control the creation and
+	  termination of system-level processes, usually the ones
+	  started during the startup of the system.
+
+config CONFIG_FEATURE_START_STOP_DAEMON_FANCY
+	bool "Support additional arguments"
+	default y
+	depends on CONFIG_START_STOP_DAEMON
+	help
+	  Support additional arguments.
+	  -o|--oknodo ignored since we exit with 0 anyway
+	  -v|--verbose
+
+config CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS
+	bool "Enable long options"
+	default n
+	depends on CONFIG_START_STOP_DAEMON && CONFIG_GETOPT_LONG
+	help
+	  Support long options for the start-stop-daemon applet.
+
+config CONFIG_WHICH
+	bool "which"
+	default n
+	help
+	  which is used to find programs in your PATH and
+	  print out their pathnames.
+
+endmenu
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/debianutils
+DEBIANUTILS_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include $(srcdir)/Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,33 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+DEBIANUTILS_AR:=debianutils.a
+ifndef $(DEBIANUTILS_DIR)
+DEBIANUTILS_DIR:=$(top_builddir)/debianutils/
+endif
+srcdir=$(top_srcdir)/debianutils
+
+DEBIANUTILS-y:=
+DEBIANUTILS-$(CONFIG_MKTEMP)		+= mktemp.o
+DEBIANUTILS-$(CONFIG_PIPE_PROGRESS)	+= pipe_progress.o
+DEBIANUTILS-$(CONFIG_READLINK)		+= readlink.o
+DEBIANUTILS-$(CONFIG_RUN_PARTS)		+= run_parts.o
+DEBIANUTILS-$(CONFIG_START_STOP_DAEMON)	+= start_stop_daemon.o
+DEBIANUTILS-$(CONFIG_WHICH)		+= which.o
+
+ifneq ($(strip $(DEBIANUTILS-y)),)
+libraries-y+=$(DEBIANUTILS_DIR)$(DEBIANUTILS_AR)
+endif
+DEBIANUTILS_SRC-y:=$(patsubst %.o,$(srcdir)/%.c,$(DEBIANUTILS-y))
+DEBIANUTILS_SRC-a:=$(wildcard $(srcdir)/*.c)
+APPLET_SRC-y+=$(DEBIANUTILS_SRC-y)
+APPLET_SRC-a+=$(DEBIANUTILS_SRC-a)
+
+$(DEBIANUTILS_DIR)$(DEBIANUTILS_AR): $(patsubst %,$(DEBIANUTILS_DIR)%, $(DEBIANUTILS-y))
+	$(do_ar)
+
+$(DEBIANUTILS_DIR)%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/mktemp.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/mktemp.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/mktemp.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,38 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini mktemp implementation for busybox
+ *
+ *
+ * Copyright (C) 2000 by Daniel Jacobowitz
+ * Written by Daniel Jacobowitz <dan at debian.org>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+int mktemp_main(int argc, char **argv)
+{
+	unsigned long flags = bb_getopt_ulflags(argc, argv, "dq");
+
+	if (optind + 1 != argc)
+		bb_show_usage();
+
+	if (flags & 1) {
+		if (mkdtemp(argv[optind]) == NULL)
+			return EXIT_FAILURE;
+	}
+	else {
+		if (mkstemp(argv[optind]) < 0)
+			return EXIT_FAILURE;
+	}
+
+	puts(argv[optind]);
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/pipe_progress.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/pipe_progress.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/pipe_progress.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,42 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Monitor a pipe with a simple progress display.
+ *
+ * Copyright (C) 2003 by Rob Landley <rob at landley.net>, Joey Hess
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+
+#define PIPE_PROGRESS_SIZE 4096
+
+/* Read a block of data from stdin, write it to stdout.
+ * Activity is indicated by a '.' to stderr
+ */
+int pipe_progress_main(int argc, char **argv)
+{
+	RESERVE_CONFIG_BUFFER(buf, PIPE_PROGRESS_SIZE);
+	time_t t = time(NULL);
+	size_t len;
+
+	while ((len = fread(buf, 1, PIPE_PROGRESS_SIZE, stdin)) > 0) {
+		time_t new_time = time(NULL);
+		if (new_time != t) {
+			t = new_time;
+			fputc('.', stderr);
+		}
+		fwrite(buf, len, 1, stdout);
+	}
+
+	fputc('\n', stderr);
+
+	if (ENABLE_FEATURE_CLEAN_UP)
+		RELEASE_CONFIG_BUFFER(buf);
+
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/readlink.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/readlink.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/readlink.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,40 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini readlink implementation for busybox
+ *
+ * Copyright (C) 2000,2001 Matt Kraai <kraai at alumni.carnegiemellon.edu>
+ *
+ * Licensed under GPL v2, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#define READLINK_FLAG_f	(1 << 0)
+
+int readlink_main(int argc, char **argv)
+{
+	char *buf;
+	unsigned long opt = ENABLE_FEATURE_READLINK_FOLLOW ?
+							bb_getopt_ulflags(argc, argv, "f") : 0;
+
+	if (argc != (ENABLE_FEATURE_READLINK_FOLLOW ? optind + 1 : 2))
+			bb_show_usage();
+
+	if (opt & READLINK_FLAG_f)
+		buf = realpath(argv[optind], bb_common_bufsiz1);
+	else
+		buf = xreadlink(argv[ENABLE_FEATURE_READLINK_FOLLOW ? optind : 1]);
+
+	if (!buf)
+		return EXIT_FAILURE;
+	puts(buf);
+
+	if (ENABLE_FEATURE_CLEAN_UP && buf != bb_common_bufsiz1)
+		free(buf);
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/run_parts.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/run_parts.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/run_parts.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,100 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini run-parts implementation for busybox
+ *
+ *
+ * Copyright (C) 2001 by Emanuele Aina <emanuele.aina at tiscali.it>
+ *
+ * Based on the Debian run-parts program, version 1.15
+ *   Copyright (C) 1996 Jeff Noxon <jeff at router.patch.net>,
+ *   Copyright (C) 1996-1999 Guy Maor <maor at debian.org>
+ *
+ *
+ * Licensed under GPL v2, see file LICENSE in this tarball for details.
+ */
+
+/* This is my first attempt to write a program in C (well, this is my first
+ * attempt to write a program! :-) . */
+
+/* This piece of code is heavily based on the original version of run-parts,
+ * taken from debian-utils. I've only removed the long options and a the
+ * report mode. As the original run-parts support only long options, I've
+ * broken compatibility because the BusyBox policy doesn't allow them.
+ * The supported options are:
+ * -t			test. Print the name of the files to be executed, without
+ *				execute them.
+ * -a ARG		argument. Pass ARG as an argument the program executed. It can
+ *				be repeated to pass multiple arguments.
+ * -u MASK		umask. Set the umask of the program executed to MASK. */
+
+/* TODO
+ * done - convert calls to error in perror... and remove error()
+ * done - convert malloc/realloc to their x... counterparts
+ * done - remove catch_sigchld
+ * done - use bb's concat_path_file()
+ * done - declare run_parts_main() as extern and any other function as static?
+ */
+
+#include "busybox.h"
+#include <getopt.h>
+#include <stdlib.h>
+
+
+static const struct option runparts_long_options[] = {
+	{ "test",		0,		NULL,		't' },
+	{ "umask",		1,		NULL,		'u' },
+	{ "arg",		1,		NULL,		'a' },
+	{ 0,			0,		0,			0 }
+};
+
+extern char **environ;
+
+/* run_parts_main */
+/* Process options */
+int run_parts_main(int argc, char **argv)
+{
+	char **args = xmalloc(2 * sizeof(char *));
+	unsigned char test_mode = 0;
+	unsigned short argcount = 1;
+	int opt;
+
+	umask(022);
+
+	while ((opt = getopt_long (argc, argv, "tu:a:",
+					runparts_long_options, NULL)) > 0)
+	{
+		switch (opt) {
+			/* Enable test mode */
+			case 't':
+				test_mode++;
+				break;
+			/* Set the umask of the programs executed */
+			case 'u':
+				/* Check and set the umask of the program executed. As stated in the original
+				 * run-parts, the octal conversion in libc is not foolproof; it will take the
+				 * 8 and 9 digits under some circumstances. We'll just have to live with it.
+				 */
+				umask(bb_xgetlarg(optarg, 8, 0, 07777));
+				break;
+			/* Pass an argument to the programs */
+			case 'a':
+				/* Add an argument to the commands that we will call.
+				 * Called once for every argument. */
+				args = xrealloc(args, (argcount + 2) * (sizeof(char *)));
+				args[argcount++] = optarg;
+				break;
+			default:
+				bb_show_usage();
+		}
+	}
+
+	/* We require exactly one argument: the directory name */
+	if (optind != (argc - 1)) {
+		bb_show_usage();
+	}
+
+	args[0] = argv[optind];
+	args[argcount] = 0;
+
+	return(run_parts(args, test_mode, environ));
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/start_stop_daemon.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/start_stop_daemon.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/start_stop_daemon.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,306 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini start-stop-daemon implementation(s) for busybox
+ *
+ * Written by Marek Michalkiewicz <marekm at i17linuxb.ists.pwr.wroc.pl>,
+ * public domain.
+ * Adapted for busybox David Kimdon <dwhedon at gordian.com>
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <getopt.h> /* struct option */
+#include "pwd_.h"
+
+static int signal_nr = 15;
+static int user_id = -1;
+static int quiet;
+static char *userspec = NULL;
+static char *cmdname = NULL;
+static char *execname = NULL;
+static char *pidfile = NULL;
+
+struct pid_list {
+	struct pid_list *next;
+	pid_t pid;
+};
+
+static struct pid_list *found = NULL;
+
+static inline void push(pid_t pid)
+{
+	struct pid_list *p;
+
+	p = xmalloc(sizeof(*p));
+	p->next = found;
+	p->pid = pid;
+	found = p;
+}
+
+static int pid_is_exec(pid_t pid, const char *name)
+{
+	char buf[32];
+	struct stat sb, exec_stat;
+
+	if (name)
+		xstat(name, &exec_stat);
+
+	sprintf(buf, "/proc/%d/exe", pid);
+	if (stat(buf, &sb) != 0)
+		return 0;
+	return (sb.st_dev == exec_stat.st_dev && sb.st_ino == exec_stat.st_ino);
+}
+
+static int pid_is_user(int pid, int uid)
+{
+	struct stat sb;
+	char buf[32];
+
+	sprintf(buf, "/proc/%d", pid);
+	if (stat(buf, &sb) != 0)
+		return 0;
+	return (sb.st_uid == uid);
+}
+
+static int pid_is_cmd(pid_t pid, const char *name)
+{
+	char buf[32];
+	FILE *f;
+	int c;
+
+	sprintf(buf, "/proc/%d/stat", pid);
+	f = fopen(buf, "r");
+	if (!f)
+		return 0;
+	while ((c = getc(f)) != EOF && c != '(')
+		;
+	if (c != '(') {
+		fclose(f);
+		return 0;
+	}
+	/* this hopefully handles command names containing ')' */
+	while ((c = getc(f)) != EOF && c == *name)
+		name++;
+	fclose(f);
+	return (c == ')' && *name == '\0');
+}
+
+
+static void check(int pid)
+{
+	if (execname && !pid_is_exec(pid, execname)) {
+		return;
+	}
+	if (userspec && !pid_is_user(pid, user_id)) {
+		return;
+	}
+	if (cmdname && !pid_is_cmd(pid, cmdname)) {
+		return;
+	}
+	push(pid);
+}
+
+
+static void do_pidfile(void)
+{
+	FILE *f;
+	pid_t pid;
+
+	f = fopen(pidfile, "r");
+	if (f) {
+		if (fscanf(f, "%d", &pid) == 1)
+			check(pid);
+		fclose(f);
+	} else if (errno != ENOENT)
+		bb_perror_msg_and_die("open pidfile %s", pidfile);
+
+}
+
+static void do_procinit(void)
+{
+	DIR *procdir;
+	struct dirent *entry;
+	int foundany, pid;
+
+	if (pidfile) {
+		do_pidfile();
+		return;
+	}
+
+	procdir = bb_xopendir("/proc");
+
+	foundany = 0;
+	while ((entry = readdir(procdir)) != NULL) {
+		if (sscanf(entry->d_name, "%d", &pid) != 1)
+			continue;
+		foundany++;
+		check(pid);
+	}
+	closedir(procdir);
+	if (!foundany)
+		bb_error_msg_and_die ("nothing in /proc - not mounted?");
+}
+
+
+static int do_stop(void)
+{
+	RESERVE_CONFIG_BUFFER(what, 1024);
+	struct pid_list *p;
+	int killed = 0;
+
+	do_procinit();
+
+	if (cmdname)
+		strcpy(what, cmdname);
+	else if (execname)
+		strcpy(what, execname);
+	else if (pidfile)
+		sprintf(what, "process in pidfile `%.200s'", pidfile);
+	else if (userspec)
+		sprintf(what, "process(es) owned by `%s'", userspec);
+	else
+		bb_error_msg_and_die ("internal error, please report");
+
+	if (!found) {
+		if (!quiet)
+			printf("no %s found; none killed.\n", what);
+		if (ENABLE_FEATURE_CLEAN_UP)
+			RELEASE_CONFIG_BUFFER(what);
+		return -1;
+	}
+	for (p = found; p; p = p->next) {
+		if (kill(p->pid, signal_nr) == 0) {
+			p->pid = -p->pid;
+			killed++;
+		} else {
+			bb_perror_msg("warning: failed to kill %d", p->pid);
+		}
+	}
+	if (!quiet && killed) {
+		printf("stopped %s (pid", what);
+		for (p = found; p; p = p->next)
+			if(p->pid < 0)
+				printf(" %d", -p->pid);
+		printf(").\n");
+	}
+	if (ENABLE_FEATURE_CLEAN_UP)
+		RELEASE_CONFIG_BUFFER(what);
+	return killed;
+}
+
+#if ENABLE_FEATURE_START_STOP_DAEMON_LONG_OPTIONS
+static const struct option ssd_long_options[] = {
+	{ "stop",			0,		NULL,		'K' },
+	{ "start",			0,		NULL,		'S' },
+	{ "background",		0,		NULL,		'b' },
+	{ "quiet",			0,		NULL,		'q' },
+	{ "make-pidfile",	0,		NULL,		'm' },
+#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
+	{ "oknodo",			0,		NULL,		'o' },
+	{ "verbose",		0,		NULL,		'v' },
+#endif
+	{ "startas",		1,		NULL,		'a' },
+	{ "name",			1,		NULL,		'n' },
+	{ "signal",			1,		NULL,		's' },
+	{ "user",			1,		NULL,		'u' },
+	{ "exec",			1,		NULL,		'x' },
+	{ "pidfile",		1,		NULL,		'p' },
+#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
+	{ "retry",			1,		NULL,		'R' },
+#endif
+	{ 0,				0,		0,		0 }
+};
+#endif
+
+#define SSD_CTX_STOP		1
+#define SSD_CTX_START		2
+#define SSD_OPT_BACKGROUND	4
+#define SSD_OPT_QUIET		8
+#define SSD_OPT_MAKEPID		16
+#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
+#define SSD_OPT_OKNODO		32
+#define SSD_OPT_VERBOSE		64
+
+#endif
+
+int start_stop_daemon_main(int argc, char **argv)
+{
+	unsigned long opt;
+	char *signame = NULL;
+	char *startas = NULL;
+#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
+//	char *retry_arg = NULL;
+//	int retries = -1;
+#endif
+#if ENABLE_FEATURE_START_STOP_DAEMON_LONG_OPTIONS
+	bb_applet_long_options = ssd_long_options;
+#endif
+
+	/* Check required one context option was given */
+	bb_opt_complementally = "K:S:?:K--S:S--K:m?p:K?xpun:S?xa";
+	opt = bb_getopt_ulflags(argc, argv, "KSbqm"
+//		USE_FEATURE_START_STOP_DAEMON_FANCY("ovR:")
+		USE_FEATURE_START_STOP_DAEMON_FANCY("ov")
+		"a:n:s:u:x:p:"
+//		USE_FEATURE_START_STOP_DAEMON_FANCY(,&retry_arg)
+		,&startas, &cmdname, &signame, &userspec, &execname, &pidfile);
+
+	quiet = (opt & SSD_OPT_QUIET)
+			USE_FEATURE_START_STOP_DAEMON_FANCY(&& !(opt & SSD_OPT_VERBOSE));
+
+	if (signame) {
+		signal_nr = bb_xgetlarg(signame, 10, 0, NSIG);
+	}
+
+	if (!startas)
+		startas = execname;
+
+//	USE_FEATURE_START_STOP_DAEMON_FANCY(
+//		if (retry_arg)
+//			retries = bb_xgetlarg(retry_arg, 10, 0, INT_MAX);
+//	)
+	argc -= optind;
+	argv += optind;
+
+	if (userspec && sscanf(userspec, "%d", &user_id) != 1)
+		user_id = bb_xgetpwnam(userspec);
+
+	if (opt & SSD_CTX_STOP) {
+		int i = do_stop();
+		return
+			USE_FEATURE_START_STOP_DAEMON_FANCY((opt & SSD_OPT_OKNODO)
+				? 0 :) !!(i<=0);
+	}
+
+	do_procinit();
+
+	if (found) {
+		if (!quiet)
+			printf("%s already running.\n%d\n", execname ,found->pid);
+		USE_FEATURE_START_STOP_DAEMON_FANCY(return !(opt & SSD_OPT_OKNODO);)
+		SKIP_FEATURE_START_STOP_DAEMON_FANCY(return EXIT_FAILURE;)
+	}
+	*--argv = startas;
+	if (opt & SSD_OPT_BACKGROUND) {
+		bb_xdaemon(0, 0);
+		setsid();
+	}
+	if (opt & SSD_OPT_MAKEPID) {
+		/* user wants _us_ to make the pidfile */
+		FILE *pidf = bb_xfopen(pidfile, "w");
+
+		pid_t pidt = getpid();
+		fprintf(pidf, "%d\n", pidt);
+		fclose(pidf);
+	}
+	execv(startas, argv);
+	bb_perror_msg_and_die ("unable to start %s", startas);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/which.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/which.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/debianutils/which.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,106 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Which implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under the GPL v2, see the file LICENSE in this tarball.
+ *
+ * Based on which from debianutils
+ */
+
+#include "busybox.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+
+static int is_executable_file(const char const * a, struct stat *b)
+{
+	return (!access(a,X_OK) && !stat(a, b) && S_ISREG(b->st_mode));
+}
+
+int which_main(int argc, char **argv)
+{
+	int status;
+	size_t i, count;
+	char *path_list;
+
+	if (argc <= 1 || **(argv + 1) == '-') {
+		bb_show_usage();
+	}
+	argc--;
+
+	path_list = getenv("PATH");
+	if (path_list != NULL) {
+		size_t path_len = strlen(path_list);
+		char *new_list = NULL;
+		count = 1;
+
+		for (i = 0; i <= path_len; i++) {
+			char *this_i = &path_list[i];
+			if (*this_i == ':') {
+				/* ^::[^:] == \.: */
+				if (!i && (*(this_i + 1) == ':')) {
+					*this_i = '.';
+					continue;
+				}
+				*this_i = 0;
+				count++;
+				/* ^:[^:] == \.0 and [^:]::[^:] == 0\.0 and [^:]:$ == 0\.0 */
+				if (!i || (*(this_i + 1) == ':') || (i == path_len-1)) {
+					new_list = xrealloc(new_list, path_len += 1);
+					if (i) {
+						memmove(&new_list[i+2], &path_list[i+1], path_len-i);
+						new_list[i+1] = '.';
+						memmove(new_list, path_list, i);
+					} else {
+						memmove(&new_list[i+1], &path_list[i], path_len-i);
+						new_list[i] = '.';
+					}
+					path_list = new_list;
+				}
+			}
+		}
+	} else {
+		path_list = "/bin\0/sbin\0/usr/bin\0/usr/sbin\0/usr/local/bin";
+		count = 5;
+	}
+
+	status = EXIT_SUCCESS;
+	while (argc-- > 0) {
+		struct stat stat_b;
+		char *buf;
+		char *path_n;
+		int found = 0;
+
+		argv++;
+		path_n = path_list;
+		buf = *argv;
+
+		/* if filename is either absolute or contains slashes,
+		 * stat it */
+		if (strchr(buf, '/') != NULL && is_executable_file(buf, &stat_b)) {
+			found++;
+		} else {
+			/* Couldn't access file and file doesn't contain slashes */
+			for (i = 0; i < count; i++) {
+				buf = concat_path_file(path_n, *argv);
+				if (is_executable_file(buf, &stat_b)) {
+					found++;
+					break;
+				}
+				free(buf);
+				path_n += (strlen(path_n) + 1);
+			}
+		}
+		if (found) {
+			puts(buf);
+		} else {
+			status = EXIT_FAILURE;
+		}
+	}
+	bb_fflush_stdout_and_exit(status);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/autodocifier.pl
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/autodocifier.pl	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/autodocifier.pl	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,299 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Getopt::Long;
+
+# collect lines continued with a '\' into an array
+sub continuation {
+	my $fh = shift;
+	my @line;
+
+	while (<$fh>) {
+		my $s = $_;
+		$s =~ s/\\\s*$//;
+		#$s =~ s/#.*$//;
+		push @line, $s;
+		last unless (/\\\s*$/);
+	}
+	return @line;
+}
+
+# regex && eval away unwanted strings from documentation
+sub beautify {
+	my $text = shift;
+	$text =~ s/USAGE_NOT\w+\(.*?"\s*\)//sxg;
+	$text =~ s/USAGE_\w+\(\s*?(.*?)"\s*\)/$1"/sxg;
+	$text =~ s/"\s*"//sg;
+	my @line = split("\n", $text);
+	$text = join('',
+		map {
+			s/^\s*"//;
+			s/"\s*$//;
+			s/%/%%/g;
+			s/\$/\\\$/g;
+			eval qq[ sprintf(qq{$_}) ]
+		} @line
+	);
+	return $text;
+}
+
+# generate POD for an applet
+sub pod_for_usage {
+	my $name  = shift;
+	my $usage = shift;
+
+	# Sigh.  Fixup the known odd-name applets.
+	$name =~ s/dpkg_deb/dpkg-deb/g;
+	$name =~ s/fsck_minix/fsck.minix/g;
+	$name =~ s/mkfs_minix/mkfs.minix/g;
+	$name =~ s/run_parts/run-parts/g;
+	$name =~ s/start_stop_daemon/start-stop-daemon/g;
+
+	# make options bold
+	my $trivial = $usage->{trivial};
+	if (!defined $usage->{trivial}) {
+		$trivial = "";
+	} else {
+		$trivial =~ s/(?<!\w)(-\w+)/B<$1>/sxg;
+	}
+	my @f0 =
+		map { $_ !~ /^\s/ && s/(?<!\w)(-\w+)/B<$1>/g; $_ }
+		split("\n", (defined $usage->{full} ? $usage->{full} : ""));
+
+	# add "\n" prior to certain lines to make indented
+	# lines look right
+	my @f1;
+	my $len = @f0;
+	for (my $i = 0; $i < $len; $i++) {
+		push @f1, $f0[$i];
+		if (($i+1) != $len && $f0[$i] !~ /^\s/ && $f0[$i+1] =~ /^\s/) {
+			next if ($f0[$i] =~ /^$/);
+			push(@f1, "") unless ($f0[$i+1] =~ /^\s*$/s);
+		}
+	}
+	my $full = join("\n", @f1);
+
+	# prepare notes if they exist
+	my $notes = (defined $usage->{notes})
+		? "$usage->{notes}\n\n"
+		: "";
+
+	# prepare examples if they exist
+	my $example = (defined $usage->{example})
+		?
+			"Example:\n\n" .
+			join ("\n",
+			map  { "\t$_" }
+			split("\n", $usage->{example})) . "\n\n"
+		: "";
+
+	# Pad the name so that the applet name gets a line
+	# by itself in BusyBox.txt
+	my $spaces = 10 - length($name);
+	if ($spaces > 0) {
+		$name .= " " x $spaces;
+	}
+
+	return
+		"=item B<$name>".
+		"\n\n$name $trivial\n\n".
+		"$full\n\n"   .
+		"$notes"  .
+		"$example" .
+		"\n\n"
+	;
+}
+
+# the keys are applet names, and
+# the values will contain hashrefs of the form:
+#
+# {
+#     trivial => "...",
+#     full    => "...",
+#     notes   => "...",
+#     example => "...",
+# }
+my %docs;
+
+
+# get command-line options
+
+my %opt;
+
+GetOptions(
+	\%opt,
+	"help|h",
+	"pod|p",
+	"verbose|v",
+);
+
+if (defined $opt{help}) {
+	print
+		"$0 [OPTION]... [FILE]...\n",
+		"\t--help\n",
+		"\t--pod\n",
+		"\t--verbose\n",
+	;
+	exit 1;
+}
+
+
+# collect documenation into %docs
+
+foreach (@ARGV) {
+	open(USAGE, $_) || die("$0: $_: $!");
+	my $fh = *USAGE;
+	my ($applet, $type, @line);
+	while (<$fh>) {
+		if (/^#define (\w+)_(\w+)_usage/) {
+			$applet = $1;
+			$type   = $2;
+			@line   = continuation($fh);
+			my $doc = $docs{$applet} ||= { };
+			my $text      = join("\n", @line);
+			$doc->{$type} = beautify($text);
+		}
+	}
+}
+
+
+# generate structured documentation
+
+my $generator = \&pod_for_usage;
+
+my @names = sort keys %docs;
+my $line = "\t[, [[, ";
+for (my $i = 0; $i < $#names; $i++) {
+	if (length ($line.$names[$i]) >= 65) {
+		print "$line\n\t";
+		$line = "";
+	}
+	$line .= "$names[$i], ";
+}
+print $line . $names[-1];
+
+print "\n\n=head1 COMMAND DESCRIPTIONS\n";
+print "\n=over 4\n\n";
+
+foreach my $applet (@names) {
+	print $generator->($applet, $docs{$applet});
+}
+
+exit 0;
+
+__END__
+
+=head1 NAME
+
+autodocifier.pl - generate docs for busybox based on usage.h
+
+=head1 SYNOPSIS
+
+autodocifier.pl [OPTION]... [FILE]...
+
+Example:
+
+    ( cat docs/busybox_header.pod; \
+      docs/autodocifier.pl usage.h; \
+      cat docs/busybox_footer.pod ) > docs/busybox.pod
+
+=head1 DESCRIPTION
+
+The purpose of this script is to automagically generate
+documentation for busybox using its usage.h as the original source
+for content.  It used to be that same content has to be duplicated
+in 3 places in slightly different formats -- F<usage.h>,
+F<docs/busybox.pod>.  This was tedious and error-prone, so it was
+decided that F<usage.h> would contain all the text in a
+machine-readable form, and scripts could be used to transform this
+text into other forms if necessary.
+
+F<autodocifier.pl> is one such script.  It is based on a script by
+Erik Andersen <andersen at codepoet.org> which was in turn based on a
+script by Mark Whitley <markw at codepoet.org>
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--help>
+
+This displays the help message.
+
+=item B<--pod>
+
+Generate POD (this is the default)
+
+=item B<--verbose>
+
+Be verbose (not implemented)
+
+=back
+
+=head1 FORMAT
+
+The following is an example of some data this script might parse.
+
+    #define length_trivial_usage \
+            "STRING"
+    #define length_full_usage \
+            "Prints out the length of the specified STRING."
+    #define length_example_usage \
+            "$ length Hello\n" \
+            "5\n"
+
+Each entry is a cpp macro that defines a string.  The macros are
+named systematically in the form:
+
+    $name_$type_usage
+
+$name is the name of the applet.  $type can be "trivial", "full", "notes",
+or "example".  Every documentation macro must end with "_usage".
+
+The definition of the types is as follows:
+
+=over 4
+
+=item B<trivial>
+
+This should be a brief, one-line description of parameters that
+the command expects.  This will be displayed when B<-h> is issued to
+a command.  I<REQUIRED>
+
+=item B<full>
+
+This should contain descriptions of each option.  This will also
+be displayed along with the trivial help if CONFIG_FEATURE_TRIVIAL_HELP
+is disabled.  I<REQUIRED>
+
+=item B<notes>
+
+This is documentation that is intended to go in the POD or SGML, but
+not be printed when a B<-h> is given to a command.  To see an example
+of notes being used, see init_notes_usage in F<usage.h>.  I<OPTIONAL>
+
+=item B<example>
+
+This should be an example of how the command is actually used.
+This will not be printed when a B<-h> is given to a command -- it
+will only be included in the POD or SGML documentation.  I<OPTIONAL>
+
+=back
+
+=head1 FILES
+
+F<usage.h>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2001 John BEPPU.  All rights reserved.  This program is
+free software; you can redistribute it and/or modify it under the same
+terms as Perl itself.
+
+=head1 AUTHOR
+
+John BEPPU <b at ax9.org>
+
+=cut
+
+# $Id: autodocifier.pl,v 1.26 2004/04/06 15:26:25 andersen Exp $


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/autodocifier.pl
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/FAQ.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/FAQ.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/FAQ.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1043 @@
+<!--#include file="header.html" -->
+
+<h3>Frequently Asked Questions</h3>
+
+This is a collection of some of the more frequently asked questions
+about BusyBox.  Some of the questions even have answers. If you
+have additions to this FAQ document, we would love to add them,
+
+<h2>General questions</h2>
+<ol>
+<li><a href="#getting_started">How can I get started using BusyBox?</a></li>
+<li><a href="#configure">How do I configure busybox?</a></li>
+<li><a href="#build_system">How do I build a BusyBox-based system?</a></li>
+<li><a href="#kernel">Which Linux kernel versions are supported?</a></li>
+<li><a href="#arch">Which architectures does BusyBox run on?</a></li>
+<li><a href="#libc">Which C libraries are supported?</a></li>
+<li><a href="#commercial">Can I include BusyBox as part of the software on my device?</a></li>
+<li><a href="#external">Where can I find other small utilities since busybox does not include the features I want?</a></li></li>
+<li><a href="#demanding">I demand that you to add <favorite feature> right now!   How come you don't answer all my questions on the mailing list instantly?  I demand that you help me with all of my problems <em>Right Now</em>!</a></li>
+<li><a href="#helpme">I need help with BusyBox!  What should I do?</a></li>
+<li><a href="#contracts">I need you to add <favorite feature>!  Are the BusyBox developers willing to be paid in order to fix bugs or add in <favorite feature>?  Are you willing to provide support contracts?</a></li>
+</ol>
+
+<h2>Troubleshooting</h2>
+<ol>
+<li><a href="#bugs">I think I found a bug in BusyBox!  What should I do?!</a></li>
+<li><a href="#init">Busybox init isn't working!</a></li>
+<li><a href="#sed">I can't configure busybox on my system.</a></li>
+<li><a href="#job_control">Why do I keep getting "sh: can't access tty; job control turned off" errors?  Why doesn't Control-C work within my shell?</a></li>
+</ol>
+
+<h2>Programming questions</h2>
+<ol>
+  <li><a href="#goals">What are the goals of busybox?</a></li>
+  <li><a href="#design">What is the design of busybox?</a></li>
+  <li><a href="#source">How is the source code organized?</a></li>
+  <ul>
+    <li><a href="#source_applets">The applet directories.</a></li>
+    <li><a href="#source_libbb">The busybox shared library (libbb)</a></li>
+  </ul>
+  <li><a href="#optimize">I want to make busybox even smaller, how do I go about it?</a></li>
+  <li><a href="#adding">Adding an applet to busybox</a></li>
+  <li><a href="#standards">What standards does busybox adhere to?</a></li>
+  <li><a href="#portability">Portability.</a></li>
+  <li><a href="#tips">Tips and tricks.</a></li>
+  <ul>
+    <li><a href="#tips_encrypted_passwords">Encrypted Passwords</a></li>
+    <li><a href="#tips_vfork">Fork and vfork</a></li>
+    <li><a href="#tips_short_read">Short reads and writes</a></li>
+    <li><a href="#tips_memory">Memory used by relocatable code, PIC, and static linking.</a></li>
+    <li><a href="#tips_kernel_headers">Including Linux kernel headers.</a></li>
+  </ul>
+  <li><a href="#who">Who are the BusyBox developers?</a></li>
+</ul>
+
+
+</ol>
+
+<h1>General questions</h1>
+
+<hr />
+<p>
+<h2><a name="getting_started">How can I get started using BusyBox?</a></h2>
+<p> If you just want to try out busybox without installing it, download the
+    tarball, extract it, run "make defconfig", and then run "make".
+</p>
+<p>
+    This will create a busybox binary with almost all features enabled.  To try
+    out a busybox applet, type "./busybox [appletname] [options]", for
+    example "./busybox ls -l" or "./busybox cat LICENSE".  Type "./busybox"
+    to see a command list, and "busybox appletname --help" to see a brief
+    usage message for a given applet.
+</p>
+<p>
+    BusyBox uses the name it was invoked under to determine which applet is
+    being invoked.  (Try "mv busybox ls" and then "./ls -l".)  Installing
+    busybox consists of creating symlinks (or hardlinks) to the busybox
+    binary for each applet in busybox, and making sure these links are in
+    the shell's command $PATH.  The special applet name "busybox" (or with
+    any optional suffix, such as "busybox-static") uses the first argument
+    to determine which applet to run, as shown above.
+</p>
+<p>
+    BusyBox also has a feature called the "standalone shell", where the busybox
+    shell runs any built-in applets before checking the command path.  This
+    feature is also enabled by "make allyesconfig", and to try it out run
+    the command line "PATH= ./busybox ash".  This will blank your command path
+    and run busybox as your command shell, so the only commands it can find
+    (without an explicit path such as /bin/ls) are the built-in busybox ones.
+    This is another good way to see what's built into busybox.  (Note that the
+    standalone shell is dependent on the existence of /proc/self/exe, so before
+    using it in a chroot environment you must mount /proc.)
+</p>
+
+<hr />
+<p>
+<h2><a name="configure">How do I configure busybox?</a></h2>
+<p> Busybox is configured similarly to the linux kernel.  Create a default
+    configuration and then run "make menuconfig" to modify it.  The end
+    result is a .config file that tells the busybox build process what features
+    to include.  So instead of "./configure; make; make install" the equivalent
+    busybox build would be "make defconfig; make; make install".
+</p>
+
+<p> Busybox configured with all features enabled is a little under a megabyte
+    dynamically linked on x86.  To create a smaller busybox, configure it with
+    fewer features.  Individual busybox applets cost anywhere from a few
+    hundred bytes to tens of kilobytes.  Disable unneeded applets to save,
+    space, using menuconfig.
+</p>
+
+<p>The most important busybox configurators are:</p>
+
+<ul>
+<li><p>make <b>defconfig</b> - Create the maximum "sane" configuration.  This
+enables almost all features, minus things like debugging options and features
+that require changes to the rest of the system to work (such as selinux or
+devfs device names).  Use this if you want to start from a full-featured
+busybox and remove features until it's small enough.</p></li>
+<li><p>make <b>allnoconfig</b> - Disable everything.  This creates a tiny version
+of busybox that doesn't do anything.  Start here if you know exactly what
+you want and would like to select only those features.</p></li>
+<li><p>make <b>menuconfig</b> - Interactively modify a .config file through a
+multi-level menu interface.  Use this after one of the previous two.</p></li>
+</ul>
+
+<p>Some other configuration options are:</p>
+<ul>
+<li><p>make <b>oldconfig</b> - Update an old .config file for a newer version
+of busybox.</p></li>
+<li><p>make <b>allyesconfig</b> - Select absolutely everything.  This creates
+a statically linked version of busybox full of debug code, with dependencies on
+selinux, using devfs names...  This makes sure everything compiles.  Whether
+or not the result would do anything useful is an open question.</p></li>
+<li><p>make <b>allbareconfig</b> - Select all applets but disable all sub-features
+within each applet.  More build coverage testing.</p></li>
+<li><p>make <b>randconfig</b> - Create a random configuration for test purposes.</p></li>
+</ul>
+
+<p> Menuconfig modifies your .config file through an interactive menu where you can enable or disable
+    busybox features, and get help about each feature.
+
+
+
+<p>
+    To build a smaller busybox binary, run "make menuconfig" and disable the
+    features you don't need.  (Or run "make allnoconfig" and then use
+    menuconfig to add just the features you need.  Don't forget to recompile
+    with "make" once you've finished configuring.)
+</p>
+<hr/>
+<p/>
+<h2><a name="build_system">How do I build a BusyBox-based system?</a></h2>
+<p>
+    BusyBox is a package that replaces a dozen standard packages, but it is
+    not by itself a complete bootable system.  Building an entire Linux
+    distribution from source is a bit beyond the scope of this FAQ, but it
+    understandably keeps cropping up on the mailing list, so here are some
+    pointers.
+</p>
+<p>
+    Start by learning how to strip a working system down to the bare essentials
+    needed to run one or two commands, so you know what it is you actually
+    need.  An excellent practical place to do
+    this is the <a href="http://www.tldp.org/HOWTO/Bootdisk-HOWTO/">Linux
+    BootDisk Howto</a>, or for a more theoretical approach try
+    <a href="http://www.tldp.org/HOWTO/From-PowerUp-To-Bash-Prompt-HOWTO.html">From
+    PowerUp to Bash Prompt</a>.
+</p>
+<p>
+    To learn how to build a working Linux system entirely from source code,
+    the place to go is the <a href="http://www.linuxfromscratch.org">Linux
+    From Scratch</a> project.  They have an entire book of step-by-step
+    instructions you can
+    <a href="http://www.linuxfromscratch.org/lfs/view/stable/">read online</a>
+    or
+    <a href="http://www.linuxfromscratch.org/lfs/downloads/stable/">download</a>.
+    Be sure to check out the other sections of their main page, including
+    Beyond Linux From Scratch, Hardened Linux From Scratch, their Hints
+    directory, and their LiveCD project.  (They also have mailing lists which
+    are better sources of answers to Linux-system building questions than
+    the busybox list.)
+</p>
+<p>
+    If you want an automated yet customizable system builder which produces
+    a BusyBox and uClibc based system, try
+    <a href="http://buildroot.uclibc.org">buildroot</a>, which is
+    another project by the maintainer of the uClibc (Erik Andersen).
+    Download the tarball, extract it, unset CC, make.
+    For more instructions, see the website.
+</p>
+
+<hr />
+<p>
+<h2><a name="kernel">Which Linux kernel versions are supported?</a></h2>
+<p>
+    Full functionality requires Linux 2.4.x or better.  (Earlier versions may
+    still work, but are no longer regularly tested.)  A large fraction of the
+    code should run on just about anything.  While the current code is fairly
+    Linux specific, it should be fairly easy to port the majority of the code
+    to support, say, FreeBSD or Solaris, or Mac OS X, or even Windows (if you
+    are into that sort of thing).
+</p>
+<hr />
+<p>
+<h2><a name="arch">Which architectures does BusyBox run on?</a></h2>
+<p>
+    BusyBox in general will build on any architecture supported by gcc.
+    Kernel module loading for 2.4 Linux kernels is currently
+    limited to ARM, CRIS, H8/300, x86, ia64, x86_64, m68k, MIPS, PowerPC,
+    S390, SH3/4/5, Sparc, v850e, and x86_64 for 2.4.x kernels.
+</p>
+<p>
+    With 2.6.x kernels, module loading support should work on all architectures.
+</p>
+<hr />
+<p>
+<h2><a name="libc">Which C libraries are supported?</a></h2>
+<p>
+    On Linux, BusyBox releases are tested against uClibc (0.9.27 or later) and
+    glibc (2.2 or later).  Both should provide full functionality with busybox,
+    and if you find a bug we want to hear about it.
+</p>
+<p>
+    Linux-libc5 is no longer maintained (and has no known advantages over
+    uClibc), dietlibc is known to have numerous unfixed bugs, and klibc is
+    missing too many features to build BusyBox.  If you require a small C
+    library for Linux, the busybox developers recommend uClibc.
+</p>
+<p>
+    Some BusyBox applets have been built and run under a combination
+    of newlib and libgloss (see
+    <a href="http://www.busybox.net/lists/busybox/2005-March/013759.html">this thread</a>).
+    This is still experimental, but may be supported in a future release.
+</p>
+
+<hr />
+<p>
+<h2><a name="commercial">Can I include BusyBox as part of the software on my device?</a></h2>
+<p>
+
+<p>
+    Yes.  As long as you <a href="http://busybox.net/license.html">fully comply
+    with the generous terms of the GPL BusyBox license</a> you can ship BusyBox
+    as part of the software on your device.
+</p>
+
+<hr />
+<p>
+<h2><a name="external">where can i find other small utilities since busybox 
+	does not include the features i want?</a></h2>
+<p>
+	we maintain such a <a href="tinyutils.html">list</a> on this site!
+</p>
+
+<hr />
+<p>
+<h2><a name="demanding">I demand that you to add <favorite feature> right now!   How come you don't answer all my questions on the mailing list instantly?  I demand that you help me with all of my problems <em>Right Now</em>!</a></h2>
+<p>
+
+    You have not paid us a single cent and yet you still have the product of
+    many years of our work.  We are not your slaves!  We work on BusyBox
+    because we find it useful and interesting.  If you go off flaming us, we
+    will ignore you.
+
+
+<hr />
+<p>
+<h2><a name="helpme">I need help with BusyBox!  What should I do?</a></h2>
+<p>
+
+    If you find that you need help with BusyBox, you can ask for help on the
+    BusyBox mailing list at busybox at busybox.net.</p>
+
+<p> In addition to the mailing list, Erik Andersen (andersee), Manuel Nova
+    (mjn3), Rob Landley (landley), Mike Frysinger (SpanKY), Bernhard Fischer
+    (blindvt), and other long-time BusyBox developers are known to hang out
+    on the uClibc IRC channel: #uclibc on irc.freenode.net.  There is a
+    <a href="http://ibot.Rikers.org/%23uclibc/">web archive of
+    daily logs of the #uclibc IRC channel</a> going back to 2002.
+</p>
+
+<p>
+    <b>Please do not send private email to Rob, Erik, Manuel, or the other
+    BusyBox contributors asking for private help unless you are planning on
+    paying for consulting services.</b>
+</p>
+
+<p>
+    When we answer questions on the BusyBox mailing list, it helps everyone
+    since people with similar problems in the future will be able to get help
+    by searching the mailing list archives.  Private help is reserved as a paid
+    service.  If you need to use private communication, or if you are serious
+    about getting timely assistance with BusyBox, you should seriously consider
+    paying for consulting services.
+</p>
+
+<hr />
+<p>
+<h2><a name="contracts">I need you to add <favorite feature>!  Are the BusyBox developers willing to be paid in order to fix bugs or add in <favorite feature>?  Are you willing to provide support contracts?</a></h2>
+</p>
+
+<p>
+    Yes we are.  The easy way to sponsor a new feature is to post an offer on
+    the mailing list to see who's interested.  You can also email the project's
+    maintainer and ask them to recommend someone.
+</p>
+
+<p> If you prefer to deal with an organization rather than an individual, Rob
+    Landley (the current BusyBox maintainer) works for
+    <a http://www.timesys.com>TimeSys</a>, and Eric Andersen (the previous
+    busybox maintainer and current uClibc maintainer) owns
+    <a href="http://codepoet-consulting.com/">CodePoet Consulting</a>.  Both
+    companies offer support contracts and handle new development, and there
+    are plenty of other companies that do the same.
+</p>
+
+
+
+
+<h1>Troubleshooting</h1>
+
+<hr />
+<p></p>
+<h2><a name="bugs">I think I found a bug in BusyBox!  What should I do?</a></h2>
+<p></p>
+
+<p>
+    If you simply need help with using or configuring BusyBox, please submit a
+    detailed description of your problem to the BusyBox mailing list at <a
+    href="mailto:busybox at busybox.net"> busybox at busybox.net</a>.
+    Please do not send email to individual developers asking
+    for private help unless you are planning on paying for consulting services.
+    When we answer questions on the BusyBox mailing list, it helps everyone,
+    while private answers help only you...
+</p>
+
+<p>
+    The developers of BusyBox are busy people, and have only so much they can
+    keep in their brains at a time.  As a result, bug reports and new feature
+    patches sometimes get lost when posted to the mailing list.  To prevent
+    your bug report from getting lost, if you find a bug in BusyBox that isn't
+    immediately addressed, please use the <a
+    href="http://bugs.busybox.net/">BusyBox Bug and Patch Tracking System</a>
+    to submit a detailed explanation and we'll get to it as soon as we can.
+</p>
+
+<hr />
+<p>
+<h2><a name="init">Busybox init isn't working!</a></h2>
+<p>
+    Init is the first program that runs, so it might be that no programs are
+    working on your new system because of a problem with your cross-compiler,
+    kernel, console settings, shared libraries, root filesystem...  To rule all
+    that out, first build a statically linked version of the following "hello
+    world" program with your cross compiler toolchain:
+</p>
+<pre>
+#include <stdio.h>
+
+int main(int argc, char *argv)
+{
+  printf("Hello world!\n");
+  sleep(999999999);
+}
+</pre>
+
+<p>
+    Now try to boot your device with an "init=" argument pointing to your
+    hello world program.  Did you see the hello world message?  Until you
+    do, don't bother messing with busybox init.
+</p>
+
+<p>
+    Once you've got it working statically linked, try getting it to work
+    dynamically linked.  Then read the FAQ entry <a href="#build_system">How
+    do I build a BusyBox-based system?</a>, and the
+    <a href="/downloads/BusyBox.html#item_init">documentation for BusyBox
+    init</a>.
+</p>
+
+<hr />
+<p>
+<h2><a name="sed">I can't configure busybox on my system.</a></h2>
+<p>
+    Configuring Busybox depends on a recent version of sed.  Older
+    distributions (Red Hat 7.2, Debian 3.0) may not come with a
+    usable version.  Luckily BusyBox can use its own sed to configure itself,
+    although this leads to a bit of a chicken and egg problem.
+    You can work around this by hand-configuring busybox to build with just
+    sed, then putting that sed in your path to configure the rest of busybox
+    with, like so:
+</p>
+
+<pre>
+  tar xvjf sources/busybox-x.x.x.tar.bz2
+  cd busybox-x.x.x
+  make allnoconfig
+  make include/bb_config.h
+  echo "CONFIG_SED=y" >> .config
+  echo "#undef ENABLE_SED" >> include/bb_config.h
+  echo "#define ENABLE_SED 1" >> include/bb_config.h
+  make
+  mv busybox sed
+  export PATH=`pwd`:"$PATH"
+</pre>
+
+<p>Then you can run "make defconfig" or "make menuconfig" normally.</p>
+
+<hr />
+<p>
+<h2><a name="job_control">Why do I keep getting "sh: can't access tty; job control turned off" errors?  Why doesn't Control-C work within my shell?</a></h2>
+<p>
+
+    Job control will be turned off since your shell can not obtain a controlling
+    terminal.  This typically happens when you run your shell on /dev/console.
+    The kernel will not provide a controlling terminal on the /dev/console
+    device.  Your should run your shell on a normal tty such as tty1 or ttyS0
+    and everything will work perfectly.  If you <em>REALLY</em> want your shell
+    to run on /dev/console, then you can hack your kernel (if you are into that
+    sortof thing) by changing drivers/char/tty_io.c to change the lines where
+    it sets "noctty = 1;" to instead set it to "0".  I recommend you instead
+    run your shell on a real console...
+</p>
+
+<h1>Development</h1>
+
+<h2><b><a name="goals">What are the goals of busybox?</a></b></h2>
+
+<p>Busybox aims to be the smallest and simplest correct implementation of the
+standard Linux command line tools.  First and foremost, this means the
+smallest executable size we can manage.  We also want to have the simplest
+and cleanest implementation we can manage, be <a href="#standards">standards
+compliant</a>, minimize run-time memory usage (heap and stack), run fast, and
+take over the world.</p>
+
+<h2><b><a name="design">What is the design of busybox?</a></b></h2>
+
+<p>Busybox is like a swiss army knife: one thing with many functions.
+The busybox executable can act like many different programs depending on
+the name used to invoke it.  Normal practice is to create a bunch of symlinks
+pointing to the busybox binary, each of which triggers a different busybox
+function.  (See <a href="FAQ.html#getting_started">getting started</a> in the
+FAQ for more information on usage, and <a href="BusyBox.html">the
+busybox documentation</a> for a list of symlink names and what they do.)
+
+<p>The "one binary to rule them all" approach is primarily for size reasons: a
+single multi-purpose executable is smaller then many small files could be.
+This way busybox only has one set of ELF headers, it can easily share code
+between different apps even when statically linked, it has better packing
+efficiency by avoding gaps between files or compression dictionary resets,
+and so on.</p>
+
+<p>Work is underway on new options such as "make standalone" to build separate
+binaries for each applet, and a "libbb.so" to make the busybox common code
+available as a shared library.  Neither is ready yet at the time of this
+writing.</p>
+
+<a name="source"></a>
+
+<h2><a name="source_applets"><b>The applet directories</b></a></h2>
+
+<p>The directory "applets" contains the busybox startup code (applets.c and
+busybox.c), and several subdirectories containing the code for the individual
+applets.</p>
+
+<p>Busybox execution starts with the main() function in applets/busybox.c,
+which sets the global variable bb_applet_name to argv[0] and calls
+run_applet_by_name() in applets/applets.c.  That uses the applets[] array
+(defined in include/busybox.h and filled out in include/applets.h) to
+transfer control to the appropriate APPLET_main() function (such as
+cat_main() or sed_main()).  The individual applet takes it from there.</p>
+
+<p>This is why calling busybox under a different name triggers different
+functionality: main() looks up argv[0] in applets[] to get a function pointer
+to APPLET_main().</p>
+
+<p>Busybox applets may also be invoked through the multiplexor applet
+"busybox" (see busybox_main() in applets/busybox.c), and through the
+standalone shell (grep for STANDALONE_SHELL in applets/shell/*.c).
+See <a href="FAQ.html#getting_started">getting started</a> in the
+FAQ for more information on these alternate usage mechanisms, which are
+just different ways to reach the relevant APPLET_main() function.</p>
+
+<p>The applet subdirectories (archival, console-tools, coreutils,
+debianutils, e2fsprogs, editors, findutils, init, loginutils, miscutils,
+modutils, networking, procps, shell, sysklogd, and util-linux) correspond
+to the configuration sub-menus in menuconfig.  Each subdirectory contains the
+code to implement the applets in that sub-menu, as well as a Config.in
+file defining that configuration sub-menu (with dependencies and help text
+for each applet), and the makefile segment (Makefile.in) for that
+subdirectory.</p>
+
+<p>The run-time --help is stored in usage_messages[], which is initialized at
+the start of applets/applets.c and gets its help text from usage.h.  During the
+build this help text is also used to generate the BusyBox documentation (in
+html, txt, and man page formats) in the docs directory.  See
+<a href="#adding">adding an applet to busybox</a> for more
+information.</p>
+
+<h2><a name="source_libbb"><b>libbb</b></a></h2>
+
+<p>Most non-setup code shared between busybox applets lives in the libbb
+directory.  It's a mess that evolved over the years without much auditing
+or cleanup.  For anybody looking for a great project to break into busybox
+development with, documenting libbb would be both incredibly useful and good
+experience.</p>
+
+<p>Common themes in libbb include allocation functions that test
+for failure and abort the program with an error message so the caller doesn't
+have to test the return value (xmalloc(), xstrdup(), etc), wrapped versions
+of open(), close(), read(), and write() that test for their own failures
+and/or retry automatically, linked list management functions (llist.c),
+command line argument parsing (getopt_ulflags.c), and a whole lot more.</p>
+
+<hr />
+<p>
+<h2><a name="optimize">I want to make busybox even smaller, how do I go about it?</a></h2>
+<p>
+	To conserve bytes it's good to know where they're being used, and the
+	size of the final executable isn't always a reliable indicator of
+	the size of the components (since various structures are rounded up,
+	so a small change may not even be visible by itself, but many small
+	savings add up).
+</p>
+
+<p>     The busybox Makefile builds two versions of busybox, one of which
+        (busybox_unstripped) has extra information that various analysis tools
+        can use.  (This has nothing to do with CONFIG_DEBUG, leave that off
+        when trying to optimize for size.)
+</p>
+
+<p>     The <b>"make bloatcheck"</b> option uses Matt Mackall's bloat-o-meter
+        script to compare two versions of busybox (busybox_unstripped vs
+        busybox_old), and report which symbols changed size and by how much.
+        To use it, first build a base version with <b>"make baseline"</b>.
+        (This creates busybox_old, which should have the original sizes for
+        comparison purposes.)  Then build the new version with your changes
+        and run "make bloatcheck" to see the size differences from the old
+        version.
+</p>
+<p>
+        The first line of output has totals: how many symbols were added or
+        removed, how many symbols grew or shrank, the number of bytes added
+        and number of bytes removed by these changes, and finally the total
+        number of bytes difference between the two files.  The remaining
+        lines show each individual symbol, the old and new sizes, and the
+        increase or decrease in size (which results are sorted by).
+</p>
+<p>
+	The <b>"make sizes"</b> option produces raw symbol size information for
+        busybox_unstripped.  This is the output from the "nm --size-sort"
+        command (see "man nm" for more information), and is the information
+        bloat-o-meter parses to produce the comparison report above.  For
+        defconfig, this is a good way to find the largest symbols in the tree
+        (which is a good place to start when trying to shrink the code).  To
+        take a closer look at individual applets, configure busybox with just
+        one applet (run "make allnoconfig" and then switch on a single applet
+        with menuconfig), and then use "make sizes" to see the size of that
+        applet's components.
+</p>
+<p>
+        The "showasm" command (in the scripts directory) produces an assembly
+        dump of a function, providing a closer look at what changed.  Try
+        "scripts/showasm busybox_unstripped" to list available symbols, and
+        "scripts/showasm busybox_unstripped symbolname" to see the assembly
+        for a sepecific symbol.
+</p>
+<hr />
+
+
+
+<h2><a name="adding"><b>Adding an applet to busybox</b></a></h2>
+
+<p>To add a new applet to busybox, first pick a name for the applet and
+a corresponding CONFIG_NAME.  Then do this:</p>
+
+<ul>
+<li>Figure out where in the busybox source tree your applet best fits,
+and put your source code there.  Be sure to use APPLET_main() instead
+of main(), where APPLET is the name of your applet.</li>
+
+<li>Add your applet to the relevant Config.in file (which file you add
+it to determines where it shows up in "make menuconfig").  This uses
+the same general format as the linux kernel's configuration system.</li>
+
+<li>Add your applet to the relevant Makefile.in file (in the same
+directory as the Config.in you chose), using the existing entries as a
+template and the same CONFIG symbol as you used for Config.in.  (Don't
+forget "needlibm" or "needcrypt" if your applet needs libm or
+libcrypt.)</li>
+
+<li>Add your applet to "include/applets.h", using one of the existing
+entries as a template.  (Note: this is in alphabetical order.  Applets
+are found via binary search, and if you add an applet out of order it
+won't work.)</li>
+
+<li>Add your applet's runtime help text to "include/usage.h".  You need
+at least appname_trivial_usage (the minimal help text, always included
+in the busybox binary when this applet is enabled) and appname_full_usage
+(extra help text included in the busybox binary with
+CONFIG_FEATURE_VERBOSE_USAGE is enabled), or it won't compile.
+The other two help entry types (appname_example_usage and
+appname_notes_usage) are optional.  They don't take up space in the binary,
+but instead show up in the generated documentation (BusyBox.html,
+BusyBox.txt, and the man page BusyBox.1).</li>
+
+<li>Run menuconfig, switch your applet on, compile, test, and fix the
+bugs.  Be sure to try both "allyesconfig" and "allnoconfig" (and
+"allbareconfig" if relevant).</li>
+
+</ul>
+
+<h2><a name="standards">What standards does busybox adhere to?</a></h2>
+
+<p>The standard we're paying attention to is the "Shell and Utilities"
+portion of the <a href="http://www.opengroup.org/onlinepubs/009695399/">Open
+Group Base Standards</a> (also known as the Single Unix Specification version
+3 or SUSv3).  Note that paying attention isn't necessarily the same thing as
+following it.</p>
+
+<p>SUSv3 doesn't even mention things like init, mount, tar, or losetup, nor
+commonly used options like echo's '-e' and '-n', or sed's '-i'.  Busybox is
+driven by what real users actually need, not the fact the standard believes
+we should implement ed or sccs.  For size reasons, we're unlikely to include
+much internationalization support beyond UTF-8, and on top of all that, our
+configuration menu lets developers chop out features to produce smaller but
+very non-standard utilities.</p>
+
+<p>Also, Busybox is aimed primarily at Linux.  Unix standards are interesting
+because Linux tries to adhere to them, but portability to dozens of platforms
+is only interesting in terms of offering a restricted feature set that works
+everywhere, not growing dozens of platform-specific extensions.  Busybox
+should be portable to all hardware platforms Linux supports, and any other
+similar operating systems that are easy to do and won't require much
+maintenance.</p>
+
+<p>In practice, standards compliance tends to be a clean-up step once an
+applet is otherwise finished.  When polishing and testing a busybox applet,
+we ensure we have at least the option of full standards compliance, or else
+document where we (intentionally) fall short.</p>
+
+<h2><a name="portability">Portability.</a></h2>
+
+<p>Busybox is a Linux project, but that doesn't mean we don't have to worry
+about portability.  First of all, there are different hardware platforms,
+different C library implementations, different versions of the kernel and
+build toolchain...  The file "include/platform.h" exists to centralize and
+encapsulate various platform-specific things in one place, so most busybox
+code doesn't have to care where it's running.</p>
+
+<p>To start with, Linux runs on dozens of hardware platforms.  We try to test
+each release on x86, x86-64, arm, power pc, and mips.  (Since qemu can handle
+all of these, this isn't that hard.)  This means we have to care about a number
+of portability issues like endianness, word size, and alignment, all of which
+belong in platform.h.  That header handles conditional #includes and gives
+us macros we can use in the rest of our code.  At some point in the future
+we might grow a platform.c, possibly even a platform subdirectory.  As long
+as the applets themselves don't have to care.</p>
+
+<p>On a related note, we made the "default signedness of char varies" problem
+go away by feeding the compiler -funsigned-char.  This gives us consistent
+behavior on all platforms, and defaults to 8-bit clean text processing (which
+gets us halfway to UTF-8 support).  NOMMU support is less easily separated
+(see the tips section later in this document), but we're working on it.</p>
+
+<p>Another type of portability is build environments: we unapologetically use
+a number of gcc and glibc extensions (as does the Linux kernel), but these have
+been picked up by packages like uClibc, TCC, and Intel's C Compiler.  As for
+gcc, we take advantage of newer compiler optimizations to get the smallest
+possible size, but we also regression test against an older build environment
+using the Red Hat 9 image at "http://busybox.net/downloads/qemu".  This has a
+2.4 kernel, gcc 3.2, make 3.79.1, and glibc 2.3, and is the oldest
+build/deployment environment we still put any effort into maintaining.  (If
+anyone takes an interest in older kernels you're welcome to submit patches,
+but the effort would probably be better spent
+<a href="http://www.selenic.com/linux-tiny/">trimming
+down the 2.6 kernel</a>.)  Older gcc versions than that are uninteresting since
+we now use c99 features, although
+<a href="http://fabrice.bellard.free.fr/tcc/">tcc</a> might be worth a
+look.</p>
+
+<p>We also test busybox against the current release of uClibc.  Older versions
+of uClibc aren't very interesting (they were buggy, and uClibc wasn't really
+usable as a general-purpose C library before version 0.9.26 anyway).</p>
+
+<p>Other unix implementations are mostly uninteresting, since Linux binaries
+have become the new standard for portable Unix programs.  Specifically,
+the ubiquity of Linux was cited as the main reason the Intel Binary
+Compatability Standard 2 died, by the standards group organized to name a
+successor to ibcs2: <a href="http://www.telly.org/86open/">the 86open
+project</a>.  That project disbanded in 1999 with the endorsement of an
+existing standard: Linux ELF binaries.  Since then, the major players at the
+time (such as <a
+href=http://www-03.ibm.com/servers/aix/products/aixos/linux/index.html>AIX</a>, <a
+href=http://www.sun.com/software/solaris/ds/linux_interop.jsp#3>Solaris</a>, and
+<a href=http://www.onlamp.com/pub/a/bsd/2000/03/17/linuxapps.html>FreeBSD</a>)
+have all either grown Linux support or folded.</p>
+
+<p>The major exceptions are newcomer MacOS X, some embedded environments
+(such as newlib+libgloss) which provide a posix environment but not a full
+Linux environment, and environments like Cygwin that provide only partial Linux
+emulation.  Also, some embedded Linux systems run a Linux kernel but amputate
+things like the /proc directory to save space.</p>
+
+<p>Supporting these systems is largely a question of providing a clean subset
+of BusyBox's functionality -- whichever applets can easily be made to
+work in that environment.  Annotating the configuration system to
+indicate which applets require which prerequisites (such as procfs) is
+also welcome.  Other efforts to support these systems (swapping #include
+files to build in different environments, adding adapter code to platform.h,
+adding more extensive special-case supporting infrastructure such as mount's
+legacy mtab support) are handled on a case-by-case basis.  Support that can be
+cleanly hidden in platform.h is reasonably attractive, and failing that
+support that can be cleanly separated into a separate conditionally compiled
+file is at least worth a look.  Special-case code in the body of an applet is
+something we're trying to avoid.</p>
+
+<h2><a name="tips" />Programming tips and tricks.</a></h2>
+
+<p>Various things busybox uses that aren't particularly well documented
+elsewhere.</p>
+
+<h2><a name="tips_encrypted_passwords">Encrypted Passwords</a></h2>
+
+<p>Password fields in /etc/passwd and /etc/shadow are in a special format.
+If the first character isn't '$', then it's an old DES style password.  If
+the first character is '$' then the password is actually three fields
+separated by '$' characters:</p>
+<pre>
+  <b>$type$salt$encrypted_password</b>
+</pre>
+
+<p>The "type" indicates which encryption algorithm to use: 1 for MD5 and 2 for SHA1.</p>
+
+<p>The "salt" is a bunch of ramdom characters (generally 8) the encryption
+algorithm uses to perturb the password in a known and reproducible way (such
+as by appending the random data to the unencrypted password, or combining
+them with exclusive or).  Salt is randomly generated when setting a password,
+and then the same salt value is re-used when checking the password.  (Salt is
+thus stored unencrypted.)</p>
+
+<p>The advantage of using salt is that the same cleartext password encrypted
+with a different salt value produces a different encrypted value.
+If each encrypted password uses a different salt value, an attacker is forced
+to do the cryptographic math all over again for each password they want to
+check.  Without salt, they could simply produce a big dictionary of commonly
+used passwords ahead of time, and look up each password in a stolen password
+file to see if it's a known value.  (Even if there are billions of possible
+passwords in the dictionary, checking each one is just a binary search against
+a file only a few gigabytes long.)  With salt they can't even tell if two
+different users share the same password without guessing what that password
+is and decrypting it.  They also can't precompute the attack dictionary for
+a specific password until they know what the salt value is.</p>
+
+<p>The third field is the encrypted password (plus the salt).  For md5 this
+is 22 bytes.</p>
+
+<p>The busybox function to handle all this is pw_encrypt(clear, salt) in
+"libbb/pw_encrypt.c".  The first argument is the clear text password to be
+encrypted, and the second is a string in "$type$salt$password" format, from
+which the "type" and "salt" fields will be extracted to produce an encrypted
+value.  (Only the first two fields are needed, the third $ is equivalent to
+the end of the string.)  The return value is an encrypted password in
+/etc/passwd format, with all three $ separated fields.  It's stored in
+a static buffer, 128 bytes long.</p>
+
+<p>So when checking an existing password, if pw_encrypt(text,
+old_encrypted_password) returns a string that compares identical to
+old_encrypted_password, you've got the right password.  When setting a new
+password, generate a random 8 character salt string, put it in the right
+format with sprintf(buffer, "$%c$%s", type, salt), and feed buffer as the
+second argument to pw_encrypt(text,buffer).</p>
+
+<h2><a name="tips_vfork">Fork and vfork</a></h2>
+
+<p>On systems that haven't got a Memory Management Unit, fork() is unreasonably
+expensive to implement (and sometimes even impossible), so a less capable
+function called vfork() is used instead.  (Using vfork() on a system with an
+MMU is like pounding a nail with a wrench.  Not the best tool for the job, but
+it works.)</p>
+
+<p>Busybox hides the difference between fork() and vfork() in
+libbb/bb_fork_exec.c.  If you ever want to fork and exec, use bb_fork_exec()
+(which returns a pid and takes the same arguments as execve(), although in
+this case envp can be NULL) and don't worry about it.  This description is
+here in case you want to know why that does what it does.</p>
+
+<p>Implementing fork() depends on having a Memory Management Unit.  With an
+MMU then you can simply set up a second set of page tables and share the
+physical memory via copy-on-write.  So a fork() followed quickly by exec()
+only copies a few pages of the parent's memory, just the ones it changes
+before freeing them.</p>
+
+<p>With a very primitive MMU (using a base pointer plus length instead of page
+tables, which can provide virtual addresses and protect processes from each
+other, but no copy on write) you can still implement fork.  But it's
+unreasonably expensive, because you have to copy all the parent process'
+memory into the new process (which could easily be several megabytes per fork).
+And you have to do this even though that memory gets freed again as soon as the
+exec happens.  (This is not just slow and a waste of space but causes memory
+usage spikes that can easily cause the system to run out of memory.)</p>
+
+<p>Without even a primitive MMU, you have no virtual addresses.  Every process
+can reach out and touch any other process' memory, because all pointers are to
+physical addresses with no protection.  Even if you copy a process' memory to
+new physical addresses, all of its pointers point to the old objects in the
+old process.  (Searching through the new copy's memory for pointers and
+redirect them to the new locations is not an easy problem.)</p>
+
+<p>So with a primitive or missing MMU, fork() is just not a good idea.</p>
+
+<p>In theory, vfork() is just a fork() that writeably shares the heap and stack
+rather than copying it (so what one process writes the other one sees).  In
+practice, vfork() has to suspend the parent process until the child does exec,
+at which point the parent wakes up and resumes by returning from the call to
+vfork().  All modern kernel/libc combinations implement vfork() to put the
+parent to sleep until the child does its exec.  There's just no other way to
+make it work: the parent has to know the child has done its exec() or exit()
+before it's safe to return from the function it's in, so it has to block
+until that happens.  In fact without suspending the parent there's no way to
+even store separate copies of the return value (the pid) from the vfork() call
+itself: both assignments write into the same memory location.</p>
+
+<p>One way to understand (and in fact implement) vfork() is this: imagine
+the parent does a setjmp and then continues on (pretending to be the child)
+until the exec() comes around, then the _exec_ does the actual fork, and the
+parent does a longjmp back to the original vfork call and continues on from
+there.  (It thus becomes obvious why the child can't return, or modify
+local variables it doesn't want the parent to see changed when it resumes.)
+
+<p>Note a common mistake: the need for vfork doesn't mean you can't have two
+processes running at the same time.  It means you can't have two processes
+sharing the same memory without stomping all over each other.  As soon as
+the child calls exec(), the parent resumes.</p>
+
+<p>If the child's attempt to call exec() fails, the child should call _exit()
+rather than a normal exit().  This avoids any atexit() code that might confuse
+the parent.  (The parent should never call _exit(), only a vforked child that
+failed to exec.)</p>
+
+<p>(Now in theory, a nommu system could just copy the _stack_ when it forks
+(which presumably is much shorter than the heap), and leave the heap shared.
+Even with no MMU at all
+In practice, you've just wound up in a multi-threaded situation and you can't
+do a malloc() or free() on your heap without freeing the other process' memory
+(and if you don't have the proper locking for being threaded, corrupting the
+heap if both of you try to do it at the same time and wind up stomping on
+each other while traversing the free memory lists).  The thing about vfork is
+that it's a big red flag warning "there be dragons here" rather than
+something subtle and thus even more dangerous.)</p>
+
+<h2><a name="tips_sort_read">Short reads and writes</a></h2>
+
+<p>Busybox has special functions, bb_full_read() and bb_full_write(), to
+check that all the data we asked for got read or written.  Is this a real
+world consideration?  Try the following:</p>
+
+<pre>while true; do echo hello; sleep 1; done | tee out.txt</pre>
+
+<p>If tee is implemented with bb_full_read(), tee doesn't display output
+in real time but blocks until its entire input buffer (generally a couple
+kilobytes) is read, then displays it all at once.  In that case, we _want_
+the short read, for user interface reasons.  (Note that read() should never
+return 0 unless it has hit the end of input, and an attempt to write 0
+bytes should be ignored by the OS.)</p>
+
+<p>As for short writes, play around with two processes piping data to each
+other on the command line (cat bigfile | gzip > out.gz) and suspend and
+resume a few times (ctrl-z to suspend, "fg" to resume).  The writer can
+experience short writes, which are especially dangerous because if you don't
+notice them you'll discard data.  They can also happen when a system is under
+load and a fast process is piping to a slower one.  (Such as an xterm waiting
+on x11 when the scheduler decides X is being a CPU hog with all that
+text console scrolling...)</p>
+
+<p>So will data always be read from the far end of a pipe at the
+same chunk sizes it was written in?  Nope.  Don't rely on that.  For one
+counterexample, see <a href="http://www.faqs.org/rfcs/rfc896.html">rfc 896 
+for Nagle's algorithm</a>, which waits a fraction of a second or so before
+sending out small amounts of data through a TCP/IP connection in case more
+data comes in that can be merged into the same packet.  (In case you were
+wondering why action games that use TCP/IP set TCP_NODELAY to lower the latency
+on their their sockets, now you know.)</p>
+
+<h2><a name="tips_memory">Memory used by relocatable code, PIC, and static linking.</a></h2>
+
+<p>The downside of standard dynamic linking is that it results in self-modifying
+code.  Although each executable's pages are mmaped() into a process' address
+space from the executable file and are thus naturally shared between processes
+out of the page cache, the library loader (ld-linux.so.2 or ld-uClibc.so.0)
+writes to these pages to supply addresses for relocatable symbols.  This
+dirties the pages, triggering copy-on-write allocation of new memory for each
+processes' dirtied pages.</p>
+
+<p>One solution to this is Position Independent Code (PIC), a way of linking
+a file so all the relocations are grouped together.  This dirties fewer
+pages (often just a single page) for each process' relocations.  The down
+side is this results in larger executables, which take up more space on disk
+(and a correspondingly larger space in memory).  But when many copies of the
+same program are running, PIC dynamic linking trades a larger disk footprint
+for a smaller memory footprint, by sharing more pages.</p>
+
+<p>A third solution is static linking.  A statically linked program has no
+relocations, and thus the entire executable is shared between all running
+instances.  This tends to have a significantly larger disk footprint, but
+on a system with only one or two executables, shared libraries aren't much
+of a win anyway.</p>
+
+<p>You can tell the glibc linker to display debugging information about its
+relocations with the environment variable "LD_DEBUG".  Try
+"LD_DEBUG=help /bin/true" for a list of commands.  Learning to interpret
+"LD_DEBUG=statistics cat /proc/self/statm" could be interesting.</p>
+
+<p>For more on this topic, here's Rich Felker:</p>
+<blockquote>
+<p>Dynamic linking (without fixed load addresses) fundamentally requires
+at least one dirty page per dso that uses symbols. Making calls (but
+never taking the address explicitly) to functions within the same dso
+does not require a dirty page by itself, but will with ELF unless you
+use -Bsymbolic or hidden symbols when linking.</p>
+
+<p>ELF uses significant additional stack space for the kernel to pass all
+the ELF data structures to the newly created process image. These are
+located above the argument list and environment. This normally adds 1
+dirty page to the process size.</p>
+
+<p>The ELF dynamic linker has its own data segment, adding one or more
+dirty pages. I believe it also performs relocations on itself.</p>
+
+<p>The ELF dynamic linker makes significant dynamic allocations to manage
+the global symbol table and the loaded dso's. This data is never
+freed. It will be needed again if libdl is used, so unconditionally
+freeing it is not possible, but normal programs do not use libdl. Of
+course with glibc all programs use libdl (due to nsswitch) so the
+issue was never addressed.</p>
+
+<p>ELF also has the issue that segments are not page-aligned on disk.
+This saves up to 4k on disk, but at the expense of using an additional
+dirty page in most cases, due to a large portion of the first data
+page being filled with a duplicate copy of the last text page.</p>
+
+<p>The above is just a partial list of the tiny memory penalties of ELF
+dynamic linking, which eventually add up to quite a bit. The smallest
+I've been able to get a process down to is 8 dirty pages, and the
+above factors seem to mostly account for it (but some were difficult
+to measure).</p>
+</blockquote>
+
+<h2><a name="tips_kernel_headers"></a>Including kernel headers</h2>
+
+<p>The "linux" or "asm" directories of /usr/include contain Linux kernel
+headers, so that the C library can talk directly to the Linux kernel.  In
+a perfect world, applications shouldn't include these headers directly, but
+we don't live in a perfect world.</p>
+
+<p>For example, Busybox's losetup code wants linux/loop.c because nothing else
+#defines the structures to call the kernel's loopback device setup ioctls.
+Attempts to cut and paste the information into a local busybox header file
+proved incredibly painful, because portions of the loop_info structure vary by
+architecture, namely the type __kernel_dev_t has different sizes on alpha,
+arm, x86, and so on.  Meaning we either #include <linux/posix_types.h> or
+we hardwire #ifdefs to check what platform we're building on and define this
+type appropriately for every single hardware architecture supported by
+Linux, which is simply unworkable.</p>
+
+<p>This is aside from the fact that the relevant type defined in
+posix_types.h was renamed to __kernel_old_dev_t during the 2.5 series, so
+to cut and paste the structure into our header we have to #include
+<linux/version.h> to figure out which name to use.  (What we actually do is
+check if we're building on 2.6, and if so just use the new 64 bit structure
+instead to avoid the rename entirely.)  But we still need the version
+check, since 2.4 didn't have the 64 bit structure.</p>
+
+<p>The BusyBox developers spent <u>two years</u> trying to figure
+out a clean way to do all this.  There isn't one.  The losetup in the
+util-linux package from kernel.org isn't doing it cleanly either, they just
+hide the ugliness by nesting #include files.  Their mount/loop.h
+#includes "my_dev_t.h", which #includes <linux/posix_types.h> and
+<linux/version.h> just like we do.  There simply is no alternative.</p>
+
+<p>Just because directly #including kernel headers is sometimes
+unavoidable doesn't me we should include them when there's a better
+way to do it.  However, block copying information out of the kernel headers
+is not a better way.</p>
+
+<h2><a name="who">Who are the BusyBox developers?</a></h2>
+
+<p>The following login accounts currently exist on busybox.net.  (I.E. these
+people can commit <a href="http://busybox.net/downloads/patches">patches</a>
+into subversion for the BusyBox, uClibc, and buildroot projects.)</p>
+
+<pre>
+aldot     :Bernhard Fischer
+andersen  :Erik Andersen      <- uClibc and BuildRoot maintainer.
+bug1      :Glenn McGrath
+davidm    :David McCullough
+gkajmowi  :Garrett Kajmowicz  <- uClibc++ maintainer
+jbglaw    :Jan-Benedict Glaw
+jocke     :Joakim Tjernlund
+landley   :Rob Landley        <- BusyBox maintainer
+lethal    :Paul Mundt
+mjn3      :Manuel Novoa III
+osuadmin  :osuadmin
+pgf       :Paul Fox
+pkj       :Peter Kjellerstedt
+prpplague :David Anders
+psm       :Peter S. Mazinger
+russ      :Russ Dill
+sandman   :Robert Griebl
+sjhill    :Steven J. Hill
+solar     :Ned Ludd
+timr      :Tim Riker
+tobiasa   :Tobias Anderberg
+vapier    :Mike Frysinger
+</pre>
+
+<p>The following accounts used to exist on busybox.net, but don't anymore so
+I can't ask /etc/passwd for their names.  (If anybody would like to make
+a stab at it...)</p>
+
+<pre>
+aaronl
+beppu
+dwhedon
+erik    : Also Erik Andersen?
+gfeldman
+jimg
+kraai
+markw
+miles
+proski
+rjune
+tausq
+vodz      :Vladimir N. Oleynik
+</pre>
+
+
+<br>
+<br>
+<br>
+
+<!--#include file="footer.html" -->

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/about.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/about.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/about.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+<!--#include file="header.html" -->
+
+<h3>BusyBox: The Swiss Army Knife of Embedded Linux</h3>
+
+<p>BusyBox combines tiny versions of many common UNIX utilities into a single
+small executable. It provides replacements for most of the utilities you
+usually find in GNU fileutils, shellutils, etc. The utilities in BusyBox
+generally have fewer options than their full-featured GNU cousins; however,
+the options that are included provide the expected functionality and behave
+very much like their GNU counterparts.  BusyBox provides a fairly complete
+environment for any small or embedded system.</p>
+
+<p>BusyBox has been written with size-optimization and limited resources in
+mind. It is also extremely modular so you can easily include or exclude
+commands (or features) at compile time. This makes it easy to customize
+your embedded systems. To create a working system, just add some device
+nodes in /dev, a few configuration files in /etc, and a Linux kernel.</p>
+
+<p>BusyBox is maintained by <a href="http://www.landley.net/">Rob Landley</a>,
+and licensed under the <a href="/license.html">GNU GENERAL PUBLIC LICENSE</a>
+version 2 or later.</p>
+
+<!--#include file="footer.html" -->

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/busybox-growth.ps
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/busybox-growth.ps	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/busybox-growth.ps	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,404 @@
+%!PS-Adobe-2.0
+%%Title: busybox-growth.ps
+%%Creator: gnuplot 3.5 (pre 3.6) patchlevel beta 347
+%%CreationDate: Tue Apr 10 14:03:36 2001
+%%DocumentFonts: (atend)
+%%BoundingBox: 50 40 554 770
+%%Orientation: Landscape
+%%Pages: (atend)
+%%EndComments
+/gnudict 120 dict def
+gnudict begin
+/Color true def
+/Solid true def
+/gnulinewidth 5.000 def
+/userlinewidth gnulinewidth def
+/vshift -46 def
+/dl {10 mul} def
+/hpt_ 31.5 def
+/vpt_ 31.5 def
+/hpt hpt_ def
+/vpt vpt_ def
+/M {moveto} bind def
+/L {lineto} bind def
+/R {rmoveto} bind def
+/V {rlineto} bind def
+/vpt2 vpt 2 mul def
+/hpt2 hpt 2 mul def
+/Lshow { currentpoint stroke M
+  0 vshift R show } def
+/Rshow { currentpoint stroke M
+  dup stringwidth pop neg vshift R show } def
+/Cshow { currentpoint stroke M
+  dup stringwidth pop -2 div vshift R show } def
+/UP { dup vpt_ mul /vpt exch def hpt_ mul /hpt exch def
+  /hpt2 hpt 2 mul def /vpt2 vpt 2 mul def } def
+/DL { Color {setrgbcolor Solid {pop []} if 0 setdash }
+ {pop pop pop Solid {pop []} if 0 setdash} ifelse } def
+/BL { stroke gnulinewidth 2 mul setlinewidth } def
+/AL { stroke gnulinewidth 2 div setlinewidth } def
+/UL { gnulinewidth mul /userlinewidth exch def } def
+/PL { stroke userlinewidth setlinewidth } def
+/LTb { BL [] 0 0 0 DL } def
+/LTa { AL [1 dl 2 dl] 0 setdash 0 0 0 setrgbcolor } def
+/LT0 { PL [] 1 0 0 DL } def
+/LT1 { PL [4 dl 2 dl] 0 1 0 DL } def
+/LT2 { PL [2 dl 3 dl] 0 0 1 DL } def
+/LT3 { PL [1 dl 1.5 dl] 1 0 1 DL } def
+/LT4 { PL [5 dl 2 dl 1 dl 2 dl] 0 1 1 DL } def
+/LT5 { PL [4 dl 3 dl 1 dl 3 dl] 1 1 0 DL } def
+/LT6 { PL [2 dl 2 dl 2 dl 4 dl] 0 0 0 DL } def
+/LT7 { PL [2 dl 2 dl 2 dl 2 dl 2 dl 4 dl] 1 0.3 0 DL } def
+/LT8 { PL [2 dl 2 dl 2 dl 2 dl 2 dl 2 dl 2 dl 4 dl] 0.5 0.5 0.5 DL } def
+/Pnt { stroke [] 0 setdash
+   gsave 1 setlinecap M 0 0 V stroke grestore } def
+/Dia { stroke [] 0 setdash 2 copy vpt add M
+  hpt neg vpt neg V hpt vpt neg V
+  hpt vpt V hpt neg vpt V closepath stroke
+  Pnt } def
+/Pls { stroke [] 0 setdash vpt sub M 0 vpt2 V
+  currentpoint stroke M
+  hpt neg vpt neg R hpt2 0 V stroke
+  } def
+/Box { stroke [] 0 setdash 2 copy exch hpt sub exch vpt add M
+  0 vpt2 neg V hpt2 0 V 0 vpt2 V
+  hpt2 neg 0 V closepath stroke
+  Pnt } def
+/Crs { stroke [] 0 setdash exch hpt sub exch vpt add M
+  hpt2 vpt2 neg V currentpoint stroke M
+  hpt2 neg 0 R hpt2 vpt2 V stroke } def
+/TriU { stroke [] 0 setdash 2 copy vpt 1.12 mul add M
+  hpt neg vpt -1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt 1.62 mul V closepath stroke
+  Pnt  } def
+/Star { 2 copy Pls Crs } def
+/BoxF { stroke [] 0 setdash exch hpt sub exch vpt add M
+  0 vpt2 neg V  hpt2 0 V  0 vpt2 V
+  hpt2 neg 0 V  closepath fill } def
+/TriUF { stroke [] 0 setdash vpt 1.12 mul add M
+  hpt neg vpt -1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt 1.62 mul V closepath fill } def
+/TriD { stroke [] 0 setdash 2 copy vpt 1.12 mul sub M
+  hpt neg vpt 1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt -1.62 mul V closepath stroke
+  Pnt  } def
+/TriDF { stroke [] 0 setdash vpt 1.12 mul sub M
+  hpt neg vpt 1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt -1.62 mul V closepath fill} def
+/DiaF { stroke [] 0 setdash vpt add M
+  hpt neg vpt neg V hpt vpt neg V
+  hpt vpt V hpt neg vpt V closepath fill } def
+/Pent { stroke [] 0 setdash 2 copy gsave
+  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
+  closepath stroke grestore Pnt } def
+/PentF { stroke [] 0 setdash gsave
+  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
+  closepath fill grestore } def
+/Circle { stroke [] 0 setdash 2 copy
+  hpt 0 360 arc stroke Pnt } def
+/CircleF { stroke [] 0 setdash hpt 0 360 arc fill } def
+/C0 { BL [] 0 setdash 2 copy moveto vpt 90 450  arc } bind def
+/C1 { BL [] 0 setdash 2 copy        moveto
+       2 copy  vpt 0 90 arc closepath fill
+               vpt 0 360 arc closepath } bind def
+/C2 { BL [] 0 setdash 2 copy moveto
+       2 copy  vpt 90 180 arc closepath fill
+               vpt 0 360 arc closepath } bind def
+/C3 { BL [] 0 setdash 2 copy moveto
+       2 copy  vpt 0 180 arc closepath fill
+               vpt 0 360 arc closepath } bind def
+/C4 { BL [] 0 setdash 2 copy moveto
+       2 copy  vpt 180 270 arc closepath fill
+               vpt 0 360 arc closepath } bind def
+/C5 { BL [] 0 setdash 2 copy moveto
+       2 copy  vpt 0 90 arc
+       2 copy moveto
+       2 copy  vpt 180 270 arc closepath fill
+               vpt 0 360 arc } bind def
+/C6 { BL [] 0 setdash 2 copy moveto
+      2 copy  vpt 90 270 arc closepath fill
+              vpt 0 360 arc closepath } bind def
+/C7 { BL [] 0 setdash 2 copy moveto
+      2 copy  vpt 0 270 arc closepath fill
+              vpt 0 360 arc closepath } bind def
+/C8 { BL [] 0 setdash 2 copy moveto
+      2 copy vpt 270 360 arc closepath fill
+              vpt 0 360 arc closepath } bind def
+/C9 { BL [] 0 setdash 2 copy moveto
+      2 copy  vpt 270 450 arc closepath fill
+              vpt 0 360 arc closepath } bind def
+/C10 { BL [] 0 setdash 2 copy 2 copy moveto vpt 270 360 arc closepath fill
+       2 copy moveto
+       2 copy vpt 90 180 arc closepath fill
+               vpt 0 360 arc closepath } bind def
+/C11 { BL [] 0 setdash 2 copy moveto
+       2 copy  vpt 0 180 arc closepath fill
+       2 copy moveto
+       2 copy  vpt 270 360 arc closepath fill
+               vpt 0 360 arc closepath } bind def
+/C12 { BL [] 0 setdash 2 copy moveto
+       2 copy  vpt 180 360 arc closepath fill
+               vpt 0 360 arc closepath } bind def
+/C13 { BL [] 0 setdash  2 copy moveto
+       2 copy  vpt 0 90 arc closepath fill
+       2 copy moveto
+       2 copy  vpt 180 360 arc closepath fill
+               vpt 0 360 arc closepath } bind def
+/C14 { BL [] 0 setdash 2 copy moveto
+       2 copy  vpt 90 360 arc closepath fill
+               vpt 0 360 arc } bind def
+/C15 { BL [] 0 setdash 2 copy vpt 0 360 arc closepath fill
+               vpt 0 360 arc closepath } bind def
+/Rec   { newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto
+       neg 0 rlineto closepath } bind def
+/Square { dup Rec } bind def
+/Bsquare { vpt sub exch vpt sub exch vpt2 Square } bind def
+/S0 { BL [] 0 setdash 2 copy moveto 0 vpt rlineto BL Bsquare } bind def
+/S1 { BL [] 0 setdash 2 copy vpt Square fill Bsquare } bind def
+/S2 { BL [] 0 setdash 2 copy exch vpt sub exch vpt Square fill Bsquare } bind def
+/S3 { BL [] 0 setdash 2 copy exch vpt sub exch vpt2 vpt Rec fill Bsquare } bind def
+/S4 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt Square fill Bsquare } bind def
+/S5 { BL [] 0 setdash 2 copy 2 copy vpt Square fill
+       exch vpt sub exch vpt sub vpt Square fill Bsquare } bind def
+/S6 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill Bsquare } bind def
+/S7 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill
+       2 copy vpt Square fill
+       Bsquare } bind def
+/S8 { BL [] 0 setdash 2 copy vpt sub vpt Square fill Bsquare } bind def
+/S9 { BL [] 0 setdash 2 copy vpt sub vpt vpt2 Rec fill Bsquare } bind def
+/S10 { BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt Square fill
+       Bsquare } bind def
+/S11 { BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt2 vpt Rec fill
+       Bsquare } bind def
+/S12 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill Bsquare } bind def
+/S13 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill
+       2 copy vpt Square fill Bsquare } bind def
+/S14 { BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill
+       2 copy exch vpt sub exch vpt Square fill Bsquare } bind def
+/S15 { BL [] 0 setdash 2 copy Bsquare fill Bsquare } bind def
+/D0 { gsave translate 45 rotate 0 0 S0 stroke grestore } bind def
+/D1 { gsave translate 45 rotate 0 0 S1 stroke grestore } bind def
+/D2 { gsave translate 45 rotate 0 0 S2 stroke grestore } bind def
+/D3 { gsave translate 45 rotate 0 0 S3 stroke grestore } bind def
+/D4 { gsave translate 45 rotate 0 0 S4 stroke grestore } bind def
+/D5 { gsave translate 45 rotate 0 0 S5 stroke grestore } bind def
+/D6 { gsave translate 45 rotate 0 0 S6 stroke grestore } bind def
+/D7 { gsave translate 45 rotate 0 0 S7 stroke grestore } bind def
+/D8 { gsave translate 45 rotate 0 0 S8 stroke grestore } bind def
+/D9 { gsave translate 45 rotate 0 0 S9 stroke grestore } bind def
+/D10 { gsave translate 45 rotate 0 0 S10 stroke grestore } bind def
+/D11 { gsave translate 45 rotate 0 0 S11 stroke grestore } bind def
+/D12 { gsave translate 45 rotate 0 0 S12 stroke grestore } bind def
+/D13 { gsave translate 45 rotate 0 0 S13 stroke grestore } bind def
+/D14 { gsave translate 45 rotate 0 0 S14 stroke grestore } bind def
+/D15 { gsave translate 45 rotate 0 0 S15 stroke grestore } bind def
+/DiaE { stroke [] 0 setdash vpt add M
+  hpt neg vpt neg V hpt vpt neg V
+  hpt vpt V hpt neg vpt V closepath stroke } def
+/BoxE { stroke [] 0 setdash exch hpt sub exch vpt add M
+  0 vpt2 neg V hpt2 0 V 0 vpt2 V
+  hpt2 neg 0 V closepath stroke } def
+/TriUE { stroke [] 0 setdash vpt 1.12 mul add M
+  hpt neg vpt -1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt 1.62 mul V closepath stroke } def
+/TriDE { stroke [] 0 setdash vpt 1.12 mul sub M
+  hpt neg vpt 1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt -1.62 mul V closepath stroke } def
+/PentE { stroke [] 0 setdash gsave
+  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
+  closepath stroke grestore } def
+/CircE { stroke [] 0 setdash
+  hpt 0 360 arc stroke } def
+/Opaque { gsave closepath 1 setgray fill grestore 0 setgray closepath } def
+/DiaW { stroke [] 0 setdash vpt add M
+  hpt neg vpt neg V hpt vpt neg V
+  hpt vpt V hpt neg vpt V Opaque stroke } def
+/BoxW { stroke [] 0 setdash exch hpt sub exch vpt add M
+  0 vpt2 neg V hpt2 0 V 0 vpt2 V
+  hpt2 neg 0 V Opaque stroke } def
+/TriUW { stroke [] 0 setdash vpt 1.12 mul add M
+  hpt neg vpt -1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt 1.62 mul V Opaque stroke } def
+/TriDW { stroke [] 0 setdash vpt 1.12 mul sub M
+  hpt neg vpt 1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt -1.62 mul V Opaque stroke } def
+/PentW { stroke [] 0 setdash gsave
+  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
+  Opaque stroke grestore } def
+/CircW { stroke [] 0 setdash
+  hpt 0 360 arc Opaque stroke } def
+/BoxFill { gsave Rec 1 setgray fill grestore } def
+end
+%%EndProlog
+%%Page: 1 1
+gnudict begin
+gsave
+50 50 translate
+0.100 0.100 scale
+90 rotate
+0 -5040 translate
+0 setgray
+newpath
+(Helvetica) findfont 140 scalefont setfont
+1.000 UL
+LTb
+560 420 M
+63 0 V
+6409 0 R
+-63 0 V
+476 420 M
+(0) Rshow
+560 1056 M
+63 0 V
+6409 0 R
+-63 0 V
+-6493 0 R
+(100) Rshow
+560 1692 M
+63 0 V
+6409 0 R
+-63 0 V
+-6493 0 R
+(200) Rshow
+560 2328 M
+63 0 V
+6409 0 R
+-63 0 V
+-6493 0 R
+(300) Rshow
+560 2964 M
+63 0 V
+6409 0 R
+-63 0 V
+-6493 0 R
+(400) Rshow
+560 3600 M
+63 0 V
+6409 0 R
+-63 0 V
+-6493 0 R
+(500) Rshow
+560 4236 M
+63 0 V
+6409 0 R
+-63 0 V
+-6493 0 R
+(600) Rshow
+560 4872 M
+63 0 V
+6409 0 R
+-63 0 V
+-6493 0 R
+(700) Rshow
+1531 420 M
+0 63 V
+0 4389 R
+0 -63 V
+0 -4529 R
+(400) Cshow
+2825 420 M
+0 63 V
+0 4389 R
+0 -63 V
+0 -4529 R
+(600) Cshow
+4120 420 M
+0 63 V
+0 4389 R
+0 -63 V
+0 -4529 R
+(800) Cshow
+5414 420 M
+0 63 V
+0 4389 R
+0 -63 V
+0 -4529 R
+(1000) Cshow
+6708 420 M
+0 63 V
+0 4389 R
+0 -63 V
+0 -4529 R
+(1200) Cshow
+1.000 UL
+LTb
+560 420 M
+6472 0 V
+0 4452 V
+-6472 0 V
+560 420 L
+0 2646 M
+currentpoint gsave translate 90 rotate 0 0 M
+(tar.gz size \(Kb\)) Cshow
+grestore
+3796 140 M
+(time \(days since Jan 1, 1998\)) Cshow
+1.000 UL
+LT0
+696 420 M
+0 593 V
+1255 0 V
+0 15 V
+214 0 V
+0 6 V
+958 0 V
+0 1 V
+-84 0 V
+0 37 V
+168 0 V
+0 262 V
+13 0 V
+0 56 V
+91 0 V
+0 33 V
+6 0 V
+0 1 V
+19 0 V
+0 11 V
+20 0 V
+0 13 V
+32 0 V
+0 104 V
+52 0 V
+0 27 V
+65 0 V
+0 15 V
+39 0 V
+0 126 V
+174 0 V
+0 103 V
+52 0 V
+0 49 V
+175 0 V
+0 56 V
+433 0 V
+0 661 V
+415 0 V
+0 857 V
+123 0 V
+0 -291 V
+498 0 V
+0 208 V
+505 0 V
+0 66 V
+291 0 V
+0 115 V
+311 0 V
+0 449 V
+162 0 V
+0 309 V
+stroke
+grestore
+end
+showpage
+%%Trailer
+%%DocumentFonts: Helvetica
+%%Pages: 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/copyright.txt
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/copyright.txt	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/copyright.txt	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,30 @@
+
+The code and graphics on this website (and it's mirror sites, if any) are
+Copyright (c) 1999-2004 by Erik Andersen.  All rights reserved.
+Copyright (c) 2005-2006 Rob Landley.
+
+Documents on this Web site including their graphical elements, design, and
+layout are protected by trade dress and other laws and MAY BE COPIED OR
+IMITATED IN WHOLE OR IN PART.  THIS WEBSITE IS LICENSED FREE OF CHARGE, THERE
+IS NO WARRANTY FOR THE WEBSITE TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+SHOULD THIS WEBSITE PROVE DEFECTIVE, YOU MAY ASSUME THAT SOMEONE MIGHT GET
+AROUND TO SERVICING, REPAIRING OR CORRECTING IT SOMETIME WHEN THEY HAVE NOTHING
+BETTER TO DO.  REGARDLESS, YOU GET TO KEEP BOTH PIECES.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY
+COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THIS
+WEBSITE AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+INABILITY TO USE THIS WEBSITE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
+LOSS OF HAIR, LOSS OF LIFE, LOSS OF MEMORY, LOSS OF YOUR CARKEYS, MISPLACEMENT
+OF YOUR PAYCHECK, OR COMMANDER DATA BEING RENDERED UNABLE TO ASSIST THE
+STARFLEET OFFICERS ABORD THE STARSHIP ENTERPRISE TO RECALIBRATE THE MAIN
+DEFLECTOR ARRAY, LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE
+WEBSITE TO OPERATE WITH YOUR WEBBROWSER), EVEN IF SUCH HOLDER OR OTHER PARTY
+HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+You have been warned.
+
+You can contact the webmaster at <rob at landley.net> if you have some sort
+of problem with this.
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/developer.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/developer.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/developer.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,69 @@
+<!--#include file="header.html" -->
+
+<h3>Morris Dancing</h3>
+
+<p>Subversion commit access requires an account on Morris.  The server
+behind busybox.net and uclibc.org.  If you want to be able to commit things to
+Subversion, first contribute some stuff to show you are serious, can handle
+some responsibility, and that your patches don't generally need a lot of
+cleanup.  Then, very nicely ask one of us (<a href="mailto:rob at landley.net">Rob
+Landley</a> for BusyBox, or <a href="mailto:andersen at codepoet.org">Erik
+Andersen</a> for uClibc) for an account.</p>
+
+<p>If you're approved for an account, you'll need to send an email from your
+preferred contact email address with the username you'd like to use when
+committing changes to SVN, and attach a public ssh key to access your account
+with.</p>
+
+<p>If you don't currently have an ssh version 2 DSA key at least 1024 bits
+long (the default), you can generate a key using the
+command <b>ssh-keygen -t dsa</b> and hitting enter at the prompts.  This
+will create the files <b>~/.ssh/id_dsa</b> and <b>~/.ssh/id_dsa.pub</b>
+You must then send the content of 'id_dsa.pub' to me so I can set up your
+account.  (The content of 'id_dsa' should of course be kept secret, anyone
+who has that can access any account that's installed your public key in
+its <b>.ssh/authorized_keys</b> file.)</p>
+
+<p>Note that if you would prefer to keep your communications with us
+private, you can encrypt your email using
+<a href="http://landley.net/pubkey.gpg">Rob's public key</a> or
+<a href="http://www.codepoet.org/andersen/erik/gpg.asc">Erik's public
+key</a>.</p>
+
+<p>Once you are setup with an account, you will need to use your account to
+checkout a copy of BusyBox from Subversion:</p>
+
+<p><b>svn checkout svn+ssh://username@busybox.net/svn/trunk/busybox</b></p>
+<p>or</p>
+<p><b>svn checkout svn+ssh://username@uclibc.org/svn/trunk/uclibc</b></p>
+
+<p>You must change <em>username</em> to your own username, or omit
+it if it's the same as your local username.</p>
+
+<p>You can then enter the newly checked out project directory, make changes,
+check your changes, diff your changes, revert your changes, and and commit your
+changes using commands such as:</p>
+
+<b><pre>
+svn diff
+svn status
+svn revert
+EDITOR=vi svn commit
+svn log -v -r PREV:HEAD
+svn help
+</pre></b>
+
+<p>For additional detail on how to use Subversion, please visit the
+<a href="http://subversion.tigris.org/">the Subversion website</a>.
+You might also want to read online or buy a copy of <a
+href="http://svnbook.red-bean.com/">the Subversion Book</a>...</p>
+
+<p>A morris account also gives you a personal web page
+(http://busybox.net/~username comes from ~/public_html on morris), and of
+course a shell prompt you can ssh into (as a regular user, root access is
+reserved for Erik and Rob).  But keep in mind an account on Morris is a
+priviledge, not a requirement.  Most contributors to busybox and uClibc
+haven't got one, and accounts are handed out to make the project maintainers'
+lives easier, not because "you deserve it".</p>
+
+<!--#include file="footer.html" -->

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/download.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/download.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/download.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,29 @@
+<!--#include file="header.html" -->
+
+
+
+<h3>Download</h3>
+
+Source for the latest release can always be
+downloaded from <a href="downloads">http://www.busybox.net/downloads</a>.
+
+<p>
+You can also obtain <a href= "downloads/snapshots/">Daily Snapshots</a> of
+the latest development source tree for those wishing to follow BusyBox development,
+but cannot or do not wish to use Subversion (svn).
+
+<ul>
+	<li> Click here to <a href="/cgi-bin/viewcvs.cgi/trunk/busybox/">browse the source tree</a>.
+	</li>
+
+	<li>Anonymous <a href="subversion.html">Subversion access</a> is available.
+	</li>
+
+	<li>For those that are actively contributing obtaining
+		<a href="developer.html">Subversion read/write access</a> is also possible.
+	</li>
+
+</ul>
+
+<!--#include file="footer.html" -->
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/footer.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/footer.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/footer.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,47 @@
+<!-- Footer -->
+
+
+    </td>
+    </tr>
+    </table>
+
+<hr />
+
+
+    <table width="100%">
+	<tr>
+	    <td width="60%">
+		<font face="arial, helvetica, sans-serif" size="-1">
+		    <a href="/copyright.txt">Copyright © 1999-2005 Erik Andersen</a>
+		    <br>
+		    Mail all comments, insults, suggestions and bribes to
+		    <br>
+		    Rob Landley <a href="mailto:rob at landley.net">rob at landley.net</a><br>
+		</font>
+	    </td>
+
+	    <td>
+		<a href="http://www.vim.org/"><img border=0 width=88 height=31
+		src="images/written.in.vi.png"
+		alt="This site created with the vi editor"></a>
+	    </td>
+
+	    <td>
+		<a href="http://osuosl.org/"><img border=0 width=114 height=63
+		src="images/osuosl.png"
+		alt="This site is kindly hosted by OSL"></a>
+	    </td>
+<!--
+	    <td>
+		<a href="http://validator.w3.org/check?uri=referer"><img
+		border="0" height="31" width="88"
+		src="images/valid-html401.png"
+		alt="Valid HTML"></a>
+	    </td>
+-->
+	</TR>
+    </table>
+
+  </body>
+</html>
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/header.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/header.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/header.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>
+
+<html>
+  <head>
+    <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'>
+    <title>BusyBox</title>
+    <style type="text/css">
+     body {
+      background-color: #DEE2DE;
+      color: #000000;
+     }
+     :link { color: #660000 }
+     :visited { color: #660000 }
+     :active { color: #660000 }
+     td.c2 {font-family: arial, helvetica, sans-serif; font-size: 80%}
+     td.c1 {font-family: lucida, helvetica; font-size: 248%}
+    </style>
+  </head>
+
+  <body>
+    <basefont face="lucida, helvetica, arial" size="3">
+
+
+
+
+<table border="0" cellpadding="0" cellspacing="0">
+
+
+<tr>
+<td>
+    <div class="c3">
+      <table border="0" cellspacing="1" cellpadding="2">
+        <tr>
+          <td class="c1">BUSYBOX</td>
+        </tr>
+      </table>
+    </div>
+
+  <a href="/"><IMG SRC="images/busybox1.png" alt="BusyBox" border="0"></a><BR>
+</td>
+</tr>
+
+<tr>
+
+<td valign="TOP">
+    <b>About</b>
+    <ul>
+      <li><a href="about.html">About BusyBox</a></li>
+      <li><a href="screenshot.html">Screenshot</a></li>
+      <li><a href="news.html">Latest News</a></li>
+    </ul>
+    <b>Documentation</b>
+    <ul>
+        <li><a href="FAQ.html">FAQ</a></li>
+        <li><a href="downloads/BusyBox.html">Command Help</a></li>
+        <li><a href="downloads/README">README</a></li>
+    </ul>
+    <b>Get BusyBox</b>
+    <ul>
+        <li><a href="download.html">Download Source</a></li>
+        <li><a href="license.html">License</a></li>
+        <li><a href="products.html">Products</a></li>
+    </ul>
+    <b>Development</b>
+    <ul>
+        <li><a href="/cgi-bin/viewcvs.cgi/trunk/busybox/">Browse Source</a></li>
+        <li><a href="subversion.html">Source Control</a></li>
+        <li><a href="lists.html">Mailing Lists</a></li>
+        <li><a href="http://bugs.busybox.net/">Bug Tracking</a></li>
+    </ul>
+    <p><b>Links</b>
+    <ul>
+        <li><a href="links.html">Related Sites</a></li>
+	<li><a href="tinyutils.html">Tiny Utilities</a></li>
+	<li><a href="sponsors.html">Sponsors</a></li>
+    </ul>
+
+<!--
+    <a href="http://validator.w3.org/check/referer"><img
+     src="/images/vh40.gif" height=31 width=88
+          align=left border=0 alt="Valid HTML 4.0!"></a>
+-->
+
+</td>
+
+
+<td Valign="TOP">
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/back.png
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/back.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/busybox.jpeg
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/busybox.jpeg
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/busybox.png
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/busybox.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/busybox1.png
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/busybox1.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/busybox2.jpg
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/busybox2.jpg
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/busybox3.jpg
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/busybox3.jpg
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/dir.png
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/dir.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/donate.png
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/donate.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/fm.mini.png
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/fm.mini.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/gfx_by_gimp.png
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/gfx_by_gimp.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/ltbutton2.png
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/ltbutton2.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/osuosl.png
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/osuosl.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/sdsmall.png
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/sdsmall.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/text.png
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/text.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/valid-html401.png
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/valid-html401.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/vh40.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/vh40.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/written.in.vi.png
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/images/written.in.vi.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/index.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/index.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/index.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+<!--#include file="news.html" -->

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/license.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/license.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/license.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,57 @@
+<!--#include file="header.html" -->
+
+<p>
+<h3>BusyBox is licensed under the GNU General Public License</h3>
+
+<p>BusyBox is licensed under <a href="http://www.gnu.org/licenses/gpl.html#SEC1">the
+GNU General Public License</a> version 2 or later, which is generally
+abbreviated as the GPL.  (This is the same license the Linux kernel is under,
+so you may be somewhat familiar with it by now.)</p>
+
+<p><a href="/products.html">Anyone thinking of shipping BusyBox as part of a
+product</a> should be familiar with the licensing terms under which they are
+allowed to use and distribute BusyBox.  Read the full test of the GPL (either
+through the above link, or in the file LICENSE in the busybox tarball), and
+also read the <a href="http://www.gnu.org/licenses/gpl-faq.html">Frequently
+Asked Questions about the GPL</a>.</p>
+
+<p>Basically, if you distribute GPL software the license requires that you also
+distribute the source code to that GPL-licensed software.  So if you distribute
+BusyBox without making the source code to the version you distribute available,
+you violate the license terms, and thus infringe on the copyrights of BusyBox.
+(This requirement applies whether or not you modified BusyBox; either way the
+license terms still apply to you.)  Read the license text for the details.</p>
+
+<p>BusyBox's copyrights are enforced by the <a
+href="http://www.softwarefreedom.org">Software Freedom Law Center</a>, which
+"accepts primary responsibility for enforcement of US copyrights on the
+software... and coordinates international copyright enforcement efforts for
+such works as necessary."  If you distribute BusyBox in a way that doesn't
+comply with the terms of the license BusyBox is distributed under, expect to
+hear from these guys.  Their entire reason for existing is to do pro-bono
+legal work for free/open source software projects.  (We used to list people who
+violate the BusyBox license in <a href="/shame.html">The Hall of Shame</a>,
+but these days we find it much more effective to hand them over to the
+lawyers.)</p>
+
+<p>Our enforcement efforts are aimed at bringing people into compliance with
+the BusyBox license.  Open source software is under a different license from
+proprietary software, but if you violate that license you're still a software
+pirate and the law gives the vendor (us) some big sticks to play with.  We
+don't want monetary awards, injunctions, or to generate bad PR for a company,
+unless that's the only way to get somebody that repeatedly ignores us to comply
+with the license on our code.</p>
+
+<h3>A Good Example</h3>
+
+<p>These days, <a href="http://www.linksys.com/">Linksys</a> is
+doing a good job at complying with the GPL, they get to be an
+example of how to do things right.  Please take a moment and
+check out what they do with
+<a href="http://www.linksys.com/servlet/Satellite?c=L_Content_C1&childpagename=US%2FLayout&cid=1115416836002&pagename=Linksys%2FCommon%2FVisitorWrapper">
+distributing the firmware for their WRT54G Router.</a>
+Following their example would be a fine way to ensure that you
+have also fulfilled your licensing obligations.</p>
+
+<!--#include file="footer.html" -->
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/links.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/links.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/links.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,19 @@
+<!--#include file="header.html" -->
+
+<h3>Related Sites</h3>
+
+<br><a href="http://uclibc.org/">uClibc.org</a>
+<br><a href="http://cxx.uclibc.org/">uClibc++</a>
+<br><a href="http://udhcp.busybox.net/">udhcp</a>
+<br><a href="http://buildroot.uclibc.org/">buildroot</a>
+<br><a href="http://www.scratchbox.org/">Scratchbox</a>
+<br><a href="http://openembedded.org/">OpenEmbedded</a>
+<br><a href="http://www.ucdot.org/">uCdot</a>
+<br><a href="http://www.linuxdevices.com">LinuxDevices</a>
+<br><a href="http://slashdot.org/">Slashdot</a>
+<br><a href="http://freshmeat.net/">Freshmeat</a>
+<br><a href="http://linuxtoday.com/">Linux Today</a>
+<br><a href="http://lwn.net/">Linux Weekly News</a>
+<br><a href="http://www.tldp.org/HOWTO">Linux HOWTOs</a>
+
+<!--#include file="footer.html" -->

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/lists.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/lists.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/lists.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,46 @@
+<!--#include file="header.html" -->
+
+
+<!-- Begin Introduction section -->
+
+<h3>Mailing List Information</h3>
+BusyBox has a <a href="/lists/busybox/">mailing list</a> for discussion and
+development.  You can subscribe by visiting
+<a href="http://busybox.net/mailman/listinfo/busybox">this page</a>.
+Only subscribers to the BusyBox mailing list are allowed to post
+to this list.
+
+<p>
+There is also a mailing list for <a href="/lists/busybox-cvs/">active developers</a>
+wishing to read the complete diff of each and every change to busybox -- not for the
+faint of heart.  Active developers can subscribe by visiting
+<a href="http://busybox.net/mailman/listinfo/busybox-cvs">this page</a>.
+The Subversion server is the only one permtted to post to this list.  And yes,
+this list name uses the word 'cvs' even though we don't use that anymore...
+
+<p>
+
+
+<h3>Search the List Archives</h3>
+Please search the mailing list archives before asking questions on the mailing
+list, since there is a good chance someone else has asked the same question
+before.  Checking the archives is a great way to avoid annoying everyone on the
+list with frequently asked questions...
+<p>
+
+<center>
+<form method="GET" action="http://www.google.com/custom">
+<input type="hidden" name="domains" value="busybox.net">
+<input type="hidden" name="sitesearch" value="busybox.net">
+<input type="text" name="q" size="31" maxlength="255" value="">
+<br>
+<input type="submit" name="sa" value="search the mailing list archives">
+<br>
+<a href="http://www.google.com"><img src="http://www.google.com/logos/Logo_25wht.gif" border="0" alt="Google" height="32" width="75" align="middle"></a>
+<br>
+</form>
+</center>
+
+
+
+<!--#include file="footer.html" -->

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/news.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/news.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/news.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,85 @@
+<!--#include file="header.html" -->
+
+
+<ul>
+  <li><b>30 June 2006 -- BusyBox 1.2.0</b>
+    <p>The -devel branch has been stabilized and the result is
+    <a href="http://busybox.net/downloads/busybox-1.2.0.tar.bz2">Busybox
+    1.2.0</a>.  Lots of stuff changed, I need to work up a decent changelog
+    over the weekend.</p>
+
+    <p>I'm still experimenting with how long is best for the development
+    cycle, and since we've got some largeish projects queued up I'm going to
+    try a longer one.  Expect 1.3.0 in December.  (Expect 1.2.1 any time
+    we fix enough bugs. :)</p>
+
+  <li><b>17 May 2006 -- BusyBox 1.1.3 (stable)</b>
+    <p><a href="http://busybox.net/downloads/busybox-1.1.3.tar.bz2">BusyBox
+    1.1.3</a> is another bugfix release.  It makes passwd use salt, fixes a
+    memory freeing bug in ls, fixes "build all sources at once" mode, makes
+    mount -a not abort on the first failure, fixes msh so ctrl-c doesn't kill
+    background processes, makes patch work with patch hunks that don't have a
+    timestamp, make less's text search a lot more robust (the old one could
+    segfault), and fixes readlink -f when built against uClibc.</p>
+
+    <p>Expect 1.2.0 sometime next month, which won't be a bugfix release.</p>
+
+  <li><b>10 April 2006 -- BusyBox 1.1.2 (stable)</b>
+    <p>You can now download <a href="http://busybox.net/downloads/busybox-1.1.2.tar.bz2">BusyBox 1.1.2</a>, a bug fix release consisting of 11 patches
+    backported from the development branch: Some build fixes, several fixes
+    for mount and nfsmount, a fix for insmod on big endian systems, a fix for
+    find -xdev, and a fix for comm.  Check the file "changelog" in the tarball
+    for more info.</p>
+
+    <p>The next new development release (1.2.0) is slated for June.  A 1.1.3
+    will be released before then if more bug fixes crop up.  (The new plan is
+    to have a 1.x.0 new development release every 3 months, with 1.x.y stable
+    bugfix only releases based on that as appropriate.)</p>
+    
+  <li><b>27 March 2006 -- Software Freedom Law Center representing BusyBox and uClibc</b>
+    <p>One issue Erik Andersen wanted to resolve when handing off BusyBox
+    maintainership to Rob Landley was license enforcement.  BusyBox and
+    uClibc's existing license enforcement efforts (pro-bono representation
+    by Erik's father's law firm, and the
+    <a href="http://www.busybox.net/shame.html">Hall of Shame</a>), haven't
+    scaled to match the popularity of the projects.  So we put our heads
+    together and did the obvious thing: ask Pamela Jones of
+    <a href="http://www.groklaw.net">Groklaw</a> for suggestions.  She
+    referred us to the fine folks at softwarefreedom.org.</p>
+
+    <p>As a result, we're pleased to announce that the
+    <a href="http://www.softwarefreedom.org">Software Freedom Law Center</a>
+    has agreed to represent BusyBox and uClibc.  We join a number of other
+    free and open source software projects (such as
+    <a href="http://lwn.net/Articles/141806/">X.org</a>,
+    <a href="http://lwn.net/Articles/135413/">Wine</a>, and
+    <a href="http://plone.org/foundation/newsitems/software-freedom-law-center-support/">Plone</a>
+    in being represented by a fairly cool bunch of lawyers, which is not a
+    phrase you get to use every day.</p>
+
+  <li><b>22 March 2006 -- BusyBox 1.1.1</b>
+    <p>The new maintainer is Rob Landley, and the new release is <a href="http://busybox.net/downloads/busybox-1.1.1.tar.bz2">BusyBox 1.1.1</a>.  Expect a "what's new" document in a few days.  (Also, Erik and I have have another announcement pending...)</p>
+    <p>Update: Rather than put out an endless stream of 1.1.1.x releases,
+    the various small fixes have been collected together into a
+    <a href="http://busybox.net/downloads/busybox-1.1.1.fixes.patch">patch</a>,
+    and new fixes will be appended to that as needed.  Expect 1.1.2 around
+    June.</p>
+  </li>
+  <li><b>11 January 2006 -- 1.1.0 is out</b>
+    <p>The new stable release is
+    <a href="http://www.busybox.net/downloads/busybox-1.1.0.tar.bz2">BusyBox
+    1.1.0</a>.  It has a number of improvements, including several new applets.
+    (It also has <a href="http://www.busybox.net/lists/busybox/2006-January/017733.html">a few rough spots</a>,
+    but we're trying out a "release early, release often" strategy to see how
+    that works.  Expect 1.1.1 sometime in March.)</p>
+
+    <li><b>Old News</b><p>
+    <a href="/oldnews.html">Click here to read older news</a>
+    </p>
+    </li>
+
+
+</ul>
+
+<!--#include file="footer.html" -->
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/oldnews.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/oldnews.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/oldnews.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1140 @@
+<!--#include file="header.html" -->
+
+
+<ul>
+  <li><b>31 October 2005 -- 1.1.0-pre1</b>
+    <p>The development branch of busybox is stable enough for wider testing, so
+    you can now 
+    <a href="http://www.busybox.net/downloads/busybox-1.1.0-pre1.tar.bz2">download</a>,
+    the first prerelease of 1.1.0.  This prerelease includes a lot of
+    <a href="http://www.busybox.net/downloads/BusyBox.html">new
+    functionality</a>: new applets, new features, and extensive rewrites of
+    several existing applets.  This prerelease should be noticeably more
+    <a href="http://www.opengroup.org/onlinepubs/009695399/">standards
+    compliant</a> than earlier versions of busybox, although we're
+    still working out the <a href="http://bugs.busybox.net">bugs</a>.</p>
+
+  <li><b>16 August 2005 -- 1.01 is out</b>
+
+    <p>A new stable release (<a href="http://www.busybox.net/downloads/busybox-1.01.tar.bz2">BusyBox
+    1.01</a>) is now available for download, containing over a hundred
+    <a href="http://www.busybox.net/lists/busybox/2005-August/015424.html">small
+    fixes</a> that have cropped up since the 1.00 release.</p>
+
+  <li><b>13 January 2005 -- Bug and Patch Tracking</b><p>
+
+    Bug reports sometimes get lost when posted to the mailing list.  The
+    developers of BusyBox are busy people, and have only so much they can keep
+    in their brains at a time. In my case, I'm lucky if I can remember my own
+    name, much less a bug report posted last week... To prevent your bug report
+    from getting lost, if you find a bug in BusyBox, please use the 
+    <a href="http://bugs.busybox.net/">shiny new Bug and Patch Tracking System</a>
+    to post all the gory details.
+
+    <p>
+
+    The same applies to patches... Regardless of whether your patch
+    is a bug fix or adds spiffy new features, please post your patch
+    to the Bug and Patch Tracking System to make certain it is
+    properly considered.
+
+
+  <p>
+  <li><b>13 October 2004 -- BusyBox 1.00 released</b><p>
+
+    When you take a careful look at nearly every embedded Linux device or
+    software distribution shipping today, you will find a copy of BusyBox.
+    With countless routers, set top boxes, wireless access points, PDAs, and
+    who knows what else, the future for Linux and BusyBox on embedded devices
+    is looking very bright.
+
+    <p>
+
+    It is therefore with great satisfaction that I declare each and every
+    device already shipping with BusyBox is now officially out of date.
+    The highly anticipated release of BusyBox 1.00 has arrived!
+
+    <p>
+
+    Over three years in development, BusyBox 1.00 represents a tremendous
+    improvement over the old 0.60.x stable series.  Now featuring a Linux
+    KernelConf based configuration system (as used by the Linux kernel),
+    Linux 2.6 kernel support, many many new applets, and the development
+    work and testing of thousands of people from around the world.
+
+    <p>
+
+    If you are already using BusyBox, you are strongly encouraged to upgrade to
+    BusyBox 1.00.  If you are considering developing an embedded Linux device
+    or software distribution, you may wish to investigate if using BusyBox is
+    right for your application.  If you need help getting started using
+    BusyBox, if you wish to donate to help cover expenses, or if you find a bug
+    and need help reporting it, you are invited to visit the <a
+    href="FAQ.html">BusyBox FAQ</a>.
+
+    <p>
+
+    As usual you can <a href="downloads">download busybox here</a>.
+
+    <p>Have Fun!
+
+    <p>
+    <li><b>Old News</b><p>
+    <a href="/oldnews.html">Click here to read older news</a>
+
+
+  <li><b>16 August 2004 -- BusyBox 1.0.0-rc3 released</b><p>
+
+    Here goes release candidate 3...
+    <p>
+    The <a href="downloads/Changelog">changelog</a> has all the details.
+    And as usual you can <a href="downloads">download busybox here</a>.
+
+    <p>Have Fun!
+
+  <p>
+  <li><b>26 July 2004 -- BusyBox 1.0.0-rc2 released</b><p>
+
+    Here goes release candidate 2...
+    <p>
+    The <a href="downloads/Changelog">changelog</a> has all the details.
+    And as usual you can <a href="downloads">download busybox here</a>.
+
+    <p>Have Fun!
+
+  <p>
+  <li><b>20 July 2004 -- BusyBox 1.0.0-rc1 released</b><p>
+
+    Here goes release candidate 1...  This fixes all (most?) of the problems
+    that have turned up since -pre10.  In particular, loading and unloading of
+    kernel modules with 2.6.x kernels should be working much better.
+    <p>
+
+    I <b>really</b> want to get BusyBox 1.0.0 released soon and I see no real
+    reason why the 1.0.0 release shouldn't happen with things pretty much as
+    is.  BusyBox is in good shape at the moment, and it works nicely for
+    everything that I'm doing with it.  And from the reports I've been getting,
+    it works nicely for what most everyone else is doing with it as well.
+    There will eventually be a 1.0.1 anyway, so we might as well get on with
+    it.  No, BusyBox is not perfect.  No piece of software ever is.  And while
+    there is still plenty that can be done to improve things, most of that work
+    is waiting till we can get a solid 1.0.0 release out the door....
+    <p>
+
+    Please do not bother to send in patches adding cool new features at this
+    time.  Only bug-fix patches will be accepted.  If you have submitted a
+    bug-fixing patch to the busybox mailing list and no one has emailed you
+    explaining why your patch was rejected, it is safe to say that your patch
+    has been lost or forgotten.  That happens sometimes.  Please re-submit your
+    bug-fixing patch to the BusyBox mailing list, and be sure to put "[PATCH]"
+    at the beginning of the email subject line!
+
+    <p>
+    The <a href="downloads/Changelog">changelog</a> has all the details.
+    And as usual you can <a href="downloads">download busybox here</a>.
+
+    <p>Have Fun!
+
+    <p>
+    On a less happy note, My 92 year old grandmother (my dad's mom) passed away
+    yesterday (June 19th).  The funeral will be Thursday in a little town about
+    2 hours south of my home.  I've checked and there is absolutely no way I
+    could be back in time for the funeral if I attend <a
+    href="http://www.linuxsymposium.org/2004/">OLS</a> and give my presentation
+    as scheduled.
+    <p>
+    As such, it is with great reluctance and sadness that I have come
+    to the conclusion I will have to make my appologies and skip OLS
+    this year.
+    <p>
+
+
+  <p>
+  <li><b>13 April 2004 -- BusyBox 1.0.0-pre10 released</b><p>
+
+    Ok, I lied.  It turns out that -pre9 will not be the final BusyBox
+    pre-release.  With any luck however -pre10 will be, since I <b>really</b>
+    want to get BusyBox 1.0.0 released very soon.  As usual, please do not
+    bother to send in patches adding cool new features at this time.  Only
+    bug-fix patches will be accepted.  It would also be <b>very</b> helpful if
+    people could continue to review the BusyBox documentation and submit
+    improvements.
+
+    <p>
+    The <a href="downloads/Changelog">changelog</a> has all the details.
+    And as usual you can <a href="downloads">download busybox here</a>.
+
+    <p>Have Fun!
+    <p>
+
+
+  <p>
+  <li><b>6 April 2004 -- BusyBox 1.0.0-pre9 released</b><p>
+
+    Here goes the final BusyBox pre-release...  This is your last chance for
+    bug fixes.  With luck this will be released as BusyBox 1.0.0 later this
+    week.  Please do not bother to send in patches adding cool new features at
+    this time.  Only bug-fix patches will be accepted.  It would also be
+    <b>very</b> helpful if people could help review the BusyBox documentation
+    and submit improvements.  I've spent a lot of time updating the
+    documentation to make it better match reality, but I could really use some
+    assistance in checking that the features supported by the various applets
+    match the features listed in the documentation.
+
+    <p>
+    I had hoped to get this released a month ago, but
+    <a href="http://codepoet.org/gallery/baby_peter/img_1796">
+    another release on 1 March 2004</a> has kept me busy...
+
+    <p>
+    The <a href="downloads/Changelog">changelog</a> has all the details.
+    And as usual you can <a href="downloads">download busybox here</a>.
+
+    <p>Have Fun!
+    <p>
+
+
+  <p>
+  <li><b>23 February 2004 -- BusyBox 1.0.0-pre8 released</b><p>
+
+    Here goes yet another BusyBox pre-release...  Please do not bother to send
+    in patches supplying new features at this time.  Only bug-fix patches will
+    be accepted.  If you have a cool new feature you would like to see
+    supported, or if you have an amazing new applet you would like to submit,
+    please wait and submit such things later.  We really want to get a release
+    out we can all be proud of.  We are still aiming to finish off the -pre
+    series in February and move on to the final 1.0.0 release...  So if you
+    spot any bugs, now would be an excellent time to send in a fix to the
+    busybox mailing list.  It would also be <b>very</b> helpful if people could
+    help review the BusyBox documentation and submit improvements.  It would be
+    especially helpful if people could check that the features supported by the
+    various applets match the features listed in the documentation.
+
+    <p>
+
+    The <a href="downloads/Changelog">changelog</a> has all the details.
+    And as usual you can <a href="downloads">download busybox here</a>.
+
+    <p>Have Fun!
+    <p>
+
+
+  <li><b>4 February 2004 -- BusyBox 1.0.0-pre7 released</b><p>
+
+    There was a bug in -pre6 that broke argument parsing for a
+    number of applets, since a variable was not being zeroed out
+    properly.  This release is primarily intended to fix that one
+    problem.  In addition, this release fixes several other
+    problems, including a rewrite by mjn3 of the code for parsing
+    the busybox.conf file used for suid handling, some shell updates
+    from vodz, and a scattering of other small fixes.  We are still
+    aiming to finish off the -pre series in February and move on to
+    the final 1.0.0 release...  If you see any problems, of have
+    suggestions to make, as always, please feel free to email the
+    busybox mailing list.
+
+    <p>
+
+    The <a href="downloads/Changelog">changelog</a> has all
+    the details.  And as usual you can
+    <a href="downloads">download busybox here</a>.
+
+    <p>Have Fun!
+    <p>
+
+
+  <p>
+  <li><b>30 January 2004 -- BusyBox 1.0.0-pre6 released</b><p>
+
+    Here goes the next pre-release for the new BusyBox stable
+    series.  This release adds a number of size optimizations,
+    updates udhcp, fixes up 2.6 modutils support, updates ash
+    and the shell command line editing, and the usual pile of
+    bug fixes both large and small.  Things appear to be
+    settling down now, so with a bit of luck and some testing
+    perhaps we can finish off the -pre series in February and
+    move on to the final 1.0.0 release...  If you see any
+    problems, of have suggestions to make, as always, please
+    feel free to email the busybox mailing list.
+
+    <p>
+
+    People who rely on the <a href= "downloads/snapshots/">daily BusyBox snapshots</a>
+    should be aware that snapshots of the old busybox 0.60.x
+    series are no longer available.  Daily snapshots are now
+    only available for the BusyBox 1.0.0 series and now use
+    the naming scheme "busybox-<date>.tar.bz2".  Please
+    adjust any build scripts using the old naming scheme accordingly.
+
+    <p>
+
+    The <a href="downloads/Changelog">changelog</a> has all
+    the details.  And as usual you can
+    <a href="downloads">download busybox here</a>.
+
+    <p>Have Fun!
+    <p>
+
+
+  <p>
+  <li><b>23 December 2003 -- BusyBox 1.0.0-pre5 released</b><p>
+
+    Here goes the next pre-release for the new BusyBox stable
+    series.  The most obvious thing in this release is a fix for
+    a terribly stupid bug in mount that prevented it from working
+    properly unless you specified the filesystem type.  This
+    release also fixes a few compile problems, updates udhcp,
+    fixes a silly bug in fdisk, fixes ifup/ifdown to behave like
+    the Debian version, updates devfsd, updates the 2.6.x
+    modutils support, add a new 'rx' applet, removes the obsolete
+    'loadacm' applet, fixes a few tar bugs, fixes a sed bug, and
+    a few other odd fixes.
+
+    <p>
+
+    If you see any problems, of have suggestions to make, as
+    always, please feel free to send an email to the busybox
+    mailing list.
+
+    <p>
+
+    The <a href="downloads/Changelog">changelog</a> has all
+    the details.  And as usual you can
+    <a href="downloads">download busybox here</a>.
+
+    <p>Have Fun!
+    <p>
+
+
+
+  <li><b>10 December 2003 -- BusyBox 1.0.0-pre4 released</b><p>
+
+    Here goes the fourth pre-release for the new BusyBox stable
+    series.  This release includes major rework to sed, lots of
+    rework on tar, a new tiny implementation of bunzip2, a new
+    devfsd applet, support for 2.6.x kernel modules, updates to
+    the ash shell, sha1sum and md5sum have been merged into a
+    common applet, the dpkg applets has been cleaned up, and tons
+    of random bugs have been fixed.  Thanks everyone for all the
+    testing, bug reports, and patches!  Once again, a big
+    thank-you goes to Glenn McGrath (bug1) for stepping in and
+    helping get patches merged!
+
+    <p>
+
+    And of course, if you are reading this, you might have noticed
+    the busybox website has been completely reworked.  Hopefully
+    things are now somewhat easier to navigate...  If you see any
+    problems, of have suggestions to make, as always, please feel
+    free to send an email to the busybox mailing list.
+
+    <p>
+
+    The <a href="downloads/Changelog">changelog</a> has all
+    the details.  And as usual you can
+    <a href="downloads">download busybox here</a>.
+
+    <p>Have Fun!
+
+
+
+  <p>
+  <li><b>12 Sept 2003 -- BusyBox 1.0.0-pre3 released</b><p>
+
+    Here goes the third pre-release for the new BusyBox stable
+    series.  The last prerelease has held up quite well under
+    testing, but a number of problems have turned up as the number
+    of people using it has increased.  Thanks everyone for all
+    the testing, bug reports, and patches!
+
+    <p>
+
+    If you have submitted a patch or a bug report to the busybox
+    mailing list and no one has emailed you explaining why your
+    patch was rejected, it is safe to say that your patch has
+    somehow gotten lost or forgotten.  That happens sometimes.
+    Please re-submit your patch or bug report to the BusyBox
+    mailing list!
+
+    <p>
+
+    The point of the "-preX" versions is to get a larger group of
+    people and vendors testing, so any problems that turn up can be
+    fixed prior to the final 1.0.0 release.  The main feature
+    (besides additional testing) that is still still on the TODO
+    list before the final BusyBox 1.0.0 release is sorting out the
+    modutils issues.  For the new 2.6.x kernels, we already have
+    patches adding insmod and rmmod support and those need to be
+    integrated.  For 2.4.x kernels, for which busybox only supports
+    a limited number of architectures, we may want to invest a bit
+    more work before we cut 1.0.0.  Or we may just leave 2.4.x
+    module loading alone.
+
+    <p>
+
+    I had hoped this release would be out a month ago.  And of
+    course, it wasn't since Erik became busy getting a release of
+    <a href="http://www.uclibc.org/">uClibc</a>
+    out the door.  Many thanks to Glenn McGrath (bug1) for
+    stepping in and helping get a bunch of patches merged!  I am
+    not even going to state a date for releasing BusyBox 1.0.0
+    -pre4 (or the final 1.0.0).  We're aiming for late September...
+    But if this release proves as to be exceptionally stable (or
+    exceptionally unstable!), the next release may be very soon
+    indeed.
+
+    <p>
+
+    The <a href="downloads/Changelog">changelog</a> has all
+    the details.  And as usual you can
+    <a href="downloads">download busybox here</a>.
+
+    <p>Have Fun!
+
+
+    <p>
+    <li><b>30 July 2003 -- BusyBox 1.0.0-pre2 released</b><p>
+
+    Here goes another pre release for the new BusyBox stable
+    series.  The last prerelease (pre1) was given quite a lot of
+    testing (thanks everyone!) which has helped turn up a number of
+    bugs, and these problems have now been fixed.
+
+    <p>
+
+    Highlights of -pre2 include updating the 'ash' shell to sync up
+    with the Debian 'dash' shell, a new 'hdparm' applet was added,
+    init again supports pivot_root,  The 'reboot' 'halt' and
+    'poweroff' applets can now be used without using busybox init.
+    an ifconfig buffer overflow was fixed, losetup now allows
+    read-write loop devices, uClinux daemon support was added, the
+    'watchdog', 'fdisk', and 'kill' applets were rewritten, there were
+    tons of doc updates, and there were many other bugs fixed.
+    <p>
+
+    If you have submitted a patch and it is not included in this
+    release and Erik has not emailed you explaining why your patch
+    was rejected, it is safe to say that he has lost your patch.
+    That happens sometimes.   Please re-submit your patch to the
+    BusyBox mailing list.
+    <p>
+
+    The point of the "-preX" versions is to get a larger group of
+    people and vendors testing, so any problems that turn up can be
+    fixed prior to the final 1.0.0 release.  The main feature that
+    is still still on the TODO list before the final BusyBox 1.0.0
+    release is adding module support for the new 2.6.x kernels.  If
+    necessary, a -pre3 BusyBox release will happen on August 6th.
+    Hopefully (i.e.  unless some horrible catastrophic problem
+	    turns up) the final BusyBox 1.0.0 release will be ready by
+    then...
+    <p>
+
+    The <a href="downloads/Changelog">changelog</a> has all
+    the details.  As usual you can <a href="downloads">download busybox here</a>.
+
+    <p>Have Fun!
+    <p>
+
+    <p>
+  <li><b>15 July 2003 -- BusyBox 1.0.0-pre1 released</b><p>
+
+    The busybox development series has been under construction for
+    nearly two years now.  Which is just entirely too long...  So
+    it is with great pleasure that I announce the imminent release
+    of a new stable series.  Due to the huge number of changes
+    since the last stable release (and the usual mindless version
+    number inflation) I am branding this new stable series verison
+    1.0.x...
+    <p>
+
+    The point of "-preX" versions is to get a larger group of
+    people and vendors testing, so any problems that turn up can be
+    fixed prior to the magic 1.0.0 release (which should happen
+    later this month)...  I plan to release BusyBox 1.0.0-pre2 next
+    Monday (July 21st), and, if necessary, -pre3 on July 28th.
+    Hopefully (i.e. unless some horrible catastrophic problem turns
+    up) the final BusyBox 1.0.0 release should be ready by the end
+    of July.
+    <p>
+
+    If you have submitted patches, and they are not in this release
+    and I have not emailed you explaining why your patch was
+    rejected, it is safe to say that I have lost your patch.  That
+    happens sometimes.  Please do <B>NOT</b> send all your patches,
+    support questions, etc, directly to Erik.  I get hundreds of
+    emails every day (which is why I end up losing patches
+    sometimes in the flood)...  The busybox mailing list is the
+    right place to send your patches, support questions, etc.
+    <p>
+
+    I would like to especially thank Vladimir Oleynik (vodz), Glenn
+    McGrath (bug1), Robert Griebl (sandman), and Manuel Novoa III
+    (mjn3) for their significant efforts and contributions that
+    have made this release possible.
+    <p>
+
+    As usual you can <a href="downloads">download busybox here</a>.
+    You don't really need to bother with the
+    <a href="downloads/Changelog">changelog</a>, as the changes
+    vs the stable version are way too extensive to easily enumerate.
+    But you can take a look if you really want too.
+
+    <p>Have Fun!
+    <p>
+
+
+
+  <p>
+  <li><b>26 October 2002 -- BusyBox 0.60.5 released</b><p>
+
+    I am very pleased to announce that the BusyBox 0.60.5 (stable)
+    is now available for download.  This is a bugfix release for
+    the stable series to address all the problems that have turned
+    up since the last release.  Unfortunately, the previous release
+    had a few nasty bugs (i.e. init could deadlock, gunzip -c tried
+    to delete source files, cp -a wouldn't copy symlinks, and init
+    was not always providing controlling ttys when it should have).
+    I know I said that the previous release would be the end of the
+    0.60.x series.  Well, it turns out I'm a liar.  But this time I
+    mean it (just like last time ;-).  This will be the last
+    release for the 0.60.x series --  all further development work
+    will be done for the development busybox tree.  Expect the development
+    version to have its first real release very very soon now...
+
+    <p>
+    The <a href="downloads/Changelog.full">changelog</a> has all
+    the details.  As usual you can <a href="downloads">download busybox here</a>.
+    <p>Have Fun!
+    <p>
+
+  <p>
+  <li><b>18 September 2002 -- BusyBox 0.60.4 released</b><p>
+
+    I am very pleased to announce that the BusyBox 0.60.4
+    (stable) is now available for download.  This is primarily
+    a bugfix release for the stable series to address all
+    the problems that have turned up since the last
+    release.  This will be the last release for the 0.60.x series.
+    I mean it this time --  all further development work will be done
+    on the development busybox tree, which is quite solid now and
+    should soon be getting its first real release.
+
+    <p>
+    The <a href="downloads/Changelog.full">changelog</a> has all
+    the details.  As usual you can <a href="downloads">download busybox here</a>.
+    <p>Have Fun!
+    <p>
+
+
+  <p>
+  <li><b>27 April 2002 -- BusyBox 0.60.3 released</b><p>
+
+    I am very pleased to announce that the BusyBox 0.60.3 (stable) is
+    now available for download.  This is primarily a bugfix release
+    for the stable series.  A number of problems have turned up since
+    the last release, and this should address most of those problems.
+    This should be the last release for the 0.60.x series.  The
+    development busybox tree has been progressing nicely, and will
+    hopefully be ready to become the next stable release.
+
+    <p>
+    The <a href="downloads/Changelog">changelog</a> has all
+    the details.  As usual you can <a href="downloads">download busybox here</a>.
+    <p>Have Fun!
+    <p>
+
+
+  <p>
+  <li><b>6 March 2002 -- busybox.net now has mirrors!</b><p>
+
+    Busybox.net is now much more available, thanks to
+    the fine folks at <a href= "http://i-netinnovations.com/">http://i-netinnovations.com/</a>
+    who are providing hosting for busybox.net and
+    uclibc.org.  In addition, we now have two mirrors:
+    <a href= "http://busybox.linuxmagic.com/">http://busybox.linuxmagic.com/</a>
+    in Canada and
+    <a href= "http://busybox.csservers.de/">http://busybox.csservers.de/</a>
+    in Germany.  I hope this makes things much more
+    accessible for everyone!
+
+
+<li>
+<b>3 January 2002 -- Welcome to busybox.net!</b>
+
+<p>Thanks to the generosity of a number of busybox
+users, we have been able to purchase busybox.net
+(which is where you are probably reading this).
+Right now, busybox.net and uclibc.org are both
+living on my home system (at the end of my DSL
+line). I apologize for the abrupt move off of
+busybox.lineo.com. Unfortunately, I no longer have
+the access needed to keep that system updated (for
+example, you might notice the daily snapshots there
+stopped some time ago).</p>
+
+<p>Busybox.net is currently hosted on my home
+server, at the end of a DSL line. Unfortunately,
+the load on them is quite heavy. To address this,
+I'm trying to make arrangements to get busybox.net
+co-located directly at an ISP. To assist in the
+co-location effort, <a href=
+"http://www.codepoet.org/~markw">Mark Whitley</a>
+(author of busybox sed, cut, and grep) has donated
+his <a href=
+"http://www.netwinder.org/">NetWinder</a> computer
+for hosting busybox.net and uclibc.org. Once this
+system is co-located, the current speed problems
+should be completely eliminated. Hopefully, too,
+some of you will volunteer to set up some mirror
+sites, to help to distribute the load a bit.</p>
+
+<p><!--
+    <center>
+    Click here to help support busybox.net!
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+    <input type="hidden" name="cmd" value="_xclick">
+    <input type="hidden" name="business" value="andersen at codepoet.org">
+    <input type="hidden" name="item_name" value="Support Busybox">
+    <input type="hidden" name="image_url" value="https://codepoet-consulting.com/images/busybox2.jpg">
+    <input type="hidden" name="no_shipping" value="1">
+    <input type="image" src="images/donate.png" border="0" name="submit" alt="Make donation using PayPal">
+    </form>
+    </center>
+    -->
+ Since some people expressed concern over BusyBox
+donations, let me assure you that no one is getting
+rich here. All BusyBox and uClibc donations will be
+spent paying for bandwidth and needed hardware
+upgrades. For example, Mark's NetWinder currently
+has just 64Meg of memory. As demonstrated when
+google spidered the site the other day, 64 Megs in
+not enough, so I'm going to be ordering 256Megs of
+ram and a larger hard drive for the box today. So
+far, donations received have been sufficient to
+cover almost all expenses. In the future, we may
+have co-location fees to worry about, but for now
+we are ok. A <b>HUGE thank-you</b> goes out to
+everyone that has contributed!<br>
+ -Erik</p>
+</li>
+
+<li>
+<b>20 November 2001 -- BusyBox 0.60.2 released</b>
+
+<p>We am very pleased to announce that the BusyBox
+0.60.2 (stable) is now released to the world. This
+one is primarily a bugfix release for the stable
+series, and it should take care of most everyone's
+needs till we can get the nice new stuff we have
+been working on in CVS ready to release (with the
+wonderful new buildsystem). The biggest change in
+this release (beyond bugfixes) is the fact that msh
+(the minix shell) has been re-worked by Vladimir N.
+Oleynik (vodz) and so it no longer crashes when
+told to do complex things with backticks.</p>
+
+<p>This release has been tested on x86, ARM, and
+powerpc using glibc 2.2.4, libc5, and uClibc, so it
+should work with just about any Linux system you
+throw it at. See the <a href=
+"downloads/Changelog">changelog</a> for <small>most
+of</small> the details. The last release was
+<em>very</em> solid for people, and this one should
+be even better.</p>
+
+<p>As usual BusyBox 0.60.2 can be downloaded from
+<a href=
+"downloads">http://www.busybox.net/downloads</a>.</p>
+
+<p>Have Fun.<br>
+ -Erik</p>
+</li>
+
+<li> <b>18 November 2001 -- Help us buy busybox.net!</b>
+
+<!-- Begin PayPal Logo -->
+<center>
+Click here to help buy busybox.net!
+<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+<input type="hidden" name="cmd" value="_xclick">
+<input type="hidden" name="business" value="andersen at codepoet.org">
+<input type="hidden" name="item_name" value="Support Busybox">
+<input type="hidden" name="image_url" value="https://busybox.net/images/busybox2.jpg">
+<input type="hidden" name="no_shipping" value="1">
+<input type="image" src="images/donate.png" border="0" name="submit" alt="Make donation using PayPal">
+</form>
+</center>
+<!-- End PayPal Logo -->
+
+I've contacted the current owner of busybox.net and he is willing
+to sell the domain name -- for $250.  He also owns busybox.org but
+will not part with it...  I will then need to pay the registry fee
+for a couple of years and start paying for bandwidth, so this will
+initially cost about $300.  I would like to host busybox.net on my
+home machine (codepoet.org) so I have full control over the system,
+but to do that would require that I increase the level of bandwidth
+I am paying for.  Did you know that so far this month, there
+have been over 1.4 Gigabytes of busybox ftp downloads?  I don't
+even <em>know</em> how much CVS bandwidth it requires.  For the
+time being, Lineo has continued to graciously provide this
+bandwidth, despite the fact that I no longer work for them.  If I
+start running this all on my home machine, paying for the needed bandwidth
+will start costing some money.
+<p>
+
+I was going to pay it all myself, but my wife didn't like that
+idea at all (big surprise).   It turns out <insert argument
+where she wins and I don't> she has better ideas
+about what we should spend our money on that don't involve
+busybox.  She suggested I should ask for contributions on the
+mailing list and web page.  So...
+<p>
+
+I am hoping that if everyone could contribute a bit, we could pick
+up the busybox.net domain name and cover the bandwidth costs.  I
+know that busybox is being used by a lot of companies as well as
+individuals -- hopefully people and companies that are willing to
+contribute back a bit.  So if everyone could please help out, that
+would be wonderful!
+<p>
+
+
+<li> <b>23 August 2001 -- BusyBox 0.60.1 released</b>
+<br>
+
+     This is a relatively minor bug fixing release that fixes
+     up the bugs that have shown up in the stable release in
+     the last few weeks.  Fortunately, nothing <em>too</em>
+     serious has shown up.  This release only fixes bugs -- no
+     new features, no new applets.  So without further ado,
+     here it is.  Come and get it.
+     <p>
+     The
+     <a href="downloads/Changelog">changelog</a> has all
+     the details.  As usual BusyBox 0.60.1 can be downloaded from
+     <a href="downloads">http://busybox.net/downloads</a>.
+     <p>Have Fun!
+     <p>
+
+
+<li> <b>2 August 2001 -- BusyBox 0.60.0 released</b>
+<br>
+     I am very pleased to announce the immediate availability of
+     BusyBox 0.60.0.  I have personally tested this release with libc5, glibc,
+     and <a href="http://uclibc.org/">uClibc</a> on
+     x86, ARM, and powerpc using linux 2.2 and 2.4, and I know a number
+     of people using it on everything from ia64 to m68k with great success.
+     Everything seems to be working very nicely now, so getting a nice
+     stable bug-free(tm) release out seems to be in order.   This releases fixes
+     a memory leak in syslogd, a number of bugs in the ash and msh shells, and
+     cleans up a number of things.
+
+     <p>
+
+     Those wanting an easy way to test the 0.60.0 release with uClibc can
+     use <a href="http://user-mode-linux.sourceforge.net/">User-Mode Linux</a>
+     to give it a try by downloading and compiling
+     <a href="ftp://busybox.net/buildroot.tar.gz">buildroot.tar.gz</a>.
+     You don't have to be root or reboot your machine to run test this way.
+     Preconfigured User-Mode Linux kernel source is also on busybox.net.
+     <p>
+     Another cool thing is the nifty <a href="downloads/tutorial/index.html">
+     BusyBox Tutorial</a> contributed by K Computing.  This requires
+     a ShockWave plugin (or standalone viewer), so you may want to grab the
+     the GPLed shockwave viewer from <a href="http://www.swift-tools.com/Flash/flash-0.4.10.tgz">here</a>
+     to view the tutorial.
+     <p>
+
+     Finally, In case you didn't notice anything odd about the
+     version number of this release, let me point out that this release
+     is <em>not</em> 0.53, because I bumped the version number up a
+     bit.  This reflects the fact that this release is intended to form
+     a new stable BusyBox release series.  If you need to rely on a
+     stable version of BusyBox, you should plan on using the stable
+     0.60.x series.  If bugs show up then I will release 0.60.1, then
+     0.60.2, etc...  This is also intended to deal with the fact that
+     the BusyBox build system will be getting a major overhaul for the
+     next release and I don't want that to break products that people
+     are shipping.  To avoid that, the new build system will be
+     released as part of a new BusyBox development series that will
+     have some not-yet-decided-on odd version number.  Once things
+     stabilize and the new build system is working for everyone, then
+     I will release that as a new stable release series.
+
+     <p>
+     The
+     <a href="downloads/Changelog">changelog</a> has all
+     the details.  As usual BusyBox 0.60.0 can be downloaded from
+     <a href="downloads">http://busybox.net/downloads</a>.
+     <p>Have Fun!
+     <p>
+
+
+<li> <b>7 July 2001 -- BusyBox 0.52 released</b>
+<br>
+
+     I am very pleased to announce the immediate availability of
+     BusyBox 0.52 (the "new-and-improved rock-solid release").  This
+     release is the result of <em>many</em> hours of work and has tons
+     of bugfixes, optimizations, and cleanups.  This release adds
+     several new applets, including several new shells (such as hush, msh,
+     and ash).
+
+     <p>
+     The
+     <a href="downloads/Changelog">changelog</a> covers
+     some of the more obvious details, but there are many many things that
+     are not mentioned, but have been improved in subtle ways.  As usual,
+     BusyBox 0.52 can be downloaded from
+     <a href="downloads">http://busybox.net/downloads</a>.
+     <p>Have Fun!
+     <p>
+
+
+<li> <b>10 April 2001 - Graph of Busybox Growth </b>
+<br>
+The illustrious Larry Doolittle has made a PostScript chart of the growth
+of the Busybox tarball size over time. It is available for downloading /
+viewing <a href= "busybox-growth.ps"> right here</a>.
+
+<p> (Note that while the number of applets in Busybox has increased, you
+can still configure Busybox to be as small as you want by selectively
+turning off whichever applets you don't need.)
+<p>
+
+
+<li> <b>10 April 2001 -- BusyBox 0.51 released</b>
+<br>
+
+     BusyBox 0.51 (the "rock-solid release") is now out there.  This
+     release adds only 2 new applets: env and vi.  The vi applet,
+     contributed by Sterling Huxley, is very functional, and is only
+     22k.  This release fixes 3 critical bugs in the 0.50 release.
+     There were 2 potential segfaults in lash (the busybox shell) in
+     the 0.50 release which are now fixed.  Another critical bug in
+     0.50 which is now fixed: syslogd from 0.50 could potentially
+     deadlock the init process and thereby break your entire system.
+     <p>
+
+     There are a number of improvements in this release as well.  For
+     one thing, the wget applet is greatly improved.  Dmitry Zakharov
+     added FTP support, and Laurence Anderson make wget fully RFC
+     compliant for HTTP 1.1.  The mechanism for including utility
+     functions in previous releases was clumsy and error prone.  Now
+     all utility functions are part of a new libbb library, which makes
+     maintaining utility functions much simpler.  And BusyBox now
+     compiles on itanium systems (thanks to the Debian itanium porters
+     for letting me use their system!).
+     <p>
+     You can read the
+     <a href="downloads/Changelog">changelog</a> for
+     complete details.  BusyBox 0.51 can be downloaded from
+     <a href="downloads">http://busybox.net/downloads</a>.
+     <p>Have Fun!
+     <p>
+
+<li> <b>Busybox Boot-Floppy Image</b>
+
+<p>Because you asked for it, we have made available a <a href=
+"downloads/busybox.floppy.img"> Busybox boot floppy
+image</a>. Here's how you use it:
+
+<ol>
+
+    <li> <a href= "downloads/busybox.floppy.img">
+    Download the image</a>
+
+    <li> dd it onto a floppy like so: <tt> dd if=busybox.floppy.img
+    of=/dev/fd0 ; sync </tt>
+
+    <li> Pop it in a machine and boot up.
+
+</ol>
+
+<p> If you want to look at the contents of the initrd image, do this:
+
+<pre>
+    mount ./busybox.floppy.img /mnt -o loop -t msdos
+    cp /mnt/initrd.gz /tmp      
+    umount /mnt
+    gunzip /tmp/initrd.gz
+    mount /tmp/initrd /mnt -o loop -t minix
+</pre>
+
+
+<li> <b>15 March 2001 -- BusyBox 0.50 released</b>
+<br>
+
+     This release adds several new applets including ifconfig, route, pivot_root, stty,
+     and tftp, and also fixes tons of bugs.  Tab completion in the
+     shell is now working very well, and the shell's environment variable
+     expansion was fixed.   Tons of other things were fixed or made
+     smaller.  For a fairly complete overview, see the
+     <a href="downloads/Changelog">changelog</a>.
+     <p>
+     lash (the busybox shell) is still with us, fixed up a bit so it
+     now behaves itself quite nicely.  It really is quite usable as
+     long as you don't expect it to provide Bourne shell grammer.
+     Standard things like pipes, redirects, command line editing, and
+     environment variable expansion work great.  But we have found that
+     this shell, while very usable, does not provide an extensible
+     framework for adding in full Bourne shell behavior.  So the first order of
+     business as we begin working on the next BusyBox release will be to merge in the new shell
+     currently in progress at
+     <a href="http://doolittle.faludi.com/~larry/parser.html">Larry Doolittle's website</a>.
+     <p>
+
+
+<li> <b>27 January 2001 -- BusyBox 0.49 released</b>
+<br>
+
+     Several new applets, lots of bug fixes, cleanups, and many smaller
+     things made nicer.  Several cleanups and improvements to the shell.
+     For a list of the most interesting changes
+     you might want to look at the <a href="downloads/Changelog">changelog</a>.
+     <p>
+     Special thanks go out to Matt Kraai and Larry Doolittle for all their
+     work on this release, and for keeping on top of things while I've been
+     out of town.
+     <p>
+     <em>Special Note</em><br>
+
+     BusyBox 0.49 was supposed to have replaced lash, the BusyBox
+     shell, with a new shell that understands full Bourne shell/Posix shell grammer.
+     Well, that simply didn't happen in time for this release.  A new
+     shell that will eventually replace lash is already under
+     construction.  This new shell is being developed by Larry
+     Doolittle, and could use all of our help.  Please see the work in
+     progress on <a href="http://doolittle.faludi.com/~larry/parser.html">Larry's website</a>
+     and help out if you can.  This shell will be included in the next
+     release of BusyBox.
+     <p>
+
+<li> <b>13 December 2000 -- BusyBox 0.48 released</b>
+<br>
+
+     This release fixes lots and lots of bugs.  This has had some very
+     rigorous testing, and looks very, very clean.  The usual tar
+     update of course: tar no longer breaks hardlinks, tar -xzf is
+     optionally supported, and the LRP folks will be pleased to know
+     that 'tar -X' and 'tar --exclude' are both now in.  Applets are
+     now looked up using a binary search making lash (the busybox
+     shell) much faster.  For the new debian-installer (for Debian
+     woody) a .udeb can now be generated.
+     <p>
+     The curious can get a list of some of the more interesting changes by reading
+     the <a href="downloads/Changelog">changelog</a>.
+     <p>
+     Many thanks go out to the many many people that have contributed to
+     this release, especially Matt Kraai, Larry Doolittle, and Kent Robotti.
+     <p>
+<p> <li> <b>26 September 2000 -- BusyBox 0.47 released</b>
+<br>
+
+     This release fixes lots of bugs (including an ugly bug in 0.46
+     syslogd that could fork-bomb your system).  Added several new
+     apps: rdate, wget, getopt, dos2unix, unix2dos, reset, unrpm,
+     renice, xargs, and expr.  syslogd now supports network logging.
+     There are the usual tar updates.  Most apps now use getopt for
+     more correct option parsing.
+     See the <a href="downloads/Changelog">changelog</a>
+     for complete details.
+
+
+<p> <li> <b>11 July 2000 -- BusyBox 0.46 released</b>
+<br>
+
+     This release fixes several bugs (including a ugly bug in tar,
+     and fixes for NFSv3 mount support).  Added a dumpkmap to allow
+     people to dump a binary keymaps for use with 'loadkmap', and a
+     completely reworked 'grep' and 'sed' which should behave better.
+     BusyBox shell can now also be used as a login shell.
+     See the <a href="downloads/Changelog">changelog</a>
+     for complete details.
+
+
+<p> <li> <b>21 June 2000 -- BusyBox 0.45 released</b>
+<br>
+
+     This release has been slow in coming, but is very solid at this
+     point.  BusyBox now supports libc5 as well as GNU libc.  This
+     release provides the following new apps: cut, tr, insmod, ar,
+     mktemp, setkeycodes, md5sum, uuencode, uudecode, which, and
+     telnet.  There are bug fixes for just about every app as well (see
+     the <a href="downloads/Changelog">changelog</a> for
+     details).
+     <p>
+     Also, some exciting infrastructure news!  Busybox now has its own
+     <a href="lists/busybox/">mailing list</a>,
+     publically browsable
+     <a href="/cgi-bin/viewcvs.cgi/trunk/busybox/">CVS tree</a>,
+     anonymous
+     <a href="cvs_anon.html">CVS access</a>, and
+     for those that are actively contributing there is even
+     <a href="cvs_write.html">CVS write access</a>.
+     I think this will be a huge help to the ongoing development of BusyBox.
+     <p>
+     Also, for the curious, there is no 0.44 release.  Somehow 0.44 got announced
+     a few weeks ago prior to its actually being released.  To avoid any confusion
+     we are just skipping 0.44.
+     <p>
+     Many thanks go out to the many people that have contributed to this release
+     of BusyBox (esp. Pavel Roskin)!
+
+
+<p> <li> <b>19 April 2000 -- syslogd bugfix</b>
+<br>
+Turns out that there was still a bug in busybox syslogd.
+For example, with the following test app:
+<pre>
+#include <syslog.h>
+
+int do_log(char* msg, int delay)
+{
+    openlog("testlog", LOG_PID, LOG_DAEMON);
+    while(1) {
+	syslog(LOG_ERR, "%s: testing one, two, three\n", msg);
+	sleep(delay);
+    }
+    closelog();
+    return(0);
+};
+
+int main(void)
+{
+    if (fork()==0)
+	do_log("A", 2);
+    do_log("B", 3);
+}
+</pre>
+it should be logging stuff from both "A" and "B".  As released in 0.43 only stuff
+from "A" would have been logged.  This means that if init tries to log something
+while say ppp has the syslog open, init would block (which is bad, bad, bad).
+<p>
+Karl M. Hegbloom has created a fix for the problem.
+Thanks Karl!
+
+
+<p> <li> <b>18 April 2000 -- BusyBox 0.43 released (finally!)</b>
+<br>
+I have finally gotten everything into a state where I feel pretty
+good about things.  This is definitely the most stable, solid release
+so far.  A lot of bugs have been fixed, and the following new apps
+have been added: sh, basename, dirname, killall, uptime,
+freeramdisk, tr, echo, test, and usleep.  Tar has been completely
+rewritten from scratch.  Bss size has also been greatly reduced.
+More details are available in the
+<a href="downloads/Changelog">changelog</a>.
+Oh, and as a special bonus, I wrote some fairly comprehensive
+<em>documentation</em>, complete with examples and full usage information.
+
+<p>
+Many thanks go out to the fine people that have helped by submitting patches
+and bug reports; particularly instrumental in helping for this release were
+Karl Hegbloom, Pavel Roskin, Friedrich Vedder, Emanuele Caratti,
+Bob Tinsley, Nicolas Pitre, Avery Pennarun, Arne Bernin, John Beppu, and Jim Gleason.
+There were others so if I somehow forgot to mention you, I'm very sorry.
+<p>
+
+You can grab BusyBox 0.43 tarballs <a href="downloads">here</a>.
+
+<p> <li> <b>9 April 2000 -- BusyBox 0.43 pre release</b>
+<br>
+Unfortunately, I have not yet finished all the things I want to
+do for BusyBox 0.43, so I am posting this pre-release for people
+to poke at.  This contains my complete rewrite of tar, which now weighs in at
+5k (7k with all options turned on) and works for reading and writing
+tarballs (which it does correctly for everything I have been able to throw
+at it).  Tar also (optionally) supports the "--exclude" option (mainly because
+the Linux Router Project folks asked for it).  This also has a pre-release
+of the micro shell I have been writing.  This pre-release should be stable
+enough for production use -- it just isn't a release since I have some structural
+changes I still want to make.
+<p>
+The pre-release can be found <a href="downloads">here</a>.
+Please let me know ASAP if you find <em>any</em> bugs.
+
+<p> <li> <b>28 March 2000 -- Andersen Baby Boy release</b>
+<br>
+I am pleased to announce that on Tuesday March 28th at 5:48pm, weighing in at 7
+lbs. 12 oz, Micah Erik Andersen was born at LDS Hospital here in Salt Lake City.
+He was born in the emergency room less then 5 minutes after we arrived -- and
+it was such a relief that we even made it to the hospital at all.  Despite the
+fact that I was driving at an amazingly unlawful speed and honking at everybody
+and thinking decidedly unkind thoughts about the people in our way, my wife
+(inconsiderate of my feelings and complete lack of medical training) was lying
+down in the back seat saying things like "I think I need to start pushing now"
+(which she then proceeded to do despite my best encouraging statements to the
+contrary).
+<p>
+Anyway, I'm glad to note that despite the much-faster-than-we-were-expecting
+labor, both Shaunalei and our new baby boy are doing wonderfully.
+<p>
+So now that I am done with my excuse for the slow release cycle...
+Progress on the next release of BusyBox has been slow but steady.  I expect
+to have a release sometime during the first week of April.  This release will
+include a number of important changes, including the addition of a shell, a
+re-write of tar (to accommodate the Linux Router Project), and syslogd can now
+accept multiple concurrent connections, fixing lots of unexpected blocking
+problems.
+
+
+<p> <li> <b>11 February 2000 -- BusyBox 0.42 released</b>
+<br>
+
+     This is the most solid BusyBox release so far.  Many, many
+	bugs have been fixed.   See the
+	<a href="downloads/Changelog">changelog</a> for details.
+
+	Of particular interest, init will now cleanly unmount
+	filesystems on reboot, cp and mv have been rewritten and
+	behave much better, and mount and umount no longer leak
+	loop devices.  Many thanks go out to Randolph Chung,
+	Karl M. Hegbloom, Taketoshi Sano, and Pavel Roskin for
+	their hard work on this release of BusyBox.  Please pound
+	on it and let me know if you find any bugs.
+
+<p> <li> <b>19 January 2000 -- BusyBox 0.41 released</b>
+<br>
+
+     This release includes bugfixes to cp, mv, logger, true, false,
+	mkdir, syslogd, and init.  New apps include wc, hostid,
+	logname, tty, whoami, and yes.  New features include loop device
+	support in mount and umount, and better TERM handling by init.
+	The changelog can be found <a href="downloads/Changelog">here</a>.
+
+<p> <li> <b>7 January 2000 -- BusyBox 0.40 released</b>
+<br>
+
+     This release includes bugfixes to init (now includes inittab support),
+     syslogd, head, logger, du, grep, cp, mv, sed, dmesg, ls, kill, gunzip, and mknod.
+     New apps include sort, uniq, lsmod, rmmod, fbset, and loadacm.
+     In particular, this release fixes an important bug in tar which
+     in some cases produced serious security problems.
+     As always, the changelog can be found <a href="downloads/Changelog">here</a>.
+
+<p> <li> <b>11 December 1999 -- BusyBox Website</b>
+<br>
+     I have received permission from Bruce Perens (the original author of BusyBox)
+	to set up this site as the new primary website for BusyBox.  This website
+	will always contain pointers to the latest and greatest, and will also
+	contain the latest documentation on how to use BusyBox, what it can do,
+	what arguments its apps support, etc.
+
+<p> <li> <b>10 December 1999 -- BusyBox 0.39 released</b>
+<br>
+     This release includes fixes to init, reboot, halt, kill, and ls, and contains
+     the new apps ping, hostname, mkfifo, free, tail, du, tee, and head.  A full
+     changelog can be found <a href="downloads/Changelog">here</a>.
+<p> <li> <b>5 December 1999 -- BusyBox 0.38 released</b>
+<br>
+     This release includes fixes to tar, cat, ls, dd, rm, umount, find, df,
+	and make install, and includes new apps syslogd/klogd and logger.
+
+
+</ul>
+
+
+<!--#include file="footer.html" -->
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/products.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/products.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/products.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,167 @@
+<!--#include file="header.html" -->
+
+
+<h3>Products/Projects Using BusyBox</h3>
+
+Do you use BusyBox? I'd love to know about it and
+I'd be happy to link to you.
+
+<p>
+I know of the following products and/or projects that use BusyBox --
+listed in the order I happen to add them to the web page:
+
+<ul>
+
+
+<li><a href="http://buildroot.uclibc.org/">buildroot</a><br>A configurable
+means for building your own busybox/uClibc based system systems.
+
+<li><a href="http://www.pengutronix.de/software/ptxdist_en.html">PTXdist</a><br>another
+configurable means for building your own busybox based system systems.
+
+</li><li><a href=
+"http://cvs.debian.org/boot-floppies/">
+Debian installer (boot floppies) project</a>
+
+</li><li><a href="http://redhat.com/">Red Hat installer</a>
+
+</li><li><a href=
+"http://distro.ibiblio.org/pub/Linux/distributions/slackware/slackware-current/source/rootdisks/">
+Slackware Installer</a>
+
+</li><li><a href="http://www.gentoo.org/">Gentoo Linux install/boot CDs</a>
+</li><li><a href="http://www.mandriva.com/">The Mandriva installer</a>
+
+</li><li><a href="http://Leaf.SourceForge.net">Linux Embedded Appliance Firewall</a><br>The sucessor of the Linux Router Project, supporting all sorts of embedded Linux gateways, routers, wireless routers, and firewalls.
+
+</li><li><a href=
+"http://www.toms.net/rb/">tomsrtbt</a>
+
+</li><li><a href="http://www.stormix.com/">Stormix
+Installer</a>
+
+</li><li><a href=
+"http://www.emacinc.com/linux2_sbc.htm">EMAC Linux
+2.0 SBC</a>
+
+</li><li><a href="http://www.trinux.org/">Trinux</a>
+
+</li><li><a href="http://oddas.sourceforge.net/">ODDAS
+project</a>
+
+</li><li><a href="http://byld.sourceforge.net/">Build Your
+Linux Disk</a>
+
+</li><li><a href=
+"http://ibiblio.org/pub/Linux/system/recovery">Zdisk</a>
+
+</li><li><a href="http://www.adtran.com">AdTran -
+VPN/firewall VPN Linux Distribution</a>
+
+</li><li><a href="http://mkcdrec.ota.be/">mkCDrec - make
+CD-ROM recovery</a>
+
+</li><li><a href=
+"http://recycle.lbl.gov/~ldoolitt/bse/">Linux on
+nanoEngine</a>
+
+</li><li><a href=
+"http://www.zelow.no/floppyfw/">Floppyfw</a>
+
+</li><li><a href="http://www.ltsp.org/">Linux Terminal
+Server Project</a>
+
+</li><li><a href="http://www.devil-linux.org/">Devil-Linux</a>
+
+</li><li><a href="http://dutnux.sourceforge.net/">DutNux</a>
+
+</li><li><a href="http://www.microwerks.net/~hugo/mindi/">Mindi</a>
+
+</li><li><a href="http://www.minimalinux.org/ttylinux/">ttylinux</a>
+
+</li><li><a href="http://www.coyotelinux.com/">Coyote Linux</a>
+
+</li><li><a href="http://www.partimage.org/">Partition
+Image</a>
+
+</li><li><a href="http://www.fli4l.de/">fli4l the on(e)-disk-router</a>
+
+</li><li><a href="http://tinfoilhat.cultists.net/">Tinfoil
+Hat Linux</a>
+
+</li><li><a href="http://sourceforge.net/projects/gp32linux/">gp32linux</a>
+</li><li><a href="http://familiar.handhelds.org/">Familiar Linux</a><br>A linux distribution for handheld computers
+</li><li><a href="http://rescuecd.sourceforge.net/">Timo's Rescue CD Set</a>
+</li><li><a href="http://sf.net/projects/netstation/">Netstation</a>
+</li><li><a href="http://www.fiwix.org/">GNU/Fiwix Operating System</a>
+</li><li><a href="http://www.softcraft.com/">Generations Linux</a>
+</li><li><a href="http://systemimager.org/relatedprojects/">SystemImager / System Installation Suite</a>
+</li><li><a href="http://www.bablokb.de/gendist/">GENDIST distribution generator</a>
+</li><li><a href="http://diet-pc.sourceforge.net/">DIET-PC embedded Linux thin client distribution</a>
+</li><li><a href="http://byzgl.sourceforge.net/">BYZantine Gnu/Linux</a>
+</li><li><a href="http://dban.sourceforge.net/">Darik's Boot and Nuke</a>
+</li><li><a href="http://www.timesys.com/">TimeSys real-time Linux</a>
+</li><li><a href="http://movix.sf.net/">MoviX</a><br>Boots from CD and automatically plays every video file on the CD
+</li><li><a href="http://katamaran.sourceforge.net">katamaran</a><br>Linux, X11, xfce windowmanager, based on BusyBox
+</li><li><a href="http://www.sourceforge.net/projects/simplygnustep">Prometheus SimplyGNUstep</a>
+</li><li><a href="http://www.renyi.hu/~ekho/lowlife/">lowlife</a><br>A documentation project on how to make your own uClibc-based systems and floppy.
+</li><li><a href="http://metadistros.hispalinux.es/">Metadistros</a><br>a project to allow you easily make Live-CD distributions.
+</li><li><a href="http://salvare.sourceforge.net/">Salvare</a><br>More Linux than tomsrtbt but less than Knoppix, aims to provide a useful workstation as well as a rescue disk.
+</li><li><a href="http://www.stresslinux.org/">stresslinux</a><br>minimal linux distribution running from a bootable cdrom or via PXE.
+</li><li><a href="http://thinstation.sourceforge.net/">thinstation</a><br>convert standard PCs into full-featured diskless thinclients.
+</li><li><a href="http://www.uhulinux.hu/">UHU-Linux Hungary</a>
+</li><li><a href="http://deep-water.berlios.de/">Deep-Water Linux</a>
+</li><li><a href="http://www.freesco.org/">Freesco router</a>
+</li><li><a href="http://Sentry.SourceForge.net/">Sentry Firewall CD</a>
+
+
+
+</li><li><a href="http://tuxscreen.net">Tuxscreen Linux Phone</a>
+</li><li><a href="http://www.kerbango.com/">The Kerbango Internet Radio</a>
+</li><li><a href="http://www.linuxmagic.com/vpn/">LinuxMagic VPN Firewall</a>
+</li><li><a href="http://www.isilver-inc.com/">I-Silver Linux appliance servers</a>
+</li><li><a href="http://zaurus.sourceforge.net/">Sharp Zaurus PDA</a>
+</li><li><a href="http://www.cyclades.com/">Cyclades-TS and other Cyclades products</a>
+</li><li><a href="http://www.linksys.com/products/product.asp?prid=508">Linksys WRT54G - Wireless-G Broadband Router</a>
+</li><li><a href="http://www.dell.com/us/en/biz/topics/sbtopic_005_truemobile.htm">Dell TrueMobile 1184</a>
+</li><li><a href="http://actiontec.com/products/modems/dual_pcmodem/dpm_overview.html">Actiontec Dual PC Modem</a>
+</li><li><a href="http://www.kiss-technology.com/">Kiss DP Series DVD players</a>
+</li><li><a href="http://www.netgear.com/products/prod_details.asp?prodID=170">NetGear WG602 wireless router</a>
+    <br>with sources <a href="http://www.netgear.com/support/support_details.asp?dnldID=453">here</a>
+</li><li><a href="http://www.trendware.com/products/TEW-411BRP.htm">TRENDnet TEW-411BRP 802.11g Wireless AP/Router/Switch</a>
+    <br>Source for busybox and udhcp <a href="http://www.trendware.com/asp/download/fileinfo.asp?file_id=277&B1=Search">here</a> though no kernel source is provided.
+</li><li><a href="http://www.buffalo-technology.com/webcontent/products/wireless/wbr-g54.htm">Buffalo WBR-G54 wireless router</a>
+  </li><li><a href="http://www.asus.com/products/communication/wireless/wl-300g/overview.htm">ASUS WL-300g Wireless LAN Access Point</a>
+    <br>with source<a href="http://www.asus.com.tw/support/download/item.aspx?ModelName=WL-300G">here</a>
+  </li><li><a href="http://catalog.belkin.com/IWCatProductPage.process?Merchant_Id=&Section_Id=201522&pcount=&Product_Id=136493">Belkin 54g Wireless DSL/Cable Gateway Router</a>
+    <br>with source<a href="http://web.belkin.com/support/gpl.asp">here</a>
+  <li><a href="http://www.acronis.com/products/partitionexpert/">Acronis PartitionExpert 2003</a>
+	<br>includes a heavily modified BusyBox v0.60.5 with built in
+	cardmgr, device detection, gpm, lspci, etc.  Also includes udhcp,
+	uClibc 0.9.26, a heavily patched up linux kernel, etc.  Source
+	can only be obtained <a href="http://www.acronis.com/files/gpl/linux.tar.bz2">here</a>
+
+</li><li><a href="http://www.usr.com/">U.S. Robotics Sureconnect 4-port ADSL router</a><br>
+    with source <a href="http://www.usr.com/support/s-gpl-code.asp">here</a>
+</li><li><a href="http://www.actiontec.com/products/broadband/54mbps_wireless_gateway_1p/index.html">
+    ActionTec GT701-WG Wireless Gateway/DSL Modem</a>
+    with source <a href="http://128.121.226.214/gtproducts/index.html">here</a>
+</li><li><a href="http://smartlinux.sourceforge.net/">S.M.A.R.T. Linux</a>
+</li><li><a href="http://www.dlink.com/">DLink - Model GSL-G604T, DSL-300T, and possibly other models</a>
+    with source <a href="ftp://ftp.dlink.co.uk/dsl_routers_modems/">here,</a>
+    with source <a href="ftp://ftp.dlink.de/dsl-products/">and here,</a>
+    and quite possibly other places as well.  You may need to dig down a bit
+    to find the source, but it does seem to be there.
+</li><li><a href="http://www.siemens-mobile.de/cds/frontdoor/0,2241,de_de_0_42931_rArNrNrNrN,00.html">Siemens SE515 DSL router</a>
+    with source <a href="http://now-portal.c-lab.de/projects/gigaset/">here, I think...</a>
+    with some details <a href="http://heinz.hippenstiel.org/familie/hp/hobby/gigaset_se515dsl.html">here.</a>
+</li><li><a href="http://frwt.stim.ru/">Free Remote Windows Terminal</a>
+    
+</li><li><a href="http://www.zyxel.com/">ZyXEL Routers</a>
+
+</li>
+</ul>
+
+
+<!--#include file="footer.html" -->
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/screenshot.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/screenshot.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/screenshot.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,62 @@
+<!--#include file="header.html" -->
+
+
+<!-- Begin Screenshot -->
+
+<h3> Busybox Screenshot! </h3>
+
+
+Everybody loves to look at screenshots, so here is a live action screenshot of BusyBox.
+
+<pre style="background-color: black; color: lightgreen; padding: 5px;
+font-family: monospace; font-size: smaller;" width="100">
+
+
+$ ./busybox
+BusyBox v1.1.2 (2006.04.11-08:27+0000) multi-call binary
+
+Usage: busybox [function] [arguments]...
+   or: [function] [arguments]...
+
+	BusyBox is a multi-call binary that combines many common Unix
+	utilities into a single executable.  Most people will create a
+	link to busybox for each function they wish to use and BusyBox
+	will act like whatever it was invoked as!
+
+Currently defined functions:
+	[, [[, addgroup, adduser, adjtimex, ar, arping, ash, awk, basename,
+	bbconfig, bunzip2, busybox, bzcat, cal, cat, chattr, chgrp, chmod,
+	chown, chroot, chvt, clear, cmp, comm, cp, cpio, crond, crontab,
+	cut, date, dc, dd, deallocvt, delgroup, deluser, devfsd, df, dirname,
+	dmesg, dnsd, dos2unix, dpkg, dpkg-deb, du, dumpkmap, dumpleases,
+	e2fsck, e2label, echo, egrep, eject, env, ether-wake, expr, fakeidentd,
+	false, fbset, fdflush, fdformat, fdisk, fgrep, find, findfs, fold,
+	free, freeramdisk, fsck, fsck.ext2, fsck.ext3, fsck.minix, ftpget,
+	ftpput, fuser, getopt, getty, grep, gunzip, gzip, halt, hdparm,
+	head, hexdump, hostid, hostname, httpd, hush, hwclock, id, ifconfig,
+	ifdown, ifup, inetd, init, insmod, install, ip, ipaddr, ipcalc,
+	ipcrm, ipcs, iplink, iproute, iptunnel, kill, killall, klogd,
+	lash, last, length, less, linux32, linux64, linuxrc, ln, loadfont,
+	loadkmap, logger, login, logname, logread, losetup, ls, lsattr,
+	lsmod, lzmacat, makedevs, md5sum, mdev, mesg, mkdir, mke2fs, mkfifo,
+	mkfs.ext2, mkfs.ext3, mkfs.minix, mknod, mkswap, mktemp, modprobe,
+	more, mount, mountpoint, msh, mt, mv, nameif, nc, netstat, nice,
+	nohup, nslookup, od, openvt, passwd, patch, pidof, ping, ping6,
+	pipe_progress, pivot_root, poweroff, printenv, printf, ps, pwd,
+	rdate, readlink, readprofile, realpath, reboot, renice, reset,
+	rm, rmdir, rmmod, route, rpm, rpm2cpio, run-parts, runlevel, rx,
+	sed, seq, setarch, setconsole, setkeycodes, setsid, sha1sum, sleep,
+	sort, start-stop-daemon, stat, strings, stty, su, sulogin, sum,
+	swapoff, swapon, switch_root, sync, sysctl, syslogd, tail, tar,
+	tee, telnet, telnetd, test, tftp, time, top, touch, tr, traceroute,
+	true, tty, tune2fs, udhcpc, udhcpd, umount, uname, uncompress,
+	uniq, unix2dos, unlzma, unzip, uptime, usleep, uudecode, uuencode,
+	vconfig, vi, vlock, watch, watchdog, wc, wget, which, who, whoami,
+	xargs, yes, zcat, zcip
+
+$ <span style="text-decoration:blink;">_</span>
+
+</pre>
+
+<!--#include file="footer.html" -->
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/shame.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/shame.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/shame.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,82 @@
+<!--#include file="header.html" -->
+
+
+<h3>Hall of Shame!!!</h3>
+
+<p>This page is no longer updated, these days we forward this sort of
+thing to the <a href="http://www.softwarefreedom.org">Software Freedom Law
+Center</a> instead.</p>
+
+<p>The following products and/or projects appear to use BusyBox, but do not
+appear to release source code as required by the <a
+href="/license.html">BusyBox license</a>.  This is a violation of the law!
+The distributors of these products are invited to contact <a href=
+"mailto:andersen at codepoet.org">Erik Andersen</a> if they have any confusion
+as to what is needed to bring their products into compliance, or if they have
+already brought their product into compliance and wish to be removed from the
+Hall of Shame.
+
+<p>
+
+Here are the details of <a href="/license.html">exactly how to comply
+with the BusyBox license</a>, so there should be no question as to
+exactly what is expected.
+Complying with the Busybox license is easy and completely free, so the
+companies listed below should be ashamed of themselves.  Furthermore, each
+product listed here is subject to being legally ordered to cease and desist
+distribution for violation of copyright law, and the distributor of each
+product is subject to being sued for statutory copyright infringement damages
+of up to $150,000 per work plus legal fees.  Nobody wants to be sued, and <a
+href="mailto:andersen at codepoet.org">Erik</a> certainly would prefer to spend
+his time doing better things than sue people.  But he will sue if forced to
+do so to maintain compliance.
+
+<p>
+
+Do everyone a favor and don't break the law -- if you use busybox, comply with
+the busybox license by releasing the source code with your product.
+
+<p>
+
+<ul>
+
+  <li><a href="http://www.trittontechnologies.com/products.html">Tritton Technologies NAS120</a>
+	<br>see <a href="http://www.ussg.iu.edu/hypermail/linux/kernel/0404.0/1611.html">here for details</a>
+  <li><a href="http://www.macsense.com/product/homepod/">Macsense HomePod</a>
+	<br>with details
+	<a href="http://developer.gloolabs.com/modules.php?op=modload&name=Forums&file=viewtopic&topic=123&forum=7">here</a>
+  <li><a href="http://www.cpx.com/products.asp?c=Wireless+Products">Compex Wireless Products</a>
+    <br>appears to be running v0.60.5 with Linux version 2.4.20-uc0 on ColdFire,
+    but no source code is mentioned or offered.
+  <li><a href="http://www.inventel.com/en/product/datasheet/10/">Inventel DW 200 wireless/ADSL router</a>
+  <li><a href="http://www.sweex.com/product.asp">Sweex DSL router</a>
+    <br>appears to be running BusyBox v1.00-pre2 and udhcpd, but no source
+	code is mentioned or offered.
+  <li><a href="http://www.trendware.com/products/TEW-410APB.htm">TRENDnet TEW-410APB</a>
+  </li><li><a href="http://www.hauppauge.com/Pages/products/data_mediamvp.html">Hauppauge Media MVP</a>
+  <br>Hauppauge contacted me on 16 Dec 2003, and claims to be working on resolving this problem.
+  </li><li><a href="http://www.hitex.com/download/adescom/data/">TriCore</a>
+  </li><li><a href="http://www.allnet.de/">ALLNET 0186 wireless router</a>
+  </li><li><a href="http://www.dmmtv.com/">Dreambox DM7000S DVB Satellite Receiver</a>
+  <br> Dream Multimedia contacted me on 22 Dec 2003 and is working on resolving this problem.
+  <br> Source _may_ be here: http://cvs.tuxbox.org/cgi-bin/viewcvs.cgi/tuxbox/cdk/
+  </li><li><a href="http://testing.lkml.org/slashdot.php?mid=331690">Sigma Designs EM8500 based DVD players</a>
+  <br>Source for the Sigma Designs reference platform is found here<br>
+    <a href="http://www.uclinux.org/pub/uClinux/ports/arm/EM8500/uClinux-2.4-sigma.tar.gz">uClinux-2.4-sigma.tar.gz</a>, so while Sigma Designs itself appears to be in compliance, as far as I can tell,
+    no vendors of Sigma Designs EM8500 based devices actually comply with the GPL....
+  </li><li><a href="http://testing.lkml.org/slashdot.php?mid=433790">Liteon LVD2001 DVD player using the Sigma Designs EM8500</a>
+  </li><li><a href="http://www.rimax.net/">Rimax DVD players using the Sigma Designs EM8500</a>
+  </li><li><a href="http://www.vinc.us/">Bravo DVD players using the Sigma Designs EM8500</a>
+  </li><li><a href="http://www.hb-direct.com/">H&B DX3110 Divx player based on Sigma Designs EM8500</a>
+  </li><li><a href="http://www.recospa.it/mdpro1/index.php">United *DVX4066 mpeg4 capable DVD players</a>
+  </li><li><a href="http://www.a-link.com/RR64AP.html">Avaks alink Roadrunner 64</a>
+  <br> Partial source available, based on source distributed under NDA from <a href="http://www.lsilogic.com/products/dsl_platform_solutions/hb_linuxr2_2.html"> LSILogic</a>. Why the NDA LSILogic, what are you hiding ?
+  <br>To verify the Avaks infrigment see my slashdot <a href="http://slashdot.org/~bug1/journal/">journal</a>. 
+  <br>The ZipIt wireless IM device appears to be using Busybox-1.00-pre1 in the ramdisk, however no source has been made available.
+  </li><li>Undoubtedly there are others...  Please report them so we can shame them (or if necessary sue them) into compliance.
+
+</ul>
+
+
+<!--#include file="footer.html" -->
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/sponsors.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/sponsors.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/sponsors.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,31 @@
+<!--#include file="header.html" -->
+
+<h3>Sponsors</h3>
+
+<p>Please visit our sponsors and thank them for their support! They have
+provided money for equipment and bandwidth. Next time you need help with a
+project, consider these fine companies!</p>
+
+
+<ul>
+  <li><a href="http://www.penguru.net">Penguru Consulting</a><br>
+  Custom development for embedded Linux systems and multimedia platforms
+  </li>
+
+  <li><a href="http://opensource.se/">opensource.se</a><br>
+  Embedded open source consulting in Europe.
+  </li>
+
+  <li><a href="http://www.codepoet-consulting.com">Codepoet Consulting</a><br>
+  Custom Linux, embedded Linux, BusyBox, and uClibc development.
+  </li>
+
+  <li><a href="http://www.timesys.com">TimeSys</a><br>
+  Embedded Linux development, cross-compilers, real-time, KGDB, tsrpm and cygwin.
+  </li>
+</ul>
+
+<p>If you wish to be a sponsor, or if you have already contributed and would
+like your name added here, email <a href="mailto:rob at landley.net">Rob</a>.</p>
+
+<!--#include file="footer.html" -->

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/subversion.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/subversion.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/subversion.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,52 @@
+<!--#include file="header.html" -->
+
+<h3>Accessing Source</h3>
+
+
+
+<h3>Patches</h3>
+
+<p>If you don't want to mess with subversion, you can download
+<a href="/downloads/patches/">all BusyBox patches</a> or check the
+<a href="/downloads/patches/recent.html">most recent patches</a>.
+
+<h3>Anonymous Subversion Access</h3>
+
+We allow anonymous (read-only) Subversion (svn) access to everyone.  To
+grab a copy of the latest version of BusyBox using anonymous svn access:
+
+<pre>
+svn co svn://busybox.net/trunk/busybox</pre>
+
+<p>
+The current <em>stable branch</em> can be obtained with
+<pre>
+svn co svn://busybox.net/branches/busybox_1_1_stable
+</pre>
+
+<p>
+
+If you are not already familiar with using Subversion, I recommend you visit <a
+href="http://subversion.tigris.org/">the Subversion website</a>.  You might
+also want to read online or buy a copy of <a
+href="http://svnbook.red-bean.com/">the Subversion Book</a>.  If you are
+already comfortable with using CVS, you may want to skip ahead to the <a
+href="http://svnbook.red-bean.com/en/1.1/apa.html">Subversion for CVS Users</a>
+part of the Subversion Book.
+
+<p>
+
+Once you've checked out a copy of the source tree, you can update your source
+tree at any time so it is in sync with the latest and greatest by entering your
+BusyBox directory and running the command:
+
+<pre>
+svn update</pre>
+
+Because you've only been granted anonymous access to the tree, you won't be
+able to commit any changes. Changes can be submitted for inclusion by posting
+them to the BusyBox mailing list.  For those that are actively contributing
+<a href="developer.html">Subversion commit access</a> can be made available.
+
+<!--#include file="footer.html" -->
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/tinyutils.html
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/tinyutils.html	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox.net/tinyutils.html	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,37 @@
+<!--#include file="header.html" -->
+
+
+<h3>External Tiny Utilities</h3>
+
+This is a list of tiny utilities whose functionality is not provided by 
+busybox.  If you have additional suggestions, please send an e-mail to our 
+dev mailing list.
+
+<br><br>
+
+<table>
+<tr>
+ <th>Feature</th>
+ <th>Utilities</th>
+</tr>
+
+<tr>
+ <td>SSH</td>
+ <td><a href="http://matt.ucc.asn.au/dropbear/">Dropbear</a> has both an ssh server and an ssh client.</td>
+</tr>
+
+<tr>
+ <td>SMTP</td>
+ <td><a href="ftp://ftp.debian.org/debian/pool/main/s/ssmtp/">ssmtp</a> is an extremely simple MTA.</td>
+</tr>
+
+</table>
+
+<p>In a gui environment, you'll probably want a web browser.
+<a href="http://www.konqueror.org/embedded/">Konqueror Embedded</a> requires QT
+(or QT Embedded), but not KDE.  The <a href="http://www.dillo.org/">Dillo</a>
+requires GTK+, but not Gnome.  Or you can try the <a href="http://links.twibright.com/">graphical
+version of links</a>.</p>
+
+<!--#include file="footer.html" -->
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox_footer.pod
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox_footer.pod	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox_footer.pod	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,258 @@
+=back
+
+=head1 LIBC NSS
+
+GNU Libc (glibc) uses the Name Service Switch (NSS) to configure the behavior
+of the C library for the local environment, and to configure how it reads
+system data, such as passwords and group information.  This is implemented
+using an /etc/nsswitch.conf configuration file, and using one or more of the
+/lib/libnss_* libraries.  BusyBox tries to avoid using any libc calls that make
+use of NSS.  Some applets however, such as login and su, will use libc functions
+that require NSS.
+
+If you enable CONFIG_USE_BB_PWD_GRP, BusyBox will use internal functions to
+directly access the /etc/passwd, /etc/group, and /etc/shadow files without
+using NSS.  This may allow you to run your system without the need for
+installing any of the NSS configuration files and libraries.
+
+When used with glibc, the BusyBox 'networking' applets will similarly require
+that you install at least some of the glibc NSS stuff (in particular,
+/etc/nsswitch.conf, /lib/libnss_dns*, /lib/libnss_files*, and /lib/libresolv*).
+
+Shameless Plug: As an alternative, one could use a C library such as uClibc.  In
+addition to making your system significantly smaller, uClibc does not require the
+use of any NSS support files or libraries.
+
+=head1 MAINTAINER
+
+Rob Landley <rob at landley.net>
+
+=head1 AUTHORS
+
+The following people have contributed code to BusyBox whether they know it or
+not.  If you have written code included in BusyBox, you should probably be
+listed here so you can obtain your bit of eternal glory.  If you should be
+listed here, or the description of what you have done needs more detail, or is
+incorect, please send in an update.
+
+
+=for html <br>
+
+Emanuele Aina <emanuele.aina at tiscali.it>
+	run-parts
+
+=for html <br>
+
+Erik Andersen <andersen at codepoet.org>
+
+    Tons of new stuff, major rewrite of most of the
+    core apps, tons of new apps as noted in header files.
+    Lots of tedious effort writing these boring docs that
+    nobody is going to actually read.
+
+=for html <br>
+
+Laurence Anderson <l.d.anderson at warwick.ac.uk>
+
+    rpm2cpio, unzip, get_header_cpio, read_gz interface, rpm
+
+=for html <br>
+
+Jeff Angielski <jeff at theptrgroup.com>
+
+    ftpput, ftpget
+
+=for html <br>
+
+Edward Betts <edward at debian.org>
+
+    expr, hostid, logname, whoami
+
+=for html <br>
+
+John Beppu <beppu at codepoet.org>
+
+    du, nslookup, sort
+
+=for html <br>
+
+Brian Candler <B.Candler at pobox.com>
+
+    tiny-ls(ls)
+
+=for html <br>
+
+Randolph Chung <tausq at debian.org>
+
+    fbset, ping, hostname
+
+=for html <br>
+
+Dave Cinege <dcinege at psychosis.com>
+
+    more(v2), makedevs, dutmp, modularization, auto links file,
+    various fixes, Linux Router Project maintenance
+
+=for html <br>
+
+Jordan Crouse <jordan at cosmicpenguin.net>
+
+	ipcalc
+
+=for html <br>
+
+Magnus Damm <damm at opensource.se>
+
+    tftp client insmod powerpc support
+
+=for html <br>
+
+Larry Doolittle <ldoolitt at recycle.lbl.gov>
+
+    pristine source directory compilation, lots of patches and fixes.
+
+=for html <br>
+
+Glenn Engel <glenne at engel.org>
+
+    httpd
+
+=for html <br>
+
+Gennady Feldman <gfeldman at gena01.com>
+
+    Sysklogd (single threaded syslogd, IPC Circular buffer support,
+    logread), various fixes.
+
+=for html <br>
+
+Karl M. Hegbloom <karlheg at debian.org>
+
+    cp_mv.c, the test suite, various fixes to utility.c, &c.
+
+=for html <br>
+
+Daniel Jacobowitz <dan at debian.org>
+
+    mktemp.c
+
+=for html <br>
+
+Matt Kraai <kraai at alumni.cmu.edu>
+
+    documentation, bugfixes, test suite
+
+=for html <br>
+
+Stephan Linz <linz at li-pro.net>
+
+	ipcalc, Red Hat equivalence
+
+=for html <br>
+
+John Lombardo <john at deltanet.com>
+
+    tr
+
+=for html <br>
+
+Glenn McGrath <bug1 at iinet.net.au>
+
+    Common unarchving code and unarchiving applets, ifupdown, ftpgetput,
+    nameif, sed, patch, fold, install, uudecode.
+    Various bugfixes, review and apply numerous patches.
+
+=for html <br>
+
+Manuel Novoa III <mjn3 at codepoet.org>
+
+    cat, head, mkfifo, mknod, rmdir, sleep, tee, tty, uniq, usleep, wc, yes,
+    mesg, vconfig, make_directory, parse_mode, dirname, mode_string,
+    get_last_path_component, simplify_path, and a number trivial libbb routines
+
+    also bug fixes, partial rewrites, and size optimizations in
+    ash, basename, cal, cmp, cp, df, du, echo, env, ln, logname, md5sum, mkdir,
+    mv, realpath, rm, sort, tail, touch, uname, watch, arith, human_readable,
+    interface, dutmp, ifconfig, route
+
+=for html <br>
+
+Vladimir Oleynik <dzo at simtreas.ru>
+
+    cmdedit; xargs(current), httpd(current);
+    ports: ash, crond, fdisk, inetd, stty, traceroute, top;
+    locale, various fixes
+    and irreconcilable critic of everything not perfect.
+
+=for html <br>
+
+Bruce Perens <bruce at pixar.com>
+
+    Original author of BusyBox in 1995, 1996. Some of his code can
+    still be found hiding here and there...
+
+=for html <br>
+
+Tim Riker <Tim at Rikers.org>
+
+    bug fixes, member of fan club
+
+=for html <br>
+
+Kent Robotti <robotti at metconnect.com>
+
+    reset, tons and tons of bug reports and patches.
+
+=for html <br>
+
+Chip Rosenthal <chip at unicom.com>, <crosenth at covad.com>
+
+    wget - Contributed by permission of Covad Communications
+
+=for html <br>
+
+Pavel Roskin <proski at gnu.org>
+
+    Lots of bugs fixes and patches.
+
+=for html <br>
+
+Gyepi Sam <gyepi at praxis-sw.com>
+
+    Remote logging feature for syslogd
+
+=for html <br>
+
+Linus Torvalds <torvalds at transmeta.com>
+
+    mkswap, fsck.minix, mkfs.minix
+
+=for html <br>
+
+Mark Whitley <markw at codepoet.org>
+
+    grep, sed, cut, xargs(previous),
+    style-guide, new-applet-HOWTO, bug fixes, etc.
+
+=for html <br>
+
+Charles P. Wright <cpwright at villagenet.com>
+
+    gzip, mini-netcat(nc)
+
+=for html <br>
+
+Enrique Zanardi <ezanardi at ull.es>
+
+    tarcat (since removed), loadkmap, various fixes, Debian maintenance
+
+=for html <br>
+
+Tito Ragusa <farmatito at tiscali.it>
+
+	devfsd and size optimizations in strings, openvt and deallocvt.
+
+=cut
+
+# $Id: busybox_footer.pod,v 1.18 2004/04/25 06:05:14 bug1 Exp $
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox_header.pod
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox_header.pod	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/busybox_header.pod	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,82 @@
+# vi: set sw=4 ts=4:
+
+=head1 NAME
+
+BusyBox - The Swiss Army Knife of Embedded Linux
+
+=head1 SYNTAX
+
+ BusyBox <function> [arguments...]  # or
+
+ <function> [arguments...]	    # if symlinked
+
+=head1 DESCRIPTION
+
+BusyBox combines tiny versions of many common UNIX utilities into a single
+small executable. It provides minimalist replacements for most of the utilities
+you usually find in GNU coreutils, util-linux, etc. The utilities in BusyBox
+generally have fewer options than their full-featured GNU cousins; however, the
+options that are included provide the expected functionality and behave very
+much like their GNU counterparts.
+
+BusyBox has been written with size-optimization and limited resources in mind.
+It is also extremely modular so you can easily include or exclude commands (or
+features) at compile time. This makes it easy to customize your embedded
+systems. To create a working system, just add /dev, /etc, and a Linux kernel.
+BusyBox provides a fairly complete POSIX environment for any small or embedded
+system.
+
+BusyBox is extremely configurable.  This allows you to include only the
+components you need, thereby reducing binary size. Run 'make config' or 'make
+menuconfig' to select the functionality that you wish to enable.  Then run
+'make' to compile BusyBox using your configuration.
+
+After the compile has finished, you should use 'make install' to install
+BusyBox. This will install the 'bin/busybox' binary, in the target directory
+specified by PREFIX. PREFIX can be set when configuring BusyBox, or you can
+specify an alternative location at install time (i.e., with a command line
+like 'make PREFIX=/tmp/foo install'). If you enabled any applet installation
+scheme (either as symlinks or hardlinks), these will also be installed in
+the location pointed to by PREFIX.
+
+=head1 USAGE
+
+BusyBox is a multi-call binary.  A multi-call binary is an executable program
+that performs the same job as more than one utility program.  That means there
+is just a single BusyBox binary, but that single binary acts like a large
+number of utilities.  This allows BusyBox to be smaller since all the built-in
+utility programs (we call them applets) can share code for many common operations.
+
+You can also invoke BusyBox by issuing a command as an argument on the
+command line.  For example, entering
+
+	/bin/busybox ls
+
+will also cause BusyBox to behave as 'ls'.
+
+Of course, adding '/bin/busybox' into every command would be painful.  So most
+people will invoke BusyBox using links to the BusyBox binary.
+
+For example, entering
+
+	ln -s /bin/busybox ls
+	./ls
+
+will cause BusyBox to behave as 'ls' (if the 'ls' command has been compiled
+into BusyBox).  Generally speaking, you should never need to make all these
+links yourself, as the BusyBox build system will do this for you when you run
+the 'make install' command.
+
+If you invoke BusyBox with no arguments, it will provide you with a list of the
+applets that have been compiled into your BusyBox binary.
+
+=head1 COMMON OPTIONS
+
+Most BusyBox commands support the B<--help> argument to provide a terse runtime
+description of their behavior.  If the CONFIG_FEATURE_VERBOSE_USAGE option has
+been enabled, more detailed usage information will also be available.
+
+=head1 COMMANDS
+
+Currently defined functions include:
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/contributing.txt
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/contributing.txt	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/contributing.txt	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,449 @@
+Contributing To Busybox
+=======================
+
+This document describes what you need to do to contribute to Busybox, where
+you can help, guidelines on testing, and how to submit a well-formed patch
+that is more likely to be accepted.
+
+The Busybox home page is at: http://busybox.net/
+
+
+
+Pre-Contribution Checklist
+--------------------------
+
+So you want to contribute to Busybox, eh? Great, wonderful, glad you want to
+help. However, before you dive in, headlong and hotfoot, there are some things
+you need to do:
+
+
+Checkout the Latest Code from CVS
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is a necessary first step. Please do not try to work with the last
+released version, as there is a good chance that somebody has already fixed
+the bug you found. Somebody might have even added the feature you had in mind.
+Don't make your work obsolete before you start!
+
+For information on how to check out Busybox from CVS, please look at the
+following links:
+
+	http://busybox.net/cvs_anon.html
+	http://busybox.net/cvs_howto.html
+
+
+Read the Mailing List
+~~~~~~~~~~~~~~~~~~~~~
+
+No one is required to read the entire archives of the mailing list, but you
+should at least read up on what people have been talking about lately. If
+you've recently discovered a problem, chances are somebody else has too. If
+you're the first to discover a problem, post a message and let the rest of us
+know.
+
+Archives can be found here:
+
+	http://busybox.net/lists/busybox/
+
+If you have a serious interest in Busybox, i.e., you are using it day-to-day or
+as part of an embedded project, it would be a good idea to join the mailing
+list.
+
+A web-based sign-up form can be found here:
+
+	http://busybox.net/mailman/listinfo/busybox
+
+
+Coordinate with the Applet Maintainer
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Some (not all) of the applets in Busybox are "owned" by a maintainer who has
+put significant effort into it and is probably more familiar with it than
+others. To find the maintainer of an applet, look at the top of the .c file
+for a name following the word 'Copyright' or 'Written by' or 'Maintainer'.
+
+Before plunging ahead, it's a good idea to send a message to the mailing list
+that says: "Hey, I was thinking about adding the 'transmogrify' feature to the
+'foo' applet.  Would this be useful? Is anyone else working on it?" You might
+want to CC the maintainer (if any) with your question.
+
+
+
+Areas Where You Can Help
+------------------------
+
+Busybox can always use improvement! If you're looking for ways to help, there
+are a variety of areas where you could help.
+
+
+What Busybox Doesn't Need
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Before listing the areas where you _can_ help, it's worthwhile to mention the
+areas where you shouldn't bother. While Busybox strives to be the "Swiss Army
+Knife" of embedded Linux, there are some applets that will not be accepted:
+
+ - Any filesystem manipulation tools: Busybox is filesystem independent and
+   we do not want to start adding mkfs/fsck tools for every (or any)
+   filesystem under the sun. (fsck_minix.c and mkfs_minix.c are living on
+   borrowed time.) There are far too many of these tools out there.  Use
+   the upstream version. Not everything has to be part of Busybox.
+
+ - Any partitioning tools: Partitioning a device is typically done once and
+   only once, and tools which do this generally do not need to reside on the
+   target device (esp a flash device). If you need a partitioning tool, grab
+   one (such as fdisk, sfdisk, or cfdisk from util-linux) and use that, but
+   don't try to merge it into busybox. These are nasty and complex and we
+   don't want to maintain them.
+
+ - Any disk, device, or media-specific tools: Use the -utils or -tools package
+   that was designed for your device; don't try to shoehorn them into Busybox.
+
+ - Any architecture specific tools: Busybox is (or should be) architecture
+   independent. Do not send us tools that cannot be used across multiple
+   platforms / arches.
+
+ - Any daemons that are not essential to basic system operation. To date, only
+   syslogd and klogd meet this requirement. We do not need a web server, an
+   ftp daemon, a dhcp server, a mail transport agent or a dns resolver. If you
+   need one of those, you are welcome to ask the folks on the mailing list for
+   recommendations, but please don't bloat up Busybox with any of these.
+
+
+Bug Reporting
+~~~~~~~~~~~~~
+
+If you find bugs, please submit a detailed bug report to the busybox mailing
+list at busybox at busybox.net.  A well-written bug report should include a
+transcript of a shell session that demonstrates the bad behavior and enables
+anyone else to duplicate the bug on their own machine. The following is such
+an example:
+
+    To: busybox at busybox.net
+    From: diligent at testing.linux.org
+    Subject: /bin/date doesn't work
+
+    Package: busybox
+    Version: 1.00
+
+    When I execute Busybox 'date' it produces unexpected results.
+    With GNU date I get the following output:
+
+	$ date
+	Wed Mar 21 14:19:41 MST 2001
+
+    But when I use BusyBox date I get this instead:
+
+	$ date
+	llegal instruction
+
+    I am using Debian unstable, kernel version 2.4.19-rmk1 on an Netwinder,
+    and the latest uClibc from CVS.  Thanks for the wonderful program!
+
+	-Diligent
+
+Note the careful description and use of examples showing not only what BusyBox
+does, but also a counter example showing what an equivalent GNU app does.  Bug
+reports lacking such detail may never be fixed...  Thanks for understanding.
+
+
+
+Write Documentation
+~~~~~~~~~~~~~~~~~~~
+
+Chances are, documentation in Busybox is either missing or needs improvement.
+Either way, help is welcome.
+
+Work is being done to automatically generate documentation from sources,
+especially from the usage.h file. If you want to correct the documentation,
+please make changes to the pre-generation parts, rather than the generated
+documentation. [More to come on this later...]
+
+It is preferred that modifications to documentation be submitted in patch
+format (more on this below), but we're a little more lenient when it comes to
+docs. You could, for example, just say "after the listing of the mount
+options, the following example would be helpful..."
+
+
+Consult Existing Sources
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+For a quick listing of "needs work" spots in the sources, cd into the Busybox
+directory and run the following:
+
+	for i in TODO FIXME XXX; do find -name '*.[ch]'|xargs grep $i; done
+
+This will show all of the trouble spots or 'questionable' code. Pick a spot,
+any spot, these are all invitations for you to contribute.
+
+
+Add a New Applet
+~~~~~~~~~~~~~~~~
+
+If you want to add a new applet to Busybox, we'd love to see it. However,
+before you write any code, please ask beforehand on the mailing list something
+like "Do you think applet 'foo' would be useful in Busybox?" or "Would you
+guys accept applet 'foo' into Busybox if I were to write it?" If the answer is
+"no" by the folks on the mailing list, then you've saved yourself some time.
+Conversely, you could get some positive responses from folks who might be
+interested in helping you implement it, or can recommend the best approach.
+Perhaps most importantly, this is your way of calling "dibs" on something and
+avoiding duplication of effort.
+
+Also, before you write a line of code, please read the 'new-applet-HOWTO.txt'
+file in the docs/ directory.
+
+
+Janitorial Work
+~~~~~~~~~~~~~~~
+
+These are dirty jobs, but somebody's gotta do 'em.
+
+ - Converting applets to use getopt() for option processing. Type 'find -name
+   '*.c'|grep -L getopt' to get a listing of the applets that currently don't
+   use getopt. If a .c file processes no options, it should have a line that
+   reads: /* no options, no getopt */ somewhere in the file.
+
+ - Replace any "naked" calls to malloc, calloc, realloc, str[n]dup, fopen with
+   the x* equivalents found in libbb/xfuncs.c.
+
+ - Security audits:
+   http://www.securityfocus.com/popups/forums/secprog/intro.shtml
+
+ - Synthetic code removal: http://www.perl.com/pub/2000/06/commify.html - This
+   is very Perl-specific, but the advice given in here applies equally well to
+   C.
+
+ - C library function use audits: Verifying that functions are being used
+   properly (called with the right args), replacing unsafe library functions
+   with safer versions, making sure return codes are being checked, etc.
+
+ - Where appropriate, replace preprocessor defined macros and values with
+   compile-time equivalents.
+
+ - Style guide compliance. See: docs/style-guide.txt
+
+ - Add testcases to tests/testcases.
+
+ - Makefile improvements:
+   http://www.canb.auug.org.au/~millerp/rmch/recu-make-cons-harm.html
+   (I think the recursive problems are pretty much taken care of at this point, non?)
+
+ - "Ten Commandments" compliance: (this is a "maybe", certainly not as
+   important as any of the previous items.)
+    http://www.lysator.liu.se/c/ten-commandments.html
+
+Other useful links:
+
+ - the comp.lang.c FAQ: http://web.onetelnet.ch/~twolf/tw/c/index.html#Sources
+
+
+
+Submitting Patches To Busybox
+-----------------------------
+
+Here are some guidelines on how to submit a patch to Busybox.
+
+
+Making A Patch
+~~~~~~~~~~~~~~
+
+If you've got anonymous CVS access set up, making a patch is simple. Just make
+sure you're in the busybox/ directory and type 'cvs diff -bwu > mychanges.patch'.
+You can send the resulting .patch file to the mailing list with a description
+of what it does. (But not before you test it! See the next section for some
+guidelines.) It is preferred that patches be sent as attachments, but it is
+not required.
+
+Also, feel free to help test other people's patches and reply to them with
+comments. You can apply a patch by saving it into your busybox/ directory and
+typing 'patch < mychanges.patch'. Then you can recompile, see if it runs, test
+if it works as advertised, and post your findings to the mailing list.
+
+NOTE: Please do not include extraneous or irrelevant changes in your patches.
+Please do not try to "bundle" two patches together into one. Make single,
+discreet changes on a per-patch basis. Sometimes you need to make a patch that
+touches code in many places, but these kind of patches are rare and should be
+coordinated with a maintainer.
+
+
+Testing Guidelines
+~~~~~~~~~~~~~~~~~~
+
+It's considered good form to test your new feature before you submit a patch
+to the mailing list, and especially before you commit a change to CVS. Here
+are some guidelines on how to test your changes.
+
+ - Always test Busybox applets against GNU counterparts and make sure the
+   behavior / output is identical between the two.
+
+ - Try several different permutations and combinations of the features you're
+   adding (i.e., different combinations of command-line switches) and make sure
+   they all work; make sure one feature does not interfere with another.
+
+ - Make sure you test compiling against the source both with the feature
+   turned on and turned off in Config.h and make sure Busybox compiles cleanly
+   both ways.
+
+ - Run the multibuild.pl script in the tests directory and make sure
+   everything checks out OK. (Do this from within the busybox/ directory by
+   typing: 'tests/multibuild.pl'.)
+
+
+Making Sure Your Patch Doesn't Get Lost
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you don't want your patch to be lost or forgotten, send it to the busybox
+mailing list with a subject line something like this:
+
+	[PATCH] - Adds "transmogrify" feature to "foo"
+
+In the body, you should have a pseudo-header that looks like the following:
+
+    Package: busybox
+    Version: v1.01pre (or whatever the current version is)
+    Severity: wishlist
+
+The remainder of the body should read along these lines:
+
+	This patch adds the "transmogrify" feature to the "foo" applet. I have
+	tested this on [arch] system(s) and it works. I have tested it against the
+	GNU counterparts and the outputs are identical. I have run the scripts in
+	the 'tests' directory and nothing breaks.
+
+
+
+Improving Your Chances of Patch Acceptance
+------------------------------------------
+
+Even after you send a brilliant patch to the mailing list, sometimes it can go
+unnoticed, un-replied-to, and sometimes (sigh) even lost. This is an
+unfortunate fact of life, but there are steps you can take to help your patch
+get noticed and convince a maintainer that it should be added:
+
+
+Be Succinct
+~~~~~~~~~~~
+
+A patch that includes small, isolated, obvious changes is more likely to be
+accepted than a patch that touches code in lots of different places or makes
+sweeping, dubious changes.
+
+
+Back It Up
+~~~~~~~~~~
+
+Hard facts on why your patch is better than the existing code will go a long
+way toward convincing maintainers that your patch should be included.
+Specifically, patches are more likely to be accepted if they are provably more
+correct, smaller, faster, simpler, or more maintainable than the existing
+code.
+
+Conversely, any patch that is supported with nothing more than "I think this
+would be cool" or "this patch is good because I say it is and I've got a Phd
+in Computer Science" will likely be ignored.
+
+
+Follow The Style Guide
+~~~~~~~~~~~~~~~~~~~~~~
+
+It's considered good form to abide by the established coding style used in a
+project; Busybox is no exception. We have gone so far as to delineate the
+"elements of Busybox style" in the file docs/style-guide.txt. Please follow
+them.
+
+
+Work With Someone Else
+~~~~~~~~~~~~~~~~~~~~~~
+
+Working on a patch in isolation is less effective than working with someone
+else for a variety of reasons. If another Busybox user is interested in what
+you're doing, then it's two (or more) voices instead of one that can petition
+for inclusion of the patch. You'll also have more people that can test your
+changes, or even offer suggestions on better approaches you could take.
+
+Getting other folks interested follows as a natural course if you've received
+responses from queries to applet maintainer or positive responses from folks
+on the mailing list.
+
+We've made strident efforts to put a useful "collaboration" infrastructure in
+place in the form of mailing lists, the bug tracking system, and CVS. Please
+use these resources.
+
+
+Send Patches to the Bug Tracking System
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This was mentioned above in the "Making Sure Your Patch Doesn't Get Lost"
+section, but it is worth mentioning again. A patch sent to the mailing list
+might be unnoticed and forgotten. A patch sent to the bug tracking system will
+be stored and closely connected to the bug it fixes.
+
+
+Be Polite
+~~~~~~~~~
+
+The old saying "You'll catch more flies with honey than you will with vinegar"
+applies when submitting patches to the mailing list for approval. The way you
+present your patch is sometimes just as important as the actual patch itself
+(if not more so). Being rude to the maintainers is not an effective way to
+convince them that your patch should be included; it will likely have the
+opposite effect.
+
+
+
+Committing Changes to CVS
+-------------------------
+
+If you submit several patches that demonstrate that you are a skilled and wise
+coder, you may be invited to become a committer, thus enabling you to commit
+changes directly to CVS. This is nice because you don't have to wait for
+someone else to commit your change for you, you can just do it yourself.
+
+But note that this is a privilege that comes with some responsibilities. You
+should test your changes before you commit them. You should also talk to an
+applet maintainer before you make any kind of sweeping changes to somebody
+else's code. Big changes should still go to the mailing list first. Remember,
+being wise, polite, and discreet is more important than being clever.
+
+
+When To Commit
+~~~~~~~~~~~~~~
+
+Generally, you should feel free to commit a change if:
+
+ - Your changes are small and don't touch many files
+ - You are fixing a bug
+ - Somebody has told you that it's okay
+ - It's obviously the Right Thing
+
+The more of the above are true, the better it is to just commit a change
+directly to CVS.
+
+
+When Not To Commit
+~~~~~~~~~~~~~~~~~~
+
+Even if you have commit rights, you should probably still post a patch to the
+mailing list if:
+
+ - Your changes are broad and touch many different files
+ - You are adding a feature
+ - Your changes are speculative or experimental (i.e., trying a new algorithm)
+ - You are not the maintainer and your changes make the maintainer cringe
+
+The more of the above are true, the better it is to post a patch to the
+mailing list instead of committing.
+
+
+
+Final Words
+-----------
+
+If all of this seems complicated, don't panic, it's really not that tough. If
+you're having difficulty following some of the steps outlined in this
+document don't worry, the folks on the Busybox mailing list are a fairly
+good-natured bunch and will work with you to help get your patches into shape
+or help you make contributions.
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/new-applet-HOWTO.txt
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/new-applet-HOWTO.txt	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/new-applet-HOWTO.txt	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,150 @@
+How to Add a New Applet to BusyBox
+==================================
+
+This document details the steps you must take to add a new applet to BusyBox.
+
+Credits:
+Matt Kraai - initial writeup
+Mark Whitley - the remix
+Thomas Lundquist - Added stuff for the new directory layout.
+
+Initial Write
+-------------
+
+First, write your applet.  Be sure to include copyright information at the top,
+such as who you stole the code from and so forth. Also include the mini-GPL
+boilerplate. Be sure to name the main function <applet>_main instead of main.
+And be sure to put it in <applet>.c. Usage does not have to be taken care of by
+your applet.
+Make sure to #include "busybox.h" as the first include file in your applet so
+the bb_config.h and appropriate platform specific files are included properly.
+
+For a new applet mu, here is the code that would go in mu.c:
+
+----begin example code------
+
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini mu implementation for busybox
+ *
+ * Copyright (C) [YEAR] by [YOUR NAME] <YOUR EMAIL>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <other.h>
+
+int mu_main(int argc, char **argv)
+{
+	int fd;
+	char mu;
+
+	fd = bb_xopen("/dev/random", O_RDONLY);
+
+	if ((n = safe_read(fd, &mu, 1)) < 1)
+		bb_perror_msg_and_die("/dev/random");
+
+	return mu;
+}
+
+----end example code------
+
+
+Coding Style
+------------
+
+Before you submit your applet for inclusion in BusyBox, (or better yet, before
+you _write_ your applet) please read through the style guide in the docs
+directory and make your program compliant.
+
+
+Some Words on libbb
+-------------------
+
+As you are writing your applet, please be aware of the body of pre-existing
+useful functions in libbb. Use these instead of reinventing the wheel.
+
+Additionally, if you have any useful, general-purpose functions in your
+applet that could be useful in other applets, consider putting them in libbb.
+
+
+Placement / Directory
+---------------------
+
+Find the appropriate directory for your new applet.
+
+Make sure you find the appropriate places in the files, the applets are
+sorted alphabetically.
+
+Add the applet to Makefile.in in the chosen directory:
+
+obj-$(CONFIG_MU)               += mu.o
+
+Add the applet to Config.in in the chosen directory:
+
+config CONFIG_MU
+	bool "MU"
+	default n
+	help
+	  Returns an indeterminate value.
+
+
+Usage String(s)
+---------------
+
+Next, add usage information for you applet to include/usage.h.
+This should look like the following:
+
+	#define mu_trivial_usage \
+		"-[abcde] FILES"
+	#define mu_full_usage \
+		"Returns an indeterminate value.\n\n" \
+		"Options:\n" \
+		"\t-a\t\tfirst function\n" \
+		"\t-b\t\tsecond function\n" \
+		...
+
+If your program supports flags, the flags should be mentioned on the first
+line (-[abcde]) and a detailed description of each flag should go in the
+mu_full_usage section, one flag per line. (Numerous examples of this
+currently exist in usage.h.)
+
+
+Header Files
+------------
+
+Next, add an entry to include/applets.h.  Be *sure* to keep the list
+in alphabetical order, or else it will break the binary-search lookup
+algorithm in busybox.c and the Gods of BusyBox smite you. Yea, verily:
+
+	/* all programs above here are alphabetically "less than" 'mu' */
+	#ifdef CONFIG_MU
+		APPLET("mu", mu_main, _BB_DIR_USR_BIN, mu_usage)
+	#endif
+	/* all programs below here are alphabetically "greater than" 'mu' */
+
+
+Documentation
+-------------
+
+If you're feeling especially nice, you should also document your applet in the
+docs directory (but nobody ever does that).
+
+Adding some text to docs/Configure.help is a nice start.
+
+
+The Grand Announcement
+----------------------
+
+Then create a diff -urN of the files you added and/or modified. Typically:
+	<appletdir>/<applet>.c
+	include/usage.c
+	include/applets.h
+	<appletdir>/Makefile.in
+	<appletdir>/config.in
+and send it to the mailing list:
+	busybox at busybox.net
+	http://busybox.net/mailman/listinfo/busybox
+
+Sending patches as attachments is preferred, but not required.

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/style-guide.txt
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/style-guide.txt	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/docs/style-guide.txt	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,689 @@
+Busybox Style Guide
+===================
+
+This document describes the coding style conventions used in Busybox. If you
+add a new file to Busybox or are editing an existing file, please format your
+code according to this style. If you are the maintainer of a file that does
+not follow these guidelines, please -- at your own convenience -- modify the
+file(s) you maintain to bring them into conformance with this style guide.
+Please note that this is a low priority task.
+
+To help you format the whitespace of your programs, an ".indent.pro" file is
+included in the main Busybox source directory that contains option flags to
+format code as per this style guide. This way you can run GNU indent on your
+files by typing 'indent myfile.c myfile.h' and it will magically apply all the
+right formatting rules to your file. Please _do_not_ run this on all the files
+in the directory, just your own.
+
+
+
+Declaration Order
+-----------------
+
+Here is the order in which code should be laid out in a file:
+
+ - commented program name and one-line description
+ - commented author name and email address(es)
+ - commented GPL boilerplate
+ - commented longer description / notes for the program (if needed)
+ - #includes of .h files with angle brackets (<>) around them
+ - #includes of .h files with quotes ("") around them
+ - #defines (if any, note the section below titled "Avoid the Preprocessor")
+ - const and global variables
+ - function declarations (if necessary)
+ - function implementations
+
+
+
+Whitespace and Formatting
+-------------------------
+
+This is everybody's favorite flame topic so let's get it out of the way right
+up front.
+
+
+Tabs vs. Spaces in Line Indentation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The preference in Busybox is to indent lines with tabs. Do not indent lines
+with spaces and do not indents lines using a mixture of tabs and spaces. (The
+indentation style in the Apache and Postfix source does this sort of thing:
+\s\s\s\sif (expr) {\n\tstmt; --ick.) The only exception to this rule is
+multi-line comments that use an asterisk at the beginning of each line, i.e.:
+
+	/t/*
+	/t * This is a block comment.
+	/t * Note that it has multiple lines
+	/t * and that the beginning of each line has a tab plus a space
+	/t * except for the opening '/*' line where the slash
+	/t * is used instead of a space.
+	/t */
+
+Furthermore, The preference is that tabs be set to display at four spaces
+wide, but the beauty of using only tabs (and not spaces) at the beginning of
+lines is that you can set your editor to display tabs at *whatever* number of
+spaces is desired and the code will still look fine.
+
+
+Operator Spacing
+~~~~~~~~~~~~~~~~
+
+Put spaces between terms and operators. Example:
+
+	Don't do this:
+
+		for(i=0;i<num_items;i++){
+
+	Do this instead:
+
+		for (i = 0; i < num_items; i++) {
+
+	While it extends the line a bit longer, the spaced version is more
+	readable. An allowable exception to this rule is the situation where
+	excluding the spacing makes it more obvious that we are dealing with a
+	single term (even if it is a compound term) such as:
+
+		if (str[idx] == '/' && str[idx-1] != '\\')
+
+	or
+
+		if ((argc-1) - (optind+1) > 0)
+
+
+Bracket Spacing
+~~~~~~~~~~~~~~~
+
+If an opening bracket starts a function, it should be on the
+next line with no spacing before it. However, if a bracket follows an opening
+control block, it should be on the same line with a single space (not a tab)
+between it and the opening control block statement. Examples:
+
+	Don't do this:
+
+		while (!done)
+		{
+
+		do
+		{
+
+	Don't do this either:
+
+		while (!done){
+
+		do{
+
+	And for heaven's sake, don't do this:
+
+		while (!done)
+		  {
+
+		do
+		  {
+
+	Do this instead:
+
+		while (!done) {
+
+		do {
+
+Exceptions:
+
+ - if you have long logic statements that need to be wrapped, then uncuddling
+   the bracket to improve readability is allowed:
+
+		if (some_really_long_checks && some_other_really_long_checks \
+		    && some_more_really_long_checks)
+		{
+			do_foo_now;
+
+Spacing around Parentheses
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Put a space between C keywords and left parens, but not between function names
+and the left paren that starts it's parameter list (whether it is being
+declared or called). Examples:
+
+	Don't do this:
+
+		while(foo) {
+		for(i = 0; i < n; i++) {
+
+	Do this instead:
+
+		while (foo) {
+		for (i = 0; i < n; i++) {
+
+	But do functions like this:
+
+		static int my_func(int foo, char bar)
+		...
+		baz = my_func(1, 2);
+
+Also, don't put a space between the left paren and the first term, nor between
+the last arg and the right paren.
+
+	Don't do this:
+
+		if ( x < 1 )
+		strcmp( thisstr, thatstr )
+
+	Do this instead:
+
+		if (x < 1)
+		strcmp(thisstr, thatstr)
+
+
+Cuddled Elses
+~~~~~~~~~~~~~
+
+Also, please "cuddle" your else statements by putting the else keyword on the
+same line after the right bracket that closes an 'if' statement.
+
+	Don't do this:
+
+	if (foo) {
+		stmt;
+	}
+	else {
+		stmt;
+	}
+
+	Do this instead:
+
+	if (foo) {
+		stmt;
+	} else {
+		stmt;
+	}
+
+The exception to this rule is if you want to include a comment before the else
+block. Example:
+
+	if (foo) {
+		stmts...
+	}
+	/* otherwise, we're just kidding ourselves, so re-frob the input */
+	else {
+		other_stmts...
+	}
+
+
+
+Variable and Function Names
+---------------------------
+
+Use the K&R style with names in all lower-case and underscores occasionally
+used to separate words (e.g., "variable_name" and "numchars" are both
+acceptable). Using underscores makes variable and function names more readable
+because it looks like whitespace; using lower-case is easy on the eyes.
+
+	Frowned upon:
+
+		hitList
+		TotalChars
+		szFileName
+		pf_Nfol_TriState
+
+	Preferred:
+
+		hit_list
+		total_chars
+		file_name
+		sensible_name
+
+Exceptions:
+
+ - Enums, macros, and constant variables are occasionally written in all
+   upper-case with words optionally seperatedy by underscores (i.e. FIFOTYPE,
+   ISBLKDEV()).
+
+ - Nobody is going to get mad at you for using 'pvar' as the name of a
+   variable that is a pointer to 'var'.
+
+
+Converting to K&R
+~~~~~~~~~~~~~~~~~
+
+The Busybox codebase is very much a mixture of code gathered from a variety of
+sources. This explains why the current codebase contains such a hodge-podge of
+different naming styles (Java, Pascal, K&R, just-plain-weird, etc.). The K&R
+guideline explained above should therefore be used on new files that are added
+to the repository. Furthermore, the maintainer of an existing file that uses
+alternate naming conventions should, at his own convenience, convert those
+names over to K&R style. Converting variable names is a very low priority
+task.
+
+If you want to do a search-and-replace of a single variable name in different
+files, you can do the following in the busybox directory:
+
+	$ perl -pi -e 's/\bOldVar\b/new_var/g' *.[ch]
+
+If you want to convert all the non-K&R vars in your file all at once, follow
+these steps:
+
+ - In the busybox directory type 'examples/mk2knr.pl files-to-convert'. This
+   does not do the actual conversion, rather, it generates a script called
+   'convertme.pl' that shows what will be converted, giving you a chance to
+   review the changes beforehand.
+
+ - Review the 'convertme.pl' script that gets generated in the busybox
+   directory and remove / edit any of the substitutions in there. Please
+   especially check for false positives (strings that should not be
+   converted).
+
+ - Type './convertme.pl same-files-as-before' to perform the actual
+   conversion.
+
+ - Compile and see if everything still works.
+
+Please be aware of changes that have cascading effects into other files. For
+example, if you're changing the name of something in, say utility.c, you
+should probably run 'examples/mk2knr.pl utility.c' at first, but when you run
+the 'convertme.pl' script you should run it on _all_ files like so:
+'./convertme.pl *.[ch]'.
+
+
+
+Avoid The Preprocessor
+----------------------
+
+At best, the preprocessor is a necessary evil, helping us account for platform
+and architecture differences. Using the preprocessor unnecessarily is just
+plain evil.
+
+
+The Folly of #define
+~~~~~~~~~~~~~~~~~~~~
+
+Use 'const <type> var' for declaring constants.
+
+	Don't do this:
+
+		#define var 80
+
+	Do this instead, when the variable is in a header file and will be used in
+	several source files:
+
+		const int var = 80;
+
+	Or do this when the variable is used only in a single source file:
+
+		static const int var = 80;
+
+Declaring variables as '[static] const' gives variables an actual type and
+makes the compiler do type checking for you; the preprocessor does _no_ type
+checking whatsoever, making it much more error prone. Declaring variables with
+'[static] const' also makes debugging programs much easier since the value of
+the variable can be easily queried and displayed.
+
+
+The Folly of Macros
+~~~~~~~~~~~~~~~~~~~
+
+Use 'static inline' instead of a macro.
+
+	Don't do this:
+
+		#define mini_func(param1, param2) (param1 << param2)
+
+	Do this instead:
+
+		static inline int mini_func(int param1, param2)
+		{
+			return (param1 << param2);
+		}
+
+Static inline functions are greatly preferred over macros. They provide type
+safety, have no length limitations, no formatting limitations, have an actual
+return value, and under gcc they are as cheap as macros. Besides, really long
+macros with backslashes at the end of each line are ugly as sin.
+
+
+The Folly of #ifdef
+~~~~~~~~~~~~~~~~~~~
+
+Code cluttered with ifdefs is difficult to read and maintain. Don't do it.
+Instead, put your ifdefs at the top of your .c file (or in a header), and
+conditionally define 'static inline' functions, (or *maybe* macros), which are
+used in the code.
+
+	Don't do this:
+
+		ret = my_func(bar, baz);
+		if (!ret)
+			return -1;
+		#ifdef CONFIG_FEATURE_FUNKY
+			maybe_do_funky_stuff(bar, baz);
+		#endif
+
+	Do this instead:
+
+	(in .h header file)
+
+		#ifdef CONFIG_FEATURE_FUNKY
+		static inline void maybe_do_funky_stuff (int bar, int baz)
+		{
+			/* lotsa code in here */
+		}
+		#else
+		static inline void maybe_do_funky_stuff (int bar, int baz) {}
+		#endif
+
+	(in the .c source file)
+
+		ret = my_func(bar, baz);
+		if (!ret)
+			return -1;
+		maybe_do_funky_stuff(bar, baz);
+
+The great thing about this approach is that the compiler will optimize away
+the "no-op" case (the empty function) when the feature is turned off.
+
+Note also the use of the word 'maybe' in the function name to indicate
+conditional execution.
+
+
+
+Notes on Strings
+----------------
+
+Strings in C can get a little thorny. Here's some guidelines for dealing with
+strings in Busybox. (There is surely more that could be added to this
+section.)
+
+
+String Files
+~~~~~~~~~~~~
+
+Put all help/usage messages in usage.c. Put other strings in messages.c.
+Putting these strings into their own file is a calculated decision designed to
+confine spelling errors to a single place and aid internationalization
+efforts, if needed. (Side Note: we might want to use a single file - maybe
+called 'strings.c' - instead of two, food for thought).
+
+
+Testing String Equivalence
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There's a right way and a wrong way to test for sting equivalence with
+strcmp():
+
+	The wrong way:
+
+		if (!strcmp(string, "foo")) {
+			...
+
+	The right way:
+
+		if (strcmp(string, "foo") == 0){
+			...
+
+The use of the "equals" (==) operator in the latter example makes it much more
+obvious that you are testing for equivalence. The former example with the
+"not" (!) operator makes it look like you are testing for an error. In a more
+perfect world, we would have a streq() function in the string library, but
+that ain't the world we're living in.
+
+
+Avoid Dangerous String Functions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Unfortunately, the way C handles strings makes them prone to overruns when
+certain library functions are (mis)used. The following table  offers a summary
+of some of the more notorious troublemakers:
+
+function     overflows         preferred
+----------------------------------------
+strcpy       dest string       strncpy
+strcat       dest string       strncat
+gets         string it gets    fgets
+getwd        buf string        getcwd
+[v]sprintf   str buffer        [v]snprintf
+realpath     path buffer       use with pathconf
+[vf]scanf    its arguments     just avoid it
+
+
+The above is by no means a complete list. Be careful out there.
+
+
+
+Avoid Big Static Buffers
+------------------------
+
+First, some background to put this discussion in context: Static buffers look
+like this in code:
+
+	/* in a .c file outside any functions */
+	static char buffer[BUFSIZ]; /* happily used by any function in this file,
+	                                but ick! big! */
+
+The problem with these is that any time any busybox app is run, you pay a
+memory penalty for this buffer, even if the applet that uses said buffer is
+not run. This can be fixed, thusly:
+
+	static char *buffer;
+	...
+	other_func()
+	{
+		strcpy(buffer, lotsa_chars); /* happily uses global *buffer */
+	...
+	foo_main()
+	{
+		buffer = xmalloc(sizeof(char)*BUFSIZ);
+	...
+
+However, this approach trades bss segment for text segment. Rather than
+mallocing the buffers (and thus growing the text size), buffers can be
+declared on the stack in the *_main() function and made available globally by
+assigning them to a global pointer thusly:
+
+	static char *pbuffer;
+	...
+	other_func()
+	{
+		strcpy(pbuffer, lotsa_chars); /* happily uses global *pbuffer */
+	...
+	foo_main()
+	{
+		char *buffer[BUFSIZ]; /* declared locally, on stack */
+		pbuffer = buffer;     /* but available globally */
+	...
+
+This last approach has some advantages (low code size, space not used until
+it's needed), but can be a problem in some low resource machines that have
+very limited stack space (e.g., uCLinux).
+
+A macro is declared in busybox.h that implements compile-time selection
+between xmalloc() and stack creation, so you can code the line in question as
+
+		RESERVE_CONFIG_BUFFER(buffer, BUFSIZ);
+
+and the right thing will happen, based on your configuration.
+
+
+
+Miscellaneous Coding Guidelines
+-------------------------------
+
+The following are important items that don't fit into any of the above
+sections.
+
+
+Model Busybox Applets After GNU Counterparts
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When in doubt about the proper behavior of a Busybox program (output,
+formatting, options, etc.), model it after the equivalent GNU program.
+Doesn't matter how that program behaves on some other flavor of *NIX; doesn't
+matter what the POSIX standard says or doesn't say, just model Busybox
+programs after their GNU counterparts and it will make life easier on (nearly)
+everyone.
+
+The only time we deviate from emulating the GNU behavior is when:
+
+	- We are deliberately not supporting a feature (such as a command line
+	  switch)
+	- Emulating the GNU behavior is prohibitively expensive (lots more code
+	  would be required, lots more memory would be used, etc.)
+	- The difference is minor or cosmetic
+
+A note on the 'cosmetic' case: Output differences might be considered
+cosmetic, but if the output is significant enough to break other scripts that
+use the output, it should really be fixed.
+
+
+Scope
+~~~~~
+
+If a const variable is used only in a single source file, put it in the source
+file and not in a header file. Likewise, if a const variable is used in only
+one function, do not make it global to the file. Instead, declare it inside
+the function body. Bottom line: Make a conscious effort to limit declarations
+to the smallest scope possible.
+
+Inside applet files, all functions should be declared static so as to keep the
+global name space clean. The only exception to this rule is the "applet_main"
+function which must be declared extern.
+
+If you write a function that performs a task that could be useful outside the
+immediate file, turn it into a general-purpose function with no ties to any
+applet and put it in the utility.c file instead.
+
+
+Brackets Are Your Friends
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Please use brackets on all if and else statements, even if it is only one
+line. Example:
+
+	Don't do this:
+
+		if (foo)
+			stmt1;
+		stmt2
+		stmt3;
+
+	Do this instead:
+
+		if (foo) {
+			stmt1;
+		}
+		stmt2
+		stmt3;
+
+The "bracketless" approach is error prone because someday you might add a line
+like this:
+
+		if (foo)
+			stmt1;
+			new_line();
+		stmt2
+		stmt3;
+
+And the resulting behavior of your program would totally bewilder you. (Don't
+laugh, it happens to us all.) Remember folks, this is C, not Python.
+
+
+Function Declarations
+~~~~~~~~~~~~~~~~~~~~~
+
+Do not use old-style function declarations that declare variable types between
+the parameter list and opening bracket. Example:
+
+	Don't do this:
+
+		int foo(parm1, parm2)
+			char parm1;
+			float parm2;
+		{
+			....
+
+	Do this instead:
+
+		int foo(char parm1, float parm2)
+		{
+			....
+
+The only time you would ever need to use the old declaration syntax is to
+support ancient, antediluvian compilers. To our good fortune, we have access
+to more modern compilers and the old declaration syntax is neither necessary
+nor desired.
+
+
+Emphasizing Logical Blocks
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Organization and readability are improved by putting extra newlines around
+blocks of code that perform a single task. These are typically blocks that
+begin with a C keyword, but not always.
+
+Furthermore, you should put a single comment (not necessarily one line, just
+one comment) before the block, rather than commenting each and every line.
+There is an optimal ammount of commenting that a program can have; you can
+comment too much as well as too little.
+
+A picture is really worth a thousand words here, the following example
+illustrates how to emphasize logical blocks:
+
+	while (line = get_line_from_file(fp)) {
+
+		/* eat the newline, if any */
+		chomp(line);
+
+		/* ignore blank lines */
+		if (strlen(file_to_act_on) == 0) {
+			continue;
+		}
+
+		/* if the search string is in this line, print it,
+		 * unless we were told to be quiet */
+		if (strstr(line, search) && !be_quiet) {
+			puts(line);
+		}
+
+		/* clean up */
+		free(line);
+	}
+
+
+Processing Options with getopt
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If your applet needs to process  command-line switches, please use getopt() to
+do so. Numerous examples can be seen in many of the existing applets, but
+basically it boils down to two things: at the top of the .c file, have this
+line in the midst of your #includes:
+
+	#include <getopt.h>
+
+And a code block similar to the following near the top of your applet_main()
+routine:
+
+    while ((opt = getopt(argc, argv, "abc")) > 0) {
+            switch (opt) {
+            case 'a':
+                do_a_opt = 1;
+                break;
+            case 'b':
+                do_b_opt = 1;
+                break;
+            case 'c':
+                do_c_opt = 1;
+                break;
+            default:
+                show_usage();    /* in utility.c */
+            }
+    }
+
+If your applet takes no options (such as 'init'), there should be a line
+somewhere in the file reads:
+
+	/* no options, no getopt */
+
+That way, when people go grepping to see which applets need to be converted to
+use getopt, they won't get false positives.
+
+Additional Note: Do not use the getopt_long library function and do not try to
+hand-roll your own long option parsing. Busybox applets should only support
+short options. Explanations and examples of the short options should be
+documented in usage.h.

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,67 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Linux Ext2 FS Progs"
+
+config CONFIG_CHATTR
+	bool "chattr"
+	default n
+	help
+	  chattr changes the file attributes on a second extended file system.
+
+config CONFIG_E2FSCK
+	bool "e2fsck"
+	default n
+	help
+	  e2fsck is used to check Linux second extended file systems (ext2fs).
+	  e2fsck also supports ext2 filesystems countaining a journal (ext3).
+	  The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also
+	  provided.
+
+config CONFIG_FSCK
+	bool "fsck"
+	default n
+	help
+	  fsck is used to check and optionally repair one or more filesystems.
+	  In actuality, fsck is simply a front-end for the various file system
+	  checkers (fsck.fstype) available under Linux.
+
+config CONFIG_LSATTR
+	bool "lsattr"
+	default n
+	help
+	  lsattr lists the file attributes on a second extended file system.
+
+config CONFIG_MKE2FS
+	bool "mke2fs"
+	default n
+	help
+	  mke2fs is used to create an ext2/ext3 filesystem.  The normal compat
+	  symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided.
+
+config CONFIG_TUNE2FS
+	bool "tune2fs"
+	default n
+	help
+	  tune2fs allows the system administrator to adjust various tunable
+	  filesystem parameters on Linux ext2/ext3 filesystems.
+
+config CONFIG_E2LABEL
+	bool "e2label"
+	default n
+	depends on CONFIG_TUNE2FS
+	help
+	  e2label will display or change the filesystem label on the ext2
+	  filesystem located on device.
+
+config CONFIG_FINDFS
+	bool "findfs"
+	default n
+	depends on CONFIG_TUNE2FS
+	help
+	  findfs will search the disks in the system looking for a filesystem
+	  which has a label matching label or a UUID equal to uuid.
+
+endmenu

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,22 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/e2fsprogs
+E2FSPROGS_DIR:=./
+include $(top_builddir)/.config
+include $(top_srcdir)/Rules.mak
+include Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a */*.o $(AR_TARGET)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,86 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+E2FSPROGS_AR:=e2fsprogs.a
+
+E2FSPROGS_DIR:=$(top_builddir)/e2fsprogs
+E2FSPROGS_SRC:=$(top_srcdir)/e2fsprogs
+
+E2FSPROGS_CFLAGS := -include $(E2FSPROGS_SRC)/e2fsbb.h
+
+BLKID_SRC   := cache.c dev.c devname.c devno.c blkid_getsize.c \
+               probe.c read.c resolve.c save.c tag.c
+BLKID_SRCS  := $(patsubst %,blkid/%, $(BLKID_SRC))
+BLKID_OBJS  := $(patsubst %.c,%.o, $(BLKID_SRCS))
+
+E2P_SRC     := fgetsetflags.c fgetsetversion.c pf.c iod.c mntopts.c \
+               feature.c ls.c uuid.c pe.c ostype.c ps.c hashstr.c \
+               parse_num.c
+E2P_SRCS    := $(patsubst %,e2p/%, $(E2P_SRC))
+E2P_OBJS    := $(patsubst %.c,%.o, $(E2P_SRCS))
+
+EXT2FS_SRC  := gen_bitmap.c bitops.c ismounted.c mkjournal.c unix_io.c \
+               rw_bitmaps.c initialize.c bitmaps.c block.c \
+               ind_block.c inode.c freefs.c alloc_stats.c closefs.c \
+               openfs.c io_manager.c finddev.c read_bb.c alloc.c badblocks.c \
+               getsize.c getsectsize.c alloc_tables.c read_bb_file.c mkdir.c \
+               bb_inode.c newdir.c alloc_sb.c lookup.c dirblock.c expanddir.c \
+               dir_iterate.c link.c res_gdt.c icount.c get_pathname.c dblist.c \
+               dirhash.c version.c flushb.c unlink.c check_desc.c valid_blk.c \
+               ext_attr.c bmap.c dblist_dir.c ext2fs_inline.c swapfs.c
+EXT2FS_SRCS := $(patsubst %,ext2fs/%, $(EXT2FS_SRC))
+EXT2FS_OBJS := $(patsubst %.c,%.o, $(EXT2FS_SRCS))
+
+UUID_SRC    := compare.c gen_uuid.c pack.c parse.c unpack.c unparse.c \
+               uuid_time.c
+UUID_SRCS   := $(patsubst %,uuid/%, $(UUID_SRC))
+UUID_OBJS   := $(patsubst %.c,%.o, $(UUID_SRCS))
+
+E2FSPROGS-y:=
+E2FSPROGS-$(CONFIG_CHATTR)     += chattr.o $(E2P_OBJS)
+E2FSPROGS-$(CONFIG_E2FSCK)     += e2fsck.o util.o $(BLKID_OBJS) $(EXT2FS_OBJS) $(UUID_OBJS)
+E2FSPROGS-$(CONFIG_FSCK)       += fsck.o util.o $(BLKID_OBJS) $(EXT2FS_OBJS) $(UUID_OBJS)
+E2FSPROGS-$(CONFIG_LSATTR)     += lsattr.o $(E2P_OBJS)
+E2FSPROGS-$(CONFIG_MKE2FS)     += mke2fs.o util.o $(E2P_OBJS) $(BLKID_OBJS) $(EXT2FS_OBJS) $(UUID_OBJS)
+E2FSPROGS-$(CONFIG_TUNE2FS)    += tune2fs.o util.o $(E2P_OBJS) $(BLKID_OBJS) $(EXT2FS_OBJS) $(UUID_OBJS)
+
+E2FSPROGS-y:=$(sort $(E2FSPROGS-y))
+
+ifneq ($(strip $(E2FSPROGS-y)),)
+libraries-y+=$(E2FSPROGS_DIR)/$(E2FSPROGS_AR)
+endif
+
+E2FSPROGS_SRC-y:=$(patsubst %.o,$(E2FSPROGS_SRC)/%.c,$(E2FSPROGS-y))
+E2FSPROGS_SRC-a:=$(wildcard $(E2FSPROGS_SRC)/*.c) $(patsubst %,$(E2FSPROGS_SRC)/%,$(BLKID_SRCS) $(E2P_SRCS) $(EXT2FS_SRCS) $(UUID_SRCS))
+APPLET_SRC-y+=$(E2FSPROGS_SRC-y)
+APPLET_SRC-a+=$(E2FSPROGS_SRC-a)
+
+# XXX: FIXME: change .c to include their stuff relative to $(E2FSPROGS_SRC)
+E2FSPROGS_TMP_KLUDGE:=$(patsubst %,-I$(E2FSPROGS_SRC)/%,blkid e2fsck e2p ext2fs uuid)
+
+APPLETS_DEFINE-y+=$(E2FSPROGS_CFLAGS) -I$(E2FSPROGS_SRC) $(E2FSPROGS_TMP_KLUDGE)
+APPLETS_DEFINE-a+=$(E2FSPROGS_CFLAGS) -I$(E2FSPROGS_SRC) $(E2FSPROGS_TMP_KLUDGE)
+
+$(E2FSPROGS_DIR)/$(E2FSPROGS_AR): $(patsubst %,$(E2FSPROGS_DIR)/%, $(E2FSPROGS-y))
+	$(do_ar)
+
+$(E2FSPROGS_DIR)/%.o: $(subst $(top_builddir),$(top_srcdir),$(E2FSPROGS_DIR)/%.c)
+	$(compile.c) $(E2FSPROGS_CFLAGS)
+
+# for building out-of-tree we need to make sure that the directories to hold
+# the object tree are created
+$(patsubst %,$(E2FSPROGS_DIR)/%, blkid e2fsck e2p ext2fs uuid):
+	@mkdir -p "$@"
+
+# make sure that the directories are order-only prerequisites. Otherwise we
+# may have object files created after the timestamp of the directory was
+# updated which would lead to spurious rebuilds (as some of the dentries
+# may be older than the dir itself).
+$(patsubst %,$(E2FSPROGS_DIR)/%, $(BLKID_OBJS)):|$(E2FSPROGS_DIR)/blkid
+$(patsubst %,$(E2FSPROGS_DIR)/%, $(E2FSCK_OBJS)):|$(E2FSPROGS_DIR)/e2fsck
+$(patsubst %,$(E2FSPROGS_DIR)/%, $(E2P_OBJS)):|$(E2FSPROGS_DIR)/e2p
+$(patsubst %,$(E2FSPROGS_DIR)/%, $(EXT2FS_OBJS)):|$(E2FSPROGS_DIR)/ext2fs
+$(patsubst %,$(E2FSPROGS_DIR)/%, $(UUID_OBJS)):|$(E2FSPROGS_DIR)/uuid

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/README
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/README	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/README	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+This is a pretty straight rip from the e2fsprogs pkg.
+
+See README's in subdirs for specific info.

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/blkid.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/blkid.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/blkid.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,109 @@
+/*
+ * blkid.h - Interface for libblkid, a library to identify block devices
+ *
+ * Copyright (C) 2001 Andreas Dilger
+ * Copyright (C) 2003 Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+#ifndef _BLKID_BLKID_H
+#define _BLKID_BLKID_H
+
+#include <sys/types.h>
+#include <linux/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BLKID_VERSION	"1.0.0"
+#define BLKID_DATE	"12-Feb-2003"
+
+typedef struct blkid_struct_dev *blkid_dev;
+typedef struct blkid_struct_cache *blkid_cache;
+typedef __s64 blkid_loff_t;
+
+typedef struct blkid_struct_tag_iterate *blkid_tag_iterate;
+typedef struct blkid_struct_dev_iterate *blkid_dev_iterate;
+
+/*
+ * Flags for blkid_get_dev
+ *
+ * BLKID_DEV_CREATE	Create an empty device structure if not found
+ *			in the cache.
+ * BLKID_DEV_VERIFY	Make sure the device structure corresponds
+ *			with reality.
+ * BLKID_DEV_FIND	Just look up a device entry, and return NULL
+ *			if it is not found.
+ * BLKID_DEV_NORMAL	Get a valid device structure, either from the
+ *			cache or by probing the device.
+ */
+#define BLKID_DEV_FIND		0x0000
+#define BLKID_DEV_CREATE	0x0001
+#define BLKID_DEV_VERIFY	0x0002
+#define BLKID_DEV_NORMAL	(BLKID_DEV_CREATE | BLKID_DEV_VERIFY)
+
+/* cache.c */
+extern void blkid_put_cache(blkid_cache cache);
+extern int blkid_get_cache(blkid_cache *cache, const char *filename);
+
+/* dev.c */
+extern const char *blkid_dev_devname(blkid_dev dev);
+
+extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache);
+extern int blkid_dev_set_search(blkid_dev_iterate iter, 
+				char *search_type, char *search_value);
+extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev);
+extern void blkid_dev_iterate_end(blkid_dev_iterate iterate);
+
+/* devno.c */
+extern char *blkid_devno_to_devname(dev_t devno);
+
+/* devname.c */
+extern int blkid_probe_all(blkid_cache cache);
+extern int blkid_probe_all_new(blkid_cache cache);
+extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname,
+			       int flags);
+
+/* getsize.c */
+extern blkid_loff_t blkid_get_dev_size(int fd);
+
+/* probe.c */
+int blkid_known_fstype(const char *fstype);
+extern blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev);
+
+/* read.c */
+
+/* resolve.c */
+extern char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
+				       const char *devname);
+extern char *blkid_get_devname(blkid_cache cache, const char *token,
+			       const char *value);
+
+/* tag.c */
+extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev);
+extern int blkid_tag_next(blkid_tag_iterate iterate,
+			      const char **type, const char **value);
+extern void blkid_tag_iterate_end(blkid_tag_iterate iterate);
+extern int blkid_dev_has_tag(blkid_dev dev, const char *type, 
+			      const char *value);
+extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
+					 const char *type,
+					 const char *value);
+extern int blkid_parse_tag_string(const char *token, char **ret_type,
+				  char **ret_val);
+
+/* version.c */
+extern int blkid_parse_version_string(const char *ver_string);
+extern int blkid_get_library_version(const char **ver_string,
+				     const char **date_string);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BLKID_BLKID_H */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/blkidP.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/blkidP.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/blkidP.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,186 @@
+/*
+ * blkidP.h - Internal interfaces for libblkid
+ *
+ * Copyright (C) 2001 Andreas Dilger
+ * Copyright (C) 2003 Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+#ifndef _BLKID_BLKIDP_H
+#define _BLKID_BLKIDP_H
+
+#include <sys/types.h>
+#include <stdio.h>
+
+#include "blkid.h"
+#include "list.h"
+
+#ifdef __GNUC__
+#define __BLKID_ATTR(x) __attribute__(x)
+#else
+#define __BLKID_ATTR(x)
+#endif
+
+
+/*
+ * This describes the attributes of a specific device.
+ * We can traverse all of the tags by bid_tags (linking to the tag bit_names).
+ * The bid_label and bid_uuid fields are shortcuts to the LABEL and UUID tag
+ * values, if they exist.
+ */
+struct blkid_struct_dev
+{
+	struct list_head	bid_devs;	/* All devices in the cache */
+	struct list_head	bid_tags;	/* All tags for this device */
+	blkid_cache		bid_cache;	/* Dev belongs to this cache */
+	char			*bid_name;	/* Device inode pathname */
+	char			*bid_type;	/* Preferred device TYPE */
+	int			bid_pri;	/* Device priority */
+	dev_t			bid_devno;	/* Device major/minor number */
+	time_t			bid_time;	/* Last update time of device */
+	unsigned int		bid_flags;	/* Device status bitflags */
+	char			*bid_label;	/* Shortcut to device LABEL */
+	char			*bid_uuid;	/* Shortcut to binary UUID */
+};
+
+#define BLKID_BID_FL_VERIFIED	0x0001	/* Device data validated from disk */
+#define BLKID_BID_FL_INVALID	0x0004	/* Device is invalid */
+
+/*
+ * Each tag defines a NAME=value pair for a particular device.  The tags
+ * are linked via bit_names for a single device, so that traversing the
+ * names list will get you a list of all tags associated with a device.
+ * They are also linked via bit_values for all devices, so one can easily
+ * search all tags with a given NAME for a specific value.
+ */
+struct blkid_struct_tag
+{
+	struct list_head	bit_tags;	/* All tags for this device */
+	struct list_head	bit_names;	/* All tags with given NAME */
+	char			*bit_name;	/* NAME of tag (shared) */
+	char			*bit_val;	/* value of tag */
+	blkid_dev		bit_dev;	/* pointer to device */
+};
+typedef struct blkid_struct_tag *blkid_tag;
+
+/*
+ * Minimum number of seconds between device probes, even when reading
+ * from the cache.  This is to avoid re-probing all devices which were
+ * just probed by another program that does not share the cache.
+ */
+#define BLKID_PROBE_MIN		2
+
+/*
+ * Time in seconds an entry remains verified in the in-memory cache
+ * before being reverified (in case of long-running processes that
+ * keep a cache in memory and continue to use it for a long time).
+ */
+#define BLKID_PROBE_INTERVAL	200
+
+/* This describes an entire blkid cache file and probed devices.
+ * We can traverse all of the found devices via bic_list.
+ * We can traverse all of the tag types by bic_tags, which hold empty tags
+ * for each tag type.  Those tags can be used as list_heads for iterating
+ * through all devices with a specific tag type (e.g. LABEL).
+ */
+struct blkid_struct_cache
+{
+	struct list_head	bic_devs;	/* List head of all devices */
+	struct list_head	bic_tags;	/* List head of all tag types */
+	time_t			bic_time;	/* Last probe time */
+	time_t			bic_ftime;	/* Mod time of the cachefile */
+	unsigned int		bic_flags;	/* Status flags of the cache */
+	char			*bic_filename;	/* filename of cache */
+};
+
+#define BLKID_BIC_FL_PROBED	0x0002	/* We probed /proc/partition devices */
+#define BLKID_BIC_FL_CHANGED	0x0004	/* Cache has changed from disk */
+
+extern char *blkid_strdup(const char *s);
+extern char *blkid_strndup(const char *s, const int length);
+
+#define BLKID_CACHE_FILE "/etc/blkid.tab"
+extern const char *blkid_devdirs[];
+
+#define BLKID_ERR_IO	 5
+#define BLKID_ERR_PROC	 9
+#define BLKID_ERR_MEM	12
+#define BLKID_ERR_CACHE	14
+#define BLKID_ERR_DEV	19
+#define BLKID_ERR_PARAM	22
+#define BLKID_ERR_BIG	27
+
+/*
+ * Priority settings for different types of devices
+ */
+#define BLKID_PRI_EVMS	30
+#define BLKID_PRI_LVM	20
+#define BLKID_PRI_MD	10
+
+#if defined(TEST_PROGRAM) && !defined(CONFIG_BLKID_DEBUG)
+#define CONFIG_BLKID_DEBUG
+#endif
+
+#define DEBUG_CACHE	0x0001
+#define DEBUG_DUMP	0x0002
+#define DEBUG_DEV	0x0004
+#define DEBUG_DEVNAME	0x0008
+#define DEBUG_DEVNO	0x0010
+#define DEBUG_PROBE	0x0020
+#define DEBUG_READ	0x0040
+#define DEBUG_RESOLVE	0x0080
+#define DEBUG_SAVE	0x0100
+#define DEBUG_TAG	0x0200
+#define DEBUG_INIT	0x8000
+#define DEBUG_ALL	0xFFFF
+
+#ifdef CONFIG_BLKID_DEBUG
+#include <stdio.h>
+extern int      blkid_debug_mask;
+#define DBG(m,x)	if ((m) & blkid_debug_mask) x;
+#else
+#define DBG(m,x)
+#endif
+
+#ifdef CONFIG_BLKID_DEBUG
+extern void blkid_debug_dump_dev(blkid_dev dev);
+extern void blkid_debug_dump_tag(blkid_tag tag);
+#endif
+
+/* lseek.c */
+/* extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence); */
+#ifdef CONFIG_LFS
+# define blkid_llseek lseek64
+#else
+# define blkid_llseek lseek
+#endif
+
+/* read.c */
+extern void blkid_read_cache(blkid_cache cache);
+
+/* save.c */
+extern int blkid_flush_cache(blkid_cache cache);
+
+/*
+ * Functions to create and find a specific tag type: tag.c
+ */
+extern void blkid_free_tag(blkid_tag tag);
+extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type);
+extern int blkid_set_tag(blkid_dev dev, const char *name,
+			 const char *value, const int vlength);
+
+/*
+ * Functions to create and find a specific tag type: dev.c
+ */
+extern blkid_dev blkid_new_dev(void);
+extern void blkid_free_dev(blkid_dev dev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BLKID_BLKIDP_H */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/blkid_getsize.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/blkid_getsize.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/blkid_getsize.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,180 @@
+/*
+ * getsize.c --- get the size of a partition.
+ *
+ * Copyright (C) 1995, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+/* include this before sys/queues.h! */
+#include "blkidP.h"
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <fcntl.h>
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_LINUX_FD_H
+#include <linux/fd.h>
+#endif
+#ifdef HAVE_SYS_DISKLABEL_H
+#include <sys/disklabel.h>
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_DISK_H
+#ifdef HAVE_SYS_QUEUE_H
+#include <sys/queue.h> /* for LIST_HEAD */
+#endif
+#include <sys/disk.h>
+#endif
+#ifdef __linux__
+#include <sys/utsname.h>
+#endif
+
+#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
+#define BLKGETSIZE _IO(0x12,96)	/* return device size */
+#endif
+
+#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
+#define BLKGETSIZE64 _IOR(0x12,114,size_t)	/* return device size in bytes (u64 *arg) */
+#endif
+
+#ifdef APPLE_DARWIN
+#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
+#endif /* APPLE_DARWIN */
+
+static int valid_offset(int fd, blkid_loff_t offset)
+{
+	char ch;
+
+	if (blkid_llseek(fd, offset, 0) < 0)
+		return 0;
+	if (read(fd, &ch, 1) < 1)
+		return 0;
+	return 1;
+}
+
+/*
+ * Returns the number of blocks in a partition
+ */
+blkid_loff_t blkid_get_dev_size(int fd)
+{
+	int valid_blkgetsize64 = 1;
+#ifdef __linux__
+	struct		utsname ut;
+#endif
+	unsigned long long size64;
+	unsigned long size;
+	blkid_loff_t high, low;
+#ifdef FDGETPRM
+	struct floppy_struct this_floppy;
+#endif
+#ifdef HAVE_SYS_DISKLABEL_H
+	int part = -1;
+	struct disklabel lab;
+	struct partition *pp;
+	char ch;
+	struct stat st;
+#endif /* HAVE_SYS_DISKLABEL_H */
+
+#ifdef DKIOCGETBLOCKCOUNT	/* For Apple Darwin */
+	if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
+		if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
+		    && (size64 << 9 > 0xFFFFFFFF))
+			return 0; /* EFBIG */
+		return (blkid_loff_t) size64 << 9;
+	}
+#endif
+
+#ifdef BLKGETSIZE64
+#ifdef __linux__
+	if ((uname(&ut) == 0) &&
+	    ((ut.release[0] == '2') && (ut.release[1] == '.') &&
+	     (ut.release[2] < '6') && (ut.release[3] == '.')))
+		valid_blkgetsize64 = 0;
+#endif
+	if (valid_blkgetsize64 &&
+	    ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
+		if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
+		    && ((size64) > 0xFFFFFFFF))
+			return 0; /* EFBIG */
+		return size64;
+	}
+#endif
+
+#ifdef BLKGETSIZE
+	if (ioctl(fd, BLKGETSIZE, &size) >= 0)
+		return (blkid_loff_t)size << 9;
+#endif
+
+#ifdef FDGETPRM
+	if (ioctl(fd, FDGETPRM, &this_floppy) >= 0)
+		return (blkid_loff_t)this_floppy.size << 9;
+#endif
+#ifdef HAVE_SYS_DISKLABEL_H
+#if 0
+	/*
+	 * This should work in theory but I haven't tested it.  Anyone
+	 * on a BSD system want to test this for me?  In the meantime,
+	 * binary search mechanism should work just fine.
+	 */
+	if ((fstat(fd, &st) >= 0) && S_ISBLK(st.st_mode))
+		part = st.st_rdev & 7;
+	if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
+		pp = &lab.d_partitions[part];
+		if (pp->p_size)
+			return pp->p_size << 9;
+	}
+#endif
+#endif /* HAVE_SYS_DISKLABEL_H */
+
+	/*
+	 * OK, we couldn't figure it out by using a specialized ioctl,
+	 * which is generally the best way.  So do binary search to
+	 * find the size of the partition.
+	 */
+	low = 0;
+	for (high = 1024; valid_offset(fd, high); high *= 2)
+		low = high;
+	while (low < high - 1)
+	{
+		const blkid_loff_t mid = (low + high) / 2;
+
+		if (valid_offset(fd, mid))
+			low = mid;
+		else
+			high = mid;
+	}
+	return low + 1;
+}
+
+#ifdef TEST_PROGRAM
+int main(int argc, char **argv)
+{
+	blkid_loff_t bytes;
+	int	fd;
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s device\n"
+			"Determine the size of a device\n", argv[0]);
+		return 1;
+	}
+
+	if ((fd = open(argv[1], O_RDONLY)) < 0)
+		perror(argv[0]);
+
+	bytes = blkid_get_dev_size(fd);
+	printf("Device %s has %lld 1k blocks.\n", argv[1], bytes >> 10);
+
+	return 0;
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/cache.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/cache.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/cache.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,125 @@
+/*
+ * cache.c - allocation/initialization/free routines for cache
+ *
+ * Copyright (C) 2001 Andreas Dilger
+ * Copyright (C) 2003 Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "blkidP.h"
+
+int blkid_debug_mask = 0;
+
+int blkid_get_cache(blkid_cache *ret_cache, const char *filename)
+{
+	blkid_cache cache;
+
+#ifdef CONFIG_BLKID_DEBUG
+	if (!(blkid_debug_mask & DEBUG_INIT)) {
+		char *dstr = getenv("BLKID_DEBUG");
+
+		if (dstr)
+			blkid_debug_mask = strtoul(dstr, 0, 0);
+		blkid_debug_mask |= DEBUG_INIT;
+	}
+#endif
+
+	DBG(DEBUG_CACHE, printf("creating blkid cache (using %s)\n",
+				filename ? filename : "default cache"));
+
+	if (!(cache = (blkid_cache) calloc(1, sizeof(struct blkid_struct_cache))))
+		return -BLKID_ERR_MEM;
+
+	INIT_LIST_HEAD(&cache->bic_devs);
+	INIT_LIST_HEAD(&cache->bic_tags);
+
+	if (filename && !strlen(filename))
+		filename = 0;
+	if (!filename && (getuid() == geteuid()))
+		filename = getenv("BLKID_FILE");
+	if (!filename)
+		filename = BLKID_CACHE_FILE;
+	cache->bic_filename = blkid_strdup(filename);
+
+	blkid_read_cache(cache);
+
+	*ret_cache = cache;
+	return 0;
+}
+
+void blkid_put_cache(blkid_cache cache)
+{
+	if (!cache)
+		return;
+
+	(void) blkid_flush_cache(cache);
+
+	DBG(DEBUG_CACHE, printf("freeing cache struct\n"));
+
+	/* DBG(DEBUG_CACHE, blkid_debug_dump_cache(cache)); */
+
+	while (!list_empty(&cache->bic_devs)) {
+		blkid_dev dev = list_entry(cache->bic_devs.next,
+					   struct blkid_struct_dev,
+					    bid_devs);
+		blkid_free_dev(dev);
+	}
+
+	while (!list_empty(&cache->bic_tags)) {
+		blkid_tag tag = list_entry(cache->bic_tags.next,
+					   struct blkid_struct_tag,
+					   bit_tags);
+
+		while (!list_empty(&tag->bit_names)) {
+			blkid_tag bad = list_entry(tag->bit_names.next,
+						   struct blkid_struct_tag,
+						   bit_names);
+
+			DBG(DEBUG_CACHE, printf("warning: unfreed tag %s=%s\n",
+						bad->bit_name, bad->bit_val));
+			blkid_free_tag(bad);
+		}
+		blkid_free_tag(tag);
+	}
+	free(cache->bic_filename);
+
+	free(cache);
+}
+
+#ifdef TEST_PROGRAM
+int main(int argc, char** argv)
+{
+	blkid_cache cache = NULL;
+	int ret;
+
+	blkid_debug_mask = DEBUG_ALL;
+	if ((argc > 2)) {
+		fprintf(stderr, "Usage: %s [filename] \n", argv[0]);
+		exit(1);
+	}
+
+	if ((ret = blkid_get_cache(&cache, argv[1])) < 0) {
+		fprintf(stderr, "error %d parsing cache file %s\n", ret,
+			argv[1] ? argv[1] : BLKID_CACHE_FILE);
+		exit(1);
+	}
+	if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
+		fprintf(stderr, "%s: error creating cache (%d)\n",
+			argv[0], ret);
+		exit(1);
+	}
+	if ((ret = blkid_probe_all(cache) < 0))
+		fprintf(stderr, "error probing devices\n");
+
+	blkid_put_cache(cache);
+
+	return ret;
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/dev.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/dev.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/dev.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,213 @@
+/*
+ * dev.c - allocation/initialization/free routines for dev
+ *
+ * Copyright (C) 2001 Andreas Dilger
+ * Copyright (C) 2003 Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "blkidP.h"
+
+blkid_dev blkid_new_dev(void)
+{
+	blkid_dev dev;
+
+	if (!(dev = (blkid_dev) calloc(1, sizeof(struct blkid_struct_dev))))
+		return NULL;
+
+	INIT_LIST_HEAD(&dev->bid_devs);
+	INIT_LIST_HEAD(&dev->bid_tags);
+
+	return dev;
+}
+
+void blkid_free_dev(blkid_dev dev)
+{
+	if (!dev)
+		return;
+
+	DBG(DEBUG_DEV,
+	    printf("  freeing dev %s (%s)\n", dev->bid_name, dev->bid_type));
+	DBG(DEBUG_DEV, blkid_debug_dump_dev(dev));
+
+	list_del(&dev->bid_devs);
+	while (!list_empty(&dev->bid_tags)) {
+		blkid_tag tag = list_entry(dev->bid_tags.next,
+					   struct blkid_struct_tag,
+					   bit_tags);
+		blkid_free_tag(tag);
+	}
+	if (dev->bid_name)
+		free(dev->bid_name);
+	free(dev);
+}
+
+/*
+ * Given a blkid device, return its name
+ */
+const char *blkid_dev_devname(blkid_dev dev)
+{
+	return dev->bid_name;
+}
+
+#ifdef CONFIG_BLKID_DEBUG
+void blkid_debug_dump_dev(blkid_dev dev)
+{
+	struct list_head *p;
+
+	if (!dev) {
+		printf("  dev: NULL\n");
+		return;
+	}
+
+	printf("  dev: name = %s\n", dev->bid_name);
+	printf("  dev: DEVNO=\"0x%0llx\"\n", dev->bid_devno);
+	printf("  dev: TIME=\"%lu\"\n", dev->bid_time);
+	printf("  dev: PRI=\"%d\"\n", dev->bid_pri);
+	printf("  dev: flags = 0x%08X\n", dev->bid_flags);
+
+	list_for_each(p, &dev->bid_tags) {
+		blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
+		if (tag)   
+			printf("    tag: %s=\"%s\"\n", tag->bit_name, 
+			       tag->bit_val);
+		else
+			printf("    tag: NULL\n");
+	}
+	printf("\n");
+}
+#endif
+
+/*
+ * dev iteration routines for the public libblkid interface.
+ *
+ * These routines do not expose the list.h implementation, which are a
+ * contamination of the namespace, and which force us to reveal far, far
+ * too much of our internal implemenation.  I'm not convinced I want
+ * to keep list.h in the long term, anyway.  It's fine for kernel
+ * programming, but performance is not the #1 priority for this
+ * library, and I really don't like the tradeoff of type-safety for
+ * performance for this application.  [tytso:20030125.2007EST]
+ */
+
+/*
+ * This series of functions iterate over all devices in a blkid cache
+ */
+#define DEV_ITERATE_MAGIC	0x01a5284c
+
+struct blkid_struct_dev_iterate {
+	int			magic;
+	blkid_cache		cache;
+	struct list_head	*p;
+};
+
+blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache)
+{
+	blkid_dev_iterate	iter;
+
+	iter = xmalloc(sizeof(struct blkid_struct_dev_iterate));
+	iter->magic = DEV_ITERATE_MAGIC;
+	iter->cache = cache;
+	iter->p	= cache->bic_devs.next;
+	return (iter);
+}
+
+/*
+ * Return 0 on success, -1 on error
+ */
+extern int blkid_dev_next(blkid_dev_iterate iter,
+			  blkid_dev *dev)
+{
+	*dev = 0;
+	if (!iter || iter->magic != DEV_ITERATE_MAGIC ||
+	    iter->p == &iter->cache->bic_devs)
+		return -1;
+	*dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs);
+	iter->p = iter->p->next;
+	return 0;
+}
+
+void blkid_dev_iterate_end(blkid_dev_iterate iter)
+{
+	if (!iter || iter->magic != DEV_ITERATE_MAGIC)
+		return;
+	iter->magic = 0;
+	free(iter);
+}
+
+#ifdef TEST_PROGRAM
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern char *optarg;
+extern int optind;
+#endif
+
+void usage(char *prog)
+{
+	fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask]\n", prog);
+	fprintf(stderr, "\tList all devices and exit\n", prog);
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	blkid_dev_iterate	iter;
+	blkid_cache 		cache = NULL;
+	blkid_dev		dev;
+	int			c, ret;
+	char			*tmp;
+	char			*file = NULL;
+	char			*search_type = NULL;
+	char			*search_value = NULL;
+
+	while ((c = getopt (argc, argv, "m:f:")) != EOF)
+		switch (c) {
+		case 'f':
+			file = optarg;
+			break;
+		case 'm':
+			blkid_debug_mask = strtoul (optarg, &tmp, 0);
+			if (*tmp) {
+				fprintf(stderr, "Invalid debug mask: %d\n", 
+					optarg);
+				exit(1);
+			}
+			break;
+		case '?':
+			usage(argv[0]);
+		}
+	if (argc >= optind+2) {
+		search_type = argv[optind];
+		search_value = argv[optind+1];
+		optind += 2;
+	}
+	if (argc != optind)
+		usage(argv[0]);
+
+	if ((ret = blkid_get_cache(&cache, file)) != 0) {
+		fprintf(stderr, "%s: error creating cache (%d)\n",
+			argv[0], ret);
+		exit(1);
+	}
+
+	iter = blkid_dev_iterate_begin(cache);
+	if (search_type)
+		blkid_dev_set_search(iter, search_type, search_value);
+	while (blkid_dev_next(iter, &dev) == 0) {
+		printf("Device: %s\n", blkid_dev_devname(dev));
+	}
+	blkid_dev_iterate_end(iter);
+
+
+	blkid_put_cache(cache);
+	return (0);
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/devname.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/devname.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/devname.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,369 @@
+/*
+ * devname.c - get a dev by its device inode name
+ *
+ * Copyright (C) Andries Brouwer
+ * Copyright (C) 1999, 2000, 2001, 2002, 2003 Theodore Ts'o
+ * Copyright (C) 2001 Andreas Dilger
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_SYS_MKDEV_H
+#include <sys/mkdev.h>
+#endif
+#include <time.h>
+
+#include "blkidP.h"
+
+/*
+ * Find a dev struct in the cache by device name, if available.
+ *
+ * If there is no entry with the specified device name, and the create
+ * flag is set, then create an empty device entry.
+ */
+blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags)
+{
+	blkid_dev dev = NULL, tmp;
+	struct list_head *p;
+
+	if (!cache || !devname)
+		return NULL;
+
+	list_for_each(p, &cache->bic_devs) {
+		tmp = list_entry(p, struct blkid_struct_dev, bid_devs);
+		if (strcmp(tmp->bid_name, devname))
+			continue;
+
+		DBG(DEBUG_DEVNAME,
+		    printf("found devname %s in cache\n", tmp->bid_name));
+		dev = tmp;
+		break;
+	}
+
+	if (!dev && (flags & BLKID_DEV_CREATE)) {
+		dev = blkid_new_dev();
+		if (!dev)
+			return NULL;
+		dev->bid_name = blkid_strdup(devname);
+		dev->bid_cache = cache;
+		list_add_tail(&dev->bid_devs, &cache->bic_devs);
+		cache->bic_flags |= BLKID_BIC_FL_CHANGED;
+	}
+
+	if (flags & BLKID_DEV_VERIFY)
+		dev = blkid_verify(cache, dev);
+	return dev;
+}
+
+/*
+ * Probe a single block device to add to the device cache.
+ */
+static void probe_one(blkid_cache cache, const char *ptname,
+		      dev_t devno, int pri)
+{
+	blkid_dev dev = NULL;
+	struct list_head *p;
+	const char **dir;
+	char *devname = NULL;
+
+	/* See if we already have this device number in the cache. */
+	list_for_each(p, &cache->bic_devs) {
+		blkid_dev tmp = list_entry(p, struct blkid_struct_dev,
+					   bid_devs);
+		if (tmp->bid_devno == devno) {
+			dev = blkid_verify(cache, tmp);
+			break;
+		}
+	}
+	if (dev && dev->bid_devno == devno)
+		goto set_pri;
+
+	/*
+	 * Take a quick look at /dev/ptname for the device number.  We check
+	 * all of the likely device directories.  If we don't find it, or if
+	 * the stat information doesn't check out, use blkid_devno_to_devname()
+	 * to find it via an exhaustive search for the device major/minor.
+	 */
+	for (dir = blkid_devdirs; *dir; dir++) {
+		struct stat st;
+		char device[256];
+
+		sprintf(device, "%s/%s", *dir, ptname);
+		if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) &&
+		    dev->bid_devno == devno)
+			goto set_pri;
+
+		if (stat(device, &st) == 0 && S_ISBLK(st.st_mode) &&
+		    st.st_rdev == devno) {
+			devname = blkid_strdup(device);
+			break;
+		}
+	}
+	if (!devname) {
+		devname = blkid_devno_to_devname(devno);
+		if (!devname)
+			return;
+	}
+	dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL);
+	free(devname);
+
+set_pri:
+	if (!pri && !strncmp(ptname, "md", 2))
+		pri = BLKID_PRI_MD;
+	if (dev)
+		dev->bid_pri = pri;
+	return;
+}
+
+#define PROC_PARTITIONS "/proc/partitions"
+#define VG_DIR		"/proc/lvm/VGs"
+
+/*
+ * This function initializes the UUID cache with devices from the LVM
+ * proc hierarchy.  We currently depend on the names of the LVM
+ * hierarchy giving us the device structure in /dev.  (XXX is this a
+ * safe thing to do?)
+ */
+#ifdef VG_DIR
+#include <dirent.h>
+static dev_t lvm_get_devno(const char *lvm_device)
+{
+	FILE *lvf;
+	char buf[1024];
+	int ma, mi;
+	dev_t ret = 0;
+
+	DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device));
+	if ((lvf = fopen(lvm_device, "r")) == NULL) {
+		DBG(DEBUG_DEVNAME, printf("%s: (%d) %s\n", lvm_device, errno,
+					  strerror(errno)));
+		return 0;
+	}
+
+	while (fgets(buf, sizeof(buf), lvf)) {
+		if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) {
+			ret = makedev(ma, mi);
+			break;
+		}
+	}
+	fclose(lvf);
+
+	return ret;
+}
+
+static void lvm_probe_all(blkid_cache cache)
+{
+	DIR		*vg_list;
+	struct dirent	*vg_iter;
+	int		vg_len = strlen(VG_DIR);
+	dev_t		dev;
+
+	if ((vg_list = opendir(VG_DIR)) == NULL)
+		return;
+
+	DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR));
+
+	while ((vg_iter = readdir(vg_list)) != NULL) {
+		DIR		*lv_list;
+		char		*vdirname;
+		char		*vg_name;
+		struct dirent	*lv_iter;
+
+		vg_name = vg_iter->d_name;
+		if (!strcmp(vg_name, ".") || !strcmp(vg_name, ".."))
+			continue;
+		vdirname = xmalloc(vg_len + strlen(vg_name) + 8);
+		sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name);
+
+		lv_list = opendir(vdirname);
+		free(vdirname);
+		if (lv_list == NULL)
+			continue;
+
+		while ((lv_iter = readdir(lv_list)) != NULL) {
+			char		*lv_name, *lvm_device;
+
+			lv_name = lv_iter->d_name;
+			if (!strcmp(lv_name, ".") || !strcmp(lv_name, ".."))
+				continue;
+
+			lvm_device = xmalloc(vg_len + strlen(vg_name) +
+					    strlen(lv_name) + 8);
+			sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name,
+				lv_name);
+			dev = lvm_get_devno(lvm_device);
+			sprintf(lvm_device, "%s/%s", vg_name, lv_name);
+			DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n",
+						  lvm_device,
+						  (unsigned int) dev));
+			probe_one(cache, lvm_device, dev, BLKID_PRI_LVM);
+			free(lvm_device);
+		}
+		closedir(lv_list);
+	}
+	closedir(vg_list);
+}
+#endif
+
+#define PROC_EVMS_VOLUMES "/proc/evms/volumes"
+
+static int
+evms_probe_all(blkid_cache cache)
+{
+	char line[100];
+	int ma, mi, sz, num = 0;
+	FILE *procpt;
+	char device[110];
+
+	procpt = fopen(PROC_EVMS_VOLUMES, "r");
+	if (!procpt)
+		return 0;
+	while (fgets(line, sizeof(line), procpt)) {
+		if (sscanf (line, " %d %d %d %*s %*s %[^\n ]",
+			    &ma, &mi, &sz, device) != 4)
+			continue;
+
+		DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n",
+					  device, ma, mi));
+
+		probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS);
+		num++;
+	}
+	fclose(procpt);
+	return num;
+}
+
+/*
+ * Read the device data for all available block devices in the system.
+ */
+int blkid_probe_all(blkid_cache cache)
+{
+	FILE *proc;
+	char line[1024];
+	char ptname0[128], ptname1[128], *ptname = 0;
+	char *ptnames[2];
+	dev_t devs[2];
+	int ma, mi;
+	unsigned long long sz;
+	int lens[2] = { 0, 0 };
+	int which = 0, last = 0;
+
+	ptnames[0] = ptname0;
+	ptnames[1] = ptname1;
+
+	if (!cache)
+		return -BLKID_ERR_PARAM;
+
+	if (cache->bic_flags & BLKID_BIC_FL_PROBED &&
+	    time(0) - cache->bic_time < BLKID_PROBE_INTERVAL)
+		return 0;
+
+	blkid_read_cache(cache);
+	evms_probe_all(cache);
+#ifdef VG_DIR
+	lvm_probe_all(cache);
+#endif
+
+	proc = fopen(PROC_PARTITIONS, "r");
+	if (!proc)
+		return -BLKID_ERR_PROC;
+
+	while (fgets(line, sizeof(line), proc)) {
+		last = which;
+		which ^= 1;
+		ptname = ptnames[which];
+
+		if (sscanf(line, " %d %d %llu %128[^\n ]",
+			   &ma, &mi, &sz, ptname) != 4)
+			continue;
+		devs[which] = makedev(ma, mi);
+
+		DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname));
+
+		/* Skip whole disk devs unless they have no partitions
+		 * If we don't have a partition on this dev, also
+		 * check previous dev to see if it didn't have a partn.
+		 * heuristic: partition name ends in a digit.
+		 *
+		 * Skip extended partitions.
+		 * heuristic: size is 1
+		 *
+		 * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs
+		 */
+
+		lens[which] = strlen(ptname);
+		if (isdigit(ptname[lens[which] - 1])) {
+			DBG(DEBUG_DEVNAME,
+			    printf("partition dev %s, devno 0x%04X\n",
+				   ptname, (unsigned int) devs[which]));
+
+			if (sz > 1)
+				probe_one(cache, ptname, devs[which], 0);
+			lens[which] = 0;
+			lens[last] = 0;
+		} else if (lens[last] && strncmp(ptnames[last], ptname,
+						 lens[last])) {
+			DBG(DEBUG_DEVNAME,
+			    printf("whole dev %s, devno 0x%04X\n",
+				   ptnames[last], (unsigned int) devs[last]));
+			probe_one(cache, ptnames[last], devs[last], 0);
+			lens[last] = 0;
+		}
+	}
+
+	/* Handle the last device if it wasn't partitioned */
+	if (lens[which])
+		probe_one(cache, ptname, devs[which], 0);
+
+	fclose(proc);
+
+	cache->bic_time = time(0);
+	cache->bic_flags |= BLKID_BIC_FL_PROBED;
+	blkid_flush_cache(cache);
+	return 0;
+}
+
+#ifdef TEST_PROGRAM
+int main(int argc, char **argv)
+{
+	blkid_cache cache = NULL;
+	int ret;
+
+	blkid_debug_mask = DEBUG_ALL;
+	if (argc != 1) {
+		fprintf(stderr, "Usage: %s\n"
+			"Probe all devices and exit\n", argv[0]);
+		exit(1);
+	}
+	if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
+		fprintf(stderr, "%s: error creating cache (%d)\n",
+			argv[0], ret);
+		exit(1);
+	}
+	if (blkid_probe_all(cache) < 0)
+		printf("%s: error probing devices\n", argv[0]);
+
+	blkid_put_cache(cache);
+	return (0);
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/devno.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/devno.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/devno.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,224 @@
+/*
+ * devno.c - find a particular device by its device number (major/minor)
+ *
+ * Copyright (C) 2000, 2001, 2003 Theodore Ts'o
+ * Copyright (C) 2001 Andreas Dilger
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#include <dirent.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_SYS_MKDEV_H
+#include <sys/mkdev.h>
+#endif
+
+#include "blkidP.h"
+
+struct dir_list {
+	char	*name;
+	struct dir_list *next;
+};
+
+char *blkid_strndup(const char *s, int length)
+{
+	char *ret;
+
+	if (!s)
+		return NULL;
+
+	if (!length)
+		length = strlen(s);
+
+	ret = xmalloc(length + 1);
+	strncpy(ret, s, length);
+	ret[length] = '\0';
+	return ret;
+}
+
+char *blkid_strdup(const char *s)
+{
+	return blkid_strndup(s, 0);
+}
+
+/*
+ * This function adds an entry to the directory list
+ */
+static void add_to_dirlist(const char *name, struct dir_list **list)
+{
+	struct dir_list *dp;
+
+	dp = xmalloc(sizeof(struct dir_list));
+	dp->name = blkid_strdup(name);
+	dp->next = *list;
+	*list = dp;
+}
+
+/*
+ * This function frees a directory list
+ */
+static void free_dirlist(struct dir_list **list)
+{
+	struct dir_list *dp, *next;
+
+	for (dp = *list; dp; dp = next) {
+		next = dp->next;
+		free(dp->name);
+		free(dp);
+	}
+	*list = NULL;
+}
+
+static void scan_dir(char *dir_name, dev_t devno, struct dir_list **list,
+			    char **devname)
+{
+	DIR	*dir;
+	struct dirent *dp;
+	char	path[1024];
+	int	dirlen;
+	struct stat st;
+
+	if ((dir = opendir(dir_name)) == NULL)
+		return;
+	dirlen = strlen(dir_name) + 2;
+	while ((dp = readdir(dir)) != 0) {
+		if (dirlen + strlen(dp->d_name) >= sizeof(path))
+			continue;
+
+		if (dp->d_name[0] == '.' &&
+		    ((dp->d_name[1] == 0) ||
+		     ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
+			continue;
+
+		sprintf(path, "%s/%s", dir_name, dp->d_name);
+		if (stat(path, &st) < 0)
+			continue;
+
+		if (S_ISDIR(st.st_mode))
+			add_to_dirlist(path, list);
+		else if (S_ISBLK(st.st_mode) && st.st_rdev == devno) {
+			*devname = blkid_strdup(path);
+			DBG(DEBUG_DEVNO,
+			    printf("found 0x%llx at %s (%p)\n", devno,
+				   path, *devname));
+			break;
+		}
+	}
+	closedir(dir);
+	return;
+}
+
+/* Directories where we will try to search for device numbers */
+const char *blkid_devdirs[] = { "/devices", "/devfs", "/dev", NULL };
+
+/*
+ * This function finds the pathname to a block device with a given
+ * device number.  It returns a pointer to allocated memory to the
+ * pathname on success, and NULL on failure.
+ */
+char *blkid_devno_to_devname(dev_t devno)
+{
+	struct dir_list *list = NULL, *new_list = NULL;
+	char *devname = NULL;
+	const char **dir;
+
+	/*
+	 * Add the starting directories to search in reverse order of
+	 * importance, since we are using a stack...
+	 */
+	for (dir = blkid_devdirs; *dir; dir++)
+		add_to_dirlist(*dir, &list);
+
+	while (list) {
+		struct dir_list *current = list;
+
+		list = list->next;
+		DBG(DEBUG_DEVNO, printf("directory %s\n", current->name));
+		scan_dir(current->name, devno, &new_list, &devname);
+		free(current->name);
+		free(current);
+		if (devname)
+			break;
+		/*
+		 * If we're done checking at this level, descend to
+		 * the next level of subdirectories. (breadth-first)
+		 */
+		if (list == NULL) {
+			list = new_list;
+			new_list = NULL;
+		}
+	}
+	free_dirlist(&list);
+	free_dirlist(&new_list);
+
+	if (!devname) {
+		DBG(DEBUG_DEVNO,
+		    printf("blkid: couldn't find devno 0x%04lx\n",
+			   (unsigned long) devno));
+	} else {
+		DBG(DEBUG_DEVNO,
+		    printf("found devno 0x%04llx as %s\n", devno, devname));
+	}
+
+
+	return devname;
+}
+
+#ifdef TEST_PROGRAM
+int main(int argc, char** argv)
+{
+	char	*devname, *tmp;
+	int	major, minor;
+	dev_t	devno;
+	const char *errmsg = "Couldn't parse %s: %s\n";
+
+	blkid_debug_mask = DEBUG_ALL;
+	if ((argc != 2) && (argc != 3)) {
+		fprintf(stderr, "Usage:\t%s device_number\n\t%s major minor\n"
+			"Resolve a device number to a device name\n",
+			argv[0], argv[0]);
+		exit(1);
+	}
+	if (argc == 2) {
+		devno = strtoul(argv[1], &tmp, 0);
+		if (*tmp) {
+			fprintf(stderr, errmsg, "device number", argv[1]);
+			exit(1);
+		}
+	} else {
+		major = strtoul(argv[1], &tmp, 0);
+		if (*tmp) {
+			fprintf(stderr, errmsg, "major number", argv[1]);
+			exit(1);
+		}
+		minor = strtoul(argv[2], &tmp, 0);
+		if (*tmp) {
+			fprintf(stderr, errmsg, "minor number", argv[2]);
+			exit(1);
+		}
+		devno = makedev(major, minor);
+	}
+	printf("Looking for device 0x%04Lx\n", devno);
+	devname = blkid_devno_to_devname(devno);
+	free(devname);
+	return 0;
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/list.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/list.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/list.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,179 @@
+#if !defined(_BLKID_LIST_H) && !defined(LIST_HEAD)
+#define _BLKID_LIST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __GNUC__
+#define _INLINE_ static __inline__
+#else                         /* For Watcom C */
+#define _INLINE_ static inline
+#endif
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+	struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+	struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+_INLINE_ void __list_add(struct list_head * add,
+	struct list_head * prev,
+	struct list_head * next)
+{
+	next->prev = add;
+	add->next = next;
+	add->prev = prev;
+	prev->next = add;
+}
+
+/**
+ * list_add - add a new entry
+ * @add:	new entry to be added
+ * @head:	list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+_INLINE_ void list_add(struct list_head *add, struct list_head *head)
+{
+	__list_add(add, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @add:	new entry to be added
+ * @head:	list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+_INLINE_ void list_add_tail(struct list_head *add, struct list_head *head)
+{
+	__list_add(add, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+_INLINE_ void __list_del(struct list_head * prev,
+				  struct list_head * next)
+{
+	next->prev = prev;
+	prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry:	the element to delete from the list.
+ *
+ * list_empty() on @entry does not return true after this, @entry is
+ * in an undefined state.
+ */
+_INLINE_ void list_del(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry:	the element to delete from the list.
+ */
+_INLINE_ void list_del_init(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+	INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head:	the list to test.
+ */
+_INLINE_ int list_empty(struct list_head *head)
+{
+	return head->next == head;
+}
+
+/**
+ * list_splice - join two lists
+ * @list:	the new list to add.
+ * @head:	the place to add it in the first list.
+ */
+_INLINE_ void list_splice(struct list_head *list, struct list_head *head)
+{
+	struct list_head *first = list->next;
+
+	if (first != list) {
+		struct list_head *last = list->prev;
+		struct list_head *at = head->next;
+
+		first->prev = head;
+		head->next = first;
+
+		last->next = at;
+		at->prev = last;
+	}
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:	the &struct list_head pointer.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+	((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+/**
+ * list_for_each - iterate over elements in a list
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @head:	the head for your list.
+ */
+#define list_for_each(pos, head) \
+	for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_safe - iterate over elements in a list, but don't dereference
+ *                      pos after the body is done (in case it is freed)
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @pnext:	the &struct list_head to use as a pointer to the next item.
+ * @head:	the head for your list (not included in iteration).
+ */
+#define list_for_each_safe(pos, pnext, head) \
+	for (pos = (head)->next, pnext = pos->next; pos != (head); \
+	     pos = pnext, pnext = pos->next)
+
+#undef _INLINE_
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BLKID_LIST_H */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/probe.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/probe.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/probe.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,720 @@
+/*
+ * probe.c - identify a block device by its contents, and return a dev
+ *           struct with the details
+ *
+ * Copyright (C) 1999 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2001 by Andreas Dilger
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_MKDEV_H
+#include <sys/mkdev.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include "blkidP.h"
+#include "../uuid/uuid.h"
+#include "probe.h"
+
+/*
+ * This is a special case code to check for an MDRAID device.  We do
+ * this special since it requires checking for a superblock at the end
+ * of the device.
+ */
+static int check_mdraid(int fd, unsigned char *ret_uuid)
+{
+	struct mdp_superblock_s *md;
+	blkid_loff_t		offset;
+	char			buf[4096];
+
+	if (fd < 0)
+		return -BLKID_ERR_PARAM;
+
+	offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536;
+
+	if (blkid_llseek(fd, offset, 0) < 0 ||
+	    read(fd, buf, 4096) != 4096)
+		return -BLKID_ERR_IO;
+
+	/* Check for magic number */
+	if (memcmp("\251+N\374", buf, 4))
+		return -BLKID_ERR_PARAM;
+
+	if (!ret_uuid)
+		return 0;
+	*ret_uuid = 0;
+
+	/* The MD UUID is not contiguous in the superblock, make it so */
+	md = (struct mdp_superblock_s *)buf;
+	if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) {
+		memcpy(ret_uuid, &md->set_uuid0, 4);
+		memcpy(ret_uuid, &md->set_uuid1, 12);
+	}
+	return 0;
+}
+
+static void set_uuid(blkid_dev dev, uuid_t uuid)
+{
+	char	str[37];
+
+	if (!uuid_is_null(uuid)) {
+		uuid_unparse(uuid, str);
+		blkid_set_tag(dev, "UUID", str, sizeof(str));
+	}
+}
+
+static void get_ext2_info(blkid_dev dev, unsigned char *buf)
+{
+	struct ext2_super_block *es = (struct ext2_super_block *) buf;
+	const char *label = 0;
+
+	DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n",
+		   blkid_le32(es->s_feature_compat),
+		   blkid_le32(es->s_feature_incompat),
+		   blkid_le32(es->s_feature_ro_compat)));
+
+	if (strlen(es->s_volume_name))
+		label = es->s_volume_name;
+	blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name));
+
+	set_uuid(dev, es->s_uuid);
+}
+
+static int probe_ext3(int fd __BLKID_ATTR((unused)),
+		      blkid_cache cache __BLKID_ATTR((unused)),
+		      blkid_dev dev,
+		      const struct blkid_magic *id __BLKID_ATTR((unused)), 
+		      unsigned char *buf)
+{
+	struct ext2_super_block *es;
+
+	es = (struct ext2_super_block *)buf;
+
+	/* Distinguish between jbd and ext2/3 fs */
+	if (blkid_le32(es->s_feature_incompat) &
+	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
+		return -BLKID_ERR_PARAM;
+
+	/* Distinguish between ext3 and ext2 */
+	if (!(blkid_le32(es->s_feature_compat) &
+	      EXT3_FEATURE_COMPAT_HAS_JOURNAL))
+		return -BLKID_ERR_PARAM;
+
+	get_ext2_info(dev, buf);
+
+	blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2"));
+
+	return 0;
+}
+
+static int probe_ext2(int fd __BLKID_ATTR((unused)),
+		      blkid_cache cache __BLKID_ATTR((unused)),
+		      blkid_dev dev,
+		      const struct blkid_magic *id __BLKID_ATTR((unused)), 
+		      unsigned char *buf)
+{
+	struct ext2_super_block *es;
+
+	es = (struct ext2_super_block *)buf;
+
+	/* Distinguish between jbd and ext2/3 fs */
+	if (blkid_le32(es->s_feature_incompat) &
+	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
+		return -BLKID_ERR_PARAM;
+
+	get_ext2_info(dev, buf);
+
+	return 0;
+}
+
+static int probe_jbd(int fd __BLKID_ATTR((unused)),
+		     blkid_cache cache __BLKID_ATTR((unused)),
+		     blkid_dev dev,
+		     const struct blkid_magic *id __BLKID_ATTR((unused)),
+		     unsigned char *buf)
+{
+	struct ext2_super_block *es = (struct ext2_super_block *) buf;
+
+	if (!(blkid_le32(es->s_feature_incompat) &
+	      EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
+		return -BLKID_ERR_PARAM;
+
+	get_ext2_info(dev, buf);
+
+	return 0;
+}
+
+static int probe_vfat(int fd __BLKID_ATTR((unused)),
+		      blkid_cache cache __BLKID_ATTR((unused)),
+		      blkid_dev dev,
+		      const struct blkid_magic *id __BLKID_ATTR((unused)),
+		      unsigned char *buf)
+{
+	struct vfat_super_block *vs;
+	char serno[10];
+	const char *label = 0;
+	int label_len = 0;
+
+	vs = (struct vfat_super_block *)buf;
+
+	if (strncmp(vs->vs_label, "NO NAME", 7)) {
+		char *end = vs->vs_label + sizeof(vs->vs_label) - 1;
+
+		while (*end == ' ' && end >= vs->vs_label)
+			--end;
+		if (end >= vs->vs_label) {
+			label = vs->vs_label;
+			label_len = end - vs->vs_label + 1;
+		}
+	}
+
+	/* We can't just print them as %04X, because they are unaligned */
+	sprintf(serno, "%02X%02X-%02X%02X", vs->vs_serno[3], vs->vs_serno[2],
+		vs->vs_serno[1], vs->vs_serno[0]);
+	blkid_set_tag(dev, "LABEL", label, label_len);
+	blkid_set_tag(dev, "UUID", serno, sizeof(serno));
+
+	return 0;
+}
+
+static int probe_msdos(int fd __BLKID_ATTR((unused)),
+		       blkid_cache cache __BLKID_ATTR((unused)),
+		       blkid_dev dev,
+		       const struct blkid_magic *id __BLKID_ATTR((unused)),
+		       unsigned char *buf)
+{
+	struct msdos_super_block *ms = (struct msdos_super_block *) buf;
+	char serno[10];
+	const char *label = 0;
+	int label_len = 0;
+
+	if (strncmp(ms->ms_label, "NO NAME", 7)) {
+		char *end = ms->ms_label + sizeof(ms->ms_label) - 1;
+
+		while (*end == ' ' && end >= ms->ms_label)
+			--end;
+		if (end >= ms->ms_label) {
+			label = ms->ms_label;
+			label_len = end - ms->ms_label + 1;
+		}
+	}
+
+	/* We can't just print them as %04X, because they are unaligned */
+	sprintf(serno, "%02X%02X-%02X%02X", ms->ms_serno[3], ms->ms_serno[2],
+		ms->ms_serno[1], ms->ms_serno[0]);
+	blkid_set_tag(dev, "UUID", serno, 0);
+	blkid_set_tag(dev, "LABEL", label, label_len);
+	blkid_set_tag(dev, "SEC_TYPE", "msdos", sizeof("msdos"));
+
+	return 0;
+}
+
+static int probe_xfs(int fd __BLKID_ATTR((unused)),
+		     blkid_cache cache __BLKID_ATTR((unused)),
+		     blkid_dev dev,
+		     const struct blkid_magic *id __BLKID_ATTR((unused)),
+		     unsigned char *buf)
+{
+	struct xfs_super_block *xs;
+	const char *label = 0;
+
+	xs = (struct xfs_super_block *)buf;
+
+	if (strlen(xs->xs_fname))
+		label = xs->xs_fname;
+	blkid_set_tag(dev, "LABEL", label, sizeof(xs->xs_fname));
+	set_uuid(dev, xs->xs_uuid);
+	return 0;
+}
+
+static int probe_reiserfs(int fd __BLKID_ATTR((unused)),
+			  blkid_cache cache __BLKID_ATTR((unused)),
+			  blkid_dev dev,
+			  const struct blkid_magic *id, unsigned char *buf)
+{
+	struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf;
+	unsigned int blocksize;
+	const char *label = 0;
+
+	blocksize = blkid_le16(rs->rs_blocksize);
+
+	/* If the superblock is inside the journal, we have the wrong one */
+	if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block))
+		return -BLKID_ERR_BIG;
+
+	/* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
+	if (!strcmp(id->bim_magic, "ReIsEr2Fs") ||
+	    !strcmp(id->bim_magic, "ReIsEr3Fs")) {
+		if (strlen(rs->rs_label))
+			label = rs->rs_label;
+		set_uuid(dev, rs->rs_uuid);
+	}
+	blkid_set_tag(dev, "LABEL", label, sizeof(rs->rs_label));
+
+	return 0;
+}
+
+static int probe_jfs(int fd __BLKID_ATTR((unused)),
+		     blkid_cache cache __BLKID_ATTR((unused)),
+		     blkid_dev dev,
+		     const struct blkid_magic *id __BLKID_ATTR((unused)),
+		     unsigned char *buf)
+{
+	struct jfs_super_block *js;
+	const char *label = 0;
+
+	js = (struct jfs_super_block *)buf;
+
+	if (strlen((char *) js->js_label))
+		label = (char *) js->js_label;
+	blkid_set_tag(dev, "LABEL", label, sizeof(js->js_label));
+	set_uuid(dev, js->js_uuid);
+	return 0;
+}
+
+static int probe_romfs(int fd __BLKID_ATTR((unused)),
+		       blkid_cache cache __BLKID_ATTR((unused)),
+		       blkid_dev dev,
+		       const struct blkid_magic *id __BLKID_ATTR((unused)),
+		       unsigned char *buf)
+{
+	struct romfs_super_block *ros;
+	const char *label = 0;
+
+	ros = (struct romfs_super_block *)buf;
+
+	if (strlen((char *) ros->ros_volume))
+		label = (char *) ros->ros_volume;
+	blkid_set_tag(dev, "LABEL", label, 0);
+	return 0;
+}
+
+static int probe_cramfs(int fd __BLKID_ATTR((unused)), 
+		       blkid_cache cache __BLKID_ATTR((unused)), 
+		       blkid_dev dev,
+		       const struct blkid_magic *id __BLKID_ATTR((unused)), 
+		       unsigned char *buf)
+{
+	struct cramfs_super_block *csb;
+	const char *label = 0;
+
+	csb = (struct cramfs_super_block *)buf;
+
+	if (strlen((char *) csb->name))
+		label = (char *) csb->name;
+	blkid_set_tag(dev, "LABEL", label, 0);
+	return 0;
+}
+
+static int probe_swap0(int fd __BLKID_ATTR((unused)),
+		       blkid_cache cache __BLKID_ATTR((unused)),
+		       blkid_dev dev,
+		       const struct blkid_magic *id __BLKID_ATTR((unused)),
+		       unsigned char *buf __BLKID_ATTR((unused)))
+{
+	blkid_set_tag(dev, "UUID", 0, 0);
+	blkid_set_tag(dev, "LABEL", 0, 0);
+	return 0;
+}
+
+static int probe_swap1(int fd,
+		       blkid_cache cache __BLKID_ATTR((unused)),
+		       blkid_dev dev,
+		       const struct blkid_magic *id __BLKID_ATTR((unused)),
+		       unsigned char *buf __BLKID_ATTR((unused)))
+{
+	struct swap_id_block *sws;
+
+	probe_swap0(fd, cache, dev, id, buf);
+	/*
+	 * Version 1 swap headers are always located at offset of 1024
+	 * bytes, although the swap signature itself is located at the
+	 * end of the page (which may vary depending on hardware
+	 * pagesize).
+	 */
+	if (lseek(fd, 1024, SEEK_SET) < 0) return 1;
+	sws = (struct swap_id_block *)xmalloc(1024);
+	if (read(fd, sws, 1024) != 1024) {
+		free(sws);
+		return 1;
+	}
+
+	/* arbitrary sanity check.. is there any garbage down there? */
+	if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0)  {
+		if (sws->sws_volume[0])
+			blkid_set_tag(dev, "LABEL", (const char*)sws->sws_volume,
+				      sizeof(sws->sws_volume));
+		if (sws->sws_uuid[0])
+			set_uuid(dev, sws->sws_uuid);
+	}
+	free(sws);
+
+	return 0;
+}
+
+static const char
+* const udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
+		 "NSR03", "TEA01", 0 };
+
+static int probe_udf(int fd, blkid_cache cache __BLKID_ATTR((unused)),
+		     blkid_dev dev __BLKID_ATTR((unused)),
+		     const struct blkid_magic *id __BLKID_ATTR((unused)),
+		     unsigned char *buf __BLKID_ATTR((unused)))
+{
+	int j, bs;
+	struct iso_volume_descriptor isosb;
+	const char * const * m;
+
+	/* determine the block size by scanning in 2K increments
+	   (block sizes larger than 2K will be null padded) */
+	for (bs = 1; bs < 16; bs++) {
+		lseek(fd, bs*2048+32768, SEEK_SET);
+		if (read(fd, (char *)&isosb, sizeof(isosb)) != sizeof(isosb))
+			return 1;
+		if (isosb.id[0])
+			break;
+	}
+
+	/* Scan up to another 64 blocks looking for additional VSD's */
+	for (j = 1; j < 64; j++) {
+		if (j > 1) {
+			lseek(fd, j*bs*2048+32768, SEEK_SET);
+			if (read(fd, (char *)&isosb, sizeof(isosb))
+			    != sizeof(isosb))
+				return 1;
+		}
+		/* If we find NSR0x then call it udf:
+		   NSR01 for UDF 1.00
+		   NSR02 for UDF 1.50
+		   NSR03 for UDF 2.00 */
+		if (!strncmp(isosb.id, "NSR0", 4))
+			return 0;
+		for (m = udf_magic; *m; m++)
+			if (!strncmp(*m, isosb.id, 5))
+				break;
+		if (*m == 0)
+			return 1;
+	}
+	return 1;
+}
+
+static int probe_ocfs(int fd __BLKID_ATTR((unused)),
+		      blkid_cache cache __BLKID_ATTR((unused)),
+		      blkid_dev dev,
+		      const struct blkid_magic *id __BLKID_ATTR((unused)),
+		      unsigned char *buf)
+{
+	struct ocfs_volume_header ovh;
+	struct ocfs_volume_label ovl;
+	__u32 major;
+
+	memcpy(&ovh, buf, sizeof(ovh));
+	memcpy(&ovl, buf+512, sizeof(ovl));
+
+	major = ocfsmajor(ovh);
+	if (major == 1)
+		blkid_set_tag(dev,"SEC_TYPE","ocfs1",sizeof("ocfs1"));
+	else if (major >= 9)
+		blkid_set_tag(dev,"SEC_TYPE","ntocfs",sizeof("ntocfs"));
+
+	blkid_set_tag(dev, "LABEL", (const char*)ovl.label, ocfslabellen(ovl));
+	blkid_set_tag(dev, "MOUNT", (const char*)ovh.mount, ocfsmountlen(ovh));
+	set_uuid(dev, ovl.vol_id);
+	return 0;
+}
+
+static int probe_ocfs2(int fd __BLKID_ATTR((unused)),
+		       blkid_cache cache __BLKID_ATTR((unused)),
+		       blkid_dev dev,
+		       const struct blkid_magic *id __BLKID_ATTR((unused)),
+		       unsigned char *buf)
+{
+	struct ocfs2_super_block *osb;
+
+	osb = (struct ocfs2_super_block *)buf;
+
+	blkid_set_tag(dev, "LABEL", (const char*)osb->s_label, sizeof(osb->s_label));
+	set_uuid(dev, osb->s_uuid);
+	return 0;
+}
+
+static int probe_oracleasm(int fd __BLKID_ATTR((unused)),
+			   blkid_cache cache __BLKID_ATTR((unused)),
+			   blkid_dev dev,
+			   const struct blkid_magic *id __BLKID_ATTR((unused)),
+			   unsigned char *buf)
+{
+	struct oracle_asm_disk_label *dl;
+
+	dl = (struct oracle_asm_disk_label *)buf;
+
+	blkid_set_tag(dev, "LABEL", dl->dl_id, sizeof(dl->dl_id));
+	return 0;
+}
+
+/*
+ * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined
+ * in the type_array table below + bim_kbalign.
+ *
+ * When probing for a lot of magics, we handle everything in 1kB buffers so
+ * that we don't have to worry about reading each combination of block sizes.
+ */
+#define BLKID_BLK_OFFS	64	/* currently reiserfs */
+
+/*
+ * Various filesystem magics that we can check for.  Note that kboff and
+ * sboff are in kilobytes and bytes respectively.  All magics are in
+ * byte strings so we don't worry about endian issues.
+ */
+static const struct blkid_magic type_array[] = {
+/*  type     kboff   sboff len  magic			probe */
+  { "oracleasm", 0,	32,  8, "ORCLDISK",		probe_oracleasm },
+  { "ntfs",      0,      3,  8, "NTFS    ",             0 },
+  { "jbd",	 1,   0x38,  2, "\123\357",		probe_jbd },
+  { "ext3",	 1,   0x38,  2, "\123\357",		probe_ext3 },
+  { "ext2",	 1,   0x38,  2, "\123\357",		probe_ext2 },
+  { "reiserfs",	 8,   0x34,  8, "ReIsErFs",		probe_reiserfs },
+  { "reiserfs", 64,   0x34,  9, "ReIsEr2Fs",		probe_reiserfs },
+  { "reiserfs", 64,   0x34,  9, "ReIsEr3Fs",		probe_reiserfs },
+  { "reiserfs", 64,   0x34,  8, "ReIsErFs",		probe_reiserfs },
+  { "reiserfs",	 8,	20,  8, "ReIsErFs",		probe_reiserfs },
+  { "vfat",      0,   0x52,  5, "MSWIN",                probe_vfat },
+  { "vfat",      0,   0x52,  8, "FAT32   ",             probe_vfat },
+  { "vfat",      0,   0x36,  5, "MSDOS",                probe_msdos },
+  { "vfat",      0,   0x36,  8, "FAT16   ",             probe_msdos },
+  { "vfat",      0,   0x36,  8, "FAT12   ",             probe_msdos },
+  { "minix",     1,   0x10,  2, "\177\023",             0 },
+  { "minix",     1,   0x10,  2, "\217\023",             0 },
+  { "minix",	 1,   0x10,  2, "\150\044",		0 },
+  { "minix",	 1,   0x10,  2, "\170\044",		0 },
+  { "vxfs",	 1,	 0,  4, "\365\374\001\245",	0 },
+  { "xfs",	 0,	 0,  4, "XFSB",			probe_xfs },
+  { "romfs",	 0,	 0,  8, "-rom1fs-",		probe_romfs },
+  { "bfs",	 0,	 0,  4, "\316\372\173\033",	0 },
+  { "cramfs",	 0,	 0,  4, "E=\315\050",		probe_cramfs },
+  { "qnx4",	 0,	 4,  6, "QNX4FS",		0 },
+  { "udf",	32,	 1,  5, "BEA01",		probe_udf },
+  { "udf",	32,	 1,  5, "BOOT2",		probe_udf },
+  { "udf",	32,	 1,  5, "CD001",		probe_udf },
+  { "udf",	32,	 1,  5, "CDW02",		probe_udf },
+  { "udf",	32,	 1,  5, "NSR02",		probe_udf },
+  { "udf",	32,	 1,  5, "NSR03",		probe_udf },
+  { "udf",	32,	 1,  5, "TEA01",		probe_udf },
+  { "iso9660",	32,	 1,  5, "CD001",		0 },
+  { "iso9660",	32,	 9,  5, "CDROM",		0 },
+  { "jfs",	32,	 0,  4, "JFS1",			probe_jfs },
+  { "hfs",	 1,	 0,  2, "BD",			0 },
+  { "ufs",	 8,  0x55c,  4, "T\031\001\000",	0 },
+  { "hpfs",	 8,	 0,  4, "I\350\225\371",	0 },
+  { "sysv",	 0,  0x3f8,  4, "\020~\030\375",	0 },
+  { "swap",	 0,  0xff6, 10, "SWAP-SPACE",		probe_swap0 },
+  { "swap",	 0,  0xff6, 10, "SWAPSPACE2",		probe_swap1 },
+  { "swap",	 0, 0x1ff6, 10, "SWAP-SPACE",		probe_swap0 },
+  { "swap",	 0, 0x1ff6, 10, "SWAPSPACE2",		probe_swap1 },
+  { "swap",	 0, 0x3ff6, 10, "SWAP-SPACE",		probe_swap0 },
+  { "swap",	 0, 0x3ff6, 10, "SWAPSPACE2",		probe_swap1 },
+  { "swap",	 0, 0x7ff6, 10, "SWAP-SPACE",		probe_swap0 },
+  { "swap",	 0, 0x7ff6, 10, "SWAPSPACE2",		probe_swap1 },
+  { "swap",	 0, 0xfff6, 10, "SWAP-SPACE",		probe_swap0 },
+  { "swap",	 0, 0xfff6, 10, "SWAPSPACE2",		probe_swap1 },
+  { "ocfs",	 0,	 8,  9,	"OracleCFS",		probe_ocfs },
+  { "ocfs2",	 1,	 0,  6,	"OCFSV2",		probe_ocfs2 },
+  { "ocfs2",	 2,	 0,  6,	"OCFSV2",		probe_ocfs2 },
+  { "ocfs2",	 4,	 0,  6,	"OCFSV2",		probe_ocfs2 },
+  { "ocfs2",	 8,	 0,  6,	"OCFSV2",		probe_ocfs2 },
+  {   NULL,	 0,	 0,  0, NULL,			NULL }
+};
+
+/*
+ * Verify that the data in dev is consistent with what is on the actual
+ * block device (using the devname field only).  Normally this will be
+ * called when finding items in the cache, but for long running processes
+ * is also desirable to revalidate an item before use.
+ *
+ * If we are unable to revalidate the data, we return the old data and
+ * do not set the BLKID_BID_FL_VERIFIED flag on it.
+ */
+blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
+{
+	const struct blkid_magic *id;
+	unsigned char *bufs[BLKID_BLK_OFFS + 1], *buf;
+	const char *type;
+	struct stat st;
+	time_t diff, now;
+	int fd, idx;
+
+	if (!dev)
+		return NULL;
+
+	now = time(0);
+	diff = now - dev->bid_time;
+
+	if ((now < dev->bid_time) ||
+	    (diff < BLKID_PROBE_MIN) ||
+	    (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
+	     diff < BLKID_PROBE_INTERVAL))
+		return dev;
+
+	DBG(DEBUG_PROBE,
+	    printf("need to revalidate %s (time since last check %lu)\n",
+		   dev->bid_name, diff));
+
+	if (((fd = open(dev->bid_name, O_RDONLY)) < 0) ||
+	    (fstat(fd, &st) < 0)) {
+		if (errno == ENXIO || errno == ENODEV || errno == ENOENT) {
+			blkid_free_dev(dev);
+			return NULL;
+		}
+		/* We don't have read permission, just return cache data. */
+		DBG(DEBUG_PROBE,
+		    printf("returning unverified data for %s\n",
+			   dev->bid_name));
+		return dev;
+	}
+
+	memset(bufs, 0, sizeof(bufs));
+
+	/*
+	 * Iterate over the type array.  If we already know the type,
+	 * then try that first.  If it doesn't work, then blow away
+	 * the type information, and try again.
+	 *
+	 */
+try_again:
+	type = 0;
+	if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) {
+		uuid_t	uuid;
+
+		if (check_mdraid(fd, uuid) == 0) {
+			set_uuid(dev, uuid);
+			type = "mdraid";
+			goto found_type;
+		}
+	}
+	for (id = type_array; id->bim_type; id++) {
+		if (dev->bid_type &&
+		    strcmp(id->bim_type, dev->bid_type))
+			continue;
+
+		idx = id->bim_kboff + (id->bim_sboff >> 10);
+		if (idx > BLKID_BLK_OFFS || idx < 0)
+			continue;
+		buf = bufs[idx];
+		if (!buf) {
+			if (lseek(fd, idx << 10, SEEK_SET) < 0)
+				continue;
+
+			buf = (unsigned char *)xmalloc(1024);
+
+			if (read(fd, buf, 1024) != 1024) {
+				free(buf);
+				continue;
+			}
+			bufs[idx] = buf;
+		}
+
+		if (memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ff),
+			   id->bim_len))
+			continue;
+
+		if ((id->bim_probe == NULL) ||
+		    (id->bim_probe(fd, cache, dev, id, buf) == 0)) {
+			type = id->bim_type;
+			goto found_type;
+		}
+	}
+
+	if (!id->bim_type && dev->bid_type) {
+		/*
+		 * Zap the device filesystem type and try again
+		 */
+		blkid_set_tag(dev, "TYPE", 0, 0);
+		blkid_set_tag(dev, "SEC_TYPE", 0, 0);
+		blkid_set_tag(dev, "LABEL", 0, 0);
+		blkid_set_tag(dev, "UUID", 0, 0);
+		goto try_again;
+	}
+
+	if (!dev->bid_type) {
+		blkid_free_dev(dev);
+		return NULL;
+	}
+
+found_type:
+	if (dev && type) {
+		dev->bid_devno = st.st_rdev;
+		dev->bid_time = time(0);
+		dev->bid_flags |= BLKID_BID_FL_VERIFIED;
+		cache->bic_flags |= BLKID_BIC_FL_CHANGED;
+
+		blkid_set_tag(dev, "TYPE", type, 0);
+
+		DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n",
+			   dev->bid_name, st.st_rdev, type));
+	}
+
+	close(fd);
+
+	return dev;
+}
+
+int blkid_known_fstype(const char *fstype)
+{
+	const struct blkid_magic *id;
+
+	for (id = type_array; id->bim_type; id++) {
+		if (strcmp(fstype, id->bim_type) == 0)
+			return 1;
+	}
+	return 0;
+}
+
+#ifdef TEST_PROGRAM
+int main(int argc, char **argv)
+{
+	blkid_dev dev;
+	blkid_cache cache;
+	int ret;
+
+	blkid_debug_mask = DEBUG_ALL;
+	if (argc != 2) {
+		fprintf(stderr, "Usage: %s device\n"
+			"Probe a single device to determine type\n", argv[0]);
+		exit(1);
+	}
+	if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
+		fprintf(stderr, "%s: error creating cache (%d)\n",
+			argv[0], ret);
+		exit(1);
+	}
+	dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL);
+	if (!dev) {
+		printf("%s: %s has an unsupported type\n", argv[0], argv[1]);
+		return (1);
+	}
+	printf("%s is type %s\n", argv[1], dev->bid_type ?
+		dev->bid_type : "(null)");
+	if (dev->bid_label)
+		printf("\tlabel is '%s'\n", dev->bid_label);
+	if (dev->bid_uuid)
+		printf("\tuuid is %s\n", dev->bid_uuid);
+
+	blkid_free_dev(dev);
+	return (0);
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/probe.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/probe.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/probe.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,374 @@
+/*
+ * probe.h - constants and on-disk structures for extracting device data
+ *
+ * Copyright (C) 1999 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2001 by Andreas Dilger
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+#ifndef _BLKID_PROBE_H
+#define _BLKID_PROBE_H
+
+#include <linux/types.h>
+
+struct blkid_magic;
+
+typedef int (*blkid_probe_t)(int fd, blkid_cache cache, blkid_dev dev,
+			     const struct blkid_magic *id, unsigned char *buf);
+
+struct blkid_magic {
+	const char	*bim_type;	/* type name for this magic */
+	long		bim_kboff;	/* kilobyte offset of superblock */
+	unsigned	bim_sboff;	/* byte offset within superblock */
+	unsigned	bim_len;	/* length of magic */
+	const char	*bim_magic;	/* magic string */
+	blkid_probe_t	bim_probe;	/* probe function */
+};
+
+/*
+ * Structures for each of the content types we want to extract information
+ * from.  We do not necessarily need the magic field here, because we have
+ * already identified the content type before we get this far.  It may still
+ * be useful if there are probe functions which handle multiple content types.
+ */
+struct ext2_super_block {
+	__u32		s_inodes_count;
+	__u32		s_blocks_count;
+	__u32		s_r_blocks_count;
+	__u32		s_free_blocks_count;
+	__u32		s_free_inodes_count;
+	__u32		s_first_data_block;
+	__u32		s_log_block_size;
+	__u32		s_dummy3[7];
+	unsigned char	s_magic[2];
+	__u16		s_state;
+	__u32		s_dummy5[8];
+	__u32		s_feature_compat;
+	__u32		s_feature_incompat;
+	__u32		s_feature_ro_compat;
+	unsigned char   s_uuid[16];
+	char	   s_volume_name[16];
+};
+#define EXT3_FEATURE_COMPAT_HAS_JOURNAL		0x00000004
+#define EXT3_FEATURE_INCOMPAT_RECOVER		0x00000004
+#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV	0x00000008
+
+struct xfs_super_block {
+	unsigned char	xs_magic[4];
+	__u32		xs_blocksize;
+	__u64		xs_dblocks;
+	__u64		xs_rblocks;
+	__u32		xs_dummy1[2];
+	unsigned char	xs_uuid[16];
+	__u32		xs_dummy2[15];
+	char		xs_fname[12];
+	__u32		xs_dummy3[2];
+	__u64		xs_icount;
+	__u64		xs_ifree;
+	__u64		xs_fdblocks;
+};
+
+struct reiserfs_super_block {
+	__u32		rs_blocks_count;
+	__u32		rs_free_blocks;
+	__u32		rs_root_block;
+	__u32		rs_journal_block;
+	__u32		rs_journal_dev;
+	__u32		rs_orig_journal_size;
+	__u32		rs_dummy2[5];
+	__u16		rs_blocksize;
+	__u16		rs_dummy3[3];
+	unsigned char	rs_magic[12];
+	__u32		rs_dummy4[5];
+	unsigned char	rs_uuid[16];
+	char		rs_label[16];
+};
+
+struct jfs_super_block {
+	unsigned char	js_magic[4];
+	__u32		js_version;
+	__u64		js_size;
+	__u32		js_bsize;
+	__u32		js_dummy1;
+	__u32		js_pbsize;
+	__u32		js_dummy2[27];
+	unsigned char	js_uuid[16];
+	unsigned char	js_label[16];
+	unsigned char	js_loguuid[16];
+};
+
+struct romfs_super_block {
+	unsigned char	ros_magic[8];
+	__u32		ros_dummy1[2];
+	unsigned char	ros_volume[16];
+};
+
+struct cramfs_super_block {
+	__u8		magic[4];
+	__u32		size;
+	__u32		flags;
+	__u32		future;
+	__u8		signature[16];
+	struct cramfs_info {
+		__u32		crc;
+		__u32		edition;
+		__u32		blocks;
+		__u32		files;
+	} info;
+	__u8		name[16];
+};
+
+struct swap_id_block {
+/*	unsigned char	sws_boot[1024]; */
+	__u32		sws_version;
+	__u32		sws_lastpage;
+	__u32		sws_nrbad;
+	unsigned char	sws_uuid[16];
+	char		sws_volume[16];
+	unsigned char	sws_pad[117];
+	__u32		sws_badpg;
+};
+
+/* Yucky misaligned values */
+struct vfat_super_block {
+/* 00*/	unsigned char	vs_ignored[3];
+/* 03*/	unsigned char	vs_sysid[8];
+/* 0b*/	unsigned char	vs_sector_size[2];
+/* 0d*/	__u8		vs_cluster_size;
+/* 0e*/	__u16		vs_reserved;
+/* 10*/	__u8		vs_fats;
+/* 11*/	unsigned char	vs_dir_entries[2];
+/* 13*/	unsigned char	vs_sectors[2];
+/* 15*/	unsigned char	vs_media;
+/* 16*/	__u16		vs_fat_length;
+/* 18*/	__u16		vs_secs_track;
+/* 1a*/	__u16		vs_heads;
+/* 1c*/	__u32		vs_hidden;
+/* 20*/	__u32		vs_total_sect;
+/* 24*/	__u32		vs_fat32_length;
+/* 28*/	__u16		vs_flags;
+/* 2a*/	__u8		vs_version[2];
+/* 2c*/	__u32		vs_root_cluster;
+/* 30*/	__u16		vs_insfo_sector;
+/* 32*/	__u16		vs_backup_boot;
+/* 34*/	__u16		vs_reserved2[6];
+/* 40*/	unsigned char	vs_unknown[3];
+/* 43*/	unsigned char	vs_serno[4];
+/* 47*/	char		vs_label[11];
+/* 52*/	unsigned char   vs_magic[8];
+/* 5a*/	unsigned char	vs_dummy2[164];
+/*1fe*/	unsigned char	vs_pmagic[2];
+};
+
+/* Yucky misaligned values */
+struct msdos_super_block {
+/* 00*/	unsigned char	ms_ignored[3];
+/* 03*/	unsigned char	ms_sysid[8];
+/* 0b*/	unsigned char	ms_sector_size[2];
+/* 0d*/	__u8		ms_cluster_size;
+/* 0e*/	__u16		ms_reserved;
+/* 10*/	__u8		ms_fats;
+/* 11*/	unsigned char	ms_dir_entries[2];
+/* 13*/	unsigned char	ms_sectors[2];
+/* 15*/	unsigned char	ms_media;
+/* 16*/	__u16		ms_fat_length;
+/* 18*/	__u16		ms_secs_track;
+/* 1a*/	__u16		ms_heads;
+/* 1c*/	__u32		ms_hidden;
+/* 20*/	__u32		ms_total_sect;
+/* 24*/	unsigned char	ms_unknown[3];
+/* 27*/	unsigned char	ms_serno[4];
+/* 2b*/	char		ms_label[11];
+/* 36*/	unsigned char   ms_magic[8];
+/* 3d*/	unsigned char	ms_dummy2[192];
+/*1fe*/	unsigned char	ms_pmagic[2];
+};
+
+struct minix_super_block {
+	__u16		ms_ninodes;
+	__u16		ms_nzones;
+	__u16		ms_imap_blocks;
+	__u16		ms_zmap_blocks;
+	__u16		ms_firstdatazone;
+	__u16		ms_log_zone_size;
+	__u32		ms_max_size;
+	unsigned char	ms_magic[2];
+	__u16		ms_state;
+	__u32		ms_zones;
+};
+
+struct mdp_superblock_s {
+	__u32 md_magic;
+	__u32 major_version;
+	__u32 minor_version;
+	__u32 patch_version;
+	__u32 gvalid_words;
+	__u32 set_uuid0;
+	__u32 ctime;
+	__u32 level;
+	__u32 size;
+	__u32 nr_disks;
+	__u32 raid_disks;
+	__u32 md_minor;
+	__u32 not_persistent;
+	__u32 set_uuid1;
+	__u32 set_uuid2;
+	__u32 set_uuid3;
+};
+
+struct hfs_super_block {
+	char	h_magic[2];
+	char	h_dummy[18];
+	__u32	h_blksize;
+};
+
+struct ocfs_volume_header {
+	unsigned char	minor_version[4];
+	unsigned char	major_version[4];
+	unsigned char	signature[128];
+	char		mount[128];
+	unsigned char   mount_len[2];
+};
+
+struct ocfs_volume_label {
+	unsigned char	disk_lock[48];
+	char		label[64];	
+	unsigned char	label_len[2];
+	unsigned char  vol_id[16];
+	unsigned char  vol_id_len[2];
+};
+
+#define ocfsmajor(o) ((__u32)o.major_version[0] \
+                   + (((__u32) o.major_version[1]) << 8) \
+                   + (((__u32) o.major_version[2]) << 16) \
+                   + (((__u32) o.major_version[3]) << 24))
+#define ocfslabellen(o)	((__u32)o.label_len[0] + (((__u32) o.label_len[1]) << 8))
+#define ocfsmountlen(o)	((__u32)o.mount_len[0] + (((__u32) o.mount_len[1])<<8))
+
+#define OCFS_MAGIC "OracleCFS"
+
+struct ocfs2_super_block {
+	unsigned char  signature[8];
+	unsigned char  s_dummy1[184];
+	unsigned char  s_dummy2[80];
+	char	       s_label[64];
+	unsigned char  s_uuid[16];
+};
+
+#define OCFS2_MIN_BLOCKSIZE             512
+#define OCFS2_MAX_BLOCKSIZE             4096
+
+#define OCFS2_SUPER_BLOCK_BLKNO         2
+
+#define OCFS2_SUPER_BLOCK_SIGNATURE     "OCFSV2"
+
+struct oracle_asm_disk_label {
+	char dummy[32];
+	char dl_tag[8];
+	char dl_id[24];
+};
+
+#define ORACLE_ASM_DISK_LABEL_MARKED    "ORCLDISK"
+#define ORACLE_ASM_DISK_LABEL_OFFSET    32
+
+#define ISODCL(from, to) (to - from + 1)
+struct iso_volume_descriptor {
+	char type[ISODCL(1,1)]; /* 711 */
+	char id[ISODCL(2,6)];
+	char version[ISODCL(7,7)];
+	char data[ISODCL(8,2048)];
+};
+
+/*
+ * Byte swap functions
+ */
+#ifdef __GNUC__
+#define _INLINE_ static __inline__
+#else				/* For Watcom C */
+#define _INLINE_ static inline
+#endif
+
+static __u16 blkid_swab16(__u16 val);
+static __u32 blkid_swab32(__u32 val);
+static __u64 blkid_swab64(__u64 val);
+
+#if ((defined __GNUC__) && \
+     (defined(__i386__) || defined(__i486__) || defined(__i586__)))
+
+#define _BLKID_HAVE_ASM_BITOPS_
+
+_INLINE_ __u32 blkid_swab32(__u32 val)
+{
+#ifdef EXT2FS_REQUIRE_486
+	__asm__("bswap %0" : "=r" (val) : "0" (val));
+#else
+	__asm__("xchgb %b0,%h0\n\t"	/* swap lower bytes	*/
+		"rorl $16,%0\n\t"	/* swap words		*/
+		"xchgb %b0,%h0"		/* swap higher bytes	*/
+		:"=q" (val)
+		: "0" (val));
+#endif
+	return val;
+}
+
+_INLINE_ __u16 blkid_swab16(__u16 val)
+{
+	__asm__("xchgb %b0,%h0"		/* swap bytes		*/ \
+		: "=q" (val) \
+		:  "0" (val)); \
+		return val;
+}
+
+_INLINE_ __u64 blkid_swab64(__u64 val)
+{
+	return (blkid_swab32(val >> 32) |
+		(((__u64) blkid_swab32(val & 0xFFFFFFFFUL)) << 32));
+}
+#endif
+
+#if !defined(_BLKID_HAVE_ASM_BITOPS_)
+
+_INLINE_  __u16 blkid_swab16(__u16 val)
+{
+	return (val >> 8) | (val << 8);
+}
+
+_INLINE_ __u32 blkid_swab32(__u32 val)
+{
+	return ((val>>24) | ((val>>8)&0xFF00) |
+		((val<<8)&0xFF0000) | (val<<24));
+}
+
+_INLINE_ __u64 blkid_swab64(__u64 val)
+{
+	return (blkid_swab32(val >> 32) |
+		(((__u64) blkid_swab32(val & 0xFFFFFFFFUL)) << 32));
+}
+#endif
+
+
+
+#if  __BYTE_ORDER == __BIG_ENDIAN
+#define blkid_le16(x) blkid_swab16(x)
+#define blkid_le32(x) blkid_swab32(x)
+#define blkid_le64(x) blkid_swab64(x)
+#define blkid_be16(x) (x)
+#define blkid_be32(x) (x)
+#define blkid_be64(x) (x)
+#else
+#define blkid_le16(x) (x)
+#define blkid_le32(x) (x)
+#define blkid_le64(x) (x)
+#define blkid_be16(x) blkid_swab16(x)
+#define blkid_be32(x) blkid_swab32(x)
+#define blkid_be64(x) blkid_swab64(x)
+#endif
+
+#undef _INLINE_
+
+#endif /* _BLKID_PROBE_H */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/read.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/read.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/read.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,486 @@
+/*
+ * read.c - read the blkid cache from disk, to avoid scanning all devices
+ *
+ * Copyright (C) 2001, 2003 Theodore Y. Ts'o
+ * Copyright (C) 2001 Andreas Dilger
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "blkidP.h"
+#include "../uuid/uuid.h"
+
+#ifdef HAVE_STRTOULL
+#define __USE_ISOC9X
+#define STRTOULL strtoull /* defined in stdlib.h if you try hard enough */
+#else
+/* FIXME: need to support real strtoull here */
+#define STRTOULL strtoul
+#endif
+
+#include <stdlib.h>
+
+#ifdef TEST_PROGRAM
+#define blkid_debug_dump_dev(dev)  (debug_dump_dev(dev))
+static void debug_dump_dev(blkid_dev dev);
+#endif
+
+/*
+ * File format:
+ *
+ *	<device [<NAME="value"> ...]>device_name</device>
+ *
+ *	The following tags are required for each entry:
+ *	<ID="id">	unique (within this file) ID number of this device
+ *	<TIME="time">	(ascii time_t) time this entry was last read from disk
+ *	<TYPE="type">	(detected) type of filesystem/data for this partition
+ *
+ *	The following tags may be present, depending on the device contents
+ *	<LABEL="label">	(user supplied) label (volume name, etc)
+ *	<UUID="uuid">	(generated) universally unique identifier (serial no)
+ */
+
+static char *skip_over_blank(char *cp)
+{
+	while (*cp && isspace(*cp))
+		cp++;
+	return cp;
+}
+
+static char *skip_over_word(char *cp)
+{
+	char ch;
+
+	while ((ch = *cp)) {
+		/* If we see a backslash, skip the next character */
+		if (ch == '\\') {
+			cp++;
+			if (*cp == '\0')
+				break;
+			cp++;
+			continue;
+		}
+		if (isspace(ch) || ch == '<' || ch == '>')
+			break;
+		cp++;
+	}
+	return cp;
+}
+
+static char *strip_line(char *line)
+{
+	char	*p;
+
+	line = skip_over_blank(line);
+
+	p = line + strlen(line) - 1;
+
+	while (*line) {
+		if (isspace(*p))
+			*p-- = '\0';
+		else
+			break;
+	}
+
+	return line;
+}
+
+#if 0
+static char *parse_word(char **buf)
+{
+	char *word, *next;
+
+	word = *buf;
+	if (*word == '\0')
+		return NULL;
+
+	word = skip_over_blank(word);
+	next = skip_over_word(word);
+	if (*next) {
+		char *end = next - 1;
+		if (*end == '"' || *end == '\'')
+			*end = '\0';
+		*next++ = '\0';
+	}
+	*buf = next;
+
+	if (*word == '"' || *word == '\'')
+		word++;
+	return word;
+}
+#endif
+
+/*
+ * Start parsing a new line from the cache.
+ *
+ * line starts with "<device" return 1 -> continue parsing line
+ * line starts with "<foo", empty, or # return 0 -> skip line
+ * line starts with other, return -BLKID_ERR_CACHE -> error
+ */
+static int parse_start(char **cp)
+{
+	char *p;
+
+	p = strip_line(*cp);
+
+	/* Skip comment or blank lines.  We can't just NUL the first '#' char,
+	 * in case it is inside quotes, or escaped.
+	 */
+	if (*p == '\0' || *p == '#')
+		return 0;
+
+	if (!strncmp(p, "<device", 7)) {
+		DBG(DEBUG_READ, printf("found device header: %8s\n", p));
+		p += 7;
+
+		*cp = p;
+		return 1;
+	}
+
+	if (*p == '<')
+		return 0;
+
+	return -BLKID_ERR_CACHE;
+}
+
+/* Consume the remaining XML on the line (cosmetic only) */
+static int parse_end(char **cp)
+{
+	*cp = skip_over_blank(*cp);
+
+	if (!strncmp(*cp, "</device>", 9)) {
+		DBG(DEBUG_READ, printf("found device trailer %9s\n", *cp));
+		*cp += 9;
+		return 0;
+	}
+
+	return -BLKID_ERR_CACHE;
+}
+
+/*
+ * Allocate a new device struct with device name filled in.  Will handle
+ * finding the device on lines of the form:
+ * <device foo=bar>devname</device>
+ * <device>devname<foo>bar</foo></device>
+ */
+static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp)
+{
+	char *start, *tmp, *end, *name;
+	int ret;
+
+	if ((ret = parse_start(cp)) <= 0)
+		return ret;
+
+	start = tmp = strchr(*cp, '>');
+	if (!start) {
+		DBG(DEBUG_READ,
+		    printf("blkid: short line parsing dev: %s\n", *cp));
+		return -BLKID_ERR_CACHE;
+	}
+	start = skip_over_blank(start + 1);
+	end = skip_over_word(start);
+
+	DBG(DEBUG_READ, printf("device should be %*s\n", end - start, start));
+
+	if (**cp == '>')
+		*cp = end;
+	else
+		(*cp)++;
+
+	*tmp = '\0';
+
+	if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0) {
+		DBG(DEBUG_READ,
+		    printf("blkid: missing </device> ending: %s\n", end));
+	} else if (tmp)
+		*tmp = '\0';
+
+	if (end - start <= 1) {
+		DBG(DEBUG_READ, printf("blkid: empty device name: %s\n", *cp));
+		return -BLKID_ERR_CACHE;
+	}
+
+	name = blkid_strndup(start, end-start);
+	if (name == NULL)
+		return -BLKID_ERR_MEM;
+
+	DBG(DEBUG_READ, printf("found dev %s\n", name));
+
+	if (!(*dev = blkid_get_dev(cache, name, BLKID_DEV_CREATE)))
+		return -BLKID_ERR_MEM;
+
+	free(name);
+	return 1;
+}
+
+/*
+ * Extract a tag of the form NAME="value" from the line.
+ */
+static int parse_token(char **name, char **value, char **cp)
+{
+	char *end;
+
+	if (!name || !value || !cp)
+		return -BLKID_ERR_PARAM;
+
+	if (!(*value = strchr(*cp, '=')))
+		return 0;
+
+	**value = '\0';
+	*name = strip_line(*cp);
+	*value = skip_over_blank(*value + 1);
+
+	if (**value == '"') {
+		end = strchr(*value + 1, '"');
+		if (!end) {
+			DBG(DEBUG_READ,
+			    printf("unbalanced quotes at: %s\n", *value));
+			*cp = *value;
+			return -BLKID_ERR_CACHE;
+		}
+		(*value)++;
+		*end = '\0';
+		end++;
+	} else {
+		end = skip_over_word(*value);
+		if (*end) {
+			*end = '\0';
+			end++;
+		}
+	}
+	*cp = end;
+
+	return 1;
+}
+
+/*
+ * Extract a tag of the form <NAME>value</NAME> from the line.
+ */
+/*
+static int parse_xml(char **name, char **value, char **cp)
+{
+	char *end;
+
+	if (!name || !value || !cp)
+		return -BLKID_ERR_PARAM;
+
+	*name = strip_line(*cp);
+
+	if ((*name)[0] != '<' || (*name)[1] == '/')
+		return 0;
+
+	FIXME: finish this.
+}
+*/
+
+/*
+ * Extract a tag from the line.
+ *
+ * Return 1 if a valid tag was found.
+ * Return 0 if no tag found.
+ * Return -ve error code.
+ */
+static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp)
+{
+	char *name;
+	char *value;
+	int ret;
+
+	if (!cache || !dev)
+		return -BLKID_ERR_PARAM;
+
+	if ((ret = parse_token(&name, &value, cp)) <= 0 /* &&
+	    (ret = parse_xml(&name, &value, cp)) <= 0 */)
+		return ret;
+
+	/* Some tags are stored directly in the device struct */
+	if (!strcmp(name, "DEVNO"))
+		dev->bid_devno = STRTOULL(value, 0, 0);
+	else if (!strcmp(name, "PRI"))
+		dev->bid_pri = strtol(value, 0, 0);
+	else if (!strcmp(name, "TIME"))
+		/* FIXME: need to parse a long long eventually */
+		dev->bid_time = strtol(value, 0, 0);
+	else
+		ret = blkid_set_tag(dev, name, value, strlen(value));
+
+	DBG(DEBUG_READ, printf("    tag: %s=\"%s\"\n", name, value));
+
+	return ret < 0 ? ret : 1;
+}
+
+/*
+ * Parse a single line of data, and return a newly allocated dev struct.
+ * Add the new device to the cache struct, if one was read.
+ *
+ * Lines are of the form <device [TAG="value" ...]>/dev/foo</device>
+ *
+ * Returns -ve value on error.
+ * Returns 0 otherwise.
+ * If a valid device was read, *dev_p is non-NULL, otherwise it is NULL
+ * (e.g. comment lines, unknown XML content, etc).
+ */
+static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp)
+{
+	blkid_dev dev;
+	int ret;
+
+	if (!cache || !dev_p)
+		return -BLKID_ERR_PARAM;
+
+	*dev_p = NULL;
+
+	DBG(DEBUG_READ, printf("line: %s\n", cp));
+
+	if ((ret = parse_dev(cache, dev_p, &cp)) <= 0)
+		return ret;
+
+	dev = *dev_p;
+
+	while ((ret = parse_tag(cache, dev, &cp)) > 0) {
+		;
+	}
+
+	if (dev->bid_type == NULL) {
+		DBG(DEBUG_READ,
+		    printf("blkid: device %s has no TYPE\n",dev->bid_name));
+		blkid_free_dev(dev);
+	}
+
+	DBG(DEBUG_READ, blkid_debug_dump_dev(dev));
+
+	return ret;
+}
+
+/*
+ * Parse the specified filename, and return the data in the supplied or
+ * a newly allocated cache struct.  If the file doesn't exist, return a
+ * new empty cache struct.
+ */
+void blkid_read_cache(blkid_cache cache)
+{
+	FILE *file;
+	char buf[4096];
+	int fd, lineno = 0;
+	struct stat st;
+
+	if (!cache)
+		return;
+
+	/*
+	 * If the file doesn't exist, then we just return an empty
+	 * struct so that the cache can be populated.
+	 */
+	if ((fd = open(cache->bic_filename, O_RDONLY)) < 0)
+		return;
+	if (fstat(fd, &st) < 0)
+		goto errout;
+	if ((st.st_mtime == cache->bic_ftime) ||
+	    (cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
+		DBG(DEBUG_CACHE, printf("skipping re-read of %s\n",
+					cache->bic_filename));
+		goto errout;
+	}
+
+	DBG(DEBUG_CACHE, printf("reading cache file %s\n",
+				cache->bic_filename));
+
+	file = fdopen(fd, "r");
+	if (!file)
+		goto errout;
+
+	while (fgets(buf, sizeof(buf), file)) {
+		blkid_dev dev;
+		unsigned int end;
+
+		lineno++;
+		if (buf[0] == 0)
+			continue;
+		end = strlen(buf) - 1;
+		/* Continue reading next line if it ends with a backslash */
+		while (buf[end] == '\\' && end < sizeof(buf) - 2 &&
+		       fgets(buf + end, sizeof(buf) - end, file)) {
+			end = strlen(buf) - 1;
+			lineno++;
+		}
+
+		if (blkid_parse_line(cache, &dev, buf) < 0) {
+			DBG(DEBUG_READ,
+			    printf("blkid: bad format on line %d\n", lineno));
+			continue;
+		}
+	}
+	fclose(file);
+
+	/*
+	 * Initially we do not need to write out the cache file.
+	 */
+	cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
+	cache->bic_ftime = st.st_mtime;
+
+	return;
+errout:
+	close(fd);
+	return;
+}
+
+#ifdef TEST_PROGRAM
+static void debug_dump_dev(blkid_dev dev)
+{
+	struct list_head *p;
+
+	if (!dev) {
+		printf("  dev: NULL\n");
+		return;
+	}
+
+	printf("  dev: name = %s\n", dev->bid_name);
+	printf("  dev: DEVNO=\"0x%0llx\"\n", dev->bid_devno);
+	printf("  dev: TIME=\"%lu\"\n", dev->bid_time);
+	printf("  dev: PRI=\"%d\"\n", dev->bid_pri);
+	printf("  dev: flags = 0x%08X\n", dev->bid_flags);
+
+	list_for_each(p, &dev->bid_tags) {
+		blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
+		if (tag)
+			printf("    tag: %s=\"%s\"\n", tag->bit_name, 
+			       tag->bit_val);
+		else
+			printf("    tag: NULL\n");
+	}
+	printf("\n");
+}
+
+int main(int argc, char**argv)
+{
+	blkid_cache cache = NULL;
+	int ret;
+
+	blkid_debug_mask = DEBUG_ALL;
+	if (argc > 2) {
+		fprintf(stderr, "Usage: %s [filename]\n"
+			"Test parsing of the cache (filename)\n", argv[0]);
+		exit(1);
+	}
+	if ((ret = blkid_get_cache(&cache, argv[1])) < 0)
+		fprintf(stderr, "error %d reading cache file %s\n", ret,
+			argv[1] ? argv[1] : BLKID_CACHE_FILE);
+
+	blkid_put_cache(cache);
+
+	return ret;
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/resolve.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/resolve.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/resolve.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,138 @@
+/*
+ * resolve.c - resolve names and tags into specific devices
+ *
+ * Copyright (C) 2001, 2003 Theodore Ts'o.
+ * Copyright (C) 2001 Andreas Dilger
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "blkidP.h"
+#include "probe.h"
+
+/*
+ * Find a tagname (e.g. LABEL or UUID) on a specific device.
+ */
+char *blkid_get_tag_value(blkid_cache cache, const char *tagname,
+			  const char *devname)
+{
+	blkid_tag found;
+	blkid_dev dev;
+	blkid_cache c = cache;
+	char *ret = NULL;
+
+	DBG(DEBUG_RESOLVE, printf("looking for %s on %s\n", tagname, devname));
+
+	if (!devname)
+		return NULL;
+
+	if (!cache) {
+		if (blkid_get_cache(&c, NULL) < 0)
+			return NULL;
+	}
+
+	if ((dev = blkid_get_dev(c, devname, BLKID_DEV_NORMAL)) &&
+	    (found = blkid_find_tag_dev(dev, tagname)))
+		ret = blkid_strdup(found->bit_val);
+
+	if (!cache)
+		blkid_put_cache(c);
+
+	return ret;
+}
+
+/*
+ * Locate a device name from a token (NAME=value string), or (name, value)
+ * pair.  In the case of a token, value is ignored.  If the "token" is not
+ * of the form "NAME=value" and there is no value given, then it is assumed
+ * to be the actual devname and a copy is returned.
+ */
+char *blkid_get_devname(blkid_cache cache, const char *token,
+			const char *value)
+{
+	blkid_dev dev;
+	blkid_cache c = cache;
+	char *t = 0, *v = 0;
+	char *ret = NULL;
+
+	if (!token)
+		return NULL;
+
+	if (!cache) {
+		if (blkid_get_cache(&c, NULL) < 0)
+			return NULL;
+	}
+
+	DBG(DEBUG_RESOLVE,
+	    printf("looking for %s%s%s %s\n", token, value ? "=" : "",
+		   value ? value : "", cache ? "in cache" : "from disk"));
+
+	if (!value) {
+		if (!strchr(token, '='))
+			return blkid_strdup(token);
+		blkid_parse_tag_string(token, &t, &v);
+		if (!t || !v)
+			goto errout;
+		token = t;
+		value = v;
+	}
+
+	dev = blkid_find_dev_with_tag(c, token, value);
+	if (!dev)
+		goto errout;
+
+	ret = blkid_strdup(blkid_dev_devname(dev));
+
+errout:
+	free(t);
+	free(v);
+	if (!cache) {
+		blkid_put_cache(c);
+	}
+	return (ret);
+}
+
+#ifdef TEST_PROGRAM
+int main(int argc, char **argv)
+{
+	char *value;
+	blkid_cache cache;
+
+	blkid_debug_mask = DEBUG_ALL;
+	if (argc != 2 && argc != 3) {
+		fprintf(stderr, "Usage:\t%s tagname=value\n"
+			"\t%s tagname devname\n"
+			"Find which device holds a given token or\n"
+			"Find what the value of a tag is in a device\n",
+			argv[0], argv[0]);
+		exit(1);
+	}
+	if (blkid_get_cache(&cache, bb_dev_null) < 0) {
+		fprintf(stderr, "Couldn't get blkid cache\n");
+		exit(1);
+	}
+
+	if (argv[2]) {
+		value = blkid_get_tag_value(cache, argv[1], argv[2]);
+		printf("%s has tag %s=%s\n", argv[2], argv[1],
+		       value ? value : "<missing>");
+	} else {
+		value = blkid_get_devname(cache, argv[1], NULL);
+		printf("%s has tag %s\n", value ? value : "<none>", argv[1]);
+	}
+	blkid_put_cache(cache);
+	return value ? 0 : 1;
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/save.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/save.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/save.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,188 @@
+/*
+ * save.c - write the cache struct to disk
+ *
+ * Copyright (C) 2001 by Andreas Dilger
+ * Copyright (C) 2003 Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_MKDEV_H
+#include <sys/mkdev.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include "blkidP.h"
+
+static int save_dev(blkid_dev dev, FILE *file)
+{
+	struct list_head *p;
+
+	if (!dev || dev->bid_name[0] != '/')
+		return 0;
+
+	DBG(DEBUG_SAVE,
+	    printf("device %s, type %s\n", dev->bid_name, dev->bid_type));
+
+	fprintf(file,
+		"<device DEVNO=\"0x%04lx\" TIME=\"%lu\"",
+		(unsigned long) dev->bid_devno, dev->bid_time);
+	if (dev->bid_pri)
+		fprintf(file, " PRI=\"%d\"", dev->bid_pri);
+	list_for_each(p, &dev->bid_tags) {
+		blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
+		fprintf(file, " %s=\"%s\"", tag->bit_name,tag->bit_val);
+	}
+	fprintf(file, ">%s</device>\n", dev->bid_name);
+
+	return 0;
+}
+
+/*
+ * Write out the cache struct to the cache file on disk.
+ */
+int blkid_flush_cache(blkid_cache cache)
+{
+	struct list_head *p;
+	char *tmp = NULL;
+	const char *opened = NULL;
+	const char *filename;
+	FILE *file = NULL;
+	int fd, ret = 0;
+	struct stat st;
+
+	if (!cache)
+		return -BLKID_ERR_PARAM;
+
+	if (list_empty(&cache->bic_devs) ||
+	    !(cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
+		DBG(DEBUG_SAVE, printf("skipping cache file write\n"));
+		return 0;
+	}
+
+	filename = cache->bic_filename ? cache->bic_filename: BLKID_CACHE_FILE;
+
+	/* If we can't write to the cache file, then don't even try */
+	if (((ret = stat(filename, &st)) < 0 && errno != ENOENT) ||
+	    (ret == 0 && access(filename, W_OK) < 0)) {
+		DBG(DEBUG_SAVE,
+		    printf("can't write to cache file %s\n", filename));
+		return 0;
+	}
+
+	/*
+	 * Try and create a temporary file in the same directory so
+	 * that in case of error we don't overwrite the cache file.
+	 * If the cache file doesn't yet exist, it isn't a regular
+	 * file (e.g. /dev/null or a socket), or we couldn't create
+	 * a temporary file then we open it directly.
+	 */
+	if (ret == 0 && S_ISREG(st.st_mode)) {
+		tmp = xmalloc(strlen(filename) + 8);
+		sprintf(tmp, "%s-XXXXXX", filename);
+		fd = mkstemp(tmp);
+		if (fd >= 0) {
+			file = fdopen(fd, "w");
+			opened = tmp;
+		}
+		fchmod(fd, 0644);
+	}
+
+	if (!file) {
+		file = fopen(filename, "w");
+		opened = filename;
+	}
+
+	DBG(DEBUG_SAVE,
+	    printf("writing cache file %s (really %s)\n",
+		   filename, opened));
+
+	if (!file) {
+		ret = errno;
+		goto errout;
+	}
+
+	list_for_each(p, &cache->bic_devs) {
+		blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
+		if (!dev->bid_type)
+			continue;
+		if ((ret = save_dev(dev, file)) < 0)
+			break;
+	}
+
+	if (ret >= 0) {
+		cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
+		ret = 1;
+	}
+
+	fclose(file);
+	if (opened != filename) {
+		if (ret < 0) {
+			unlink(opened);
+			DBG(DEBUG_SAVE,
+			    printf("unlinked temp cache %s\n", opened));
+		} else {
+			char *backup;
+
+			backup = xmalloc(strlen(filename) + 5);
+			sprintf(backup, "%s.old", filename);
+			unlink(backup);
+			link(filename, backup);
+			free(backup);
+			rename(opened, filename);
+			DBG(DEBUG_SAVE,
+			    printf("moved temp cache %s\n", opened));
+		}
+	}
+
+errout:
+	free(tmp);
+	return ret;
+}
+
+#ifdef TEST_PROGRAM
+int main(int argc, char **argv)
+{
+	blkid_cache cache = NULL;
+	int ret;
+
+	blkid_debug_mask = DEBUG_ALL;
+	if (argc > 2) {
+		fprintf(stderr, "Usage: %s [filename]\n"
+			"Test loading/saving a cache (filename)\n", argv[0]);
+		exit(1);
+	}
+
+	if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) {
+		fprintf(stderr, "%s: error creating cache (%d)\n",
+			argv[0], ret);
+		exit(1);
+	}
+	if ((ret = blkid_probe_all(cache)) < 0) {
+		fprintf(stderr, "error (%d) probing devices\n", ret);
+		exit(1);
+	}
+	cache->bic_filename = blkid_strdup(argv[1]);
+
+	if ((ret = blkid_flush_cache(cache)) < 0) {
+		fprintf(stderr, "error (%d) saving cache\n", ret);
+		exit(1);
+	}
+
+	blkid_put_cache(cache);
+
+	return ret;
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/tag.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/tag.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/tag.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,431 @@
+/*
+ * tag.c - allocation/initialization/free routines for tag structs
+ *
+ * Copyright (C) 2001 Andreas Dilger
+ * Copyright (C) 2003 Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "blkidP.h"
+
+static blkid_tag blkid_new_tag(void)
+{
+	blkid_tag tag;
+
+	if (!(tag = (blkid_tag) calloc(1, sizeof(struct blkid_struct_tag))))
+		return NULL;
+
+	INIT_LIST_HEAD(&tag->bit_tags);
+	INIT_LIST_HEAD(&tag->bit_names);
+
+	return tag;
+}
+
+#ifdef CONFIG_BLKID_DEBUG
+void blkid_debug_dump_tag(blkid_tag tag)
+{
+	if (!tag) {
+		printf("    tag: NULL\n");
+		return;
+	}
+
+	printf("    tag: %s=\"%s\"\n", tag->bit_name, tag->bit_val);
+}
+#endif
+
+void blkid_free_tag(blkid_tag tag)
+{
+	if (!tag)
+		return;
+
+	DBG(DEBUG_TAG, printf("    freeing tag %s=%s\n", tag->bit_name,
+		   tag->bit_val ? tag->bit_val : "(NULL)"));
+	DBG(DEBUG_TAG, blkid_debug_dump_tag(tag));
+
+	list_del(&tag->bit_tags);	/* list of tags for this device */
+	list_del(&tag->bit_names);	/* list of tags with this type */
+
+	free(tag->bit_name);
+	free(tag->bit_val);
+	free(tag);
+}
+
+/*
+ * Find the desired tag on a device.  If value is NULL, then the
+ * first such tag is returned, otherwise return only exact tag if found.
+ */
+blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type)
+{
+	struct list_head *p;
+
+	if (!dev || !type)
+		return NULL;
+
+	list_for_each(p, &dev->bid_tags) {
+		blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
+					   bit_tags);
+
+		if (!strcmp(tmp->bit_name, type))
+			return tmp;
+	}
+	return NULL;
+}
+
+/*
+ * Find the desired tag type in the cache.
+ * We return the head tag for this tag type.
+ */
+static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type)
+{
+	blkid_tag head = NULL, tmp;
+	struct list_head *p;
+
+	if (!cache || !type)
+		return NULL;
+
+	list_for_each(p, &cache->bic_tags) {
+		tmp = list_entry(p, struct blkid_struct_tag, bit_tags);
+		if (!strcmp(tmp->bit_name, type)) {
+			DBG(DEBUG_TAG,
+			    printf("    found cache tag head %s\n", type));
+			head = tmp;
+			break;
+		}
+	}
+	return head;
+}
+
+/*
+ * Set a tag on an existing device.
+ *
+ * If value is NULL, then delete the tagsfrom the device.
+ */
+int blkid_set_tag(blkid_dev dev, const char *name,
+		  const char *value, const int vlength)
+{
+	blkid_tag	t = 0, head = 0;
+	char		*val = 0;
+
+	if (!dev || !name)
+		return -BLKID_ERR_PARAM;
+
+	if (!(val = blkid_strndup(value, vlength)) && value)
+		return -BLKID_ERR_MEM;
+	t = blkid_find_tag_dev(dev, name);
+	if (!value) {
+		blkid_free_tag(t);
+	} else if (t) {
+		if (!strcmp(t->bit_val, val)) {
+			/* Same thing, exit */
+			free(val);
+			return 0;
+		}
+		free(t->bit_val);
+		t->bit_val = val;
+	} else {
+		/* Existing tag not present, add to device */
+		if (!(t = blkid_new_tag()))
+			goto errout;
+		t->bit_name = blkid_strdup(name);
+		t->bit_val = val;
+		t->bit_dev = dev;
+
+		list_add_tail(&t->bit_tags, &dev->bid_tags);
+
+		if (dev->bid_cache) {
+			head = blkid_find_head_cache(dev->bid_cache,
+						     t->bit_name);
+			if (!head) {
+				head = blkid_new_tag();
+				if (!head)
+					goto errout;
+
+				DBG(DEBUG_TAG,
+				    printf("    creating new cache tag head %s\n", name));
+				head->bit_name = blkid_strdup(name);
+				if (!head->bit_name)
+					goto errout;
+				list_add_tail(&head->bit_tags,
+					      &dev->bid_cache->bic_tags);
+			}
+			list_add_tail(&t->bit_names, &head->bit_names);
+		}
+	}
+
+	/* Link common tags directly to the device struct */
+	if (!strcmp(name, "TYPE"))
+		dev->bid_type = val;
+	else if (!strcmp(name, "LABEL"))
+		dev->bid_label = val;
+	else if (!strcmp(name, "UUID"))
+		dev->bid_uuid = val;
+
+	if (dev->bid_cache)
+		dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED;
+	return 0;
+
+errout:
+	blkid_free_tag(t);
+	if (!t)
+		free(val);
+	blkid_free_tag(head);
+	return -BLKID_ERR_MEM;
+}
+
+
+/*
+ * Parse a "NAME=value" string.  This is slightly different than
+ * parse_token, because that will end an unquoted value at a space, while
+ * this will assume that an unquoted value is the rest of the token (e.g.
+ * if we are passed an already quoted string from the command-line we don't
+ * have to both quote and escape quote so that the quotes make it to
+ * us).
+ *
+ * Returns 0 on success, and -1 on failure.
+ */
+int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val)
+{
+	char *name, *value, *cp;
+
+	DBG(DEBUG_TAG, printf("trying to parse '%s' as a tag\n", token));
+
+	if (!token || !(cp = strchr(token, '=')))
+		return -1;
+
+	name = blkid_strdup(token);
+	if (!name)
+		return -1;
+	value = name + (cp - token);
+	*value++ = '\0';
+	if (*value == '"' || *value == '\'') {
+		char c = *value++;
+		if (!(cp = strrchr(value, c)))
+			goto errout; /* missing closing quote */
+		*cp = '\0';
+	}
+	value = blkid_strdup(value);
+	if (!value)
+		goto errout;
+
+	*ret_type = name;
+	*ret_val = value;
+
+	return 0;
+
+errout:
+	free(name);
+	return -1;
+}
+
+/*
+ * Tag iteration routines for the public libblkid interface.
+ *
+ * These routines do not expose the list.h implementation, which are a
+ * contamination of the namespace, and which force us to reveal far, far
+ * too much of our internal implemenation.  I'm not convinced I want
+ * to keep list.h in the long term, anyway.  It's fine for kernel
+ * programming, but performance is not the #1 priority for this
+ * library, and I really don't like the tradeoff of type-safety for
+ * performance for this application.  [tytso:20030125.2007EST]
+ */
+
+/*
+ * This series of functions iterate over all tags in a device
+ */
+#define TAG_ITERATE_MAGIC	0x01a5284c
+
+struct blkid_struct_tag_iterate {
+	int			magic;
+	blkid_dev		dev;
+	struct list_head	*p;
+};
+
+blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev)
+{
+	blkid_tag_iterate	iter;
+
+	iter = xmalloc(sizeof(struct blkid_struct_tag_iterate));
+	iter->magic = TAG_ITERATE_MAGIC;
+	iter->dev = dev;
+	iter->p	= dev->bid_tags.next;
+	return (iter);
+}
+
+/*
+ * Return 0 on success, -1 on error
+ */
+extern int blkid_tag_next(blkid_tag_iterate iter,
+			  const char **type, const char **value)
+{
+	blkid_tag tag;
+
+	*type = 0;
+	*value = 0;
+	if (!iter || iter->magic != TAG_ITERATE_MAGIC ||
+	    iter->p == &iter->dev->bid_tags)
+		return -1;
+	tag = list_entry(iter->p, struct blkid_struct_tag, bit_tags);
+	*type = tag->bit_name;
+	*value = tag->bit_val;
+	iter->p = iter->p->next;
+	return 0;
+}
+
+void blkid_tag_iterate_end(blkid_tag_iterate iter)
+{
+	if (!iter || iter->magic != TAG_ITERATE_MAGIC)
+		return;
+	iter->magic = 0;
+	free(iter);
+}
+
+/*
+ * This function returns a device which matches a particular
+ * type/value pair.  If there is more than one device that matches the
+ * search specification, it returns the one with the highest priority
+ * value.  This allows us to give preference to EVMS or LVM devices.
+ *
+ * XXX there should also be an interface which uses an iterator so we
+ * can get all of the devices which match a type/value search parameter.
+ */
+extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
+					 const char *type,
+					 const char *value)
+{
+	blkid_tag	head;
+	blkid_dev	dev;
+	int		pri;
+	struct list_head *p;
+
+	if (!cache || !type || !value)
+		return NULL;
+
+	blkid_read_cache(cache);
+
+	DBG(DEBUG_TAG, printf("looking for %s=%s in cache\n", type, value));
+
+try_again:
+	pri = -1;
+	dev = 0;
+	head = blkid_find_head_cache(cache, type);
+
+	if (head) {
+		list_for_each(p, &head->bit_names) {
+			blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
+						   bit_names);
+
+			if (!strcmp(tmp->bit_val, value) &&
+			    tmp->bit_dev->bid_pri > pri) {
+				dev = tmp->bit_dev;
+				pri = dev->bid_pri;
+			}
+		}
+	}
+	if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) {
+		dev = blkid_verify(cache, dev);
+		if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED))
+			goto try_again;
+	}
+
+	if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) {
+		if (blkid_probe_all(cache) < 0)
+			return NULL;
+		goto try_again;
+	}
+	return dev;
+}
+
+#ifdef TEST_PROGRAM
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern char *optarg;
+extern int optind;
+#endif
+
+void usage(char *prog)
+{
+	fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask] device "
+		"[type value]\n", 
+		prog);
+	fprintf(stderr, "\tList all tags for a device and exit\n", prog);
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	blkid_tag_iterate	iter;
+	blkid_cache 		cache = NULL;
+	blkid_dev		dev;
+	int			c, ret, found;
+	int			flags = BLKID_DEV_FIND;
+	char			*tmp;
+	char			*file = NULL;
+	char			*devname = NULL;
+	char			*search_type = NULL;
+	char			*search_value = NULL;
+	const char		*type, *value;
+
+	while ((c = getopt (argc, argv, "m:f:")) != EOF)
+		switch (c) {
+		case 'f':
+			file = optarg;
+			break;
+		case 'm':
+			blkid_debug_mask = strtoul (optarg, &tmp, 0);
+			if (*tmp) {
+				fprintf(stderr, "Invalid debug mask: %d\n", 
+					optarg);
+				exit(1);
+			}
+			break;
+		case '?':
+			usage(argv[0]);
+		}
+	if (argc > optind)
+		devname = argv[optind++];
+	if (argc > optind)
+		search_type = argv[optind++];
+	if (argc > optind)
+		search_value = argv[optind++];
+	if (!devname || (argc != optind))
+		usage(argv[0]);
+
+	if ((ret = blkid_get_cache(&cache, file)) != 0) {
+		fprintf(stderr, "%s: error creating cache (%d)\n",
+			argv[0], ret);
+		exit(1);
+	}
+
+	dev = blkid_get_dev(cache, devname, flags);
+	if (!dev) {
+		fprintf(stderr, "%s: Can not find device in blkid cache\n");
+		exit(1);
+	}
+	if (search_type) {
+		found = blkid_dev_has_tag(dev, search_type, search_value);
+		printf("Device %s: (%s, %s) %s\n", blkid_dev_devname(dev),
+		       search_type, search_value ? search_value : "NULL", 
+		       found ? "FOUND" : "NOT FOUND");
+		return(!found);
+	}
+	printf("Device %s...\n", blkid_dev_devname(dev));
+
+	iter = blkid_tag_iterate_begin(dev);
+	while (blkid_tag_next(iter, &type, &value) == 0) {
+		printf("\tTag %s has value %s\n", type, value);
+	}
+	blkid_tag_iterate_end(iter);
+
+	blkid_put_cache(cache);
+	return (0);
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/version.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/version.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/blkid/version.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,48 @@
+/*
+ * version.c --- Return the version of the blkid library
+ *
+ * Copyright (C) 2004 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "blkid.h"
+
+static const char *lib_version = E2FSPROGS_VERSION;
+static const char *lib_date = E2FSPROGS_DATE;
+
+int blkid_parse_version_string(const char *ver_string)
+{
+	const char *cp;
+	int version = 0;
+
+	for (cp = ver_string; *cp; cp++) {
+		if (*cp == '.')
+			continue;
+		if (!isdigit(*cp))
+			break;
+		version = (version * 10) + (*cp - '0');
+	}
+	return version;
+}
+
+int blkid_get_library_version(const char **ver_string,
+			       const char **date_string)
+{
+	if (ver_string)
+		*ver_string = lib_version;
+	if (date_string)
+		*date_string = lib_date;
+
+	return blkid_parse_version_string(lib_version);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/chattr.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/chattr.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/chattr.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,225 @@
+/*
+ * chattr.c		- Change file attributes on an ext2 file system
+ *
+ * Copyright (C) 1993, 1994  Remy Card <card at masi.ibp.fr>
+ *                           Laboratoire MASI, Institut Blaise Pascal
+ *                           Universite Pierre et Marie Curie (Paris VI)
+ *
+ * This file can be redistributed under the terms of the GNU General
+ * Public License
+ */
+
+/*
+ * History:
+ * 93/10/30	- Creation
+ * 93/11/13	- Replace stat() calls by lstat() to avoid loops
+ * 94/02/27	- Integrated in Ted's distribution
+ * 98/12/29	- Ignore symlinks when working recursively (G M Sipe)
+ * 98/12/29	- Display version info only when -V specified (G M Sipe)
+ */
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include "ext2fs/ext2_fs.h"
+
+#ifdef __GNUC__
+# define EXT2FS_ATTR(x) __attribute__(x)
+#else
+# define EXT2FS_ATTR(x)
+#endif
+
+#include "e2fsbb.h"
+#include "e2p/e2p.h"
+
+#define OPT_ADD 1
+#define OPT_REM 2
+#define OPT_SET 4
+#define OPT_SET_VER 8
+static int flags;
+static int recursive;
+
+static unsigned long version;
+
+static unsigned long af;
+static unsigned long rf;
+static unsigned long sf;
+
+#ifdef CONFIG_LFS
+# define LSTAT lstat64
+# define STRUCT_STAT struct stat64
+#else
+# define LSTAT lstat
+# define STRUCT_STAT struct stat
+#endif
+
+struct flags_char {
+	unsigned long flag;
+	char optchar;
+};
+
+static const struct flags_char flags_array[] = {
+	{ EXT2_NOATIME_FL,      'A' },
+	{ EXT2_SYNC_FL,         'S' },
+	{ EXT2_DIRSYNC_FL,      'D' },
+	{ EXT2_APPEND_FL,       'a' },
+	{ EXT2_COMPR_FL,        'c' },
+	{ EXT2_NODUMP_FL,       'd' },
+	{ EXT2_IMMUTABLE_FL,    'i' },
+	{ EXT3_JOURNAL_DATA_FL, 'j' },
+	{ EXT2_SECRM_FL,        's' },
+	{ EXT2_UNRM_FL,         'u' },
+	{ EXT2_NOTAIL_FL,       't' },
+	{ EXT2_TOPDIR_FL,       'T' },
+	{ 0, 0 }
+};
+
+static unsigned long get_flag(char c)
+{
+	const struct flags_char *fp;
+	for (fp = flags_array; fp->flag; fp++)
+		if (fp->optchar == c)
+			return fp->flag;
+	bb_show_usage();
+	return 0;
+}
+
+static int decode_arg(char *arg)
+{
+	unsigned long *fl;
+	char opt = *arg++;
+
+	if (opt == '-') {
+		flags |= OPT_REM;
+		fl = &rf;
+	} else if (opt == '+') {
+		flags |= OPT_ADD;
+		fl = ⁡
+	} else if (opt == '=') {
+		flags |= OPT_SET;
+		fl = &sf;
+	} else
+		return EOF;
+
+	for (; *arg ; ++arg)
+		(*fl) |= get_flag(*arg);
+
+	return 1;
+}
+
+static int chattr_dir_proc(const char *, struct dirent *, void *);
+
+static void change_attributes(const char * name)
+{
+	unsigned long fsflags;
+	STRUCT_STAT	st;
+
+	if (LSTAT(name, &st) == -1) {
+		bb_error_msg("stat %s failed", name);
+		return;
+	}
+	if (S_ISLNK(st.st_mode) && recursive)
+		return;
+
+	/* Don't try to open device files, fifos etc.  We probably
+	 * ought to display an error if the file was explicitly given
+	 * on the command line (whether or not recursive was
+	 * requested).  */
+	if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode))
+		return;
+
+	if (flags & OPT_SET_VER)
+		if (fsetversion(name, version) == -1)
+			bb_error_msg("setting version on %s", name);
+
+	if (flags & OPT_SET) {
+		fsflags = sf;
+	} else {
+		if (fgetflags(name, &fsflags) == -1) {
+			bb_error_msg("reading flags on %s", name);
+			goto skip_setflags;
+		}
+		if (flags & OPT_REM)
+			fsflags &= ~rf;
+		if (flags & OPT_ADD)
+			fsflags |= af;
+		if (!S_ISDIR(st.st_mode))
+			fsflags &= ~EXT2_DIRSYNC_FL;
+	}
+	if (fsetflags(name, fsflags) == -1)
+		bb_error_msg("setting flags on %s", name);
+
+skip_setflags:
+	if (S_ISDIR(st.st_mode) && recursive)
+		iterate_on_dir(name, chattr_dir_proc, NULL);
+}
+
+static int chattr_dir_proc(const char *dir_name, struct dirent *de,
+			   void *private EXT2FS_ATTR((unused)))
+{
+	/*if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) {*/
+	if (de->d_name[0] == '.' && (de->d_name[1] == '\0' || \
+	   (de->d_name[1] == '.' && de->d_name[2] == '\0'))) {
+		char *path = concat_subpath_file(dir_name, de->d_name);
+		if (path) {
+			change_attributes(path);
+			free(path);
+		}
+	}
+	return 0;
+}
+
+int chattr_main(int argc, char **argv)
+{
+	int i;
+	char *arg;
+
+	/* parse the args */
+	for (i = 1; i < argc; ++i) {
+		arg = argv[i];
+
+		/* take care of -R and -v <version> */
+		if (arg[0] == '-') {
+			if (arg[1] == 'R' && arg[2] == '\0') {
+				recursive = 1;
+				continue;
+			} else if (arg[1] == 'v' && arg[2] == '\0') {
+				char *tmp;
+				++i;
+				if (i >= argc)
+					bb_show_usage();
+				version = strtol(argv[i], &tmp, 0);
+				if (*tmp)
+					bb_error_msg_and_die("bad version '%s'", arg);
+				flags |= OPT_SET_VER;
+				continue;
+			}
+		}
+
+		if (decode_arg(arg) == EOF)
+			break;
+	}
+
+	/* run sanity checks on all the arguments given us */
+	if (i >= argc)
+		bb_show_usage();
+	if ((flags & OPT_SET) && ((flags & OPT_ADD) || (flags & OPT_REM)))
+		bb_error_msg_and_die("= is incompatible with - and +");
+	if ((rf & af) != 0)
+		bb_error_msg_and_die("Can't set and unset a flag");
+	if (!flags)
+		bb_error_msg_and_die("Must use '-v', =, - or +");
+
+	/* now run chattr on all the files passed to us */
+	while (i < argc)
+		change_attributes(argv[i++]);
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2fsbb.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2fsbb.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2fsbb.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,42 @@
+/*
+ * File: e2fsbb.h
+ *
+ * Redefine a bunch of e2fsprogs stuff to use busybox routines
+ * instead.  This makes upgrade between e2fsprogs versions easy.
+ */
+
+#ifndef __E2FSBB_H__
+#define __E2FSBB_H__ 1
+
+#include "libbb.h"
+
+/* version we've last synced against */
+#define E2FSPROGS_VERSION "1.38"
+#define E2FSPROGS_DATE "30-Jun-2005"
+
+typedef long errcode_t;
+#define ERRCODE_RANGE 8
+#define error_message(code) strerror((int) (code & ((1<<ERRCODE_RANGE)-1)))
+
+/* header defines */
+#define ENABLE_HTREE 1
+#define HAVE_ERRNO_H 1
+#define HAVE_EXT2_IOCTLS 1
+#define HAVE_LINUX_FD_H 1
+#define HAVE_MNTENT_H 1
+#define HAVE_NETINET_IN_H 1
+#define HAVE_NET_IF_H 1
+#define HAVE_SYS_IOCTL_H 1
+#define HAVE_SYS_MOUNT_H 1
+#define HAVE_SYS_QUEUE_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_UNISTD_H 1
+
+/* Endianness */
+#if BB_BIG_ENDIAN
+#define ENABLE_SWAPFS 1
+#define WORDS_BIGENDIAN 1
+#endif
+
+#endif /* __E2FSBB_H__ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2fsck.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2fsck.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2fsck.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,13551 @@
+/*
+ * e2fsck
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
+ * Copyright (C) 2006 Garrett Kajmowicz
+ *
+ * Dictionary Abstract Data Type
+ * Copyright (C) 1997 Kaz Kylheku <kaz at ashi.footprints.net>
+ * Free Software License:
+ * All rights are reserved by the author, with the following exceptions:
+ * Permission is granted to freely reproduce and distribute this software,
+ * possibly in exchange for a fee, provided that this copyright notice appears
+ * intact. Permission is also granted to adapt this software to produce
+ * derivative works, as long as the modified versions carry this copyright
+ * notice and additional notices stating that the work has been modified.
+ * This source code may be translated into executable form and incorporated
+ * into proprietary software; there is no requirement for such software to
+ * contain a copyright notice related to this source.
+ *
+ * linux/fs/recovery  and linux/fs/revoke
+ * Written by Stephen C. Tweedie <sct at redhat.com>, 1999
+ *
+ * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
+ *
+ * Journal recovery routines for the generic filesystem journaling code;
+ * part of the ext2fs journaling system.
+ *
+ * Licensed under GPLv2 or later, see file License in this tarball for details.
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1 /* get strnlen() */
+#endif
+
+#include "e2fsck.h"	/*Put all of our defines here to clean things up*/
+
+#define _(x) x
+#define N_(x) x
+
+/*
+ * Procedure declarations
+ */
+
+static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
+
+/* pass1.c */
+static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
+
+/* pass2.c */
+static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
+				    ext2_ino_t ino, char *buf);
+
+/* pass3.c */
+static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
+static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
+					 int num, int gauranteed_size);
+static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
+static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
+					   int adj);
+
+/* rehash.c */
+static void e2fsck_rehash_directories(e2fsck_t ctx);
+
+/* util.c */
+static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
+				    const char *description);
+static int ask(e2fsck_t ctx, const char * string, int def);
+static void e2fsck_read_bitmaps(e2fsck_t ctx);
+static void preenhalt(e2fsck_t ctx);
+static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
+			      struct ext2_inode * inode, const char * proc);
+static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
+			       struct ext2_inode * inode, const char * proc);
+static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
+			   const char *name, io_manager manager);
+
+/* unix.c */
+static void e2fsck_clear_progbar(e2fsck_t ctx);
+static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
+				  float percent, unsigned int dpynum);
+
+
+/*
+ * problem.h --- e2fsck problem error codes
+ */
+
+typedef __u32 problem_t;
+
+struct problem_context {
+	errcode_t       errcode;
+	ext2_ino_t ino, ino2, dir;
+	struct ext2_inode *inode;
+	struct ext2_dir_entry *dirent;
+	blk_t   blk, blk2;
+	e2_blkcnt_t     blkcount;
+	int             group;
+	__u64   num;
+	const char *str;
+};
+
+
+/*
+ * Function declarations
+ */
+static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
+static int end_problem_latch(e2fsck_t ctx, int mask);
+static int set_latch_flags(int mask, int setflags, int clearflags);
+static void clear_problem_context(struct problem_context *ctx);
+
+/*
+ * Dictionary Abstract Data Type
+ * Copyright (C) 1997 Kaz Kylheku <kaz at ashi.footprints.net>
+ *
+ * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
+ * kazlib_1_20
+ */
+
+#ifndef DICT_H
+#define DICT_H
+
+/*
+ * Blurb for inclusion into C++ translation units
+ */
+
+typedef unsigned long dictcount_t;
+#define DICTCOUNT_T_MAX ULONG_MAX
+
+/*
+ * The dictionary is implemented as a red-black tree
+ */
+
+typedef enum { dnode_red, dnode_black } dnode_color_t;
+
+typedef struct dnode_t {
+    struct dnode_t *dict_left;
+    struct dnode_t *dict_right;
+    struct dnode_t *dict_parent;
+    dnode_color_t dict_color;
+    const void *dict_key;
+    void *dict_data;
+} dnode_t;
+
+typedef int (*dict_comp_t)(const void *, const void *);
+typedef void (*dnode_free_t)(dnode_t *);
+
+typedef struct dict_t {
+    dnode_t dict_nilnode;
+    dictcount_t dict_nodecount;
+    dictcount_t dict_maxcount;
+    dict_comp_t dict_compare;
+    dnode_free_t dict_freenode;
+    int dict_dupes;
+} dict_t;
+
+typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
+
+typedef struct dict_load_t {
+    dict_t *dict_dictptr;
+    dnode_t dict_nilnode;
+} dict_load_t;
+
+#define dict_count(D) ((D)->dict_nodecount)
+#define dnode_get(N) ((N)->dict_data)
+#define dnode_getkey(N) ((N)->dict_key)
+
+#endif
+
+/*
+ * Compatibility header file for e2fsck which should be included
+ * instead of linux/jfs.h
+ *
+ * Copyright (C) 2000 Stephen C. Tweedie
+ */
+
+/*
+ * Pull in the definition of the e2fsck context structure
+ */
+
+struct buffer_head {
+	char            b_data[8192];
+	e2fsck_t        b_ctx;
+	io_channel      b_io;
+	int             b_size;
+	blk_t           b_blocknr;
+	int             b_dirty;
+	int             b_uptodate;
+	int             b_err;
+};
+
+
+#define K_DEV_FS        1
+#define K_DEV_JOURNAL   2
+
+#define lock_buffer(bh) do {} while(0)
+#define unlock_buffer(bh) do {} while(0)
+#define buffer_req(bh) 1
+#define do_readahead(journal, start) do {} while(0)
+
+static e2fsck_t e2fsck_global_ctx;  /* Try your very best not to use this! */
+
+typedef struct {
+	int     object_length;
+} kmem_cache_t;
+
+#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
+
+/*
+ * We use the standard libext2fs portability tricks for inline
+ * functions.
+ */
+
+static kmem_cache_t * do_cache_create(int len)
+{
+	kmem_cache_t *new_cache;
+
+	new_cache = malloc(sizeof(*new_cache));
+	if (new_cache)
+		new_cache->object_length = len;
+	return new_cache;
+}
+
+static void do_cache_destroy(kmem_cache_t *cache)
+{
+	free(cache);
+}
+
+
+/*
+ * Dictionary Abstract Data Type
+ */
+
+
+/*
+ * These macros provide short convenient names for structure members,
+ * which are embellished with dict_ prefixes so that they are
+ * properly confined to the documented namespace. It's legal for a
+ * program which uses dict to define, for instance, a macro called ``parent''.
+ * Such a macro would interfere with the dnode_t struct definition.
+ * In general, highly portable and reusable C modules which expose their
+ * structures need to confine structure member names to well-defined spaces.
+ * The resulting identifiers aren't necessarily convenient to use, nor
+ * readable, in the implementation, however!
+ */
+
+#define left dict_left
+#define right dict_right
+#define parent dict_parent
+#define color dict_color
+#define key dict_key
+#define data dict_data
+
+#define nilnode dict_nilnode
+#define maxcount dict_maxcount
+#define compare dict_compare
+#define dupes dict_dupes
+
+#define dict_root(D) ((D)->nilnode.left)
+#define dict_nil(D) (&(D)->nilnode)
+
+static void dnode_free(dnode_t *node);
+
+/*
+ * Perform a ``left rotation'' adjustment on the tree.  The given node P and
+ * its right child C are rearranged so that the P instead becomes the left
+ * child of C.   The left subtree of C is inherited as the new right subtree
+ * for P.  The ordering of the keys within the tree is thus preserved.
+ */
+
+static void rotate_left(dnode_t *upper)
+{
+    dnode_t *lower, *lowleft, *upparent;
+
+    lower = upper->right;
+    upper->right = lowleft = lower->left;
+    lowleft->parent = upper;
+
+    lower->parent = upparent = upper->parent;
+
+    /* don't need to check for root node here because root->parent is
+       the sentinel nil node, and root->parent->left points back to root */
+
+    if (upper == upparent->left) {
+	upparent->left = lower;
+    } else {
+	assert (upper == upparent->right);
+	upparent->right = lower;
+    }
+
+    lower->left = upper;
+    upper->parent = lower;
+}
+
+/*
+ * This operation is the ``mirror'' image of rotate_left. It is
+ * the same procedure, but with left and right interchanged.
+ */
+
+static void rotate_right(dnode_t *upper)
+{
+    dnode_t *lower, *lowright, *upparent;
+
+    lower = upper->left;
+    upper->left = lowright = lower->right;
+    lowright->parent = upper;
+
+    lower->parent = upparent = upper->parent;
+
+    if (upper == upparent->right) {
+	upparent->right = lower;
+    } else {
+	assert (upper == upparent->left);
+	upparent->left = lower;
+    }
+
+    lower->right = upper;
+    upper->parent = lower;
+}
+
+/*
+ * Do a postorder traversal of the tree rooted at the specified
+ * node and free everything under it.  Used by dict_free().
+ */
+
+static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
+{
+    if (node == nil)
+	return;
+    free_nodes(dict, node->left, nil);
+    free_nodes(dict, node->right, nil);
+    dict->dict_freenode(node);
+}
+
+/*
+ * Verify that the tree contains the given node. This is done by
+ * traversing all of the nodes and comparing their pointers to the
+ * given pointer. Returns 1 if the node is found, otherwise
+ * returns zero. It is intended for debugging purposes.
+ */
+
+static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
+{
+    if (root != nil) {
+	return root == node
+		|| verify_dict_has_node(nil, root->left, node)
+		|| verify_dict_has_node(nil, root->right, node);
+    }
+    return 0;
+}
+
+
+/*
+ * Select a different set of node allocator routines.
+ */
+
+static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
+{
+    assert (dict_count(dict) == 0);
+    dict->dict_freenode = fr;
+}
+
+/*
+ * Free all the nodes in the dictionary by using the dictionary's
+ * installed free routine. The dictionary is emptied.
+ */
+
+static void dict_free_nodes(dict_t *dict)
+{
+    dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
+    free_nodes(dict, root, nil);
+    dict->dict_nodecount = 0;
+    dict->nilnode.left = &dict->nilnode;
+    dict->nilnode.right = &dict->nilnode;
+}
+
+/*
+ * Initialize a user-supplied dictionary object.
+ */
+
+static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
+{
+    dict->compare = comp;
+    dict->dict_freenode = dnode_free;
+    dict->dict_nodecount = 0;
+    dict->maxcount = maxcount;
+    dict->nilnode.left = &dict->nilnode;
+    dict->nilnode.right = &dict->nilnode;
+    dict->nilnode.parent = &dict->nilnode;
+    dict->nilnode.color = dnode_black;
+    dict->dupes = 0;
+    return dict;
+}
+
+/*
+ * Locate a node in the dictionary having the given key.
+ * If the node is not found, a null a pointer is returned (rather than
+ * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
+ * located node is returned.
+ */
+
+static dnode_t *dict_lookup(dict_t *dict, const void *key)
+{
+    dnode_t *root = dict_root(dict);
+    dnode_t *nil = dict_nil(dict);
+    dnode_t *saved;
+    int result;
+
+    /* simple binary search adapted for trees that contain duplicate keys */
+
+    while (root != nil) {
+	result = dict->compare(key, root->key);
+	if (result < 0)
+	    root = root->left;
+	else if (result > 0)
+	    root = root->right;
+	else {
+	    if (!dict->dupes) { /* no duplicates, return match          */
+		return root;
+	    } else {            /* could be dupes, find leftmost one    */
+		do {
+		    saved = root;
+		    root = root->left;
+		    while (root != nil && dict->compare(key, root->key))
+			root = root->right;
+		} while (root != nil);
+		return saved;
+	    }
+	}
+    }
+
+    return NULL;
+}
+
+/*
+ * Insert a node into the dictionary. The node should have been
+ * initialized with a data field. All other fields are ignored.
+ * The behavior is undefined if the user attempts to insert into
+ * a dictionary that is already full (for which the dict_isfull()
+ * function returns true).
+ */
+
+static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
+{
+    dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
+    dnode_t *parent = nil, *uncle, *grandpa;
+    int result = -1;
+
+    node->key = key;
+
+    /* basic binary tree insert */
+
+    while (where != nil) {
+	parent = where;
+	result = dict->compare(key, where->key);
+	/* trap attempts at duplicate key insertion unless it's explicitly allowed */
+	assert (dict->dupes || result != 0);
+	if (result < 0)
+	    where = where->left;
+	else
+	    where = where->right;
+    }
+
+    assert (where == nil);
+
+    if (result < 0)
+	parent->left = node;
+    else
+	parent->right = node;
+
+    node->parent = parent;
+    node->left = nil;
+    node->right = nil;
+
+    dict->dict_nodecount++;
+
+    /* red black adjustments */
+
+    node->color = dnode_red;
+
+    while (parent->color == dnode_red) {
+	grandpa = parent->parent;
+	if (parent == grandpa->left) {
+	    uncle = grandpa->right;
+	    if (uncle->color == dnode_red) {    /* red parent, red uncle */
+		parent->color = dnode_black;
+		uncle->color = dnode_black;
+		grandpa->color = dnode_red;
+		node = grandpa;
+		parent = grandpa->parent;
+	    } else {                            /* red parent, black uncle */
+		if (node == parent->right) {
+		    rotate_left(parent);
+		    parent = node;
+		    assert (grandpa == parent->parent);
+		    /* rotation between parent and child preserves grandpa */
+		}
+		parent->color = dnode_black;
+		grandpa->color = dnode_red;
+		rotate_right(grandpa);
+		break;
+	    }
+	} else {        /* symmetric cases: parent == parent->parent->right */
+	    uncle = grandpa->left;
+	    if (uncle->color == dnode_red) {
+		parent->color = dnode_black;
+		uncle->color = dnode_black;
+		grandpa->color = dnode_red;
+		node = grandpa;
+		parent = grandpa->parent;
+	    } else {
+		if (node == parent->left) {
+		    rotate_right(parent);
+		    parent = node;
+		    assert (grandpa == parent->parent);
+		}
+		parent->color = dnode_black;
+		grandpa->color = dnode_red;
+		rotate_left(grandpa);
+		break;
+	    }
+	}
+    }
+
+    dict_root(dict)->color = dnode_black;
+
+}
+
+/*
+ * Allocate a node using the dictionary's allocator routine, give it
+ * the data item.
+ */
+
+static dnode_t *dnode_init(dnode_t *dnode, void *data)
+{
+    dnode->data = data;
+    dnode->parent = NULL;
+    dnode->left = NULL;
+    dnode->right = NULL;
+    return dnode;
+}
+
+static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
+{
+    dnode_t *node = malloc(sizeof(dnode_t));
+
+    if (node) {
+	dnode_init(node, data);
+	dict_insert(dict, node, key);
+	return 1;
+    }
+    return 0;
+}
+
+/*
+ * Return the node with the lowest (leftmost) key. If the dictionary is empty
+ * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
+ */
+
+static dnode_t *dict_first(dict_t *dict)
+{
+    dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
+
+    if (root != nil)
+	while ((left = root->left) != nil)
+	    root = left;
+
+    return (root == nil) ? NULL : root;
+}
+
+/*
+ * Return the given node's successor node---the node which has the
+ * next key in the the left to right ordering. If the node has
+ * no successor, a null pointer is returned rather than a pointer to
+ * the nil node.
+ */
+
+static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
+{
+    dnode_t *nil = dict_nil(dict), *parent, *left;
+
+    if (curr->right != nil) {
+	curr = curr->right;
+	while ((left = curr->left) != nil)
+	    curr = left;
+	return curr;
+    }
+
+    parent = curr->parent;
+
+    while (parent != nil && curr == parent->right) {
+	curr = parent;
+	parent = curr->parent;
+    }
+
+    return (parent == nil) ? NULL : parent;
+}
+
+
+static void dnode_free(dnode_t *node)
+{
+    free(node);
+}
+
+
+#undef left
+#undef right
+#undef parent
+#undef color
+#undef key
+#undef data
+
+#undef nilnode
+#undef maxcount
+#undef compare
+#undef dupes
+
+
+/*
+ * dirinfo.c --- maintains the directory information table for e2fsck.
+ */
+
+/*
+ * This subroutine is called during pass1 to create a directory info
+ * entry.  During pass1, the passed-in parent is 0; it will get filled
+ * in during pass2.
+ */
+static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
+{
+	struct dir_info *dir;
+	int             i, j;
+	ext2_ino_t      num_dirs;
+	errcode_t       retval;
+	unsigned long   old_size;
+
+	if (!ctx->dir_info) {
+		ctx->dir_info_count = 0;
+		retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
+		if (retval)
+			num_dirs = 1024;        /* Guess */
+		ctx->dir_info_size = num_dirs + 10;
+		ctx->dir_info  = (struct dir_info *)
+			e2fsck_allocate_memory(ctx, ctx->dir_info_size
+					       * sizeof (struct dir_info),
+					       "directory map");
+	}
+
+	if (ctx->dir_info_count >= ctx->dir_info_size) {
+		old_size = ctx->dir_info_size * sizeof(struct dir_info);
+		ctx->dir_info_size += 10;
+		retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
+					   sizeof(struct dir_info),
+					   &ctx->dir_info);
+		if (retval) {
+			ctx->dir_info_size -= 10;
+			return;
+		}
+	}
+
+	/*
+	 * Normally, add_dir_info is called with each inode in
+	 * sequential order; but once in a while (like when pass 3
+	 * needs to recreate the root directory or lost+found
+	 * directory) it is called out of order.  In those cases, we
+	 * need to move the dir_info entries down to make room, since
+	 * the dir_info array needs to be sorted by inode number for
+	 * get_dir_info()'s sake.
+	 */
+	if (ctx->dir_info_count &&
+	    ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
+		for (i = ctx->dir_info_count-1; i > 0; i--)
+			if (ctx->dir_info[i-1].ino < ino)
+				break;
+		dir = &ctx->dir_info[i];
+		if (dir->ino != ino)
+			for (j = ctx->dir_info_count++; j > i; j--)
+				ctx->dir_info[j] = ctx->dir_info[j-1];
+	} else
+		dir = &ctx->dir_info[ctx->dir_info_count++];
+
+	dir->ino = ino;
+	dir->dotdot = parent;
+	dir->parent = parent;
+}
+
+/*
+ * get_dir_info() --- given an inode number, try to find the directory
+ * information entry for it.
+ */
+static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
+{
+	int     low, high, mid;
+
+	low = 0;
+	high = ctx->dir_info_count-1;
+	if (!ctx->dir_info)
+		return 0;
+	if (ino == ctx->dir_info[low].ino)
+		return &ctx->dir_info[low];
+	if  (ino == ctx->dir_info[high].ino)
+		return &ctx->dir_info[high];
+
+	while (low < high) {
+		mid = (low+high)/2;
+		if (mid == low || mid == high)
+			break;
+		if (ino == ctx->dir_info[mid].ino)
+			return &ctx->dir_info[mid];
+		if (ino < ctx->dir_info[mid].ino)
+			high = mid;
+		else
+			low = mid;
+	}
+	return 0;
+}
+
+/*
+ * Free the dir_info structure when it isn't needed any more.
+ */
+static void e2fsck_free_dir_info(e2fsck_t ctx)
+{
+	ext2fs_free_mem(&ctx->dir_info);
+	ctx->dir_info_size = 0;
+	ctx->dir_info_count = 0;
+}
+
+/*
+ * Return the count of number of directories in the dir_info structure
+ */
+static inline int e2fsck_get_num_dirinfo(e2fsck_t ctx)
+{
+	return ctx->dir_info_count;
+}
+
+/*
+ * A simple interator function
+ */
+static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
+{
+	if (*control >= ctx->dir_info_count)
+		return 0;
+
+	return(ctx->dir_info + (*control)++);
+}
+
+/*
+ * dirinfo.c --- maintains the directory information table for e2fsck.
+ *
+ */
+
+#ifdef ENABLE_HTREE
+
+/*
+ * This subroutine is called during pass1 to create a directory info
+ * entry.  During pass1, the passed-in parent is 0; it will get filled
+ * in during pass2.
+ */
+static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
+{
+	struct dx_dir_info *dir;
+	int             i, j;
+	errcode_t       retval;
+	unsigned long   old_size;
+
+	if (!ctx->dx_dir_info) {
+		ctx->dx_dir_info_count = 0;
+		ctx->dx_dir_info_size = 100; /* Guess */
+		ctx->dx_dir_info  = (struct dx_dir_info *)
+			e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
+					       * sizeof (struct dx_dir_info),
+					       "directory map");
+	}
+
+	if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
+		old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
+		ctx->dx_dir_info_size += 10;
+		retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
+					   sizeof(struct dx_dir_info),
+					   &ctx->dx_dir_info);
+		if (retval) {
+			ctx->dx_dir_info_size -= 10;
+			return;
+		}
+	}
+
+	/*
+	 * Normally, add_dx_dir_info is called with each inode in
+	 * sequential order; but once in a while (like when pass 3
+	 * needs to recreate the root directory or lost+found
+	 * directory) it is called out of order.  In those cases, we
+	 * need to move the dx_dir_info entries down to make room, since
+	 * the dx_dir_info array needs to be sorted by inode number for
+	 * get_dx_dir_info()'s sake.
+	 */
+	if (ctx->dx_dir_info_count &&
+	    ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
+		for (i = ctx->dx_dir_info_count-1; i > 0; i--)
+			if (ctx->dx_dir_info[i-1].ino < ino)
+				break;
+		dir = &ctx->dx_dir_info[i];
+		if (dir->ino != ino)
+			for (j = ctx->dx_dir_info_count++; j > i; j--)
+				ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
+	} else
+		dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
+
+	dir->ino = ino;
+	dir->numblocks = num_blocks;
+	dir->hashversion = 0;
+	dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
+				       * sizeof (struct dx_dirblock_info),
+				       "dx_block info array");
+
+}
+
+/*
+ * get_dx_dir_info() --- given an inode number, try to find the directory
+ * information entry for it.
+ */
+static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
+{
+	int     low, high, mid;
+
+	low = 0;
+	high = ctx->dx_dir_info_count-1;
+	if (!ctx->dx_dir_info)
+		return 0;
+	if (ino == ctx->dx_dir_info[low].ino)
+		return &ctx->dx_dir_info[low];
+	if  (ino == ctx->dx_dir_info[high].ino)
+		return &ctx->dx_dir_info[high];
+
+	while (low < high) {
+		mid = (low+high)/2;
+		if (mid == low || mid == high)
+			break;
+		if (ino == ctx->dx_dir_info[mid].ino)
+			return &ctx->dx_dir_info[mid];
+		if (ino < ctx->dx_dir_info[mid].ino)
+			high = mid;
+		else
+			low = mid;
+	}
+	return 0;
+}
+
+/*
+ * Free the dx_dir_info structure when it isn't needed any more.
+ */
+static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
+{
+	int     i;
+	struct dx_dir_info *dir;
+
+	if (ctx->dx_dir_info) {
+		dir = ctx->dx_dir_info;
+		for (i=0; i < ctx->dx_dir_info_count; i++) {
+			ext2fs_free_mem(&dir->dx_block);
+		}
+		ext2fs_free_mem(&ctx->dx_dir_info);
+	}
+	ctx->dx_dir_info_size = 0;
+	ctx->dx_dir_info_count = 0;
+}
+
+/*
+ * A simple interator function
+ */
+static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
+{
+	if (*control >= ctx->dx_dir_info_count)
+		return 0;
+
+	return(ctx->dx_dir_info + (*control)++);
+}
+
+#endif /* ENABLE_HTREE */
+/*
+ * e2fsck.c - a consistency checker for the new extended file system.
+ *
+ */
+
+/*
+ * This function allocates an e2fsck context
+ */
+static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
+{
+	e2fsck_t        context;
+	errcode_t       retval;
+
+	retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
+	if (retval)
+		return retval;
+
+	memset(context, 0, sizeof(struct e2fsck_struct));
+
+	context->process_inode_size = 256;
+	context->ext_attr_ver = 2;
+
+	*ret = context;
+	return 0;
+}
+
+struct ea_refcount_el {
+	blk_t   ea_blk;
+	int     ea_count;
+};
+
+struct ea_refcount {
+	blk_t           count;
+	blk_t           size;
+	blk_t           cursor;
+	struct ea_refcount_el   *list;
+};
+
+static void ea_refcount_free(ext2_refcount_t refcount)
+{
+	if (!refcount)
+		return;
+
+	ext2fs_free_mem(&refcount->list);
+	ext2fs_free_mem(&refcount);
+}
+
+/*
+ * This function resets an e2fsck context; it is called when e2fsck
+ * needs to be restarted.
+ */
+static errcode_t e2fsck_reset_context(e2fsck_t ctx)
+{
+	ctx->flags = 0;
+	ctx->lost_and_found = 0;
+	ctx->bad_lost_and_found = 0;
+	ext2fs_free_inode_bitmap(ctx->inode_used_map);
+	ctx->inode_used_map = 0;
+	ext2fs_free_inode_bitmap(ctx->inode_dir_map);
+	ctx->inode_dir_map = 0;
+	ext2fs_free_inode_bitmap(ctx->inode_reg_map);
+	ctx->inode_reg_map = 0;
+	ext2fs_free_block_bitmap(ctx->block_found_map);
+	ctx->block_found_map = 0;
+	ext2fs_free_icount(ctx->inode_link_info);
+	ctx->inode_link_info = 0;
+	if (ctx->journal_io) {
+		if (ctx->fs && ctx->fs->io != ctx->journal_io)
+			io_channel_close(ctx->journal_io);
+		ctx->journal_io = 0;
+	}
+	if (ctx->fs) {
+		ext2fs_free_dblist(ctx->fs->dblist);
+		ctx->fs->dblist = 0;
+	}
+	e2fsck_free_dir_info(ctx);
+#ifdef ENABLE_HTREE
+	e2fsck_free_dx_dir_info(ctx);
+#endif
+	ea_refcount_free(ctx->refcount);
+	ctx->refcount = 0;
+	ea_refcount_free(ctx->refcount_extra);
+	ctx->refcount_extra = 0;
+	ext2fs_free_block_bitmap(ctx->block_dup_map);
+	ctx->block_dup_map = 0;
+	ext2fs_free_block_bitmap(ctx->block_ea_map);
+	ctx->block_ea_map = 0;
+	ext2fs_free_inode_bitmap(ctx->inode_bad_map);
+	ctx->inode_bad_map = 0;
+	ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
+	ctx->inode_imagic_map = 0;
+	ext2fs_u32_list_free(ctx->dirs_to_hash);
+	ctx->dirs_to_hash = 0;
+
+	/*
+	 * Clear the array of invalid meta-data flags
+	 */
+	ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
+	ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
+	ext2fs_free_mem(&ctx->invalid_inode_table_flag);
+
+	/* Clear statistic counters */
+	ctx->fs_directory_count = 0;
+	ctx->fs_regular_count = 0;
+	ctx->fs_blockdev_count = 0;
+	ctx->fs_chardev_count = 0;
+	ctx->fs_links_count = 0;
+	ctx->fs_symlinks_count = 0;
+	ctx->fs_fast_symlinks_count = 0;
+	ctx->fs_fifo_count = 0;
+	ctx->fs_total_count = 0;
+	ctx->fs_sockets_count = 0;
+	ctx->fs_ind_count = 0;
+	ctx->fs_dind_count = 0;
+	ctx->fs_tind_count = 0;
+	ctx->fs_fragmented = 0;
+	ctx->large_files = 0;
+
+	/* Reset the superblock to the user's requested value */
+	ctx->superblock = ctx->use_superblock;
+
+	return 0;
+}
+
+static void e2fsck_free_context(e2fsck_t ctx)
+{
+	if (!ctx)
+		return;
+
+	e2fsck_reset_context(ctx);
+	if (ctx->blkid)
+		blkid_put_cache(ctx->blkid);
+
+	ext2fs_free_mem(&ctx);
+}
+
+/*
+ * ea_refcount.c
+ */
+
+/*
+ * The strategy we use for keeping track of EA refcounts is as
+ * follows.  We keep a sorted array of first EA blocks and its
+ * reference counts.  Once the refcount has dropped to zero, it is
+ * removed from the array to save memory space.  Once the EA block is
+ * checked, its bit is set in the block_ea_map bitmap.
+ */
+
+
+static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
+{
+	ext2_refcount_t refcount;
+	errcode_t       retval;
+	size_t          bytes;
+
+	retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
+	if (retval)
+		return retval;
+	memset(refcount, 0, sizeof(struct ea_refcount));
+
+	if (!size)
+		size = 500;
+	refcount->size = size;
+	bytes = (size_t) (size * sizeof(struct ea_refcount_el));
+#ifdef DEBUG
+	printf("Refcount allocated %d entries, %d bytes.\n",
+	       refcount->size, bytes);
+#endif
+	retval = ext2fs_get_mem(bytes, &refcount->list);
+	if (retval)
+		goto errout;
+	memset(refcount->list, 0, bytes);
+
+	refcount->count = 0;
+	refcount->cursor = 0;
+
+	*ret = refcount;
+	return 0;
+
+errout:
+	ea_refcount_free(refcount);
+	return(retval);
+}
+
+/*
+ * collapse_refcount() --- go through the refcount array, and get rid
+ * of any count == zero entries
+ */
+static void refcount_collapse(ext2_refcount_t refcount)
+{
+	unsigned int    i, j;
+	struct ea_refcount_el   *list;
+
+	list = refcount->list;
+	for (i = 0, j = 0; i < refcount->count; i++) {
+		if (list[i].ea_count) {
+			if (i != j)
+				list[j] = list[i];
+			j++;
+		}
+	}
+#if defined(DEBUG) || defined(TEST_PROGRAM)
+	printf("Refcount_collapse: size was %d, now %d\n",
+	       refcount->count, j);
+#endif
+	refcount->count = j;
+}
+
+
+/*
+ * insert_refcount_el() --- Insert a new entry into the sorted list at a
+ *      specified position.
+ */
+static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
+						 blk_t blk, int pos)
+{
+	struct ea_refcount_el   *el;
+	errcode_t               retval;
+	blk_t                   new_size = 0;
+	int                     num;
+
+	if (refcount->count >= refcount->size) {
+		new_size = refcount->size + 100;
+#ifdef DEBUG
+		printf("Reallocating refcount %d entries...\n", new_size);
+#endif
+		retval = ext2fs_resize_mem((size_t) refcount->size *
+					   sizeof(struct ea_refcount_el),
+					   (size_t) new_size *
+					   sizeof(struct ea_refcount_el),
+					   &refcount->list);
+		if (retval)
+			return 0;
+		refcount->size = new_size;
+	}
+	num = (int) refcount->count - pos;
+	if (num < 0)
+		return 0;       /* should never happen */
+	if (num) {
+		memmove(&refcount->list[pos+1], &refcount->list[pos],
+			sizeof(struct ea_refcount_el) * num);
+	}
+	refcount->count++;
+	el = &refcount->list[pos];
+	el->ea_count = 0;
+	el->ea_blk = blk;
+	return el;
+}
+
+
+/*
+ * get_refcount_el() --- given an block number, try to find refcount
+ *      information in the sorted list.  If the create flag is set,
+ *      and we can't find an entry, create one in the sorted list.
+ */
+static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
+					      blk_t blk, int create)
+{
+	float   range;
+	int     low, high, mid;
+	blk_t   lowval, highval;
+
+	if (!refcount || !refcount->list)
+		return 0;
+retry:
+	low = 0;
+	high = (int) refcount->count-1;
+	if (create && ((refcount->count == 0) ||
+		       (blk > refcount->list[high].ea_blk))) {
+		if (refcount->count >= refcount->size)
+			refcount_collapse(refcount);
+
+		return insert_refcount_el(refcount, blk,
+					  (unsigned) refcount->count);
+	}
+	if (refcount->count == 0)
+		return 0;
+
+	if (refcount->cursor >= refcount->count)
+		refcount->cursor = 0;
+	if (blk == refcount->list[refcount->cursor].ea_blk)
+		return &refcount->list[refcount->cursor++];
+#ifdef DEBUG
+	printf("Non-cursor get_refcount_el: %u\n", blk);
+#endif
+	while (low <= high) {
+		if (low == high)
+			mid = low;
+		else {
+			/* Interpolate for efficiency */
+			lowval = refcount->list[low].ea_blk;
+			highval = refcount->list[high].ea_blk;
+
+			if (blk < lowval)
+				range = 0;
+			else if (blk > highval)
+				range = 1;
+			else
+				range = ((float) (blk - lowval)) /
+					(highval - lowval);
+			mid = low + ((int) (range * (high-low)));
+		}
+
+		if (blk == refcount->list[mid].ea_blk) {
+			refcount->cursor = mid+1;
+			return &refcount->list[mid];
+		}
+		if (blk < refcount->list[mid].ea_blk)
+			high = mid-1;
+		else
+			low = mid+1;
+	}
+	/*
+	 * If we need to create a new entry, it should be right at
+	 * low (where high will be left at low-1).
+	 */
+	if (create) {
+		if (refcount->count >= refcount->size) {
+			refcount_collapse(refcount);
+			if (refcount->count < refcount->size)
+				goto retry;
+		}
+		return insert_refcount_el(refcount, blk, low);
+	}
+	return 0;
+}
+
+static errcode_t
+ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
+{
+	struct ea_refcount_el   *el;
+
+	el = get_refcount_el(refcount, blk, 1);
+	if (!el)
+		return EXT2_ET_NO_MEMORY;
+	el->ea_count++;
+
+	if (ret)
+		*ret = el->ea_count;
+	return 0;
+}
+
+static errcode_t
+ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
+{
+	struct ea_refcount_el   *el;
+
+	el = get_refcount_el(refcount, blk, 0);
+	if (!el || el->ea_count == 0)
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	el->ea_count--;
+
+	if (ret)
+		*ret = el->ea_count;
+	return 0;
+}
+
+static errcode_t
+ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
+{
+	struct ea_refcount_el   *el;
+
+	/*
+	 * Get the refcount element
+	 */
+	el = get_refcount_el(refcount, blk, count ? 1 : 0);
+	if (!el)
+		return count ? EXT2_ET_NO_MEMORY : 0;
+	el->ea_count = count;
+	return 0;
+}
+
+static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
+{
+	refcount->cursor = 0;
+}
+
+
+static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
+{
+	struct ea_refcount_el   *list;
+
+	while (1) {
+		if (refcount->cursor >= refcount->count)
+			return 0;
+		list = refcount->list;
+		if (list[refcount->cursor].ea_count) {
+			if (ret)
+				*ret = list[refcount->cursor].ea_count;
+			return list[refcount->cursor++].ea_blk;
+		}
+		refcount->cursor++;
+	}
+}
+
+
+/*
+ * ehandler.c --- handle bad block errors which come up during the
+ *      course of an e2fsck session.
+ */
+
+
+static const char *operation;
+
+static errcode_t
+e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
+			 void *data, size_t size FSCK_ATTR((unused)),
+			 int actual FSCK_ATTR((unused)), errcode_t error)
+{
+	int     i;
+	char    *p;
+	ext2_filsys fs = (ext2_filsys) channel->app_data;
+	e2fsck_t ctx;
+
+	ctx = (e2fsck_t) fs->priv_data;
+
+	/*
+	 * If more than one block was read, try reading each block
+	 * separately.  We could use the actual bytes read to figure
+	 * out where to start, but we don't bother.
+	 */
+	if (count > 1) {
+		p = (char *) data;
+		for (i=0; i < count; i++, p += channel->block_size, block++) {
+			error = io_channel_read_blk(channel, block,
+						    1, p);
+			if (error)
+				return error;
+		}
+		return 0;
+	}
+	if (operation)
+		printf(_("Error reading block %lu (%s) while %s.  "), block,
+		       error_message(error), operation);
+	else
+		printf(_("Error reading block %lu (%s).  "), block,
+		       error_message(error));
+	preenhalt(ctx);
+	if (ask(ctx, _("Ignore error"), 1)) {
+		if (ask(ctx, _("Force rewrite"), 1))
+			io_channel_write_blk(channel, block, 1, data);
+		return 0;
+	}
+
+	return error;
+}
+
+static errcode_t
+e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
+			const void *data, size_t size FSCK_ATTR((unused)),
+			int actual FSCK_ATTR((unused)), errcode_t error)
+{
+	int             i;
+	const char      *p;
+	ext2_filsys fs = (ext2_filsys) channel->app_data;
+	e2fsck_t ctx;
+
+	ctx = (e2fsck_t) fs->priv_data;
+
+	/*
+	 * If more than one block was written, try writing each block
+	 * separately.  We could use the actual bytes read to figure
+	 * out where to start, but we don't bother.
+	 */
+	if (count > 1) {
+		p = (const char *) data;
+		for (i=0; i < count; i++, p += channel->block_size, block++) {
+			error = io_channel_write_blk(channel, block,
+						     1, p);
+			if (error)
+				return error;
+		}
+		return 0;
+	}
+
+	if (operation)
+		printf(_("Error writing block %lu (%s) while %s.  "), block,
+		       error_message(error), operation);
+	else
+		printf(_("Error writing block %lu (%s).  "), block,
+		       error_message(error));
+	preenhalt(ctx);
+	if (ask(ctx, _("Ignore error"), 1))
+		return 0;
+
+	return error;
+}
+
+static inline const char *ehandler_operation(const char *op)
+{
+	const char *ret = operation;
+
+	operation = op;
+	return ret;
+}
+
+static void ehandler_init(io_channel channel)
+{
+	channel->read_error = e2fsck_handle_read_error;
+	channel->write_error = e2fsck_handle_write_error;
+}
+
+/*
+ * journal.c --- code for handling the "ext3" journal
+ *
+ * Copyright (C) 2000 Andreas Dilger
+ * Copyright (C) 2000 Theodore Ts'o
+ *
+ * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This file may be redistributed under the terms of the
+ * GNU General Public License version 2 or at your discretion
+ * any later version.
+ */
+
+/*
+ * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
+ * This creates a larger static binary, and a smaller binary using
+ * shared libraries.  It's also probably slightly less CPU-efficient,
+ * which is why it's not on by default.  But, it's a good way of
+ * testing the functions in inode_io.c and fileio.c.
+ */
+#undef USE_INODE_IO
+
+/* Kernel compatibility functions for handling the journal.  These allow us
+ * to use the recovery.c file virtually unchanged from the kernel, so we
+ * don't have to do much to keep kernel and user recovery in sync.
+ */
+static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
+{
+#ifdef USE_INODE_IO
+	*phys = block;
+	return 0;
+#else
+	struct inode    *inode = journal->j_inode;
+	errcode_t       retval;
+	blk_t           pblk;
+
+	if (!inode) {
+		*phys = block;
+		return 0;
+	}
+
+	retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
+			    &inode->i_ext2, NULL, 0, block, &pblk);
+	*phys = pblk;
+	return (retval);
+#endif
+}
+
+static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
+{
+	struct buffer_head *bh;
+
+	bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
+	if (!bh)
+		return NULL;
+
+	bh->b_ctx = kdev->k_ctx;
+	if (kdev->k_dev == K_DEV_FS)
+		bh->b_io = kdev->k_ctx->fs->io;
+	else
+		bh->b_io = kdev->k_ctx->journal_io;
+	bh->b_size = blocksize;
+	bh->b_blocknr = blocknr;
+
+	return bh;
+}
+
+static void sync_blockdev(kdev_t kdev)
+{
+	io_channel      io;
+
+	if (kdev->k_dev == K_DEV_FS)
+		io = kdev->k_ctx->fs->io;
+	else
+		io = kdev->k_ctx->journal_io;
+
+	io_channel_flush(io);
+}
+
+static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
+{
+	int retval;
+	struct buffer_head *bh;
+
+	for (; nr > 0; --nr) {
+		bh = *bhp++;
+		if (rw == READ && !bh->b_uptodate) {
+			retval = io_channel_read_blk(bh->b_io,
+						     bh->b_blocknr,
+						     1, bh->b_data);
+			if (retval) {
+				bb_error_msg("while reading block %lu\n",
+					(unsigned long) bh->b_blocknr);
+				bh->b_err = retval;
+				continue;
+			}
+			bh->b_uptodate = 1;
+		} else if (rw == WRITE && bh->b_dirty) {
+			retval = io_channel_write_blk(bh->b_io,
+						      bh->b_blocknr,
+						      1, bh->b_data);
+			if (retval) {
+				bb_error_msg("while writing block %lu\n",
+					(unsigned long) bh->b_blocknr);
+				bh->b_err = retval;
+				continue;
+			}
+			bh->b_dirty = 0;
+			bh->b_uptodate = 1;
+		}
+	}
+}
+
+static inline void mark_buffer_dirty(struct buffer_head *bh)
+{
+	bh->b_dirty = 1;
+}
+
+static inline void mark_buffer_clean(struct buffer_head * bh)
+{
+	bh->b_dirty = 0;
+}
+
+static void brelse(struct buffer_head *bh)
+{
+	if (bh->b_dirty)
+		ll_rw_block(WRITE, 1, &bh);
+	ext2fs_free_mem(&bh);
+}
+
+static inline int buffer_uptodate(struct buffer_head *bh)
+{
+	return bh->b_uptodate;
+}
+
+static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
+{
+	bh->b_uptodate = val;
+}
+
+static void wait_on_buffer(struct buffer_head *bh)
+{
+	if (!bh->b_uptodate)
+		ll_rw_block(READ, 1, &bh);
+}
+
+
+static void e2fsck_clear_recover(e2fsck_t ctx, int error)
+{
+	ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
+
+	/* if we had an error doing journal recovery, we need a full fsck */
+	if (error)
+		ctx->fs->super->s_state &= ~EXT2_VALID_FS;
+	ext2fs_mark_super_dirty(ctx->fs);
+}
+
+static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
+{
+	struct ext2_super_block *sb = ctx->fs->super;
+	struct ext2_super_block jsuper;
+	struct problem_context  pctx;
+	struct buffer_head      *bh;
+	struct inode            *j_inode = NULL;
+	struct kdev_s           *dev_fs = NULL, *dev_journal;
+	const char              *journal_name = 0;
+	journal_t               *journal = NULL;
+	errcode_t               retval = 0;
+	io_manager              io_ptr = 0;
+	unsigned long           start = 0;
+	blk_t                   blk;
+	int                     ext_journal = 0;
+	int                     tried_backup_jnl = 0;
+	int                     i;
+
+	clear_problem_context(&pctx);
+
+	journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
+	if (!journal) {
+		return EXT2_ET_NO_MEMORY;
+	}
+
+	dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
+	if (!dev_fs) {
+		retval = EXT2_ET_NO_MEMORY;
+		goto errout;
+	}
+	dev_journal = dev_fs+1;
+
+	dev_fs->k_ctx = dev_journal->k_ctx = ctx;
+	dev_fs->k_dev = K_DEV_FS;
+	dev_journal->k_dev = K_DEV_JOURNAL;
+
+	journal->j_dev = dev_journal;
+	journal->j_fs_dev = dev_fs;
+	journal->j_inode = NULL;
+	journal->j_blocksize = ctx->fs->blocksize;
+
+	if (uuid_is_null(sb->s_journal_uuid)) {
+		if (!sb->s_journal_inum)
+			return EXT2_ET_BAD_INODE_NUM;
+		j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
+						 "journal inode");
+		if (!j_inode) {
+			retval = EXT2_ET_NO_MEMORY;
+			goto errout;
+		}
+
+		j_inode->i_ctx = ctx;
+		j_inode->i_ino = sb->s_journal_inum;
+
+		if ((retval = ext2fs_read_inode(ctx->fs,
+						sb->s_journal_inum,
+						&j_inode->i_ext2))) {
+		try_backup_journal:
+			if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
+			    tried_backup_jnl)
+				goto errout;
+			memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
+			memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
+			       EXT2_N_BLOCKS*4);
+			j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
+			j_inode->i_ext2.i_links_count = 1;
+			j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
+			tried_backup_jnl++;
+		}
+		if (!j_inode->i_ext2.i_links_count ||
+		    !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
+			retval = EXT2_ET_NO_JOURNAL;
+			goto try_backup_journal;
+		}
+		if (j_inode->i_ext2.i_size / journal->j_blocksize <
+		    JFS_MIN_JOURNAL_BLOCKS) {
+			retval = EXT2_ET_JOURNAL_TOO_SMALL;
+			goto try_backup_journal;
+		}
+		for (i=0; i < EXT2_N_BLOCKS; i++) {
+			blk = j_inode->i_ext2.i_block[i];
+			if (!blk) {
+				if (i < EXT2_NDIR_BLOCKS) {
+					retval = EXT2_ET_JOURNAL_TOO_SMALL;
+					goto try_backup_journal;
+				}
+				continue;
+			}
+			if (blk < sb->s_first_data_block ||
+			    blk >= sb->s_blocks_count) {
+				retval = EXT2_ET_BAD_BLOCK_NUM;
+				goto try_backup_journal;
+			}
+		}
+		journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
+
+#ifdef USE_INODE_IO
+		retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
+						 &j_inode->i_ext2,
+						 &journal_name);
+		if (retval)
+			goto errout;
+
+		io_ptr = inode_io_manager;
+#else
+		journal->j_inode = j_inode;
+		ctx->journal_io = ctx->fs->io;
+		if ((retval = journal_bmap(journal, 0, &start)) != 0)
+			goto errout;
+#endif
+	} else {
+		ext_journal = 1;
+		if (!ctx->journal_name) {
+			char uuid[37];
+
+			uuid_unparse(sb->s_journal_uuid, uuid);
+			ctx->journal_name = blkid_get_devname(ctx->blkid,
+							      "UUID", uuid);
+			if (!ctx->journal_name)
+				ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
+		}
+		journal_name = ctx->journal_name;
+
+		if (!journal_name) {
+			fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
+			return EXT2_ET_LOAD_EXT_JOURNAL;
+		}
+
+		io_ptr = unix_io_manager;
+	}
+
+#ifndef USE_INODE_IO
+	if (ext_journal)
+#endif
+		retval = io_ptr->open(journal_name, IO_FLAG_RW,
+				      &ctx->journal_io);
+	if (retval)
+		goto errout;
+
+	io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
+
+	if (ext_journal) {
+		if (ctx->fs->blocksize == 1024)
+			start = 1;
+		bh = getblk(dev_journal, start, ctx->fs->blocksize);
+		if (!bh) {
+			retval = EXT2_ET_NO_MEMORY;
+			goto errout;
+		}
+		ll_rw_block(READ, 1, &bh);
+		if ((retval = bh->b_err) != 0)
+			goto errout;
+		memcpy(&jsuper, start ? bh->b_data :  bh->b_data + 1024,
+		       sizeof(jsuper));
+		brelse(bh);
+#if BB_BIG_ENDIAN
+		if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
+			ext2fs_swap_super(&jsuper);
+#endif
+		if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
+		    !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+			fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
+			retval = EXT2_ET_LOAD_EXT_JOURNAL;
+			goto errout;
+		}
+		/* Make sure the journal UUID is correct */
+		if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
+			   sizeof(jsuper.s_uuid))) {
+			fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
+			retval = EXT2_ET_LOAD_EXT_JOURNAL;
+			goto errout;
+		}
+
+		journal->j_maxlen = jsuper.s_blocks_count;
+		start++;
+	}
+
+	if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
+		retval = EXT2_ET_NO_MEMORY;
+		goto errout;
+	}
+
+	journal->j_sb_buffer = bh;
+	journal->j_superblock = (journal_superblock_t *)bh->b_data;
+
+#ifdef USE_INODE_IO
+	ext2fs_free_mem(&j_inode);
+#endif
+
+	*ret_journal = journal;
+	return 0;
+
+errout:
+	ext2fs_free_mem(&dev_fs);
+	ext2fs_free_mem(&j_inode);
+	ext2fs_free_mem(&journal);
+	return retval;
+
+}
+
+static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
+					      struct problem_context *pctx)
+{
+	struct ext2_super_block *sb = ctx->fs->super;
+	int recover = ctx->fs->super->s_feature_incompat &
+		EXT3_FEATURE_INCOMPAT_RECOVER;
+	int has_journal = ctx->fs->super->s_feature_compat &
+		EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+
+	if (has_journal || sb->s_journal_inum) {
+		/* The journal inode is bogus, remove and force full fsck */
+		pctx->ino = sb->s_journal_inum;
+		if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
+			if (has_journal && sb->s_journal_inum)
+				printf("*** ext3 journal has been deleted - "
+				       "filesystem is now ext2 only ***\n\n");
+			sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+			sb->s_journal_inum = 0;
+			ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
+			e2fsck_clear_recover(ctx, 1);
+			return 0;
+		}
+		return EXT2_ET_BAD_INODE_NUM;
+	} else if (recover) {
+		if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
+			e2fsck_clear_recover(ctx, 1);
+			return 0;
+		}
+		return EXT2_ET_UNSUPP_FEATURE;
+	}
+	return 0;
+}
+
+#define V1_SB_SIZE      0x0024
+static void clear_v2_journal_fields(journal_t *journal)
+{
+	e2fsck_t ctx = journal->j_dev->k_ctx;
+	struct problem_context pctx;
+
+	clear_problem_context(&pctx);
+
+	if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
+		return;
+
+	memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
+	       ctx->fs->blocksize-V1_SB_SIZE);
+	mark_buffer_dirty(journal->j_sb_buffer);
+}
+
+
+static errcode_t e2fsck_journal_load(journal_t *journal)
+{
+	e2fsck_t ctx = journal->j_dev->k_ctx;
+	journal_superblock_t *jsb;
+	struct buffer_head *jbh = journal->j_sb_buffer;
+	struct problem_context pctx;
+
+	clear_problem_context(&pctx);
+
+	ll_rw_block(READ, 1, &jbh);
+	if (jbh->b_err) {
+		bb_error_msg(_("reading journal superblock\n"));
+		return jbh->b_err;
+	}
+
+	jsb = journal->j_superblock;
+	/* If we don't even have JFS_MAGIC, we probably have a wrong inode */
+	if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
+		return e2fsck_journal_fix_bad_inode(ctx, &pctx);
+
+	switch (ntohl(jsb->s_header.h_blocktype)) {
+	case JFS_SUPERBLOCK_V1:
+		journal->j_format_version = 1;
+		if (jsb->s_feature_compat ||
+		    jsb->s_feature_incompat ||
+		    jsb->s_feature_ro_compat ||
+		    jsb->s_nr_users)
+			clear_v2_journal_fields(journal);
+		break;
+
+	case JFS_SUPERBLOCK_V2:
+		journal->j_format_version = 2;
+		if (ntohl(jsb->s_nr_users) > 1 &&
+		    uuid_is_null(ctx->fs->super->s_journal_uuid))
+			clear_v2_journal_fields(journal);
+		if (ntohl(jsb->s_nr_users) > 1) {
+			fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
+			return EXT2_ET_JOURNAL_UNSUPP_VERSION;
+		}
+		break;
+
+	/*
+	 * These should never appear in a journal super block, so if
+	 * they do, the journal is badly corrupted.
+	 */
+	case JFS_DESCRIPTOR_BLOCK:
+	case JFS_COMMIT_BLOCK:
+	case JFS_REVOKE_BLOCK:
+		return EXT2_ET_CORRUPT_SUPERBLOCK;
+
+	/* If we don't understand the superblock major type, but there
+	 * is a magic number, then it is likely to be a new format we
+	 * just don't understand, so leave it alone. */
+	default:
+		return EXT2_ET_JOURNAL_UNSUPP_VERSION;
+	}
+
+	if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
+		return EXT2_ET_UNSUPP_FEATURE;
+
+	if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
+		return EXT2_ET_RO_UNSUPP_FEATURE;
+
+	/* We have now checked whether we know enough about the journal
+	 * format to be able to proceed safely, so any other checks that
+	 * fail we should attempt to recover from. */
+	if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
+		bb_error_msg(_("%s: no valid journal superblock found\n"),
+			ctx->device_name);
+		return EXT2_ET_CORRUPT_SUPERBLOCK;
+	}
+
+	if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
+		journal->j_maxlen = ntohl(jsb->s_maxlen);
+	else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
+		bb_error_msg(_("%s: journal too short\n"),
+			ctx->device_name);
+		return EXT2_ET_CORRUPT_SUPERBLOCK;
+	}
+
+	journal->j_tail_sequence = ntohl(jsb->s_sequence);
+	journal->j_transaction_sequence = journal->j_tail_sequence;
+	journal->j_tail = ntohl(jsb->s_start);
+	journal->j_first = ntohl(jsb->s_first);
+	journal->j_last = ntohl(jsb->s_maxlen);
+
+	return 0;
+}
+
+static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
+				       journal_t *journal)
+{
+	char *p;
+	union {
+		uuid_t uuid;
+		__u32 val[4];
+	} u;
+	__u32 new_seq = 0;
+	int i;
+
+	/* Leave a valid existing V1 superblock signature alone.
+	 * Anything unrecognisable we overwrite with a new V2
+	 * signature. */
+
+	if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
+	    jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
+		jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
+		jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
+	}
+
+	/* Zero out everything else beyond the superblock header */
+
+	p = ((char *) jsb) + sizeof(journal_header_t);
+	memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
+
+	jsb->s_blocksize = htonl(ctx->fs->blocksize);
+	jsb->s_maxlen = htonl(journal->j_maxlen);
+	jsb->s_first = htonl(1);
+
+	/* Initialize the journal sequence number so that there is "no"
+	 * chance we will find old "valid" transactions in the journal.
+	 * This avoids the need to zero the whole journal (slow to do,
+	 * and risky when we are just recovering the filesystem).
+	 */
+	uuid_generate(u.uuid);
+	for (i = 0; i < 4; i ++)
+		new_seq ^= u.val[i];
+	jsb->s_sequence = htonl(new_seq);
+
+	mark_buffer_dirty(journal->j_sb_buffer);
+	ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
+}
+
+static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
+						  journal_t *journal,
+						  struct problem_context *pctx)
+{
+	struct ext2_super_block *sb = ctx->fs->super;
+	int recover = ctx->fs->super->s_feature_incompat &
+		EXT3_FEATURE_INCOMPAT_RECOVER;
+
+	if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
+		if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
+			e2fsck_journal_reset_super(ctx, journal->j_superblock,
+						   journal);
+			journal->j_transaction_sequence = 1;
+			e2fsck_clear_recover(ctx, recover);
+			return 0;
+		}
+		return EXT2_ET_CORRUPT_SUPERBLOCK;
+	} else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
+		return EXT2_ET_CORRUPT_SUPERBLOCK;
+
+	return 0;
+}
+
+static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
+				   int reset, int drop)
+{
+	journal_superblock_t *jsb;
+
+	if (drop)
+		mark_buffer_clean(journal->j_sb_buffer);
+	else if (!(ctx->options & E2F_OPT_READONLY)) {
+		jsb = journal->j_superblock;
+		jsb->s_sequence = htonl(journal->j_transaction_sequence);
+		if (reset)
+			jsb->s_start = 0; /* this marks the journal as empty */
+		mark_buffer_dirty(journal->j_sb_buffer);
+	}
+	brelse(journal->j_sb_buffer);
+
+	if (ctx->journal_io) {
+		if (ctx->fs && ctx->fs->io != ctx->journal_io)
+			io_channel_close(ctx->journal_io);
+		ctx->journal_io = 0;
+	}
+
+#ifndef USE_INODE_IO
+	ext2fs_free_mem(&journal->j_inode);
+#endif
+	ext2fs_free_mem(&journal->j_fs_dev);
+	ext2fs_free_mem(&journal);
+}
+
+/*
+ * This function makes sure that the superblock fields regarding the
+ * journal are consistent.
+ */
+static int e2fsck_check_ext3_journal(e2fsck_t ctx)
+{
+	struct ext2_super_block *sb = ctx->fs->super;
+	journal_t *journal;
+	int recover = ctx->fs->super->s_feature_incompat &
+		EXT3_FEATURE_INCOMPAT_RECOVER;
+	struct problem_context pctx;
+	problem_t problem;
+	int reset = 0, force_fsck = 0;
+	int retval;
+
+	/* If we don't have any journal features, don't do anything more */
+	if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
+	    !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
+	    uuid_is_null(sb->s_journal_uuid))
+		return 0;
+
+	clear_problem_context(&pctx);
+	pctx.num = sb->s_journal_inum;
+
+	retval = e2fsck_get_journal(ctx, &journal);
+	if (retval) {
+		if ((retval == EXT2_ET_BAD_INODE_NUM) ||
+		    (retval == EXT2_ET_BAD_BLOCK_NUM) ||
+		    (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
+		    (retval == EXT2_ET_NO_JOURNAL))
+			return e2fsck_journal_fix_bad_inode(ctx, &pctx);
+		return retval;
+	}
+
+	retval = e2fsck_journal_load(journal);
+	if (retval) {
+		if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
+		    ((retval == EXT2_ET_UNSUPP_FEATURE) &&
+		    (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
+				  &pctx))) ||
+		    ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
+		    (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
+				  &pctx))) ||
+		    ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
+		    (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
+			retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
+								  &pctx);
+		e2fsck_journal_release(ctx, journal, 0, 1);
+		return retval;
+	}
+
+	/*
+	 * We want to make the flags consistent here.  We will not leave with
+	 * needs_recovery set but has_journal clear.  We can't get in a loop
+	 * with -y, -n, or -p, only if a user isn't making up their mind.
+	 */
+no_has_journal:
+	if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
+		recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
+		pctx.str = "inode";
+		if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
+			if (recover &&
+			    !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
+				goto no_has_journal;
+			/*
+			 * Need a full fsck if we are releasing a
+			 * journal stored on a reserved inode.
+			 */
+			force_fsck = recover ||
+				(sb->s_journal_inum < EXT2_FIRST_INODE(sb));
+			/* Clear all of the journal fields */
+			sb->s_journal_inum = 0;
+			sb->s_journal_dev = 0;
+			memset(sb->s_journal_uuid, 0,
+			       sizeof(sb->s_journal_uuid));
+			e2fsck_clear_recover(ctx, force_fsck);
+		} else if (!(ctx->options & E2F_OPT_READONLY)) {
+			sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+			ext2fs_mark_super_dirty(ctx->fs);
+		}
+	}
+
+	if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
+	    !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
+	    journal->j_superblock->s_start != 0) {
+		/* Print status information */
+		fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
+		if (ctx->superblock)
+			problem = PR_0_JOURNAL_RUN_DEFAULT;
+		else
+			problem = PR_0_JOURNAL_RUN;
+		if (fix_problem(ctx, problem, &pctx)) {
+			ctx->options |= E2F_OPT_FORCE;
+			sb->s_feature_incompat |=
+				EXT3_FEATURE_INCOMPAT_RECOVER;
+			ext2fs_mark_super_dirty(ctx->fs);
+		} else if (fix_problem(ctx,
+				       PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
+			reset = 1;
+			sb->s_state &= ~EXT2_VALID_FS;
+			ext2fs_mark_super_dirty(ctx->fs);
+		}
+		/*
+		 * If the user answers no to the above question, we
+		 * ignore the fact that journal apparently has data;
+		 * accidentally replaying over valid data would be far
+		 * worse than skipping a questionable recovery.
+		 *
+		 * XXX should we abort with a fatal error here?  What
+		 * will the ext3 kernel code do if a filesystem with
+		 * !NEEDS_RECOVERY but with a non-zero
+		 * journal->j_superblock->s_start is mounted?
+		 */
+	}
+
+	e2fsck_journal_release(ctx, journal, reset, 0);
+	return retval;
+}
+
+static errcode_t recover_ext3_journal(e2fsck_t ctx)
+{
+	journal_t *journal;
+	int retval;
+
+	journal_init_revoke_caches();
+	retval = e2fsck_get_journal(ctx, &journal);
+	if (retval)
+		return retval;
+
+	retval = e2fsck_journal_load(journal);
+	if (retval)
+		goto errout;
+
+	retval = journal_init_revoke(journal, 1024);
+	if (retval)
+		goto errout;
+
+	retval = -journal_recover(journal);
+	if (retval)
+		goto errout;
+
+	if (journal->j_superblock->s_errno) {
+		ctx->fs->super->s_state |= EXT2_ERROR_FS;
+		ext2fs_mark_super_dirty(ctx->fs);
+		journal->j_superblock->s_errno = 0;
+		mark_buffer_dirty(journal->j_sb_buffer);
+	}
+
+errout:
+	journal_destroy_revoke(journal);
+	journal_destroy_revoke_caches();
+	e2fsck_journal_release(ctx, journal, 1, 0);
+	return retval;
+}
+
+static int e2fsck_run_ext3_journal(e2fsck_t ctx)
+{
+	io_manager io_ptr = ctx->fs->io->manager;
+	int blocksize = ctx->fs->blocksize;
+	errcode_t       retval, recover_retval;
+
+	printf(_("%s: recovering journal\n"), ctx->device_name);
+	if (ctx->options & E2F_OPT_READONLY) {
+		printf(_("%s: won't do journal recovery while read-only\n"),
+		       ctx->device_name);
+		return EXT2_ET_FILE_RO;
+	}
+
+	if (ctx->fs->flags & EXT2_FLAG_DIRTY)
+		ext2fs_flush(ctx->fs);  /* Force out any modifications */
+
+	recover_retval = recover_ext3_journal(ctx);
+
+	/*
+	 * Reload the filesystem context to get up-to-date data from disk
+	 * because journal recovery will change the filesystem under us.
+	 */
+	ext2fs_close(ctx->fs);
+	retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
+			     ctx->superblock, blocksize, io_ptr,
+			     &ctx->fs);
+
+	if (retval) {
+		bb_error_msg(_("while trying to re-open %s"),
+			ctx->device_name);
+		bb_error_msg_and_die(0);
+	}
+	ctx->fs->priv_data = ctx;
+
+	/* Set the superblock flags */
+	e2fsck_clear_recover(ctx, recover_retval);
+	return recover_retval;
+}
+
+/*
+ * This function will move the journal inode from a visible file in
+ * the filesystem directory hierarchy to the reserved inode if necessary.
+ */
+static const char * const journal_names[] = {
+	".journal", "journal", ".journal.dat", "journal.dat", 0 };
+
+static void e2fsck_move_ext3_journal(e2fsck_t ctx)
+{
+	struct ext2_super_block *sb = ctx->fs->super;
+	struct problem_context  pctx;
+	struct ext2_inode       inode;
+	ext2_filsys             fs = ctx->fs;
+	ext2_ino_t              ino;
+	errcode_t               retval;
+	const char * const *    cpp;
+	int                     group, mount_flags;
+
+	clear_problem_context(&pctx);
+
+	/*
+	 * If the filesystem is opened read-only, or there is no
+	 * journal, then do nothing.
+	 */
+	if ((ctx->options & E2F_OPT_READONLY) ||
+	    (sb->s_journal_inum == 0) ||
+	    !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
+		return;
+
+	/*
+	 * Read in the journal inode
+	 */
+	if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
+		return;
+
+	/*
+	 * If it's necessary to backup the journal inode, do so.
+	 */
+	if ((sb->s_jnl_backup_type == 0) ||
+	    ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
+	     memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
+		if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
+			memcpy(sb->s_jnl_blocks, inode.i_block,
+			       EXT2_N_BLOCKS*4);
+			sb->s_jnl_blocks[16] = inode.i_size;
+			sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
+			ext2fs_mark_super_dirty(fs);
+			fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
+		}
+	}
+
+	/*
+	 * If the journal is already the hidden inode, then do nothing
+	 */
+	if (sb->s_journal_inum == EXT2_JOURNAL_INO)
+		return;
+
+	/*
+	 * The journal inode had better have only one link and not be readable.
+	 */
+	if (inode.i_links_count != 1)
+		return;
+
+	/*
+	 * If the filesystem is mounted, or we can't tell whether
+	 * or not it's mounted, do nothing.
+	 */
+	retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
+	if (retval || (mount_flags & EXT2_MF_MOUNTED))
+		return;
+
+	/*
+	 * If we can't find the name of the journal inode, then do
+	 * nothing.
+	 */
+	for (cpp = journal_names; *cpp; cpp++) {
+		retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
+				       strlen(*cpp), 0, &ino);
+		if ((retval == 0) && (ino == sb->s_journal_inum))
+			break;
+	}
+	if (*cpp == 0)
+		return;
+
+	/* We need the inode bitmap to be loaded */
+	retval = ext2fs_read_bitmaps(fs);
+	if (retval)
+		return;
+
+	pctx.str = *cpp;
+	if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
+		return;
+
+	/*
+	 * OK, we've done all the checks, let's actually move the
+	 * journal inode.  Errors at this point mean we need to force
+	 * an ext2 filesystem check.
+	 */
+	if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
+		goto err_out;
+	if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
+		goto err_out;
+	sb->s_journal_inum = EXT2_JOURNAL_INO;
+	ext2fs_mark_super_dirty(fs);
+	fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
+	inode.i_links_count = 0;
+	inode.i_dtime = time(0);
+	if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
+		goto err_out;
+
+	group = ext2fs_group_of_ino(fs, ino);
+	ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
+	ext2fs_mark_ib_dirty(fs);
+	fs->group_desc[group].bg_free_inodes_count++;
+	fs->super->s_free_inodes_count++;
+	return;
+
+err_out:
+	pctx.errcode = retval;
+	fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
+	fs->super->s_state &= ~EXT2_VALID_FS;
+	ext2fs_mark_super_dirty(fs);
+	return;
+}
+
+/*
+ * message.c --- print e2fsck messages (with compression)
+ *
+ * print_e2fsck_message() prints a message to the user, using
+ * compression techniques and expansions of abbreviations.
+ *
+ * The following % expansions are supported:
+ *
+ *      %b      <blk>                   block number
+ *      %B      <blkcount>              integer
+ *      %c      <blk2>                  block number
+ *      %Di     <dirent>->ino           inode number
+ *      %Dn     <dirent>->name          string
+ *      %Dr     <dirent>->rec_len
+ *      %Dl     <dirent>->name_len
+ *      %Dt     <dirent>->filetype
+ *      %d      <dir>                   inode number
+ *      %g      <group>                 integer
+ *      %i      <ino>                   inode number
+ *      %Is     <inode> -> i_size
+ *      %IS     <inode> -> i_extra_isize
+ *      %Ib     <inode> -> i_blocks
+ *      %Il     <inode> -> i_links_count
+ *      %Im     <inode> -> i_mode
+ *      %IM     <inode> -> i_mtime
+ *      %IF     <inode> -> i_faddr
+ *      %If     <inode> -> i_file_acl
+ *      %Id     <inode> -> i_dir_acl
+ *      %Iu     <inode> -> i_uid
+ *      %Ig     <inode> -> i_gid
+ *      %j      <ino2>                  inode number
+ *      %m      <com_err error message>
+ *      %N      <num>
+ *      %p      ext2fs_get_pathname of directory <ino>
+ *      %P      ext2fs_get_pathname of <dirent>->ino with <ino2> as
+ *                      the containing directory.  (If dirent is NULL
+ *                      then return the pathname of directory <ino2>)
+ *      %q      ext2fs_get_pathname of directory <dir>
+ *      %Q      ext2fs_get_pathname of directory <ino> with <dir> as
+ *                      the containing directory.
+ *      %s      <str>                   miscellaneous string
+ *      %S      backup superblock
+ *      %X      <num> hexadecimal format
+ *
+ * The following '@' expansions are supported:
+ *
+ *      @a      extended attribute
+ *      @A      error allocating
+ *      @b      block
+ *      @B      bitmap
+ *      @c      compress
+ *      @C      conflicts with some other fs block
+ *      @D      deleted
+ *      @d      directory
+ *      @e      entry
+ *      @E      Entry '%Dn' in %p (%i)
+ *      @f      filesystem
+ *      @F      for @i %i (%Q) is
+ *      @g      group
+ *      @h      HTREE directory inode
+ *      @i      inode
+ *      @I      illegal
+ *      @j      journal
+ *      @l      lost+found
+ *      @L      is a link
+ *      @m      multiply-claimed
+ *      @n      invalid
+ *      @o      orphaned
+ *      @p      problem in
+ *      @r      root inode
+ *      @s      should be
+ *      @S      superblock
+ *      @u      unattached
+ *      @v      device
+ *      @z      zero-length
+ */
+
+
+/*
+ * This structure defines the abbreviations used by the text strings
+ * below.  The first character in the string is the index letter.  An
+ * abbreviation of the form '@<i>' is expanded by looking up the index
+ * letter <i> in the table below.
+ */
+static const char * const abbrevs[] = {
+	N_("aextended attribute"),
+	N_("Aerror allocating"),
+	N_("bblock"),
+	N_("Bbitmap"),
+	N_("ccompress"),
+	N_("Cconflicts with some other fs @b"),
+	N_("iinode"),
+	N_("Iillegal"),
+	N_("jjournal"),
+	N_("Ddeleted"),
+	N_("ddirectory"),
+	N_("eentry"),
+	N_("E at e '%Dn' in %p (%i)"),
+	N_("ffilesystem"),
+	N_("Ffor @i %i (%Q) is"),
+	N_("ggroup"),
+	N_("hHTREE @d @i"),
+	N_("llost+found"),
+	N_("Lis a link"),
+    N_("mmultiply-claimed"),
+    N_("ninvalid"),
+	N_("oorphaned"),
+	N_("pproblem in"),
+	N_("rroot @i"),
+	N_("sshould be"),
+	N_("Ssuper at b"),
+	N_("uunattached"),
+	N_("vdevice"),
+	N_("zzero-length"),
+	"@@",
+	0
+	};
+
+/*
+ * Give more user friendly names to the "special" inodes.
+ */
+#define num_special_inodes      11
+static const char * const special_inode_name[] =
+{
+	N_("<The NULL inode>"),                 /* 0 */
+	N_("<The bad blocks inode>"),           /* 1 */
+	"/",                                    /* 2 */
+	N_("<The ACL index inode>"),            /* 3 */
+	N_("<The ACL data inode>"),             /* 4 */
+	N_("<The boot loader inode>"),          /* 5 */
+	N_("<The undelete directory inode>"),   /* 6 */
+	N_("<The group descriptor inode>"),     /* 7 */
+	N_("<The journal inode>"),              /* 8 */
+	N_("<Reserved inode 9>"),               /* 9 */
+	N_("<Reserved inode 10>"),              /* 10 */
+};
+
+/*
+ * This function does "safe" printing.  It will convert non-printable
+ * ASCII characters using '^' and M- notation.
+ */
+static void safe_print(const char *cp, int len)
+{
+	unsigned char   ch;
+
+	if (len < 0)
+		len = strlen(cp);
+
+	while (len--) {
+		ch = *cp++;
+		if (ch > 128) {
+			fputs("M-", stdout);
+			ch -= 128;
+		}
+		if ((ch < 32) || (ch == 0x7f)) {
+			fputc('^', stdout);
+			ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
+		}
+		fputc(ch, stdout);
+	}
+}
+
+
+/*
+ * This function prints a pathname, using the ext2fs_get_pathname
+ * function
+ */
+static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
+{
+	errcode_t       retval;
+	char            *path;
+
+	if (!dir && (ino < num_special_inodes)) {
+		fputs(_(special_inode_name[ino]), stdout);
+		return;
+	}
+
+	retval = ext2fs_get_pathname(fs, dir, ino, &path);
+	if (retval)
+		fputs("???", stdout);
+	else {
+		safe_print(path, -1);
+		ext2fs_free_mem(&path);
+	}
+}
+
+static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
+			  struct problem_context *pctx, int first);
+/*
+ * This function handles the '@' expansion.  We allow recursive
+ * expansion; an @ expression can contain further '@' and '%'
+ * expressions.
+ */
+static void expand_at_expression(e2fsck_t ctx, char ch,
+					  struct problem_context *pctx,
+					  int *first)
+{
+	const char * const *cpp;
+	const char *str;
+
+	/* Search for the abbreviation */
+	for (cpp = abbrevs; *cpp; cpp++) {
+		if (ch == *cpp[0])
+			break;
+	}
+	if (*cpp) {
+		str = _(*cpp) + 1;
+		if (*first && islower(*str)) {
+			*first = 0;
+			fputc(toupper(*str++), stdout);
+		}
+		print_e2fsck_message(ctx, str, pctx, *first);
+	} else
+		printf("@%c", ch);
+}
+
+/*
+ * This function expands '%IX' expressions
+ */
+static void expand_inode_expression(char ch,
+					     struct problem_context *ctx)
+{
+	struct ext2_inode       *inode;
+	struct ext2_inode_large *large_inode;
+	char *                  time_str;
+	time_t                  t;
+	int                     do_gmt = -1;
+
+	if (!ctx || !ctx->inode)
+		goto no_inode;
+
+	inode = ctx->inode;
+	large_inode = (struct ext2_inode_large *) inode;
+
+	switch (ch) {
+	case 's':
+		if (LINUX_S_ISDIR(inode->i_mode))
+			printf("%u", inode->i_size);
+		else {
+			printf("%"PRIu64, (inode->i_size |
+					((uint64_t) inode->i_size_high << 32)));
+		}
+		break;
+	case 'S':
+		printf("%u", large_inode->i_extra_isize);
+		break;
+	case 'b':
+		printf("%u", inode->i_blocks);
+		break;
+	case 'l':
+		printf("%d", inode->i_links_count);
+		break;
+	case 'm':
+		printf("0%o", inode->i_mode);
+		break;
+	case 'M':
+		/* The diet libc doesn't respect the TZ environemnt variable */
+		if (do_gmt == -1) {
+			time_str = getenv("TZ");
+			if (!time_str)
+				time_str = "";
+			do_gmt = !strcmp(time_str, "GMT");
+		}
+		t = inode->i_mtime;
+		time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
+		printf("%.24s", time_str);
+		break;
+	case 'F':
+		printf("%u", inode->i_faddr);
+		break;
+	case 'f':
+		printf("%u", inode->i_file_acl);
+		break;
+	case 'd':
+		printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
+			      inode->i_dir_acl : 0));
+		break;
+	case 'u':
+		printf("%d", (inode->i_uid |
+			      (inode->osd2.linux2.l_i_uid_high << 16)));
+		break;
+	case 'g':
+		printf("%d", (inode->i_gid |
+			      (inode->osd2.linux2.l_i_gid_high << 16)));
+		break;
+	default:
+	no_inode:
+		printf("%%I%c", ch);
+		break;
+	}
+}
+
+/*
+ * This function expands '%dX' expressions
+ */
+static void expand_dirent_expression(char ch,
+					      struct problem_context *ctx)
+{
+	struct ext2_dir_entry   *dirent;
+	int     len;
+
+	if (!ctx || !ctx->dirent)
+		goto no_dirent;
+
+	dirent = ctx->dirent;
+
+	switch (ch) {
+	case 'i':
+		printf("%u", dirent->inode);
+		break;
+	case 'n':
+		len = dirent->name_len & 0xFF;
+		if (len > EXT2_NAME_LEN)
+			len = EXT2_NAME_LEN;
+		if (len > dirent->rec_len)
+			len = dirent->rec_len;
+		safe_print(dirent->name, len);
+		break;
+	case 'r':
+		printf("%u", dirent->rec_len);
+		break;
+	case 'l':
+		printf("%u", dirent->name_len & 0xFF);
+		break;
+	case 't':
+		printf("%u", dirent->name_len >> 8);
+		break;
+	default:
+	no_dirent:
+		printf("%%D%c", ch);
+		break;
+	}
+}
+
+static void expand_percent_expression(ext2_filsys fs, char ch,
+					       struct problem_context *ctx)
+{
+	if (!ctx)
+		goto no_context;
+
+	switch (ch) {
+	case '%':
+		fputc('%', stdout);
+		break;
+	case 'b':
+		printf("%u", ctx->blk);
+		break;
+	case 'B':
+		printf("%"PRIi64, ctx->blkcount);
+		break;
+	case 'c':
+		printf("%u", ctx->blk2);
+		break;
+	case 'd':
+		printf("%u", ctx->dir);
+		break;
+	case 'g':
+		printf("%d", ctx->group);
+		break;
+	case 'i':
+		printf("%u", ctx->ino);
+		break;
+	case 'j':
+		printf("%u", ctx->ino2);
+		break;
+	case 'm':
+		printf("%s", error_message(ctx->errcode));
+		break;
+	case 'N':
+		printf("%"PRIi64, ctx->num);
+		break;
+	case 'p':
+		print_pathname(fs, ctx->ino, 0);
+		break;
+	case 'P':
+		print_pathname(fs, ctx->ino2,
+			       ctx->dirent ? ctx->dirent->inode : 0);
+		break;
+	case 'q':
+		print_pathname(fs, ctx->dir, 0);
+		break;
+	case 'Q':
+		print_pathname(fs, ctx->dir, ctx->ino);
+		break;
+	case 'S':
+		printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
+		break;
+	case 's':
+		printf("%s", ctx->str ? ctx->str : "NULL");
+		break;
+	case 'X':
+		printf("0x%"PRIi64, ctx->num);
+		break;
+	default:
+	no_context:
+		printf("%%%c", ch);
+		break;
+	}
+}
+
+
+static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
+			  struct problem_context *pctx, int first)
+{
+	ext2_filsys fs = ctx->fs;
+	const char *    cp;
+	int             i;
+
+	e2fsck_clear_progbar(ctx);
+	for (cp = msg; *cp; cp++) {
+		if (cp[0] == '@') {
+			cp++;
+			expand_at_expression(ctx, *cp, pctx, &first);
+		} else if (cp[0] == '%' && cp[1] == 'I') {
+			cp += 2;
+			expand_inode_expression(*cp, pctx);
+		} else if (cp[0] == '%' && cp[1] == 'D') {
+			cp += 2;
+			expand_dirent_expression(*cp, pctx);
+		} else if ((cp[0] == '%')) {
+			cp++;
+			expand_percent_expression(fs, *cp, pctx);
+		} else {
+			for (i=0; cp[i]; i++)
+				if ((cp[i] == '@') || cp[i] == '%')
+					break;
+			printf("%.*s", i, cp);
+			cp += i-1;
+		}
+		first = 0;
+	}
+}
+
+
+/*
+ * region.c --- code which manages allocations within a region.
+ */
+
+struct region_el {
+	region_addr_t   start;
+	region_addr_t   end;
+	struct region_el *next;
+};
+
+struct region_struct {
+	region_addr_t   min;
+	region_addr_t   max;
+	struct region_el *allocated;
+};
+
+static region_t region_create(region_addr_t min, region_addr_t max)
+{
+	region_t        region;
+
+	region = malloc(sizeof(struct region_struct));
+	if (!region)
+		return NULL;
+	memset(region, 0, sizeof(struct region_struct));
+	region->min = min;
+	region->max = max;
+	return region;
+}
+
+static void region_free(region_t region)
+{
+	struct region_el        *r, *next;
+
+	for (r = region->allocated; r; r = next) {
+		next = r->next;
+		free(r);
+	}
+	memset(region, 0, sizeof(struct region_struct));
+	free(region);
+}
+
+static int region_allocate(region_t region, region_addr_t start, int n)
+{
+	struct region_el        *r, *new_region, *prev, *next;
+	region_addr_t end;
+
+	end = start+n;
+	if ((start < region->min) || (end > region->max))
+		return -1;
+	if (n == 0)
+		return 1;
+
+	/*
+	 * Search through the linked list.  If we find that it
+	 * conflicts witih something that's already allocated, return
+	 * 1; if we can find an existing region which we can grow, do
+	 * so.  Otherwise, stop when we find the appropriate place
+	 * insert a new region element into the linked list.
+	 */
+	for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
+		if (((start >= r->start) && (start < r->end)) ||
+		    ((end > r->start) && (end <= r->end)) ||
+		    ((start <= r->start) && (end >= r->end)))
+			return 1;
+		if (end == r->start) {
+			r->start = start;
+			return 0;
+		}
+		if (start == r->end) {
+			if ((next = r->next)) {
+				if (end > next->start)
+					return 1;
+				if (end == next->start) {
+					r->end = next->end;
+					r->next = next->next;
+					free(next);
+					return 0;
+				}
+			}
+			r->end = end;
+			return 0;
+		}
+		if (start < r->start)
+			break;
+	}
+	/*
+	 * Insert a new region element structure into the linked list
+	 */
+	new_region = malloc(sizeof(struct region_el));
+	if (!new_region)
+		return -1;
+	new_region->start = start;
+	new_region->end = start + n;
+	new_region->next = r;
+	if (prev)
+		prev->next = new_region;
+	else
+		region->allocated = new_region;
+	return 0;
+}
+
+/*
+ * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
+ *
+ * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
+ * and applies the following tests to each inode:
+ *
+ *      - The mode field of the inode must be legal.
+ *      - The size and block count fields of the inode are correct.
+ *      - A data block must not be used by another inode
+ *
+ * Pass 1 also gathers the collects the following information:
+ *
+ *      - A bitmap of which inodes are in use.          (inode_used_map)
+ *      - A bitmap of which inodes are directories.     (inode_dir_map)
+ *      - A bitmap of which inodes are regular files.   (inode_reg_map)
+ *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
+ *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
+ *      - A bitmap of which blocks are in use.          (block_found_map)
+ *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
+ *      - The data blocks of the directory inodes.      (dir_map)
+ *
+ * Pass 1 is designed to stash away enough information so that the
+ * other passes should not need to read in the inode information
+ * during the normal course of a filesystem check.  (Althogh if an
+ * inconsistency is detected, other passes may need to read in an
+ * inode to fix it.)
+ *
+ * Note that pass 1B will be invoked if there are any duplicate blocks
+ * found.
+ */
+
+
+static int process_block(ext2_filsys fs, blk_t  *blocknr,
+			 e2_blkcnt_t blockcnt, blk_t ref_blk,
+			 int ref_offset, void *priv_data);
+static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
+			     e2_blkcnt_t blockcnt, blk_t ref_blk,
+			     int ref_offset, void *priv_data);
+static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
+			 char *block_buf);
+static void mark_table_blocks(e2fsck_t ctx);
+static void alloc_imagic_map(e2fsck_t ctx);
+static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
+static void handle_fs_bad_blocks(e2fsck_t ctx);
+static void process_inodes(e2fsck_t ctx, char *block_buf);
+static int process_inode_cmp(const void *a, const void *b);
+static errcode_t scan_callback(ext2_filsys fs,
+				  dgrp_t group, void * priv_data);
+static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
+				    char *block_buf, int adjust_sign);
+/* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
+
+static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
+			       struct ext2_inode * inode, int bufsize,
+			       const char *proc);
+
+struct process_block_struct_1 {
+	ext2_ino_t      ino;
+	unsigned        is_dir:1, is_reg:1, clear:1, suppress:1,
+				fragmented:1, compressed:1, bbcheck:1;
+	blk_t           num_blocks;
+	blk_t           max_blocks;
+	e2_blkcnt_t     last_block;
+	int             num_illegal_blocks;
+	blk_t           previous_block;
+	struct ext2_inode *inode;
+	struct problem_context *pctx;
+	ext2fs_block_bitmap fs_meta_blocks;
+	e2fsck_t        ctx;
+};
+
+struct process_inode_block {
+	ext2_ino_t ino;
+	struct ext2_inode inode;
+};
+
+struct scan_callback_struct {
+	e2fsck_t        ctx;
+	char            *block_buf;
+};
+
+/*
+ * For the inodes to process list.
+ */
+static struct process_inode_block *inodes_to_process;
+static int process_inode_count;
+
+static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
+			    EXT2_MIN_BLOCK_LOG_SIZE + 1];
+
+/*
+ * Free all memory allocated by pass1 in preparation for restarting
+ * things.
+ */
+static void unwind_pass1(void)
+{
+	ext2fs_free_mem(&inodes_to_process);
+}
+
+/*
+ * Check to make sure a device inode is real.  Returns 1 if the device
+ * checks out, 0 if not.
+ *
+ * Note: this routine is now also used to check FIFO's and Sockets,
+ * since they have the same requirement; the i_block fields should be
+ * zero.
+ */
+static int
+e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
+{
+	int     i;
+
+	/*
+	 * If i_blocks is non-zero, or the index flag is set, then
+	 * this is a bogus device/fifo/socket
+	 */
+	if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
+	    (inode->i_flags & EXT2_INDEX_FL))
+		return 0;
+
+	/*
+	 * We should be able to do the test below all the time, but
+	 * because the kernel doesn't forcibly clear the device
+	 * inode's additional i_block fields, there are some rare
+	 * occasions when a legitimate device inode will have non-zero
+	 * additional i_block fields.  So for now, we only complain
+	 * when the immutable flag is set, which should never happen
+	 * for devices.  (And that's when the problem is caused, since
+	 * you can't set or clear immutable flags for devices.)  Once
+	 * the kernel has been fixed we can change this...
+	 */
+	if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
+		for (i=4; i < EXT2_N_BLOCKS; i++)
+			if (inode->i_block[i])
+				return 0;
+	}
+	return 1;
+}
+
+/*
+ * Check to make sure a symlink inode is real.  Returns 1 if the symlink
+ * checks out, 0 if not.
+ */
+static int
+e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
+{
+	unsigned int len;
+	int i;
+	blk_t   blocks;
+
+	if ((inode->i_size_high || inode->i_size == 0) ||
+	    (inode->i_flags & EXT2_INDEX_FL))
+		return 0;
+
+	blocks = ext2fs_inode_data_blocks(fs, inode);
+	if (blocks) {
+		if ((inode->i_size >= fs->blocksize) ||
+		    (blocks != fs->blocksize >> 9) ||
+		    (inode->i_block[0] < fs->super->s_first_data_block) ||
+		    (inode->i_block[0] >= fs->super->s_blocks_count))
+			return 0;
+
+		for (i = 1; i < EXT2_N_BLOCKS; i++)
+			if (inode->i_block[i])
+				return 0;
+
+		if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
+			return 0;
+
+		len = strnlen(buf, fs->blocksize);
+		if (len == fs->blocksize)
+			return 0;
+	} else {
+		if (inode->i_size >= sizeof(inode->i_block))
+			return 0;
+
+		len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
+		if (len == sizeof(inode->i_block))
+			return 0;
+	}
+	if (len != inode->i_size)
+		return 0;
+	return 1;
+}
+
+/*
+ * If the immutable (or append-only) flag is set on the inode, offer
+ * to clear it.
+ */
+#define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
+static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
+{
+	if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
+		return;
+
+	if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
+		return;
+
+	pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
+	e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
+}
+
+/*
+ * If device, fifo or socket, check size is zero -- if not offer to
+ * clear it
+ */
+static void check_size(e2fsck_t ctx, struct problem_context *pctx)
+{
+	struct ext2_inode *inode = pctx->inode;
+
+	if ((inode->i_size == 0) && (inode->i_size_high == 0))
+		return;
+
+	if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
+		return;
+
+	inode->i_size = 0;
+	inode->i_size_high = 0;
+	e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
+}
+
+static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
+{
+	struct ext2_super_block *sb = ctx->fs->super;
+	struct ext2_inode_large *inode;
+	struct ext2_ext_attr_entry *entry;
+	char *start, *end;
+	int storage_size, remain, offs;
+	int problem = 0;
+
+	inode = (struct ext2_inode_large *) pctx->inode;
+	storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
+		inode->i_extra_isize;
+	start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
+		inode->i_extra_isize + sizeof(__u32);
+	end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
+	entry = (struct ext2_ext_attr_entry *) start;
+
+	/* scan all entry's headers first */
+
+	/* take finish entry 0UL into account */
+	remain = storage_size - sizeof(__u32);
+	offs = end - start;
+
+	while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
+
+		/* header eats this space */
+		remain -= sizeof(struct ext2_ext_attr_entry);
+
+		/* is attribute name valid? */
+		if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
+			pctx->num = entry->e_name_len;
+			problem = PR_1_ATTR_NAME_LEN;
+			goto fix;
+		}
+
+		/* attribute len eats this space */
+		remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
+
+		/* check value size */
+		if (entry->e_value_size == 0 || entry->e_value_size > remain) {
+			pctx->num = entry->e_value_size;
+			problem = PR_1_ATTR_VALUE_SIZE;
+			goto fix;
+		}
+
+		/* check value placement */
+		if (entry->e_value_offs +
+		    EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
+			printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
+			pctx->num = entry->e_value_offs;
+			problem = PR_1_ATTR_VALUE_OFFSET;
+			goto fix;
+		}
+
+		/* e_value_block must be 0 in inode's ea */
+		if (entry->e_value_block != 0) {
+			pctx->num = entry->e_value_block;
+			problem = PR_1_ATTR_VALUE_BLOCK;
+			goto fix;
+		}
+
+		/* e_hash must be 0 in inode's ea */
+		if (entry->e_hash != 0) {
+			pctx->num = entry->e_hash;
+			problem = PR_1_ATTR_HASH;
+			goto fix;
+		}
+
+		remain -= entry->e_value_size;
+		offs -= EXT2_XATTR_SIZE(entry->e_value_size);
+
+		entry = EXT2_EXT_ATTR_NEXT(entry);
+	}
+fix:
+	/*
+	 * it seems like a corruption. it's very unlikely we could repair
+	 * EA(s) in automatic fashion -bzzz
+	 */
+	if (problem == 0 || !fix_problem(ctx, problem, pctx))
+		return;
+
+	/* simple remove all possible EA(s) */
+	*((__u32 *)start) = 0UL;
+	e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
+				EXT2_INODE_SIZE(sb), "pass1");
+}
+
+static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
+{
+	struct ext2_super_block *sb = ctx->fs->super;
+	struct ext2_inode_large *inode;
+	__u32 *eamagic;
+	int min, max;
+
+	inode = (struct ext2_inode_large *) pctx->inode;
+	if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
+		/* this isn't large inode. so, nothing to check */
+		return;
+	}
+
+	/* i_extra_isize must cover i_extra_isize + i_pad1 at least */
+	min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
+	max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
+	/*
+	 * For now we will allow i_extra_isize to be 0, but really
+	 * implementations should never allow i_extra_isize to be 0
+	 */
+	if (inode->i_extra_isize &&
+	    (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
+		if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
+			return;
+		inode->i_extra_isize = min;
+		e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
+					EXT2_INODE_SIZE(sb), "pass1");
+		return;
+	}
+
+	eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
+			inode->i_extra_isize);
+	if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
+		/* it seems inode has an extended attribute(s) in body */
+		check_ea_in_inode(ctx, pctx);
+	}
+}
+
+static void e2fsck_pass1(e2fsck_t ctx)
+{
+	int     i;
+	__u64   max_sizes;
+	ext2_filsys fs = ctx->fs;
+	ext2_ino_t      ino;
+	struct ext2_inode *inode;
+	ext2_inode_scan scan;
+	char            *block_buf;
+	unsigned char   frag, fsize;
+	struct          problem_context pctx;
+	struct          scan_callback_struct scan_struct;
+	struct ext2_super_block *sb = ctx->fs->super;
+	int             imagic_fs;
+	int             busted_fs_time = 0;
+	int             inode_size;
+
+	clear_problem_context(&pctx);
+
+	if (!(ctx->options & E2F_OPT_PREEN))
+		fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
+
+	if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
+	    !(ctx->options & E2F_OPT_NO)) {
+		if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
+			ctx->dirs_to_hash = 0;
+	}
+
+	/* Pass 1 */
+
+#define EXT2_BPP(bits) (1ULL << ((bits) - 2))
+
+	for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
+		max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
+		max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
+		max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
+		max_sizes = (max_sizes * (1UL << i)) - 1;
+		ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
+	}
+#undef EXT2_BPP
+
+	imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
+
+	/*
+	 * Allocate bitmaps structures
+	 */
+	pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
+					      &ctx->inode_used_map);
+	if (pctx.errcode) {
+		pctx.num = 1;
+		fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+	pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
+				_("directory inode map"), &ctx->inode_dir_map);
+	if (pctx.errcode) {
+		pctx.num = 2;
+		fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+	pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
+			_("regular file inode map"), &ctx->inode_reg_map);
+	if (pctx.errcode) {
+		pctx.num = 6;
+		fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+	pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
+					      &ctx->block_found_map);
+	if (pctx.errcode) {
+		pctx.num = 1;
+		fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+	pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
+					     &ctx->inode_link_info);
+	if (pctx.errcode) {
+		fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+	inode_size = EXT2_INODE_SIZE(fs->super);
+	inode = (struct ext2_inode *)
+		e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
+
+	inodes_to_process = (struct process_inode_block *)
+		e2fsck_allocate_memory(ctx,
+				       (ctx->process_inode_size *
+					sizeof(struct process_inode_block)),
+				       "array of inodes to process");
+	process_inode_count = 0;
+
+	pctx.errcode = ext2fs_init_dblist(fs, 0);
+	if (pctx.errcode) {
+		fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+
+	/*
+	 * If the last orphan field is set, clear it, since the pass1
+	 * processing will automatically find and clear the orphans.
+	 * In the future, we may want to try using the last_orphan
+	 * linked list ourselves, but for now, we clear it so that the
+	 * ext3 mount code won't get confused.
+	 */
+	if (!(ctx->options & E2F_OPT_READONLY)) {
+		if (fs->super->s_last_orphan) {
+			fs->super->s_last_orphan = 0;
+			ext2fs_mark_super_dirty(fs);
+		}
+	}
+
+	mark_table_blocks(ctx);
+	block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
+						    "block interate buffer");
+	e2fsck_use_inode_shortcuts(ctx, 1);
+	ehandler_operation(_("doing inode scan"));
+	pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
+					      &scan);
+	if (pctx.errcode) {
+		fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+	ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
+	ctx->stashed_inode = inode;
+	scan_struct.ctx = ctx;
+	scan_struct.block_buf = block_buf;
+	ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
+	if (ctx->progress)
+		if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
+			return;
+	if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
+	    (fs->super->s_mtime < fs->super->s_inodes_count))
+		busted_fs_time = 1;
+
+	while (1) {
+		pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
+							  inode, inode_size);
+		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+			return;
+		if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
+			continue;
+		}
+		if (pctx.errcode) {
+			fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
+			ctx->flags |= E2F_FLAG_ABORT;
+			return;
+		}
+		if (!ino)
+			break;
+		pctx.ino = ino;
+		pctx.inode = inode;
+		ctx->stashed_ino = ino;
+		if (inode->i_links_count) {
+			pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
+					   ino, inode->i_links_count);
+			if (pctx.errcode) {
+				pctx.num = inode->i_links_count;
+				fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
+				ctx->flags |= E2F_FLAG_ABORT;
+				return;
+			}
+		}
+		if (ino == EXT2_BAD_INO) {
+			struct process_block_struct_1 pb;
+
+			pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
+							  &pb.fs_meta_blocks);
+			if (pctx.errcode) {
+				pctx.num = 4;
+				fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
+				ctx->flags |= E2F_FLAG_ABORT;
+				return;
+			}
+			pb.ino = EXT2_BAD_INO;
+			pb.num_blocks = pb.last_block = 0;
+			pb.num_illegal_blocks = 0;
+			pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
+			pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
+			pb.inode = inode;
+			pb.pctx = &pctx;
+			pb.ctx = ctx;
+			pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
+				     block_buf, process_bad_block, &pb);
+			ext2fs_free_block_bitmap(pb.fs_meta_blocks);
+			if (pctx.errcode) {
+				fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
+				ctx->flags |= E2F_FLAG_ABORT;
+				return;
+			}
+			if (pb.bbcheck)
+				if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
+				ctx->flags |= E2F_FLAG_ABORT;
+				return;
+			}
+			ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
+			clear_problem_context(&pctx);
+			continue;
+		} else if (ino == EXT2_ROOT_INO) {
+			/*
+			 * Make sure the root inode is a directory; if
+			 * not, offer to clear it.  It will be
+			 * regnerated in pass #3.
+			 */
+			if (!LINUX_S_ISDIR(inode->i_mode)) {
+				if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
+					inode->i_dtime = time(0);
+					inode->i_links_count = 0;
+					ext2fs_icount_store(ctx->inode_link_info,
+							    ino, 0);
+					e2fsck_write_inode(ctx, ino, inode,
+							   "pass1");
+				}
+
+			}
+			/*
+			 * If dtime is set, offer to clear it.  mke2fs
+			 * version 0.2b created filesystems with the
+			 * dtime field set for the root and lost+found
+			 * directories.  We won't worry about
+			 * /lost+found, since that can be regenerated
+			 * easily.  But we will fix the root directory
+			 * as a special case.
+			 */
+			if (inode->i_dtime && inode->i_links_count) {
+				if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
+					inode->i_dtime = 0;
+					e2fsck_write_inode(ctx, ino, inode,
+							   "pass1");
+				}
+			}
+		} else if (ino == EXT2_JOURNAL_INO) {
+			ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
+			if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
+				if (!LINUX_S_ISREG(inode->i_mode) &&
+				    fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
+						&pctx)) {
+					inode->i_mode = LINUX_S_IFREG;
+					e2fsck_write_inode(ctx, ino, inode,
+							   "pass1");
+				}
+				check_blocks(ctx, &pctx, block_buf);
+				continue;
+			}
+			if ((inode->i_links_count || inode->i_blocks ||
+			     inode->i_blocks || inode->i_block[0]) &&
+			    fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
+					&pctx)) {
+				memset(inode, 0, inode_size);
+				ext2fs_icount_store(ctx->inode_link_info,
+						    ino, 0);
+				e2fsck_write_inode_full(ctx, ino, inode,
+							inode_size, "pass1");
+			}
+		} else if (ino < EXT2_FIRST_INODE(fs->super)) {
+			int     problem = 0;
+
+			ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
+			if (ino == EXT2_BOOT_LOADER_INO) {
+				if (LINUX_S_ISDIR(inode->i_mode))
+					problem = PR_1_RESERVED_BAD_MODE;
+			} else if (ino == EXT2_RESIZE_INO) {
+				if (inode->i_mode &&
+				    !LINUX_S_ISREG(inode->i_mode))
+					problem = PR_1_RESERVED_BAD_MODE;
+			} else {
+				if (inode->i_mode != 0)
+					problem = PR_1_RESERVED_BAD_MODE;
+			}
+			if (problem) {
+				if (fix_problem(ctx, problem, &pctx)) {
+					inode->i_mode = 0;
+					e2fsck_write_inode(ctx, ino, inode,
+							   "pass1");
+				}
+			}
+			check_blocks(ctx, &pctx, block_buf);
+			continue;
+		}
+		/*
+		 * Check for inodes who might have been part of the
+		 * orphaned list linked list.  They should have gotten
+		 * dealt with by now, unless the list had somehow been
+		 * corrupted.
+		 *
+		 * FIXME: In the future, inodes which are still in use
+		 * (and which are therefore) pending truncation should
+		 * be handled specially.  Right now we just clear the
+		 * dtime field, and the normal e2fsck handling of
+		 * inodes where i_size and the inode blocks are
+		 * inconsistent is to fix i_size, instead of releasing
+		 * the extra blocks.  This won't catch the inodes that
+		 * was at the end of the orphan list, but it's better
+		 * than nothing.  The right answer is that there
+		 * shouldn't be any bugs in the orphan list handling.  :-)
+		 */
+		if (inode->i_dtime && !busted_fs_time &&
+		    inode->i_dtime < ctx->fs->super->s_inodes_count) {
+			if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
+				inode->i_dtime = inode->i_links_count ?
+					0 : time(0);
+				e2fsck_write_inode(ctx, ino, inode,
+						   "pass1");
+			}
+		}
+
+		/*
+		 * This code assumes that deleted inodes have
+		 * i_links_count set to 0.
+		 */
+		if (!inode->i_links_count) {
+			if (!inode->i_dtime && inode->i_mode) {
+				if (fix_problem(ctx,
+					    PR_1_ZERO_DTIME, &pctx)) {
+					inode->i_dtime = time(0);
+					e2fsck_write_inode(ctx, ino, inode,
+							   "pass1");
+				}
+			}
+			continue;
+		}
+		/*
+		 * n.b.  0.3c ext2fs code didn't clear i_links_count for
+		 * deleted files.  Oops.
+		 *
+		 * Since all new ext2 implementations get this right,
+		 * we now assume that the case of non-zero
+		 * i_links_count and non-zero dtime means that we
+		 * should keep the file, not delete it.
+		 *
+		 */
+		if (inode->i_dtime) {
+			if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
+				inode->i_dtime = 0;
+				e2fsck_write_inode(ctx, ino, inode, "pass1");
+			}
+		}
+
+		ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
+		switch (fs->super->s_creator_os) {
+		    case EXT2_OS_LINUX:
+			frag = inode->osd2.linux2.l_i_frag;
+			fsize = inode->osd2.linux2.l_i_fsize;
+			break;
+		    case EXT2_OS_HURD:
+			frag = inode->osd2.hurd2.h_i_frag;
+			fsize = inode->osd2.hurd2.h_i_fsize;
+			break;
+		    case EXT2_OS_MASIX:
+			frag = inode->osd2.masix2.m_i_frag;
+			fsize = inode->osd2.masix2.m_i_fsize;
+			break;
+		    default:
+			frag = fsize = 0;
+		}
+
+		if (inode->i_faddr || frag || fsize ||
+		    (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
+			mark_inode_bad(ctx, ino);
+		if (inode->i_flags & EXT2_IMAGIC_FL) {
+			if (imagic_fs) {
+				if (!ctx->inode_imagic_map)
+					alloc_imagic_map(ctx);
+				ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
+							 ino);
+			} else {
+				if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
+					inode->i_flags &= ~EXT2_IMAGIC_FL;
+					e2fsck_write_inode(ctx, ino,
+							   inode, "pass1");
+				}
+			}
+		}
+
+		check_inode_extra_space(ctx, &pctx);
+
+		if (LINUX_S_ISDIR(inode->i_mode)) {
+			ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
+			e2fsck_add_dir_info(ctx, ino, 0);
+			ctx->fs_directory_count++;
+		} else if (LINUX_S_ISREG (inode->i_mode)) {
+			ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
+			ctx->fs_regular_count++;
+		} else if (LINUX_S_ISCHR (inode->i_mode) &&
+			   e2fsck_pass1_check_device_inode(fs, inode)) {
+			check_immutable(ctx, &pctx);
+			check_size(ctx, &pctx);
+			ctx->fs_chardev_count++;
+		} else if (LINUX_S_ISBLK (inode->i_mode) &&
+			   e2fsck_pass1_check_device_inode(fs, inode)) {
+			check_immutable(ctx, &pctx);
+			check_size(ctx, &pctx);
+			ctx->fs_blockdev_count++;
+		} else if (LINUX_S_ISLNK (inode->i_mode) &&
+			   e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
+			check_immutable(ctx, &pctx);
+			ctx->fs_symlinks_count++;
+			if (ext2fs_inode_data_blocks(fs, inode) == 0) {
+				ctx->fs_fast_symlinks_count++;
+				check_blocks(ctx, &pctx, block_buf);
+				continue;
+			}
+		}
+		else if (LINUX_S_ISFIFO (inode->i_mode) &&
+			 e2fsck_pass1_check_device_inode(fs, inode)) {
+			check_immutable(ctx, &pctx);
+			check_size(ctx, &pctx);
+			ctx->fs_fifo_count++;
+		} else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
+			   e2fsck_pass1_check_device_inode(fs, inode)) {
+			check_immutable(ctx, &pctx);
+			check_size(ctx, &pctx);
+			ctx->fs_sockets_count++;
+		} else
+			mark_inode_bad(ctx, ino);
+		if (inode->i_block[EXT2_IND_BLOCK])
+			ctx->fs_ind_count++;
+		if (inode->i_block[EXT2_DIND_BLOCK])
+			ctx->fs_dind_count++;
+		if (inode->i_block[EXT2_TIND_BLOCK])
+			ctx->fs_tind_count++;
+		if (inode->i_block[EXT2_IND_BLOCK] ||
+		    inode->i_block[EXT2_DIND_BLOCK] ||
+		    inode->i_block[EXT2_TIND_BLOCK] ||
+		    inode->i_file_acl) {
+			inodes_to_process[process_inode_count].ino = ino;
+			inodes_to_process[process_inode_count].inode = *inode;
+			process_inode_count++;
+		} else
+			check_blocks(ctx, &pctx, block_buf);
+
+		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+			return;
+
+		if (process_inode_count >= ctx->process_inode_size) {
+			process_inodes(ctx, block_buf);
+
+			if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+				return;
+		}
+	}
+	process_inodes(ctx, block_buf);
+	ext2fs_close_inode_scan(scan);
+	ehandler_operation(0);
+
+	/*
+	 * If any extended attribute blocks' reference counts need to
+	 * be adjusted, either up (ctx->refcount_extra), or down
+	 * (ctx->refcount), then fix them.
+	 */
+	if (ctx->refcount) {
+		adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
+		ea_refcount_free(ctx->refcount);
+		ctx->refcount = 0;
+	}
+	if (ctx->refcount_extra) {
+		adjust_extattr_refcount(ctx, ctx->refcount_extra,
+					block_buf, +1);
+		ea_refcount_free(ctx->refcount_extra);
+		ctx->refcount_extra = 0;
+	}
+
+	if (ctx->invalid_bitmaps)
+		handle_fs_bad_blocks(ctx);
+
+	/* We don't need the block_ea_map any more */
+	ext2fs_free_block_bitmap(ctx->block_ea_map);
+	ctx->block_ea_map = 0;
+
+	if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
+		ext2fs_block_bitmap save_bmap;
+
+		save_bmap = fs->block_map;
+		fs->block_map = ctx->block_found_map;
+		clear_problem_context(&pctx);
+		pctx.errcode = ext2fs_create_resize_inode(fs);
+		if (pctx.errcode) {
+			fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
+			/* Should never get here */
+			ctx->flags |= E2F_FLAG_ABORT;
+			return;
+		}
+		e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
+				  "recreate inode");
+		inode->i_mtime = time(0);
+		e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode, 
+				  "recreate inode");
+		fs->block_map = save_bmap;
+		ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
+	}
+
+	if (ctx->flags & E2F_FLAG_RESTART) {
+		/*
+		 * Only the master copy of the superblock and block
+		 * group descriptors are going to be written during a
+		 * restart, so set the superblock to be used to be the
+		 * master superblock.
+		 */
+		ctx->use_superblock = 0;
+		unwind_pass1();
+		goto endit;
+	}
+
+	if (ctx->block_dup_map) {
+		if (ctx->options & E2F_OPT_PREEN) {
+			clear_problem_context(&pctx);
+			fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
+		}
+		e2fsck_pass1_dupblocks(ctx, block_buf);
+	}
+	ext2fs_free_mem(&inodes_to_process);
+endit:
+	e2fsck_use_inode_shortcuts(ctx, 0);
+
+	ext2fs_free_mem(&block_buf);
+	ext2fs_free_mem(&inode);
+
+}
+
+/*
+ * When the inode_scan routines call this callback at the end of the
+ * glock group, call process_inodes.
+ */
+static errcode_t scan_callback(ext2_filsys fs,
+			       dgrp_t group, void * priv_data)
+{
+	struct scan_callback_struct *scan_struct;
+	e2fsck_t ctx;
+
+	scan_struct = (struct scan_callback_struct *) priv_data;
+	ctx = scan_struct->ctx;
+
+	process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
+
+	if (ctx->progress)
+		if ((ctx->progress)(ctx, 1, group+1,
+				    ctx->fs->group_desc_count))
+			return EXT2_ET_CANCEL_REQUESTED;
+
+	return 0;
+}
+
+/*
+ * Process the inodes in the "inodes to process" list.
+ */
+static void process_inodes(e2fsck_t ctx, char *block_buf)
+{
+	int                     i;
+	struct ext2_inode       *old_stashed_inode;
+	ext2_ino_t              old_stashed_ino;
+	const char              *old_operation;
+	char                    buf[80];
+	struct problem_context  pctx;
+
+	/* begin process_inodes */
+	if (process_inode_count == 0)
+		return;
+	old_operation = ehandler_operation(0);
+	old_stashed_inode = ctx->stashed_inode;
+	old_stashed_ino = ctx->stashed_ino;
+	qsort(inodes_to_process, process_inode_count,
+		      sizeof(struct process_inode_block), process_inode_cmp);
+	clear_problem_context(&pctx);
+	for (i=0; i < process_inode_count; i++) {
+		pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
+		pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
+		sprintf(buf, _("reading indirect blocks of inode %u"),
+			pctx.ino);
+		ehandler_operation(buf);
+		check_blocks(ctx, &pctx, block_buf);
+		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+			break;
+	}
+	ctx->stashed_inode = old_stashed_inode;
+	ctx->stashed_ino = old_stashed_ino;
+	process_inode_count = 0;
+	/* end process inodes */
+
+	ehandler_operation(old_operation);
+}
+
+static int process_inode_cmp(const void *a, const void *b)
+{
+	const struct process_inode_block *ib_a =
+		(const struct process_inode_block *) a;
+	const struct process_inode_block *ib_b =
+		(const struct process_inode_block *) b;
+	int     ret;
+
+	ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
+	       ib_b->inode.i_block[EXT2_IND_BLOCK]);
+	if (ret == 0)
+		ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
+	return ret;
+}
+
+/*
+ * Mark an inode as being bad in some what
+ */
+static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
+{
+	struct          problem_context pctx;
+
+	if (!ctx->inode_bad_map) {
+		clear_problem_context(&pctx);
+
+		pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
+			    _("bad inode map"), &ctx->inode_bad_map);
+		if (pctx.errcode) {
+			pctx.num = 3;
+			fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
+			/* Should never get here */
+			ctx->flags |= E2F_FLAG_ABORT;
+			return;
+		}
+	}
+	ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
+}
+
+
+/*
+ * This procedure will allocate the inode imagic table
+ */
+static void alloc_imagic_map(e2fsck_t ctx)
+{
+	struct          problem_context pctx;
+
+	clear_problem_context(&pctx);
+	pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
+					      _("imagic inode map"),
+					      &ctx->inode_imagic_map);
+	if (pctx.errcode) {
+		pctx.num = 5;
+		fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
+		/* Should never get here */
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+}
+
+/*
+ * Marks a block as in use, setting the dup_map if it's been set
+ * already.  Called by process_block and process_bad_block.
+ *
+ * WARNING: Assumes checks have already been done to make sure block
+ * is valid.  This is true in both process_block and process_bad_block.
+ */
+static void mark_block_used(e2fsck_t ctx, blk_t block)
+{
+	struct          problem_context pctx;
+
+	clear_problem_context(&pctx);
+
+	if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
+		if (!ctx->block_dup_map) {
+			pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
+			      _("multiply claimed block map"),
+			      &ctx->block_dup_map);
+			if (pctx.errcode) {
+				pctx.num = 3;
+				fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
+					    &pctx);
+				/* Should never get here */
+				ctx->flags |= E2F_FLAG_ABORT;
+				return;
+			}
+		}
+		ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
+	} else {
+		ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
+	}
+}
+
+/*
+ * Adjust the extended attribute block's reference counts at the end
+ * of pass 1, either by subtracting out references for EA blocks that
+ * are still referenced in ctx->refcount, or by adding references for
+ * EA blocks that had extra references as accounted for in
+ * ctx->refcount_extra.
+ */
+static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
+				    char *block_buf, int adjust_sign)
+{
+	struct ext2_ext_attr_header     *header;
+	struct problem_context          pctx;
+	ext2_filsys                     fs = ctx->fs;
+	blk_t                           blk;
+	__u32                           should_be;
+	int                             count;
+
+	clear_problem_context(&pctx);
+
+	ea_refcount_intr_begin(refcount);
+	while (1) {
+		if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
+			break;
+		pctx.blk = blk;
+		pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
+		if (pctx.errcode) {
+			fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
+			return;
+		}
+		header = (struct ext2_ext_attr_header *) block_buf;
+		pctx.blkcount = header->h_refcount;
+		should_be = header->h_refcount + adjust_sign * count;
+		pctx.num = should_be;
+		if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
+			header->h_refcount = should_be;
+			pctx.errcode = ext2fs_write_ext_attr(fs, blk,
+							     block_buf);
+			if (pctx.errcode) {
+				fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
+				continue;
+			}
+		}
+	}
+}
+
+/*
+ * Handle processing the extended attribute blocks
+ */
+static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
+			   char *block_buf)
+{
+	ext2_filsys fs = ctx->fs;
+	ext2_ino_t      ino = pctx->ino;
+	struct ext2_inode *inode = pctx->inode;
+	blk_t           blk;
+	char *          end;
+	struct ext2_ext_attr_header *header;
+	struct ext2_ext_attr_entry *entry;
+	int             count;
+	region_t        region;
+
+	blk = inode->i_file_acl;
+	if (blk == 0)
+		return 0;
+
+	/*
+	 * If the Extended attribute flag isn't set, then a non-zero
+	 * file acl means that the inode is corrupted.
+	 *
+	 * Or if the extended attribute block is an invalid block,
+	 * then the inode is also corrupted.
+	 */
+	if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
+	    (blk < fs->super->s_first_data_block) ||
+	    (blk >= fs->super->s_blocks_count)) {
+		mark_inode_bad(ctx, ino);
+		return 0;
+	}
+
+	/* If ea bitmap hasn't been allocated, create it */
+	if (!ctx->block_ea_map) {
+		pctx->errcode = ext2fs_allocate_block_bitmap(fs,
+						      _("ext attr block map"),
+						      &ctx->block_ea_map);
+		if (pctx->errcode) {
+			pctx->num = 2;
+			fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
+			ctx->flags |= E2F_FLAG_ABORT;
+			return 0;
+		}
+	}
+
+	/* Create the EA refcount structure if necessary */
+	if (!ctx->refcount) {
+		pctx->errcode = ea_refcount_create(0, &ctx->refcount);
+		if (pctx->errcode) {
+			pctx->num = 1;
+			fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
+			ctx->flags |= E2F_FLAG_ABORT;
+			return 0;
+		}
+	}
+
+	/* Have we seen this EA block before? */
+	if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
+		if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
+			return 1;
+		/* Ooops, this EA was referenced more than it stated */
+		if (!ctx->refcount_extra) {
+			pctx->errcode = ea_refcount_create(0,
+					   &ctx->refcount_extra);
+			if (pctx->errcode) {
+				pctx->num = 2;
+				fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
+				ctx->flags |= E2F_FLAG_ABORT;
+				return 0;
+			}
+		}
+		ea_refcount_increment(ctx->refcount_extra, blk, 0);
+		return 1;
+	}
+
+	/*
+	 * OK, we haven't seen this EA block yet.  So we need to
+	 * validate it
+	 */
+	pctx->blk = blk;
+	pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
+	if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
+		goto clear_extattr;
+	header = (struct ext2_ext_attr_header *) block_buf;
+	pctx->blk = inode->i_file_acl;
+	if (((ctx->ext_attr_ver == 1) &&
+	     (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
+	    ((ctx->ext_attr_ver == 2) &&
+	     (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
+		if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
+			goto clear_extattr;
+	}
+
+	if (header->h_blocks != 1) {
+		if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
+			goto clear_extattr;
+	}
+
+	region = region_create(0, fs->blocksize);
+	if (!region) {
+		fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return 0;
+	}
+	if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
+		if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
+			goto clear_extattr;
+	}
+
+	entry = (struct ext2_ext_attr_entry *)(header+1);
+	end = block_buf + fs->blocksize;
+	while ((char *)entry < end && *(__u32 *)entry) {
+		if (region_allocate(region, (char *)entry - (char *)header,
+				   EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
+			if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
+				goto clear_extattr;
+		}
+		if ((ctx->ext_attr_ver == 1 &&
+		     (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
+		    (ctx->ext_attr_ver == 2 &&
+		     entry->e_name_index == 0)) {
+			if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
+				goto clear_extattr;
+		}
+		if (entry->e_value_block != 0) {
+			if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
+				goto clear_extattr;
+		}
+		if (entry->e_value_size &&
+		    region_allocate(region, entry->e_value_offs,
+				    EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
+			if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
+				goto clear_extattr;
+		}
+		entry = EXT2_EXT_ATTR_NEXT(entry);
+	}
+	if (region_allocate(region, (char *)entry - (char *)header, 4)) {
+		if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
+			goto clear_extattr;
+	}
+	region_free(region);
+
+	count = header->h_refcount - 1;
+	if (count)
+		ea_refcount_store(ctx->refcount, blk, count);
+	mark_block_used(ctx, blk);
+	ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
+
+	return 1;
+
+clear_extattr:
+	inode->i_file_acl = 0;
+	e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
+	return 0;
+}
+
+/* Returns 1 if bad htree, 0 if OK */
+static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
+			ext2_ino_t ino FSCK_ATTR((unused)),
+			struct ext2_inode *inode,
+			char *block_buf)
+{
+	struct ext2_dx_root_info        *root;
+	ext2_filsys                     fs = ctx->fs;
+	errcode_t                       retval;
+	blk_t                           blk;
+
+	if ((!LINUX_S_ISDIR(inode->i_mode) &&
+	     fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
+	    (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
+	     fix_problem(ctx, PR_1_HTREE_SET, pctx)))
+		return 1;
+
+	blk = inode->i_block[0];
+	if (((blk == 0) ||
+	     (blk < fs->super->s_first_data_block) ||
+	     (blk >= fs->super->s_blocks_count)) &&
+	    fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
+		return 1;
+
+	retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
+	if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
+		return 1;
+
+	/* XXX should check that beginning matches a directory */
+	root = (struct ext2_dx_root_info *) (block_buf + 24);
+
+	if ((root->reserved_zero || root->info_length < 8) &&
+	    fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
+		return 1;
+
+	pctx->num = root->hash_version;
+	if ((root->hash_version != EXT2_HASH_LEGACY) &&
+	    (root->hash_version != EXT2_HASH_HALF_MD4) &&
+	    (root->hash_version != EXT2_HASH_TEA) &&
+	    fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
+		return 1;
+
+	if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
+	    fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
+		return 1;
+
+	pctx->num = root->indirect_levels;
+	if ((root->indirect_levels > 1) &&
+	    fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * This subroutine is called on each inode to account for all of the
+ * blocks used by that inode.
+ */
+static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
+			 char *block_buf)
+{
+	ext2_filsys fs = ctx->fs;
+	struct process_block_struct_1 pb;
+	ext2_ino_t      ino = pctx->ino;
+	struct ext2_inode *inode = pctx->inode;
+	int             bad_size = 0;
+	int             dirty_inode = 0;
+	__u64           size;
+
+	pb.ino = ino;
+	pb.num_blocks = 0;
+	pb.last_block = -1;
+	pb.num_illegal_blocks = 0;
+	pb.suppress = 0; pb.clear = 0;
+	pb.fragmented = 0;
+	pb.compressed = 0;
+	pb.previous_block = 0;
+	pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
+	pb.is_reg = LINUX_S_ISREG(inode->i_mode);
+	pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
+	pb.inode = inode;
+	pb.pctx = pctx;
+	pb.ctx = ctx;
+	pctx->ino = ino;
+	pctx->errcode = 0;
+
+	if (inode->i_flags & EXT2_COMPRBLK_FL) {
+		if (fs->super->s_feature_incompat &
+		    EXT2_FEATURE_INCOMPAT_COMPRESSION)
+			pb.compressed = 1;
+		else {
+			if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
+				inode->i_flags &= ~EXT2_COMPRBLK_FL;
+				dirty_inode++;
+			}
+		}
+	}
+
+	if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
+		pb.num_blocks++;
+
+	if (ext2fs_inode_has_valid_blocks(inode))
+		pctx->errcode = ext2fs_block_iterate2(fs, ino,
+				       pb.is_dir ? BLOCK_FLAG_HOLE : 0,
+				       block_buf, process_block, &pb);
+	end_problem_latch(ctx, PR_LATCH_BLOCK);
+	end_problem_latch(ctx, PR_LATCH_TOOBIG);
+	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+		goto out;
+	if (pctx->errcode)
+		fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
+
+	if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
+		ctx->fs_fragmented++;
+
+	if (pb.clear) {
+		inode->i_links_count = 0;
+		ext2fs_icount_store(ctx->inode_link_info, ino, 0);
+		inode->i_dtime = time(0);
+		dirty_inode++;
+		ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
+		ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
+		ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
+		/*
+		 * The inode was probably partially accounted for
+		 * before processing was aborted, so we need to
+		 * restart the pass 1 scan.
+		 */
+		ctx->flags |= E2F_FLAG_RESTART;
+		goto out;
+	}
+
+	if (inode->i_flags & EXT2_INDEX_FL) {
+		if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
+			inode->i_flags &= ~EXT2_INDEX_FL;
+			dirty_inode++;
+		} else {
+#ifdef ENABLE_HTREE
+			e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
+#endif
+		}
+	}
+	if (ctx->dirs_to_hash && pb.is_dir &&
+	    !(inode->i_flags & EXT2_INDEX_FL) &&
+	    ((inode->i_size / fs->blocksize) >= 3))
+		ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
+
+	if (!pb.num_blocks && pb.is_dir) {
+		if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
+			inode->i_links_count = 0;
+			ext2fs_icount_store(ctx->inode_link_info, ino, 0);
+			inode->i_dtime = time(0);
+			dirty_inode++;
+			ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
+			ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
+			ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
+			ctx->fs_directory_count--;
+			goto out;
+		}
+	}
+
+	pb.num_blocks *= (fs->blocksize / 512);
+
+	if (pb.is_dir) {
+		int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
+		if (nblock > (pb.last_block + 1))
+			bad_size = 1;
+		else if (nblock < (pb.last_block + 1)) {
+			if (((pb.last_block + 1) - nblock) >
+			    fs->super->s_prealloc_dir_blocks)
+				bad_size = 2;
+		}
+	} else {
+		size = EXT2_I_SIZE(inode);
+		if ((pb.last_block >= 0) &&
+		    (size < (__u64) pb.last_block * fs->blocksize))
+			bad_size = 3;
+		else if (size > ext2_max_sizes[fs->super->s_log_block_size])
+			bad_size = 4;
+	}
+	/* i_size for symlinks is checked elsewhere */
+	if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
+		pctx->num = (pb.last_block+1) * fs->blocksize;
+		if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
+			inode->i_size = pctx->num;
+			if (!LINUX_S_ISDIR(inode->i_mode))
+				inode->i_size_high = pctx->num >> 32;
+			dirty_inode++;
+		}
+		pctx->num = 0;
+	}
+	if (LINUX_S_ISREG(inode->i_mode) &&
+	    (inode->i_size_high || inode->i_size & 0x80000000UL))
+		ctx->large_files++;
+	if (pb.num_blocks != inode->i_blocks) {
+		pctx->num = pb.num_blocks;
+		if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
+			inode->i_blocks = pb.num_blocks;
+			dirty_inode++;
+		}
+		pctx->num = 0;
+	}
+out:
+	if (dirty_inode)
+		e2fsck_write_inode(ctx, ino, inode, "check_blocks");
+}
+
+
+/*
+ * This is a helper function for check_blocks().
+ */
+static int process_block(ext2_filsys fs,
+		  blk_t *block_nr,
+		  e2_blkcnt_t blockcnt,
+		  blk_t ref_block FSCK_ATTR((unused)),
+		  int ref_offset FSCK_ATTR((unused)),
+		  void *priv_data)
+{
+	struct process_block_struct_1 *p;
+	struct problem_context *pctx;
+	blk_t   blk = *block_nr;
+	int     ret_code = 0;
+	int     problem = 0;
+	e2fsck_t        ctx;
+
+	p = (struct process_block_struct_1 *) priv_data;
+	pctx = p->pctx;
+	ctx = p->ctx;
+
+	if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
+		/* todo: Check that the comprblk_fl is high, that the
+		   blkaddr pattern looks right (all non-holes up to
+		   first EXT2FS_COMPRESSED_BLKADDR, then all
+		   EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
+		   that the feature_incompat bit is high, and that the
+		   inode is a regular file.  If we're doing a "full
+		   check" (a concept introduced to e2fsck by e2compr,
+		   meaning that we look at data blocks as well as
+		   metadata) then call some library routine that
+		   checks the compressed data.  I'll have to think
+		   about this, because one particularly important
+		   problem to be able to fix is to recalculate the
+		   cluster size if necessary.  I think that perhaps
+		   we'd better do most/all e2compr-specific checks
+		   separately, after the non-e2compr checks.  If not
+		   doing a full check, it may be useful to test that
+		   the personality is linux; e.g. if it isn't then
+		   perhaps this really is just an illegal block. */
+		return 0;
+	}
+
+	if (blk == 0) {
+		if (p->is_dir == 0) {
+			/*
+			 * Should never happen, since only directories
+			 * get called with BLOCK_FLAG_HOLE
+			 */
+#if DEBUG_E2FSCK
+			printf("process_block() called with blk == 0, "
+			       "blockcnt=%d, inode %lu???\n",
+			       blockcnt, p->ino);
+#endif
+			return 0;
+		}
+		if (blockcnt < 0)
+			return 0;
+		if (blockcnt * fs->blocksize < p->inode->i_size) {
+			goto mark_dir;
+		}
+		return 0;
+	}
+
+	/*
+	 * Simplistic fragmentation check.  We merely require that the
+	 * file be contiguous.  (Which can never be true for really
+	 * big files that are greater than a block group.)
+	 */
+	if (!HOLE_BLKADDR(p->previous_block)) {
+		if (p->previous_block+1 != blk)
+			p->fragmented = 1;
+	}
+	p->previous_block = blk;
+
+	if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
+		problem = PR_1_TOOBIG_DIR;
+	if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
+		problem = PR_1_TOOBIG_REG;
+	if (!p->is_dir && !p->is_reg && blockcnt > 0)
+		problem = PR_1_TOOBIG_SYMLINK;
+
+	if (blk < fs->super->s_first_data_block ||
+	    blk >= fs->super->s_blocks_count)
+		problem = PR_1_ILLEGAL_BLOCK_NUM;
+
+	if (problem) {
+		p->num_illegal_blocks++;
+		if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
+			if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
+				p->clear = 1;
+				return BLOCK_ABORT;
+			}
+			if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
+				p->suppress = 1;
+				set_latch_flags(PR_LATCH_BLOCK,
+						PRL_SUPPRESS, 0);
+			}
+		}
+		pctx->blk = blk;
+		pctx->blkcount = blockcnt;
+		if (fix_problem(ctx, problem, pctx)) {
+			blk = *block_nr = 0;
+			ret_code = BLOCK_CHANGED;
+			goto mark_dir;
+		} else
+			return 0;
+	}
+
+	if (p->ino == EXT2_RESIZE_INO) {
+		/*
+		 * The resize inode has already be sanity checked
+		 * during pass #0 (the superblock checks).  All we
+		 * have to do is mark the double indirect block as
+		 * being in use; all of the other blocks are handled
+		 * by mark_table_blocks()).
+		 */
+		if (blockcnt == BLOCK_COUNT_DIND)
+			mark_block_used(ctx, blk);
+	} else
+		mark_block_used(ctx, blk);
+	p->num_blocks++;
+	if (blockcnt >= 0)
+		p->last_block = blockcnt;
+mark_dir:
+	if (p->is_dir && (blockcnt >= 0)) {
+		pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
+						    blk, blockcnt);
+		if (pctx->errcode) {
+			pctx->blk = blk;
+			pctx->num = blockcnt;
+			fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
+			/* Should never get here */
+			ctx->flags |= E2F_FLAG_ABORT;
+			return BLOCK_ABORT;
+		}
+	}
+	return ret_code;
+}
+
+static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
+		      blk_t *block_nr,
+		      e2_blkcnt_t blockcnt,
+		      blk_t ref_block FSCK_ATTR((unused)),
+		      int ref_offset FSCK_ATTR((unused)),
+		      void *priv_data EXT2FS_ATTR((unused)))
+{
+	/*
+	 * Note: This function processes blocks for the bad blocks
+	 * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
+	 */
+
+	printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
+	return BLOCK_ERROR;
+}
+
+/*
+ * This routine gets called at the end of pass 1 if bad blocks are
+ * detected in the superblock, group descriptors, inode_bitmaps, or
+ * block bitmaps.  At this point, all of the blocks have been mapped
+ * out, so we can try to allocate new block(s) to replace the bad
+ * blocks.
+ */
+static void handle_fs_bad_blocks(e2fsck_t ctx)
+{
+	printf("Bad blocks detected on your filesystem\n"
+		"You should get your data off as the device will soon die\n");
+}
+
+/*
+ * This routine marks all blocks which are used by the superblock,
+ * group descriptors, inode bitmaps, and block bitmaps.
+ */
+static void mark_table_blocks(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	blk_t   block, b;
+	dgrp_t  i;
+	int     j;
+	struct problem_context pctx;
+
+	clear_problem_context(&pctx);
+
+	block = fs->super->s_first_data_block;
+	for (i = 0; i < fs->group_desc_count; i++) {
+		pctx.group = i;
+
+		ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
+
+		/*
+		 * Mark the blocks used for the inode table
+		 */
+		if (fs->group_desc[i].bg_inode_table) {
+			for (j = 0, b = fs->group_desc[i].bg_inode_table;
+			     j < fs->inode_blocks_per_group;
+			     j++, b++) {
+				if (ext2fs_test_block_bitmap(ctx->block_found_map,
+							     b)) {
+					pctx.blk = b;
+					if (fix_problem(ctx,
+						PR_1_ITABLE_CONFLICT, &pctx)) {
+						ctx->invalid_inode_table_flag[i]++;
+						ctx->invalid_bitmaps++;
+					}
+				} else {
+				    ext2fs_mark_block_bitmap(ctx->block_found_map,
+							     b);
+				}
+			}
+		}
+
+		/*
+		 * Mark block used for the block bitmap
+		 */
+		if (fs->group_desc[i].bg_block_bitmap) {
+			if (ext2fs_test_block_bitmap(ctx->block_found_map,
+				     fs->group_desc[i].bg_block_bitmap)) {
+				pctx.blk = fs->group_desc[i].bg_block_bitmap;
+				if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
+					ctx->invalid_block_bitmap_flag[i]++;
+					ctx->invalid_bitmaps++;
+				}
+			} else {
+			    ext2fs_mark_block_bitmap(ctx->block_found_map,
+				     fs->group_desc[i].bg_block_bitmap);
+		    }
+
+		}
+		/*
+		 * Mark block used for the inode bitmap
+		 */
+		if (fs->group_desc[i].bg_inode_bitmap) {
+			if (ext2fs_test_block_bitmap(ctx->block_found_map,
+				     fs->group_desc[i].bg_inode_bitmap)) {
+				pctx.blk = fs->group_desc[i].bg_inode_bitmap;
+				if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
+					ctx->invalid_inode_bitmap_flag[i]++;
+					ctx->invalid_bitmaps++;
+				}
+			} else {
+			    ext2fs_mark_block_bitmap(ctx->block_found_map,
+				     fs->group_desc[i].bg_inode_bitmap);
+			}
+		}
+		block += fs->super->s_blocks_per_group;
+	}
+}
+
+/*
+ * Thes subroutines short circuits ext2fs_get_blocks and
+ * ext2fs_check_directory; we use them since we already have the inode
+ * structure, so there's no point in letting the ext2fs library read
+ * the inode again.
+ */
+static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
+				  blk_t *blocks)
+{
+	e2fsck_t ctx = (e2fsck_t) fs->priv_data;
+	int     i;
+
+	if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
+		return EXT2_ET_CALLBACK_NOTHANDLED;
+
+	for (i=0; i < EXT2_N_BLOCKS; i++)
+		blocks[i] = ctx->stashed_inode->i_block[i];
+	return 0;
+}
+
+static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
+				  struct ext2_inode *inode)
+{
+	e2fsck_t ctx = (e2fsck_t) fs->priv_data;
+
+	if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
+		return EXT2_ET_CALLBACK_NOTHANDLED;
+	*inode = *ctx->stashed_inode;
+	return 0;
+}
+
+static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
+			    struct ext2_inode *inode)
+{
+	e2fsck_t ctx = (e2fsck_t) fs->priv_data;
+
+	if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
+		*ctx->stashed_inode = *inode;
+	return EXT2_ET_CALLBACK_NOTHANDLED;
+}
+
+static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
+{
+	e2fsck_t ctx = (e2fsck_t) fs->priv_data;
+
+	if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
+		return EXT2_ET_CALLBACK_NOTHANDLED;
+
+	if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
+		return EXT2_ET_NO_DIRECTORY;
+	return 0;
+}
+
+void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
+{
+	ext2_filsys fs = ctx->fs;
+
+	if (bool) {
+		fs->get_blocks = pass1_get_blocks;
+		fs->check_directory = pass1_check_directory;
+		fs->read_inode = pass1_read_inode;
+		fs->write_inode = pass1_write_inode;
+		ctx->stashed_ino = 0;
+	} else {
+		fs->get_blocks = 0;
+		fs->check_directory = 0;
+		fs->read_inode = 0;
+		fs->write_inode = 0;
+	}
+}
+
+/*
+ * pass1b.c --- Pass #1b of e2fsck
+ *
+ * This file contains pass1B, pass1C, and pass1D of e2fsck.  They are
+ * only invoked if pass 1 discovered blocks which are in use by more
+ * than one inode.
+ *
+ * Pass1B scans the data blocks of all the inodes again, generating a
+ * complete list of duplicate blocks and which inodes have claimed
+ * them.
+ *
+ * Pass1C does a tree-traversal of the filesystem, to determine the
+ * parent directories of these inodes.  This step is necessary so that
+ * e2fsck can print out the pathnames of affected inodes.
+ *
+ * Pass1D is a reconciliation pass.  For each inode with duplicate
+ * blocks, the user is prompted if s/he would like to clone the file
+ * (so that the file gets a fresh copy of the duplicated blocks) or
+ * simply to delete the file.
+ *
+ */
+
+
+/* Needed for architectures where sizeof(int) != sizeof(void *) */
+#define INT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
+#define VOIDPTR_TO_INT(ptr)  ((int)(intptr_t)(ptr))
+
+/* Define an extension to the ext2 library's block count information */
+#define BLOCK_COUNT_EXTATTR     (-5)
+
+struct block_el {
+	blk_t   block;
+	struct block_el *next;
+};
+
+struct inode_el {
+	ext2_ino_t      inode;
+	struct inode_el *next;
+};
+
+struct dup_block {
+	int             num_bad;
+	struct inode_el *inode_list;
+};
+
+/*
+ * This structure stores information about a particular inode which
+ * is sharing blocks with other inodes.  This information is collected
+ * to display to the user, so that the user knows what files he or she
+ * is dealing with, when trying to decide how to resolve the conflict
+ * of multiply-claimed blocks.
+ */
+struct dup_inode {
+	ext2_ino_t              dir;
+	int                     num_dupblocks;
+	struct ext2_inode       inode;
+	struct block_el         *block_list;
+};
+
+static int process_pass1b_block(ext2_filsys fs, blk_t   *blocknr,
+				e2_blkcnt_t blockcnt, blk_t ref_blk,
+				int ref_offset, void *priv_data);
+static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
+			struct dup_inode *dp, char *block_buf);
+static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
+		      struct dup_inode *dp, char* block_buf);
+static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
+
+static void pass1b(e2fsck_t ctx, char *block_buf);
+static void pass1c(e2fsck_t ctx, char *block_buf);
+static void pass1d(e2fsck_t ctx, char *block_buf);
+
+static int dup_inode_count = 0;
+
+static dict_t blk_dict, ino_dict;
+
+static ext2fs_inode_bitmap inode_dup_map;
+
+static int dict_int_cmp(const void *a, const void *b)
+{
+	intptr_t        ia, ib;
+
+	ia = (intptr_t)a;
+	ib = (intptr_t)b;
+
+	return (ia-ib);
+}
+
+/*
+ * Add a duplicate block record
+ */
+static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
+		     struct ext2_inode *inode)
+{
+	dnode_t *n;
+	struct dup_block        *db;
+	struct dup_inode        *di;
+	struct block_el         *blk_el;
+	struct inode_el         *ino_el;
+
+	n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
+	if (n)
+		db = (struct dup_block *) dnode_get(n);
+	else {
+		db = (struct dup_block *) e2fsck_allocate_memory(ctx,
+			 sizeof(struct dup_block), "duplicate block header");
+		db->num_bad = 0;
+		db->inode_list = 0;
+		dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
+	}
+	ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
+			 sizeof(struct inode_el), "inode element");
+	ino_el->inode = ino;
+	ino_el->next = db->inode_list;
+	db->inode_list = ino_el;
+	db->num_bad++;
+
+	n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
+	if (n)
+		di = (struct dup_inode *) dnode_get(n);
+	else {
+		di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
+			 sizeof(struct dup_inode), "duplicate inode header");
+		di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0 ;
+		di->num_dupblocks = 0;
+		di->block_list = 0;
+		di->inode = *inode;
+		dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
+	}
+	blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
+			 sizeof(struct block_el), "block element");
+	blk_el->block = blk;
+	blk_el->next = di->block_list;
+	di->block_list = blk_el;
+	di->num_dupblocks++;
+}
+
+/*
+ * Free a duplicate inode record
+ */
+static void inode_dnode_free(dnode_t *node)
+{
+	struct dup_inode        *di;
+	struct block_el         *p, *next;
+
+	di = (struct dup_inode *) dnode_get(node);
+	for (p = di->block_list; p; p = next) {
+		next = p->next;
+		free(p);
+	}
+	free(node);
+}
+
+/*
+ * Free a duplicate block record
+ */
+static void block_dnode_free(dnode_t *node)
+{
+	struct dup_block        *db;
+	struct inode_el         *p, *next;
+
+	db = (struct dup_block *) dnode_get(node);
+	for (p = db->inode_list; p; p = next) {
+		next = p->next;
+		free(p);
+	}
+	free(node);
+}
+
+
+/*
+ * Main procedure for handling duplicate blocks
+ */
+void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
+{
+	ext2_filsys             fs = ctx->fs;
+	struct problem_context  pctx;
+
+	clear_problem_context(&pctx);
+
+	pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
+		      _("multiply claimed inode map"), &inode_dup_map);
+	if (pctx.errcode) {
+		fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+
+	dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
+	dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
+	dict_set_allocator(&ino_dict, inode_dnode_free);
+	dict_set_allocator(&blk_dict, block_dnode_free);
+
+	pass1b(ctx, block_buf);
+	pass1c(ctx, block_buf);
+	pass1d(ctx, block_buf);
+
+	/*
+	 * Time to free all of the accumulated data structures that we
+	 * don't need anymore.
+	 */
+	dict_free_nodes(&ino_dict);
+	dict_free_nodes(&blk_dict);
+}
+
+/*
+ * Scan the inodes looking for inodes that contain duplicate blocks.
+ */
+struct process_block_struct_1b {
+	e2fsck_t        ctx;
+	ext2_ino_t      ino;
+	int             dup_blocks;
+	struct ext2_inode *inode;
+	struct problem_context *pctx;
+};
+
+static void pass1b(e2fsck_t ctx, char *block_buf)
+{
+	ext2_filsys fs = ctx->fs;
+	ext2_ino_t ino;
+	struct ext2_inode inode;
+	ext2_inode_scan scan;
+	struct process_block_struct_1b pb;
+	struct problem_context pctx;
+
+	clear_problem_context(&pctx);
+
+	if (!(ctx->options & E2F_OPT_PREEN))
+		fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
+	pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
+					      &scan);
+	if (pctx.errcode) {
+		fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+	ctx->stashed_inode = &inode;
+	pb.ctx = ctx;
+	pb.pctx = &pctx;
+	pctx.str = "pass1b";
+	while (1) {
+		pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
+		if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
+			continue;
+		if (pctx.errcode) {
+			fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
+			ctx->flags |= E2F_FLAG_ABORT;
+			return;
+		}
+		if (!ino)
+			break;
+		pctx.ino = ctx->stashed_ino = ino;
+		if ((ino != EXT2_BAD_INO) &&
+		    !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
+			continue;
+
+		pb.ino = ino;
+		pb.dup_blocks = 0;
+		pb.inode = &inode;
+
+		if (ext2fs_inode_has_valid_blocks(&inode) ||
+		    (ino == EXT2_BAD_INO))
+			pctx.errcode = ext2fs_block_iterate2(fs, ino,
+				     0, block_buf, process_pass1b_block, &pb);
+		if (inode.i_file_acl)
+			process_pass1b_block(fs, &inode.i_file_acl,
+					     BLOCK_COUNT_EXTATTR, 0, 0, &pb);
+		if (pb.dup_blocks) {
+			end_problem_latch(ctx, PR_LATCH_DBLOCK);
+			if (ino >= EXT2_FIRST_INODE(fs->super) ||
+			    ino == EXT2_ROOT_INO)
+				dup_inode_count++;
+		}
+		if (pctx.errcode)
+			fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
+	}
+	ext2fs_close_inode_scan(scan);
+	e2fsck_use_inode_shortcuts(ctx, 0);
+}
+
+static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
+				blk_t   *block_nr,
+				e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
+				blk_t ref_blk FSCK_ATTR((unused)),
+				int ref_offset FSCK_ATTR((unused)),
+				void *priv_data)
+{
+	struct process_block_struct_1b *p;
+	e2fsck_t ctx;
+
+	if (HOLE_BLKADDR(*block_nr))
+		return 0;
+	p = (struct process_block_struct_1b *) priv_data;
+	ctx = p->ctx;
+
+	if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
+		return 0;
+
+	/* OK, this is a duplicate block */
+	if (p->ino != EXT2_BAD_INO) {
+		p->pctx->blk = *block_nr;
+		fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
+	}
+	p->dup_blocks++;
+	ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
+
+	add_dupe(ctx, p->ino, *block_nr, p->inode);
+
+	return 0;
+}
+
+/*
+ * Pass 1c: Scan directories for inodes with duplicate blocks.  This
+ * is used so that we can print pathnames when prompting the user for
+ * what to do.
+ */
+struct search_dir_struct {
+	int             count;
+	ext2_ino_t      first_inode;
+	ext2_ino_t      max_inode;
+};
+
+static int search_dirent_proc(ext2_ino_t dir, int entry,
+			      struct ext2_dir_entry *dirent,
+			      int offset FSCK_ATTR((unused)),
+			      int blocksize FSCK_ATTR((unused)),
+			      char *buf FSCK_ATTR((unused)),
+			      void *priv_data)
+{
+	struct search_dir_struct *sd;
+	struct dup_inode        *p;
+	dnode_t                 *n;
+
+	sd = (struct search_dir_struct *) priv_data;
+
+	if (dirent->inode > sd->max_inode)
+		/* Should abort this inode, but not everything */
+		return 0;
+
+	if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
+	    !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
+		return 0;
+
+	n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
+	if (!n)
+		return 0;
+	p = (struct dup_inode *) dnode_get(n);
+	p->dir = dir;
+	sd->count--;
+
+	return(sd->count ? 0 : DIRENT_ABORT);
+}
+
+
+static void pass1c(e2fsck_t ctx, char *block_buf)
+{
+	ext2_filsys fs = ctx->fs;
+	struct search_dir_struct sd;
+	struct problem_context pctx;
+
+	clear_problem_context(&pctx);
+
+	if (!(ctx->options & E2F_OPT_PREEN))
+		fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
+
+	/*
+	 * Search through all directories to translate inodes to names
+	 * (by searching for the containing directory for that inode.)
+	 */
+	sd.count = dup_inode_count;
+	sd.first_inode = EXT2_FIRST_INODE(fs->super);
+	sd.max_inode = fs->super->s_inodes_count;
+	ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
+				  search_dirent_proc, &sd);
+}
+
+static void pass1d(e2fsck_t ctx, char *block_buf)
+{
+	ext2_filsys fs = ctx->fs;
+	struct dup_inode        *p, *t;
+	struct dup_block        *q;
+	ext2_ino_t              *shared, ino;
+	int     shared_len;
+	int     i;
+	int     file_ok;
+	int     meta_data = 0;
+	struct problem_context pctx;
+	dnode_t *n, *m;
+	struct block_el *s;
+	struct inode_el *r;
+
+	clear_problem_context(&pctx);
+
+	if (!(ctx->options & E2F_OPT_PREEN))
+		fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
+	e2fsck_read_bitmaps(ctx);
+
+	pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
+	fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
+	shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
+				sizeof(ext2_ino_t) * dict_count(&ino_dict),
+				"Shared inode list");
+	for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
+		p = (struct dup_inode *) dnode_get(n);
+		shared_len = 0;
+		file_ok = 1;
+		ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
+		if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
+			continue;
+
+		/*
+		 * Find all of the inodes which share blocks with this
+		 * one.  First we find all of the duplicate blocks
+		 * belonging to this inode, and then search each block
+		 * get the list of inodes, and merge them together.
+		 */
+		for (s = p->block_list; s; s = s->next) {
+			m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
+			if (!m)
+				continue; /* Should never happen... */
+			q = (struct dup_block *) dnode_get(m);
+			if (q->num_bad > 1)
+				file_ok = 0;
+			if (check_if_fs_block(ctx, s->block)) {
+				file_ok = 0;
+				meta_data = 1;
+			}
+
+			/*
+			 * Add all inodes used by this block to the
+			 * shared[] --- which is a unique list, so
+			 * if an inode is already in shared[], don't
+			 * add it again.
+			 */
+			for (r = q->inode_list; r; r = r->next) {
+				if (r->inode == ino)
+					continue;
+				for (i = 0; i < shared_len; i++)
+					if (shared[i] == r->inode)
+						break;
+				if (i == shared_len) {
+					shared[shared_len++] = r->inode;
+				}
+			}
+		}
+
+		/*
+		 * Report the inode that we are working on
+		 */
+		pctx.inode = &p->inode;
+		pctx.ino = ino;
+		pctx.dir = p->dir;
+		pctx.blkcount = p->num_dupblocks;
+		pctx.num = meta_data ? shared_len+1 : shared_len;
+		fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
+		pctx.blkcount = 0;
+		pctx.num = 0;
+
+		if (meta_data)
+			fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
+
+		for (i = 0; i < shared_len; i++) {
+			m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
+			if (!m)
+				continue; /* should never happen */
+			t = (struct dup_inode *) dnode_get(m);
+			/*
+			 * Report the inode that we are sharing with
+			 */
+			pctx.inode = &t->inode;
+			pctx.ino = shared[i];
+			pctx.dir = t->dir;
+			fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
+		}
+		if (file_ok) {
+			fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
+			continue;
+		}
+		if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
+			pctx.errcode = clone_file(ctx, ino, p, block_buf);
+			if (pctx.errcode)
+				fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
+			else
+				continue;
+		}
+		if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
+			delete_file(ctx, ino, p, block_buf);
+		else
+			ext2fs_unmark_valid(fs);
+	}
+	ext2fs_free_mem(&shared);
+}
+
+/*
+ * Drop the refcount on the dup_block structure, and clear the entry
+ * in the block_dup_map if appropriate.
+ */
+static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
+{
+	p->num_bad--;
+	if (p->num_bad <= 0 ||
+	    (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
+		ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
+}
+
+static int delete_file_block(ext2_filsys fs,
+			     blk_t      *block_nr,
+			     e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
+			     blk_t ref_block FSCK_ATTR((unused)),
+			     int ref_offset FSCK_ATTR((unused)),
+			     void *priv_data)
+{
+	struct process_block_struct_1b *pb;
+	struct dup_block *p;
+	dnode_t *n;
+	e2fsck_t ctx;
+
+	pb = (struct process_block_struct_1b *) priv_data;
+	ctx = pb->ctx;
+
+	if (HOLE_BLKADDR(*block_nr))
+		return 0;
+
+	if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
+		n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
+		if (n) {
+			p = (struct dup_block *) dnode_get(n);
+			decrement_badcount(ctx, *block_nr, p);
+		} else
+			bb_error_msg(_("internal error; can't find dup_blk for %d\n"),
+				*block_nr);
+	} else {
+		ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
+		ext2fs_block_alloc_stats(fs, *block_nr, -1);
+	}
+
+	return 0;
+}
+
+static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
+			struct dup_inode *dp, char* block_buf)
+{
+	ext2_filsys fs = ctx->fs;
+	struct process_block_struct_1b pb;
+	struct ext2_inode       inode;
+	struct problem_context  pctx;
+	unsigned int            count;
+
+	clear_problem_context(&pctx);
+	pctx.ino = pb.ino = ino;
+	pb.dup_blocks = dp->num_dupblocks;
+	pb.ctx = ctx;
+	pctx.str = "delete_file";
+
+	e2fsck_read_inode(ctx, ino, &inode, "delete_file");
+	if (ext2fs_inode_has_valid_blocks(&inode))
+		pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
+						     delete_file_block, &pb);
+	if (pctx.errcode)
+		fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
+	ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
+	ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
+	if (ctx->inode_bad_map)
+		ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
+	ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
+
+	/* Inode may have changed by block_iterate, so reread it */
+	e2fsck_read_inode(ctx, ino, &inode, "delete_file");
+	inode.i_links_count = 0;
+	inode.i_dtime = time(0);
+	if (inode.i_file_acl &&
+	    (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
+		count = 1;
+		pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
+						   block_buf, -1, &count);
+		if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
+			pctx.errcode = 0;
+			count = 1;
+		}
+		if (pctx.errcode) {
+			pctx.blk = inode.i_file_acl;
+			fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
+		}
+		/*
+		 * If the count is zero, then arrange to have the
+		 * block deleted.  If the block is in the block_dup_map,
+		 * also call delete_file_block since it will take care
+		 * of keeping the accounting straight.
+		 */
+		if ((count == 0) ||
+		    ext2fs_test_block_bitmap(ctx->block_dup_map,
+					     inode.i_file_acl))
+			delete_file_block(fs, &inode.i_file_acl,
+					  BLOCK_COUNT_EXTATTR, 0, 0, &pb);
+	}
+	e2fsck_write_inode(ctx, ino, &inode, "delete_file");
+}
+
+struct clone_struct {
+	errcode_t       errcode;
+	ext2_ino_t      dir;
+	char    *buf;
+	e2fsck_t ctx;
+};
+
+static int clone_file_block(ext2_filsys fs,
+			    blk_t       *block_nr,
+			    e2_blkcnt_t blockcnt,
+			    blk_t ref_block FSCK_ATTR((unused)),
+			    int ref_offset FSCK_ATTR((unused)),
+			    void *priv_data)
+{
+	struct dup_block *p;
+	blk_t   new_block;
+	errcode_t       retval;
+	struct clone_struct *cs = (struct clone_struct *) priv_data;
+	dnode_t *n;
+	e2fsck_t ctx;
+
+	ctx = cs->ctx;
+
+	if (HOLE_BLKADDR(*block_nr))
+		return 0;
+
+	if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
+		n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
+		if (n) {
+			p = (struct dup_block *) dnode_get(n);
+			retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
+						  &new_block);
+			if (retval) {
+				cs->errcode = retval;
+				return BLOCK_ABORT;
+			}
+			if (cs->dir && (blockcnt >= 0)) {
+				retval = ext2fs_set_dir_block(fs->dblist,
+				      cs->dir, new_block, blockcnt);
+				if (retval) {
+					cs->errcode = retval;
+					return BLOCK_ABORT;
+				}
+			}
+
+			retval = io_channel_read_blk(fs->io, *block_nr, 1,
+						     cs->buf);
+			if (retval) {
+				cs->errcode = retval;
+				return BLOCK_ABORT;
+			}
+			retval = io_channel_write_blk(fs->io, new_block, 1,
+						      cs->buf);
+			if (retval) {
+				cs->errcode = retval;
+				return BLOCK_ABORT;
+			}
+			decrement_badcount(ctx, *block_nr, p);
+			*block_nr = new_block;
+			ext2fs_mark_block_bitmap(ctx->block_found_map,
+						 new_block);
+			ext2fs_mark_block_bitmap(fs->block_map, new_block);
+			return BLOCK_CHANGED;
+		} else
+			bb_error_msg(_("internal error; can't find dup_blk for %d\n"),
+				*block_nr);
+	}
+	return 0;
+}
+
+static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
+		      struct dup_inode *dp, char* block_buf)
+{
+	ext2_filsys fs = ctx->fs;
+	errcode_t       retval;
+	struct clone_struct cs;
+	struct problem_context  pctx;
+	blk_t           blk;
+	dnode_t         *n;
+	struct inode_el *ino_el;
+	struct dup_block        *db;
+	struct dup_inode        *di;
+
+	clear_problem_context(&pctx);
+	cs.errcode = 0;
+	cs.dir = 0;
+	cs.ctx = ctx;
+	retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
+	if (retval)
+		return retval;
+
+	if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
+		cs.dir = ino;
+
+	pctx.ino = ino;
+	pctx.str = "clone_file";
+	if (ext2fs_inode_has_valid_blocks(&dp->inode))
+		pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
+						     clone_file_block, &cs);
+	ext2fs_mark_bb_dirty(fs);
+	if (pctx.errcode) {
+		fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
+		retval = pctx.errcode;
+		goto errout;
+	}
+	if (cs.errcode) {
+		bb_error_msg(_("returned from clone_file_block"));
+		retval = cs.errcode;
+		goto errout;
+	}
+	/* The inode may have changed on disk, so we have to re-read it */
+	e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
+	blk = dp->inode.i_file_acl;
+	if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
+				     BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
+		    BLOCK_CHANGED)) {
+		e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
+		/*
+		 * If we cloned the EA block, find all other inodes
+		 * which refered to that EA block, and modify
+		 * them to point to the new EA block.
+		 */
+		n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
+		db = (struct dup_block *) dnode_get(n);
+		for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
+			if (ino_el->inode == ino)
+				continue;
+			n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
+			di = (struct dup_inode *) dnode_get(n);
+			if (di->inode.i_file_acl == blk) {
+				di->inode.i_file_acl = dp->inode.i_file_acl;
+				e2fsck_write_inode(ctx, ino_el->inode,
+					   &di->inode, "clone file EA");
+				decrement_badcount(ctx, blk, db);
+			}
+		}
+	}
+	retval = 0;
+errout:
+	ext2fs_free_mem(&cs.buf);
+	return retval;
+}
+
+/*
+ * This routine returns 1 if a block overlaps with one of the superblocks,
+ * group descriptors, inode bitmaps, or block bitmaps.
+ */
+static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
+{
+	ext2_filsys fs = ctx->fs;
+	blk_t   block;
+	dgrp_t  i;
+
+	block = fs->super->s_first_data_block;
+	for (i = 0; i < fs->group_desc_count; i++) {
+
+		/* Check superblocks/block group descriptros */
+		if (ext2fs_bg_has_super(fs, i)) {
+			if (test_block >= block &&
+			    (test_block <= block + fs->desc_blocks))
+				return 1;
+		}
+
+		/* Check the inode table */
+		if ((fs->group_desc[i].bg_inode_table) &&
+		    (test_block >= fs->group_desc[i].bg_inode_table) &&
+		    (test_block < (fs->group_desc[i].bg_inode_table +
+				   fs->inode_blocks_per_group)))
+			return 1;
+
+		/* Check the bitmap blocks */
+		if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
+		    (test_block == fs->group_desc[i].bg_inode_bitmap))
+			return 1;
+
+		block += fs->super->s_blocks_per_group;
+	}
+	return 0;
+}
+/*
+ * pass2.c --- check directory structure
+ *
+ * Pass 2 of e2fsck iterates through all active directory inodes, and
+ * applies to following tests to each directory entry in the directory
+ * blocks in the inodes:
+ *
+ *      - The length of the directory entry (rec_len) should be at
+ *              least 8 bytes, and no more than the remaining space
+ *              left in the directory block.
+ *      - The length of the name in the directory entry (name_len)
+ *              should be less than (rec_len - 8).
+ *      - The inode number in the directory entry should be within
+ *              legal bounds.
+ *      - The inode number should refer to a in-use inode.
+ *      - The first entry should be '.', and its inode should be
+ *              the inode of the directory.
+ *      - The second entry should be '..'.
+ *
+ * To minimize disk seek time, the directory blocks are processed in
+ * sorted order of block numbers.
+ *
+ * Pass 2 also collects the following information:
+ *      - The inode numbers of the subdirectories for each directory.
+ *
+ * Pass 2 relies on the following information from previous passes:
+ *      - The directory information collected in pass 1.
+ *      - The inode_used_map bitmap
+ *      - The inode_bad_map bitmap
+ *      - The inode_dir_map bitmap
+ *
+ * Pass 2 frees the following data structures
+ *      - The inode_bad_map bitmap
+ *      - The inode_reg_map bitmap
+ */
+
+/*
+ * Keeps track of how many times an inode is referenced.
+ */
+static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
+static int check_dir_block(ext2_filsys fs,
+			   struct ext2_db_entry *dir_blocks_info,
+			   void *priv_data);
+static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
+			      struct problem_context *pctx);
+static int update_dir_block(ext2_filsys fs,
+			    blk_t       *block_nr,
+			    e2_blkcnt_t blockcnt,
+			    blk_t       ref_block,
+			    int         ref_offset,
+			    void        *priv_data);
+static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
+static int htree_depth(struct dx_dir_info *dx_dir,
+		       struct dx_dirblock_info *dx_db);
+static int special_dir_block_cmp(const void *a, const void *b);
+
+struct check_dir_struct {
+	char *buf;
+	struct problem_context  pctx;
+	int     count, max;
+	e2fsck_t ctx;
+};
+
+static void e2fsck_pass2(e2fsck_t ctx)
+{
+	struct ext2_super_block *sb = ctx->fs->super;
+	struct problem_context  pctx;
+	ext2_filsys             fs = ctx->fs;
+	char                    *buf;
+	struct dir_info         *dir;
+	struct check_dir_struct cd;
+	struct dx_dir_info      *dx_dir;
+	struct dx_dirblock_info *dx_db, *dx_parent;
+	int                     b;
+	int                     i, depth;
+	problem_t               code;
+	int                     bad_dir;
+
+	clear_problem_context(&cd.pctx);
+
+	/* Pass 2 */
+
+	if (!(ctx->options & E2F_OPT_PREEN))
+		fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
+
+	cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
+						0, ctx->inode_link_info,
+						&ctx->inode_count);
+	if (cd.pctx.errcode) {
+		fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+	buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
+					      "directory scan buffer");
+
+	/*
+	 * Set up the parent pointer for the root directory, if
+	 * present.  (If the root directory is not present, we will
+	 * create it in pass 3.)
+	 */
+	dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
+	if (dir)
+		dir->parent = EXT2_ROOT_INO;
+
+	cd.buf = buf;
+	cd.ctx = ctx;
+	cd.count = 1;
+	cd.max = ext2fs_dblist_count(fs->dblist);
+
+	if (ctx->progress)
+		(void) (ctx->progress)(ctx, 2, 0, cd.max);
+
+	if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
+		ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
+
+	cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
+						&cd);
+	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+		return;
+	if (cd.pctx.errcode) {
+		fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+
+#ifdef ENABLE_HTREE
+	for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
+		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+			return;
+		if (dx_dir->numblocks == 0)
+			continue;
+		clear_problem_context(&pctx);
+		bad_dir = 0;
+		pctx.dir = dx_dir->ino;
+		dx_db = dx_dir->dx_block;
+		if (dx_db->flags & DX_FLAG_REFERENCED)
+			dx_db->flags |= DX_FLAG_DUP_REF;
+		else
+			dx_db->flags |= DX_FLAG_REFERENCED;
+		/*
+		 * Find all of the first and last leaf blocks, and
+		 * update their parent's min and max hash values
+		 */
+		for (b=0, dx_db = dx_dir->dx_block;
+		     b < dx_dir->numblocks;
+		     b++, dx_db++) {
+			if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
+			    !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
+				continue;
+			dx_parent = &dx_dir->dx_block[dx_db->parent];
+			/*
+			 * XXX Make sure dx_parent->min_hash > dx_db->min_hash
+			 */
+			if (dx_db->flags & DX_FLAG_FIRST)
+				dx_parent->min_hash = dx_db->min_hash;
+			/*
+			 * XXX Make sure dx_parent->max_hash < dx_db->max_hash
+			 */
+			if (dx_db->flags & DX_FLAG_LAST)
+				dx_parent->max_hash = dx_db->max_hash;
+		}
+
+		for (b=0, dx_db = dx_dir->dx_block;
+		     b < dx_dir->numblocks;
+		     b++, dx_db++) {
+			pctx.blkcount = b;
+			pctx.group = dx_db->parent;
+			code = 0;
+			if (!(dx_db->flags & DX_FLAG_FIRST) &&
+			    (dx_db->min_hash < dx_db->node_min_hash)) {
+				pctx.blk = dx_db->min_hash;
+				pctx.blk2 = dx_db->node_min_hash;
+				code = PR_2_HTREE_MIN_HASH;
+				fix_problem(ctx, code, &pctx);
+				bad_dir++;
+			}
+			if (dx_db->type == DX_DIRBLOCK_LEAF) {
+				depth = htree_depth(dx_dir, dx_db);
+				if (depth != dx_dir->depth) {
+					code = PR_2_HTREE_BAD_DEPTH;
+					fix_problem(ctx, code, &pctx);
+					bad_dir++;
+				}
+			}
+			/*
+			 * This test doesn't apply for the root block
+			 * at block #0
+			 */
+			if (b &&
+			    (dx_db->max_hash > dx_db->node_max_hash)) {
+				pctx.blk = dx_db->max_hash;
+				pctx.blk2 = dx_db->node_max_hash;
+				code = PR_2_HTREE_MAX_HASH;
+				fix_problem(ctx, code, &pctx);
+				bad_dir++;
+			}
+			if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
+				code = PR_2_HTREE_NOTREF;
+				fix_problem(ctx, code, &pctx);
+				bad_dir++;
+			} else if (dx_db->flags & DX_FLAG_DUP_REF) {
+				code = PR_2_HTREE_DUPREF;
+				fix_problem(ctx, code, &pctx);
+				bad_dir++;
+			}
+			if (code == 0)
+				continue;
+		}
+		if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
+			clear_htree(ctx, dx_dir->ino);
+			dx_dir->numblocks = 0;
+		}
+	}
+#endif
+	ext2fs_free_mem(&buf);
+	ext2fs_free_dblist(fs->dblist);
+
+	ext2fs_free_inode_bitmap(ctx->inode_bad_map);
+	ctx->inode_bad_map = 0;
+	ext2fs_free_inode_bitmap(ctx->inode_reg_map);
+	ctx->inode_reg_map = 0;
+
+	clear_problem_context(&pctx);
+	if (ctx->large_files) {
+		if (!(sb->s_feature_ro_compat &
+		      EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
+		    fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
+			sb->s_feature_ro_compat |=
+				EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
+			ext2fs_mark_super_dirty(fs);
+		}
+		if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
+		    fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
+			ext2fs_update_dynamic_rev(fs);
+			ext2fs_mark_super_dirty(fs);
+		}
+	} else if (!ctx->large_files &&
+	    (sb->s_feature_ro_compat &
+	      EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
+		if (fs->flags & EXT2_FLAG_RW) {
+			sb->s_feature_ro_compat &=
+				~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
+			ext2fs_mark_super_dirty(fs);
+		}
+	}
+
+}
+
+#define MAX_DEPTH 32000
+static int htree_depth(struct dx_dir_info *dx_dir,
+		       struct dx_dirblock_info *dx_db)
+{
+	int     depth = 0;
+
+	while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
+		dx_db = &dx_dir->dx_block[dx_db->parent];
+		depth++;
+	}
+	return depth;
+}
+
+static int dict_de_cmp(const void *a, const void *b)
+{
+	const struct ext2_dir_entry *de_a, *de_b;
+	int     a_len, b_len;
+
+	de_a = (const struct ext2_dir_entry *) a;
+	a_len = de_a->name_len & 0xFF;
+	de_b = (const struct ext2_dir_entry *) b;
+	b_len = de_b->name_len & 0xFF;
+
+	if (a_len != b_len)
+		return (a_len - b_len);
+
+	return strncmp(de_a->name, de_b->name, a_len);
+}
+
+/*
+ * This is special sort function that makes sure that directory blocks
+ * with a dirblock of zero are sorted to the beginning of the list.
+ * This guarantees that the root node of the htree directories are
+ * processed first, so we know what hash version to use.
+ */
+static int special_dir_block_cmp(const void *a, const void *b)
+{
+	const struct ext2_db_entry *db_a =
+		(const struct ext2_db_entry *) a;
+	const struct ext2_db_entry *db_b =
+		(const struct ext2_db_entry *) b;
+
+	if (db_a->blockcnt && !db_b->blockcnt)
+		return 1;
+
+	if (!db_a->blockcnt && db_b->blockcnt)
+		return -1;
+
+	if (db_a->blk != db_b->blk)
+		return (int) (db_a->blk - db_b->blk);
+
+	if (db_a->ino != db_b->ino)
+		return (int) (db_a->ino - db_b->ino);
+
+	return (int) (db_a->blockcnt - db_b->blockcnt);
+}
+
+
+/*
+ * Make sure the first entry in the directory is '.', and that the
+ * directory entry is sane.
+ */
+static int check_dot(e2fsck_t ctx,
+		     struct ext2_dir_entry *dirent,
+		     ext2_ino_t ino, struct problem_context *pctx)
+{
+	struct ext2_dir_entry *nextdir;
+	int     status = 0;
+	int     created = 0;
+	int     new_len;
+	int     problem = 0;
+
+	if (!dirent->inode)
+		problem = PR_2_MISSING_DOT;
+	else if (((dirent->name_len & 0xFF) != 1) ||
+		 (dirent->name[0] != '.'))
+		problem = PR_2_1ST_NOT_DOT;
+	else if (dirent->name[1] != '\0')
+		problem = PR_2_DOT_NULL_TERM;
+
+	if (problem) {
+		if (fix_problem(ctx, problem, pctx)) {
+			if (dirent->rec_len < 12)
+				dirent->rec_len = 12;
+			dirent->inode = ino;
+			dirent->name_len = 1;
+			dirent->name[0] = '.';
+			dirent->name[1] = '\0';
+			status = 1;
+			created = 1;
+		}
+	}
+	if (dirent->inode != ino) {
+		if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
+			dirent->inode = ino;
+			status = 1;
+		}
+	}
+	if (dirent->rec_len > 12) {
+		new_len = dirent->rec_len - 12;
+		if (new_len > 12) {
+			if (created ||
+			    fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
+				nextdir = (struct ext2_dir_entry *)
+					((char *) dirent + 12);
+				dirent->rec_len = 12;
+				nextdir->rec_len = new_len;
+				nextdir->inode = 0;
+				nextdir->name_len = 0;
+				status = 1;
+			}
+		}
+	}
+	return status;
+}
+
+/*
+ * Make sure the second entry in the directory is '..', and that the
+ * directory entry is sane.  We do not check the inode number of '..'
+ * here; this gets done in pass 3.
+ */
+static int check_dotdot(e2fsck_t ctx,
+			struct ext2_dir_entry *dirent,
+			struct dir_info *dir, struct problem_context *pctx)
+{
+	int             problem = 0;
+
+	if (!dirent->inode)
+		problem = PR_2_MISSING_DOT_DOT;
+	else if (((dirent->name_len & 0xFF) != 2) ||
+		 (dirent->name[0] != '.') ||
+		 (dirent->name[1] != '.'))
+		problem = PR_2_2ND_NOT_DOT_DOT;
+	else if (dirent->name[2] != '\0')
+		problem = PR_2_DOT_DOT_NULL_TERM;
+
+	if (problem) {
+		if (fix_problem(ctx, problem, pctx)) {
+			if (dirent->rec_len < 12)
+				dirent->rec_len = 12;
+			/*
+			 * Note: we don't have the parent inode just
+			 * yet, so we will fill it in with the root
+			 * inode.  This will get fixed in pass 3.
+			 */
+			dirent->inode = EXT2_ROOT_INO;
+			dirent->name_len = 2;
+			dirent->name[0] = '.';
+			dirent->name[1] = '.';
+			dirent->name[2] = '\0';
+			return 1;
+		}
+		return 0;
+	}
+	dir->dotdot = dirent->inode;
+	return 0;
+}
+
+/*
+ * Check to make sure a directory entry doesn't contain any illegal
+ * characters.
+ */
+static int check_name(e2fsck_t ctx,
+		      struct ext2_dir_entry *dirent,
+		      struct problem_context *pctx)
+{
+	int     i;
+	int     fixup = -1;
+	int     ret = 0;
+
+	for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
+		if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
+			if (fixup < 0) {
+				fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
+			}
+			if (fixup) {
+				dirent->name[i] = '.';
+				ret = 1;
+			}
+		}
+	}
+	return ret;
+}
+
+/*
+ * Check the directory filetype (if present)
+ */
+
+/*
+ * Given a mode, return the ext2 file type
+ */
+static int ext2_file_type(unsigned int mode)
+{
+	if (LINUX_S_ISREG(mode))
+		return EXT2_FT_REG_FILE;
+
+	if (LINUX_S_ISDIR(mode))
+		return EXT2_FT_DIR;
+
+	if (LINUX_S_ISCHR(mode))
+		return EXT2_FT_CHRDEV;
+
+	if (LINUX_S_ISBLK(mode))
+		return EXT2_FT_BLKDEV;
+
+	if (LINUX_S_ISLNK(mode))
+		return EXT2_FT_SYMLINK;
+
+	if (LINUX_S_ISFIFO(mode))
+		return EXT2_FT_FIFO;
+
+	if (LINUX_S_ISSOCK(mode))
+		return EXT2_FT_SOCK;
+
+	return 0;
+}
+
+static int check_filetype(e2fsck_t ctx,
+				   struct ext2_dir_entry *dirent,
+				   struct problem_context *pctx)
+{
+	int     filetype = dirent->name_len >> 8;
+	int     should_be = EXT2_FT_UNKNOWN;
+	struct ext2_inode       inode;
+
+	if (!(ctx->fs->super->s_feature_incompat &
+	      EXT2_FEATURE_INCOMPAT_FILETYPE)) {
+		if (filetype == 0 ||
+		    !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
+			return 0;
+		dirent->name_len = dirent->name_len & 0xFF;
+		return 1;
+	}
+
+	if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
+		should_be = EXT2_FT_DIR;
+	} else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
+					    dirent->inode)) {
+		should_be = EXT2_FT_REG_FILE;
+	} else if (ctx->inode_bad_map &&
+		   ext2fs_test_inode_bitmap(ctx->inode_bad_map,
+					    dirent->inode))
+		should_be = 0;
+	else {
+		e2fsck_read_inode(ctx, dirent->inode, &inode,
+				  "check_filetype");
+		should_be = ext2_file_type(inode.i_mode);
+	}
+	if (filetype == should_be)
+		return 0;
+	pctx->num = should_be;
+
+	if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
+			pctx) == 0)
+		return 0;
+
+	dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
+	return 1;
+}
+
+#ifdef ENABLE_HTREE
+static void parse_int_node(ext2_filsys fs,
+			   struct ext2_db_entry *db,
+			   struct check_dir_struct *cd,
+			   struct dx_dir_info   *dx_dir,
+			   char *block_buf)
+{
+	struct          ext2_dx_root_info  *root;
+	struct          ext2_dx_entry *ent;
+	struct          ext2_dx_countlimit *limit;
+	struct dx_dirblock_info *dx_db;
+	int             i, expect_limit, count;
+	blk_t           blk;
+	ext2_dirhash_t  min_hash = 0xffffffff;
+	ext2_dirhash_t  max_hash = 0;
+	ext2_dirhash_t  hash = 0, prev_hash;
+
+	if (db->blockcnt == 0) {
+		root = (struct ext2_dx_root_info *) (block_buf + 24);
+		ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
+	} else {
+		ent = (struct ext2_dx_entry *) (block_buf+8);
+	}
+	limit = (struct ext2_dx_countlimit *) ent;
+
+	count = ext2fs_le16_to_cpu(limit->count);
+	expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
+		sizeof(struct ext2_dx_entry);
+	if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
+		cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
+		if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
+			goto clear_and_exit;
+	}
+	if (count > expect_limit) {
+		cd->pctx.num = count;
+		if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
+			goto clear_and_exit;
+		count = expect_limit;
+	}
+
+	for (i=0; i < count; i++) {
+		prev_hash = hash;
+		hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
+		blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
+		/* Check to make sure the block is valid */
+		if (blk > (blk_t) dx_dir->numblocks) {
+			cd->pctx.blk = blk;
+			if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
+					&cd->pctx))
+				goto clear_and_exit;
+		}
+		if (hash < prev_hash &&
+		    fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
+			goto clear_and_exit;
+		dx_db = &dx_dir->dx_block[blk];
+		if (dx_db->flags & DX_FLAG_REFERENCED) {
+			dx_db->flags |= DX_FLAG_DUP_REF;
+		} else {
+			dx_db->flags |= DX_FLAG_REFERENCED;
+			dx_db->parent = db->blockcnt;
+		}
+		if (hash < min_hash)
+			min_hash = hash;
+		if (hash > max_hash)
+			max_hash = hash;
+		dx_db->node_min_hash = hash;
+		if ((i+1) < count)
+			dx_db->node_max_hash =
+			  ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
+		else {
+			dx_db->node_max_hash = 0xfffffffe;
+			dx_db->flags |= DX_FLAG_LAST;
+		}
+		if (i == 0)
+			dx_db->flags |= DX_FLAG_FIRST;
+	}
+	dx_db = &dx_dir->dx_block[db->blockcnt];
+	dx_db->min_hash = min_hash;
+	dx_db->max_hash = max_hash;
+	return;
+
+clear_and_exit:
+	clear_htree(cd->ctx, cd->pctx.ino);
+	dx_dir->numblocks = 0;
+}
+#endif /* ENABLE_HTREE */
+
+/*
+ * Given a busted directory, try to salvage it somehow.
+ *
+ */
+static void salvage_directory(ext2_filsys fs,
+			      struct ext2_dir_entry *dirent,
+			      struct ext2_dir_entry *prev,
+			      unsigned int *offset)
+{
+	char    *cp = (char *) dirent;
+	int left = fs->blocksize - *offset - dirent->rec_len;
+	int name_len = dirent->name_len & 0xFF;
+
+	/*
+	 * Special case of directory entry of size 8: copy what's left
+	 * of the directory block up to cover up the invalid hole.
+	 */
+	if ((left >= 12) && (dirent->rec_len == 8)) {
+		memmove(cp, cp+8, left);
+		memset(cp + left, 0, 8);
+		return;
+	}
+	/*
+	 * If the directory entry overruns the end of the directory
+	 * block, and the name is small enough to fit, then adjust the
+	 * record length.
+	 */
+	if ((left < 0) &&
+	    (name_len + 8 <= dirent->rec_len + left) &&
+	    dirent->inode <= fs->super->s_inodes_count &&
+	    strnlen(dirent->name, name_len) == name_len) {
+		dirent->rec_len += left;
+		return;
+	}
+	/*
+	 * If the directory entry is a multiple of four, so it is
+	 * valid, let the previous directory entry absorb the invalid
+	 * one.
+	 */
+	if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
+		prev->rec_len += dirent->rec_len;
+		*offset += dirent->rec_len;
+		return;
+	}
+	/*
+	 * Default salvage method --- kill all of the directory
+	 * entries for the rest of the block.  We will either try to
+	 * absorb it into the previous directory entry, or create a
+	 * new empty directory entry the rest of the directory block.
+	 */
+	if (prev) {
+		prev->rec_len += fs->blocksize - *offset;
+		*offset = fs->blocksize;
+	} else {
+		dirent->rec_len = fs->blocksize - *offset;
+		dirent->name_len = 0;
+		dirent->inode = 0;
+	}
+}
+
+static int check_dir_block(ext2_filsys fs,
+			   struct ext2_db_entry *db,
+			   void *priv_data)
+{
+	struct dir_info         *subdir, *dir;
+	struct dx_dir_info      *dx_dir;
+#ifdef ENABLE_HTREE
+	struct dx_dirblock_info *dx_db = 0;
+#endif /* ENABLE_HTREE */
+	struct ext2_dir_entry   *dirent, *prev;
+	ext2_dirhash_t          hash;
+	unsigned int            offset = 0;
+	int                     dir_modified = 0;
+	int                     dot_state;
+	blk_t                   block_nr = db->blk;
+	ext2_ino_t              ino = db->ino;
+	__u16                   links;
+	struct check_dir_struct *cd;
+	char                    *buf;
+	e2fsck_t                ctx;
+	int                     problem;
+	struct ext2_dx_root_info *root;
+	struct ext2_dx_countlimit *limit;
+	static dict_t de_dict;
+	struct problem_context  pctx;
+	int     dups_found = 0;
+
+	cd = (struct check_dir_struct *) priv_data;
+	buf = cd->buf;
+	ctx = cd->ctx;
+
+	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+		return DIRENT_ABORT;
+
+	if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
+		return DIRENT_ABORT;
+
+	/*
+	 * Make sure the inode is still in use (could have been
+	 * deleted in the duplicate/bad blocks pass.
+	 */
+	if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
+		return 0;
+
+	cd->pctx.ino = ino;
+	cd->pctx.blk = block_nr;
+	cd->pctx.blkcount = db->blockcnt;
+	cd->pctx.ino2 = 0;
+	cd->pctx.dirent = 0;
+	cd->pctx.num = 0;
+
+	if (db->blk == 0) {
+		if (allocate_dir_block(ctx, db, &cd->pctx))
+			return 0;
+		block_nr = db->blk;
+	}
+
+	if (db->blockcnt)
+		dot_state = 2;
+	else
+		dot_state = 0;
+
+	if (ctx->dirs_to_hash &&
+	    ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
+		dups_found++;
+
+	cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
+	if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
+		cd->pctx.errcode = 0; /* We'll handle this ourselves */
+	if (cd->pctx.errcode) {
+		if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
+			ctx->flags |= E2F_FLAG_ABORT;
+			return DIRENT_ABORT;
+		}
+		memset(buf, 0, fs->blocksize);
+	}
+#ifdef ENABLE_HTREE
+	dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
+	if (dx_dir && dx_dir->numblocks) {
+		if (db->blockcnt >= dx_dir->numblocks) {
+			printf("XXX should never happen!!!\n");
+			abort();
+		}
+		dx_db = &dx_dir->dx_block[db->blockcnt];
+		dx_db->type = DX_DIRBLOCK_LEAF;
+		dx_db->phys = block_nr;
+		dx_db->min_hash = ~0;
+		dx_db->max_hash = 0;
+
+		dirent = (struct ext2_dir_entry *) buf;
+		limit = (struct ext2_dx_countlimit *) (buf+8);
+		if (db->blockcnt == 0) {
+			root = (struct ext2_dx_root_info *) (buf + 24);
+			dx_db->type = DX_DIRBLOCK_ROOT;
+			dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
+			if ((root->reserved_zero ||
+			     root->info_length < 8 ||
+			     root->indirect_levels > 1) &&
+			    fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
+				clear_htree(ctx, ino);
+				dx_dir->numblocks = 0;
+				dx_db = 0;
+			}
+			dx_dir->hashversion = root->hash_version;
+			dx_dir->depth = root->indirect_levels + 1;
+		} else if ((dirent->inode == 0) &&
+			   (dirent->rec_len == fs->blocksize) &&
+			   (dirent->name_len == 0) &&
+			   (ext2fs_le16_to_cpu(limit->limit) ==
+			    ((fs->blocksize-8) /
+			     sizeof(struct ext2_dx_entry))))
+			dx_db->type = DX_DIRBLOCK_NODE;
+	}
+#endif /* ENABLE_HTREE */
+
+	dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
+	prev = 0;
+	do {
+		problem = 0;
+		dirent = (struct ext2_dir_entry *) (buf + offset);
+		cd->pctx.dirent = dirent;
+		cd->pctx.num = offset;
+		if (((offset + dirent->rec_len) > fs->blocksize) ||
+		    (dirent->rec_len < 12) ||
+		    ((dirent->rec_len % 4) != 0) ||
+		    (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
+			if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
+				salvage_directory(fs, dirent, prev, &offset);
+				dir_modified++;
+				continue;
+			} else
+				goto abort_free_dict;
+		}
+		if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
+			if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
+				dirent->name_len = EXT2_NAME_LEN;
+				dir_modified++;
+			}
+		}
+
+		if (dot_state == 0) {
+			if (check_dot(ctx, dirent, ino, &cd->pctx))
+				dir_modified++;
+		} else if (dot_state == 1) {
+			dir = e2fsck_get_dir_info(ctx, ino);
+			if (!dir) {
+				fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
+				goto abort_free_dict;
+			}
+			if (check_dotdot(ctx, dirent, dir, &cd->pctx))
+				dir_modified++;
+		} else if (dirent->inode == ino) {
+			problem = PR_2_LINK_DOT;
+			if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
+				dirent->inode = 0;
+				dir_modified++;
+				goto next;
+			}
+		}
+		if (!dirent->inode)
+			goto next;
+
+		/*
+		 * Make sure the inode listed is a legal one.
+		 */
+		if (((dirent->inode != EXT2_ROOT_INO) &&
+		     (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
+		    (dirent->inode > fs->super->s_inodes_count)) {
+			problem = PR_2_BAD_INO;
+		} else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
+					       dirent->inode))) {
+			/*
+			 * If the inode is unused, offer to clear it.
+			 */
+			problem = PR_2_UNUSED_INODE;
+		} else if ((dot_state > 1) &&
+			   ((dirent->name_len & 0xFF) == 1) &&
+			   (dirent->name[0] == '.')) {
+			/*
+			 * If there's a '.' entry in anything other
+			 * than the first directory entry, it's a
+			 * duplicate entry that should be removed.
+			 */
+			problem = PR_2_DUP_DOT;
+		} else if ((dot_state > 1) &&
+			   ((dirent->name_len & 0xFF) == 2) &&
+			   (dirent->name[0] == '.') &&
+			   (dirent->name[1] == '.')) {
+			/*
+			 * If there's a '..' entry in anything other
+			 * than the second directory entry, it's a
+			 * duplicate entry that should be removed.
+			 */
+			problem = PR_2_DUP_DOT_DOT;
+		} else if ((dot_state > 1) &&
+			   (dirent->inode == EXT2_ROOT_INO)) {
+			/*
+			 * Don't allow links to the root directory.
+			 * We check this specially to make sure we
+			 * catch this error case even if the root
+			 * directory hasn't been created yet.
+			 */
+			problem = PR_2_LINK_ROOT;
+		} else if ((dot_state > 1) &&
+			   (dirent->name_len & 0xFF) == 0) {
+			/*
+			 * Don't allow zero-length directory names.
+			 */
+			problem = PR_2_NULL_NAME;
+		}
+
+		if (problem) {
+			if (fix_problem(ctx, problem, &cd->pctx)) {
+				dirent->inode = 0;
+				dir_modified++;
+				goto next;
+			} else {
+				ext2fs_unmark_valid(fs);
+				if (problem == PR_2_BAD_INO)
+					goto next;
+			}
+		}
+
+		/*
+		 * If the inode was marked as having bad fields in
+		 * pass1, process it and offer to fix/clear it.
+		 * (We wait until now so that we can display the
+		 * pathname to the user.)
+		 */
+		if (ctx->inode_bad_map &&
+		    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
+					     dirent->inode)) {
+			if (e2fsck_process_bad_inode(ctx, ino,
+						     dirent->inode,
+						     buf + fs->blocksize)) {
+				dirent->inode = 0;
+				dir_modified++;
+				goto next;
+			}
+			if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+				return DIRENT_ABORT;
+		}
+
+		if (check_name(ctx, dirent, &cd->pctx))
+			dir_modified++;
+
+		if (check_filetype(ctx, dirent, &cd->pctx))
+			dir_modified++;
+
+#ifdef ENABLE_HTREE
+		if (dx_db) {
+			ext2fs_dirhash(dx_dir->hashversion, dirent->name,
+				       (dirent->name_len & 0xFF),
+				       fs->super->s_hash_seed, &hash, 0);
+			if (hash < dx_db->min_hash)
+				dx_db->min_hash = hash;
+			if (hash > dx_db->max_hash)
+				dx_db->max_hash = hash;
+		}
+#endif
+
+		/*
+		 * If this is a directory, then mark its parent in its
+		 * dir_info structure.  If the parent field is already
+		 * filled in, then this directory has more than one
+		 * hard link.  We assume the first link is correct,
+		 * and ask the user if he/she wants to clear this one.
+		 */
+		if ((dot_state > 1) &&
+		    (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
+					      dirent->inode))) {
+			subdir = e2fsck_get_dir_info(ctx, dirent->inode);
+			if (!subdir) {
+				cd->pctx.ino = dirent->inode;
+				fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
+				goto abort_free_dict;
+			}
+			if (subdir->parent) {
+				cd->pctx.ino2 = subdir->parent;
+				if (fix_problem(ctx, PR_2_LINK_DIR,
+						&cd->pctx)) {
+					dirent->inode = 0;
+					dir_modified++;
+					goto next;
+				}
+				cd->pctx.ino2 = 0;
+			} else
+				subdir->parent = ino;
+		}
+
+		if (dups_found) {
+			;
+		} else if (dict_lookup(&de_dict, dirent)) {
+			clear_problem_context(&pctx);
+			pctx.ino = ino;
+			pctx.dirent = dirent;
+			fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
+			if (!ctx->dirs_to_hash)
+				ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
+			if (ctx->dirs_to_hash)
+				ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
+			dups_found++;
+		} else
+			dict_alloc_insert(&de_dict, dirent, dirent);
+
+		ext2fs_icount_increment(ctx->inode_count, dirent->inode,
+					&links);
+		if (links > 1)
+			ctx->fs_links_count++;
+		ctx->fs_total_count++;
+	next:
+		prev = dirent;
+		offset += dirent->rec_len;
+		dot_state++;
+	} while (offset < fs->blocksize);
+#ifdef ENABLE_HTREE
+	if (dx_db) {
+		cd->pctx.dir = cd->pctx.ino;
+		if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
+		    (dx_db->type == DX_DIRBLOCK_NODE))
+			parse_int_node(fs, db, cd, dx_dir, buf);
+	}
+#endif /* ENABLE_HTREE */
+	if (offset != fs->blocksize) {
+		cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
+		if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
+			dirent->rec_len = cd->pctx.num;
+			dir_modified++;
+		}
+	}
+	if (dir_modified) {
+		cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
+		if (cd->pctx.errcode) {
+			if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
+					 &cd->pctx))
+				goto abort_free_dict;
+		}
+		ext2fs_mark_changed(fs);
+	}
+	dict_free_nodes(&de_dict);
+	return 0;
+abort_free_dict:
+	dict_free_nodes(&de_dict);
+	ctx->flags |= E2F_FLAG_ABORT;
+	return DIRENT_ABORT;
+}
+
+/*
+ * This function is called to deallocate a block, and is an interator
+ * functioned called by deallocate inode via ext2fs_iterate_block().
+ */
+static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
+				  e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
+				  blk_t ref_block FSCK_ATTR((unused)),
+				  int ref_offset FSCK_ATTR((unused)),
+				  void *priv_data)
+{
+	e2fsck_t        ctx = (e2fsck_t) priv_data;
+
+	if (HOLE_BLKADDR(*block_nr))
+		return 0;
+	if ((*block_nr < fs->super->s_first_data_block) ||
+	    (*block_nr >= fs->super->s_blocks_count))
+		return 0;
+	ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
+	ext2fs_block_alloc_stats(fs, *block_nr, -1);
+	return 0;
+}
+
+/*
+ * This fuction deallocates an inode
+ */
+static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
+{
+	ext2_filsys fs = ctx->fs;
+	struct ext2_inode       inode;
+	struct problem_context  pctx;
+	__u32                   count;
+
+	ext2fs_icount_store(ctx->inode_link_info, ino, 0);
+	e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
+	inode.i_links_count = 0;
+	inode.i_dtime = time(0);
+	e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
+	clear_problem_context(&pctx);
+	pctx.ino = ino;
+
+	/*
+	 * Fix up the bitmaps...
+	 */
+	e2fsck_read_bitmaps(ctx);
+	ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
+	ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
+	if (ctx->inode_bad_map)
+		ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
+	ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
+
+	if (inode.i_file_acl &&
+	    (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
+		pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
+						   block_buf, -1, &count);
+		if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
+			pctx.errcode = 0;
+			count = 1;
+		}
+		if (pctx.errcode) {
+			pctx.blk = inode.i_file_acl;
+			fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
+			ctx->flags |= E2F_FLAG_ABORT;
+			return;
+		}
+		if (count == 0) {
+			ext2fs_unmark_block_bitmap(ctx->block_found_map,
+						   inode.i_file_acl);
+			ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
+		}
+		inode.i_file_acl = 0;
+	}
+
+	if (!ext2fs_inode_has_valid_blocks(&inode))
+		return;
+
+	if (LINUX_S_ISREG(inode.i_mode) &&
+	    (inode.i_size_high || inode.i_size & 0x80000000UL))
+		ctx->large_files--;
+
+	pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
+					    deallocate_inode_block, ctx);
+	if (pctx.errcode) {
+		fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+}
+
+/*
+ * This fuction clears the htree flag on an inode
+ */
+static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
+{
+	struct ext2_inode       inode;
+
+	e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
+	inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
+	e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
+	if (ctx->dirs_to_hash)
+		ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
+}
+
+
+static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
+				    ext2_ino_t ino, char *buf)
+{
+	ext2_filsys fs = ctx->fs;
+	struct ext2_inode       inode;
+	int                     inode_modified = 0;
+	int                     not_fixed = 0;
+	unsigned char           *frag, *fsize;
+	struct problem_context  pctx;
+	int     problem = 0;
+
+	e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
+
+	clear_problem_context(&pctx);
+	pctx.ino = ino;
+	pctx.dir = dir;
+	pctx.inode = &inode;
+
+	if (inode.i_file_acl &&
+	    !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
+	    fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
+		inode.i_file_acl = 0;
+#if BB_BIG_ENDIAN
+		/*
+		 * This is a special kludge to deal with long symlinks
+		 * on big endian systems.  i_blocks had already been
+		 * decremented earlier in pass 1, but since i_file_acl
+		 * hadn't yet been cleared, ext2fs_read_inode()
+		 * assumed that the file was short symlink and would
+		 * not have byte swapped i_block[0].  Hence, we have
+		 * to byte-swap it here.
+		 */
+		if (LINUX_S_ISLNK(inode.i_mode) &&
+		    (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
+		    (inode.i_blocks == fs->blocksize >> 9))
+			inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
+#endif
+		inode_modified++;
+	} else
+		not_fixed++;
+
+	if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
+	    !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
+	    !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
+	    !(LINUX_S_ISSOCK(inode.i_mode)))
+		problem = PR_2_BAD_MODE;
+	else if (LINUX_S_ISCHR(inode.i_mode)
+		 && !e2fsck_pass1_check_device_inode(fs, &inode))
+		problem = PR_2_BAD_CHAR_DEV;
+	else if (LINUX_S_ISBLK(inode.i_mode)
+		 && !e2fsck_pass1_check_device_inode(fs, &inode))
+		problem = PR_2_BAD_BLOCK_DEV;
+	else if (LINUX_S_ISFIFO(inode.i_mode)
+		 && !e2fsck_pass1_check_device_inode(fs, &inode))
+		problem = PR_2_BAD_FIFO;
+	else if (LINUX_S_ISSOCK(inode.i_mode)
+		 && !e2fsck_pass1_check_device_inode(fs, &inode))
+		problem = PR_2_BAD_SOCKET;
+	else if (LINUX_S_ISLNK(inode.i_mode)
+		 && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
+		problem = PR_2_INVALID_SYMLINK;
+	}
+
+	if (problem) {
+		if (fix_problem(ctx, problem, &pctx)) {
+			deallocate_inode(ctx, ino, 0);
+			if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+				return 0;
+			return 1;
+		} else
+			not_fixed++;
+		problem = 0;
+	}
+
+	if (inode.i_faddr) {
+		if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
+			inode.i_faddr = 0;
+			inode_modified++;
+		} else
+			not_fixed++;
+	}
+
+	switch (fs->super->s_creator_os) {
+	    case EXT2_OS_LINUX:
+		frag = &inode.osd2.linux2.l_i_frag;
+		fsize = &inode.osd2.linux2.l_i_fsize;
+		break;
+	    case EXT2_OS_HURD:
+		frag = &inode.osd2.hurd2.h_i_frag;
+		fsize = &inode.osd2.hurd2.h_i_fsize;
+		break;
+	    case EXT2_OS_MASIX:
+		frag = &inode.osd2.masix2.m_i_frag;
+		fsize = &inode.osd2.masix2.m_i_fsize;
+		break;
+	    default:
+		frag = fsize = 0;
+	}
+	if (frag && *frag) {
+		pctx.num = *frag;
+		if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
+			*frag = 0;
+			inode_modified++;
+		} else
+			not_fixed++;
+		pctx.num = 0;
+	}
+	if (fsize && *fsize) {
+		pctx.num = *fsize;
+		if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
+			*fsize = 0;
+			inode_modified++;
+		} else
+			not_fixed++;
+		pctx.num = 0;
+	}
+
+	if (inode.i_file_acl &&
+	    ((inode.i_file_acl < fs->super->s_first_data_block) ||
+	     (inode.i_file_acl >= fs->super->s_blocks_count))) {
+		if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
+			inode.i_file_acl = 0;
+			inode_modified++;
+		} else
+			not_fixed++;
+	}
+	if (inode.i_dir_acl &&
+	    LINUX_S_ISDIR(inode.i_mode)) {
+		if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
+			inode.i_dir_acl = 0;
+			inode_modified++;
+		} else
+			not_fixed++;
+	}
+
+	if (inode_modified)
+		e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
+	if (!not_fixed)
+		ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
+	return 0;
+}
+
+
+/*
+ * allocate_dir_block --- this function allocates a new directory
+ *      block for a particular inode; this is done if a directory has
+ *      a "hole" in it, or if a directory has a illegal block number
+ *      that was zeroed out and now needs to be replaced.
+ */
+static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
+			      struct problem_context *pctx)
+{
+	ext2_filsys fs = ctx->fs;
+	blk_t                   blk;
+	char                    *block;
+	struct ext2_inode       inode;
+
+	if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
+		return 1;
+
+	/*
+	 * Read the inode and block bitmaps in; we'll be messing with
+	 * them.
+	 */
+	e2fsck_read_bitmaps(ctx);
+
+	/*
+	 * First, find a free block
+	 */
+	pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
+	if (pctx->errcode) {
+		pctx->str = "ext2fs_new_block";
+		fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
+		return 1;
+	}
+	ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
+	ext2fs_mark_block_bitmap(fs->block_map, blk);
+	ext2fs_mark_bb_dirty(fs);
+
+	/*
+	 * Now let's create the actual data block for the inode
+	 */
+	if (db->blockcnt)
+		pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
+	else
+		pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
+						     EXT2_ROOT_INO, &block);
+
+	if (pctx->errcode) {
+		pctx->str = "ext2fs_new_dir_block";
+		fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
+		return 1;
+	}
+
+	pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
+	ext2fs_free_mem(&block);
+	if (pctx->errcode) {
+		pctx->str = "ext2fs_write_dir_block";
+		fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
+		return 1;
+	}
+
+	/*
+	 * Update the inode block count
+	 */
+	e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
+	inode.i_blocks += fs->blocksize / 512;
+	if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
+		inode.i_size = (db->blockcnt+1) * fs->blocksize;
+	e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
+
+	/*
+	 * Finally, update the block pointers for the inode
+	 */
+	db->blk = blk;
+	pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
+				      0, update_dir_block, db);
+	if (pctx->errcode) {
+		pctx->str = "ext2fs_block_iterate";
+		fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * This is a helper function for allocate_dir_block().
+ */
+static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
+			    blk_t       *block_nr,
+			    e2_blkcnt_t blockcnt,
+			    blk_t ref_block FSCK_ATTR((unused)),
+			    int ref_offset FSCK_ATTR((unused)),
+			    void *priv_data)
+{
+	struct ext2_db_entry *db;
+
+	db = (struct ext2_db_entry *) priv_data;
+	if (db->blockcnt == (int) blockcnt) {
+		*block_nr = db->blk;
+		return BLOCK_CHANGED;
+	}
+	return 0;
+}
+
+/*
+ * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
+ *
+ * Pass #3 assures that all directories are connected to the
+ * filesystem tree, using the following algorithm:
+ *
+ * First, the root directory is checked to make sure it exists; if
+ * not, e2fsck will offer to create a new one.  It is then marked as
+ * "done".
+ *
+ * Then, pass3 interates over all directory inodes; for each directory
+ * it attempts to trace up the filesystem tree, using dirinfo.parent
+ * until it reaches a directory which has been marked "done".  If it
+ * can not do so, then the directory must be disconnected, and e2fsck
+ * will offer to reconnect it to /lost+found.  While it is chasing
+ * parent pointers up the filesystem tree, if pass3 sees a directory
+ * twice, then it has detected a filesystem loop, and it will again
+ * offer to reconnect the directory to /lost+found in to break the
+ * filesystem loop.
+ *
+ * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
+ * reconnect inodes to /lost+found; this subroutine is also used by
+ * pass 4.  e2fsck_reconnect_file() calls get_lost_and_found(), which
+ * is responsible for creating /lost+found if it does not exist.
+ *
+ * Pass 3 frees the following data structures:
+ *      - The dirinfo directory information cache.
+ */
+
+static void check_root(e2fsck_t ctx);
+static int check_directory(e2fsck_t ctx, struct dir_info *dir,
+			   struct problem_context *pctx);
+static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
+
+static ext2fs_inode_bitmap inode_loop_detect;
+static ext2fs_inode_bitmap inode_done_map;
+
+static void e2fsck_pass3(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	int             i;
+	struct problem_context  pctx;
+	struct dir_info *dir;
+	unsigned long maxdirs, count;
+
+	clear_problem_context(&pctx);
+
+	/* Pass 3 */
+
+	if (!(ctx->options & E2F_OPT_PREEN))
+		fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
+
+	/*
+	 * Allocate some bitmaps to do loop detection.
+	 */
+	pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
+						    &inode_done_map);
+	if (pctx.errcode) {
+		pctx.num = 2;
+		fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		goto abort_exit;
+	}
+	check_root(ctx);
+	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+		goto abort_exit;
+
+	ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
+
+	maxdirs = e2fsck_get_num_dirinfo(ctx);
+	count = 1;
+
+	if (ctx->progress)
+		if ((ctx->progress)(ctx, 3, 0, maxdirs))
+			goto abort_exit;
+
+	for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
+		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+			goto abort_exit;
+		if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
+			goto abort_exit;
+		if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
+			if (check_directory(ctx, dir, &pctx))
+				goto abort_exit;
+	}
+
+	/*
+	 * Force the creation of /lost+found if not present
+	 */
+	if ((ctx->flags & E2F_OPT_READONLY) == 0)
+		e2fsck_get_lost_and_found(ctx, 1);
+
+	/*
+	 * If there are any directories that need to be indexed or
+	 * optimized, do it here.
+	 */
+	e2fsck_rehash_directories(ctx);
+
+abort_exit:
+	e2fsck_free_dir_info(ctx);
+	ext2fs_free_inode_bitmap(inode_loop_detect);
+	inode_loop_detect = 0;
+	ext2fs_free_inode_bitmap(inode_done_map);
+	inode_done_map = 0;
+}
+
+/*
+ * This makes sure the root inode is present; if not, we ask if the
+ * user wants us to create it.  Not creating it is a fatal error.
+ */
+static void check_root(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	blk_t                   blk;
+	struct ext2_inode       inode;
+	char *                  block;
+	struct problem_context  pctx;
+
+	clear_problem_context(&pctx);
+
+	if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
+		/*
+		 * If the root inode is not a directory, die here.  The
+		 * user must have answered 'no' in pass1 when we
+		 * offered to clear it.
+		 */
+		if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
+					       EXT2_ROOT_INO))) {
+			fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
+			ctx->flags |= E2F_FLAG_ABORT;
+		}
+		return;
+	}
+
+	if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
+		fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+
+	e2fsck_read_bitmaps(ctx);
+
+	/*
+	 * First, find a free block
+	 */
+	pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
+	if (pctx.errcode) {
+		pctx.str = "ext2fs_new_block";
+		fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+	ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
+	ext2fs_mark_block_bitmap(fs->block_map, blk);
+	ext2fs_mark_bb_dirty(fs);
+
+	/*
+	 * Now let's create the actual data block for the inode
+	 */
+	pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
+					    &block);
+	if (pctx.errcode) {
+		pctx.str = "ext2fs_new_dir_block";
+		fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+
+	pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
+	if (pctx.errcode) {
+		pctx.str = "ext2fs_write_dir_block";
+		fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+	ext2fs_free_mem(&block);
+
+	/*
+	 * Set up the inode structure
+	 */
+	memset(&inode, 0, sizeof(inode));
+	inode.i_mode = 040755;
+	inode.i_size = fs->blocksize;
+	inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
+	inode.i_links_count = 2;
+	inode.i_blocks = fs->blocksize / 512;
+	inode.i_block[0] = blk;
+
+	/*
+	 * Write out the inode.
+	 */
+	pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
+	if (pctx.errcode) {
+		pctx.str = "ext2fs_write_inode";
+		fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+
+	/*
+	 * Miscellaneous bookkeeping...
+	 */
+	e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
+	ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
+	ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
+
+	ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
+	ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
+	ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
+	ext2fs_mark_ib_dirty(fs);
+}
+
+/*
+ * This subroutine is responsible for making sure that a particular
+ * directory is connected to the root; if it isn't we trace it up as
+ * far as we can go, and then offer to connect the resulting parent to
+ * the lost+found.  We have to do loop detection; if we ever discover
+ * a loop, we treat that as a disconnected directory and offer to
+ * reparent it to lost+found.
+ *
+ * However, loop detection is expensive, because for very large
+ * filesystems, the inode_loop_detect bitmap is huge, and clearing it
+ * is non-trivial.  Loops in filesystems are also a rare error case,
+ * and we shouldn't optimize for error cases.  So we try two passes of
+ * the algorithm.  The first time, we ignore loop detection and merely
+ * increment a counter; if the counter exceeds some extreme threshold,
+ * then we try again with the loop detection bitmap enabled.
+ */
+static int check_directory(e2fsck_t ctx, struct dir_info *dir,
+			   struct problem_context *pctx)
+{
+	ext2_filsys     fs = ctx->fs;
+	struct dir_info *p = dir;
+	int             loop_pass = 0, parent_count = 0;
+
+	if (!p)
+		return 0;
+
+	while (1) {
+		/*
+		 * Mark this inode as being "done"; by the time we
+		 * return from this function, the inode we either be
+		 * verified as being connected to the directory tree,
+		 * or we will have offered to reconnect this to
+		 * lost+found.
+		 *
+		 * If it was marked done already, then we've reached a
+		 * parent we've already checked.
+		 */
+		if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
+			break;
+
+		/*
+		 * If this directory doesn't have a parent, or we've
+		 * seen the parent once already, then offer to
+		 * reparent it to lost+found
+		 */
+		if (!p->parent ||
+		    (loop_pass &&
+		     (ext2fs_test_inode_bitmap(inode_loop_detect,
+					      p->parent)))) {
+			pctx->ino = p->ino;
+			if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
+				if (e2fsck_reconnect_file(ctx, pctx->ino))
+					ext2fs_unmark_valid(fs);
+				else {
+					p = e2fsck_get_dir_info(ctx, pctx->ino);
+					p->parent = ctx->lost_and_found;
+					fix_dotdot(ctx, p, ctx->lost_and_found);
+				}
+			}
+			break;
+		}
+		p = e2fsck_get_dir_info(ctx, p->parent);
+		if (!p) {
+			fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
+			return 0;
+		}
+		if (loop_pass) {
+			ext2fs_mark_inode_bitmap(inode_loop_detect,
+						 p->ino);
+		} else if (parent_count++ > 2048) {
+			/*
+			 * If we've run into a path depth that's
+			 * greater than 2048, try again with the inode
+			 * loop bitmap turned on and start from the
+			 * top.
+			 */
+			loop_pass = 1;
+			if (inode_loop_detect)
+				ext2fs_clear_inode_bitmap(inode_loop_detect);
+			else {
+				pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
+				if (pctx->errcode) {
+					pctx->num = 1;
+					fix_problem(ctx,
+				    PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
+					ctx->flags |= E2F_FLAG_ABORT;
+					return -1;
+				}
+			}
+			p = dir;
+		}
+	}
+
+	/*
+	 * Make sure that .. and the parent directory are the same;
+	 * offer to fix it if not.
+	 */
+	if (dir->parent != dir->dotdot) {
+		pctx->ino = dir->ino;
+		pctx->ino2 = dir->dotdot;
+		pctx->dir = dir->parent;
+		if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
+			fix_dotdot(ctx, dir, dir->parent);
+	}
+	return 0;
+}
+
+/*
+ * This routine gets the lost_and_found inode, making it a directory
+ * if necessary
+ */
+ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
+{
+	ext2_filsys fs = ctx->fs;
+	ext2_ino_t                      ino;
+	blk_t                   blk;
+	errcode_t               retval;
+	struct ext2_inode       inode;
+	char *                  block;
+	static const char       name[] = "lost+found";
+	struct  problem_context pctx;
+	struct dir_info         *dirinfo;
+
+	if (ctx->lost_and_found)
+		return ctx->lost_and_found;
+
+	clear_problem_context(&pctx);
+
+	retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
+			       sizeof(name)-1, 0, &ino);
+	if (retval && !fix)
+		return 0;
+	if (!retval) {
+		if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
+			ctx->lost_and_found = ino;
+			return ino;
+		}
+
+		/* Lost+found isn't a directory! */
+		if (!fix)
+			return 0;
+		pctx.ino = ino;
+		if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
+			return 0;
+
+		/* OK, unlink the old /lost+found file. */
+		pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
+		if (pctx.errcode) {
+			pctx.str = "ext2fs_unlink";
+			fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
+			return 0;
+		}
+		dirinfo = e2fsck_get_dir_info(ctx, ino);
+		if (dirinfo)
+			dirinfo->parent = 0;
+		e2fsck_adjust_inode_count(ctx, ino, -1);
+	} else if (retval != EXT2_ET_FILE_NOT_FOUND) {
+		pctx.errcode = retval;
+		fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
+	}
+	if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
+		return 0;
+
+	/*
+	 * Read the inode and block bitmaps in; we'll be messing with
+	 * them.
+	 */
+	e2fsck_read_bitmaps(ctx);
+
+	/*
+	 * First, find a free block
+	 */
+	retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
+	if (retval) {
+		pctx.errcode = retval;
+		fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
+		return 0;
+	}
+	ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
+	ext2fs_block_alloc_stats(fs, blk, +1);
+
+	/*
+	 * Next find a free inode.
+	 */
+	retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
+				  ctx->inode_used_map, &ino);
+	if (retval) {
+		pctx.errcode = retval;
+		fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
+		return 0;
+	}
+	ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
+	ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
+	ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
+
+	/*
+	 * Now let's create the actual data block for the inode
+	 */
+	retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
+	if (retval) {
+		pctx.errcode = retval;
+		fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
+		return 0;
+	}
+
+	retval = ext2fs_write_dir_block(fs, blk, block);
+	ext2fs_free_mem(&block);
+	if (retval) {
+		pctx.errcode = retval;
+		fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
+		return 0;
+	}
+
+	/*
+	 * Set up the inode structure
+	 */
+	memset(&inode, 0, sizeof(inode));
+	inode.i_mode = 040700;
+	inode.i_size = fs->blocksize;
+	inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
+	inode.i_links_count = 2;
+	inode.i_blocks = fs->blocksize / 512;
+	inode.i_block[0] = blk;
+
+	/*
+	 * Next, write out the inode.
+	 */
+	pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
+	if (pctx.errcode) {
+		pctx.str = "ext2fs_write_inode";
+		fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
+		return 0;
+	}
+	/*
+	 * Finally, create the directory link
+	 */
+	pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
+	if (pctx.errcode) {
+		pctx.str = "ext2fs_link";
+		fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
+		return 0;
+	}
+
+	/*
+	 * Miscellaneous bookkeeping that needs to be kept straight.
+	 */
+	e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
+	e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
+	ext2fs_icount_store(ctx->inode_count, ino, 2);
+	ext2fs_icount_store(ctx->inode_link_info, ino, 2);
+	ctx->lost_and_found = ino;
+	return ino;
+}
+
+/*
+ * This routine will connect a file to lost+found
+ */
+int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
+{
+	ext2_filsys fs = ctx->fs;
+	errcode_t       retval;
+	char            name[80];
+	struct problem_context  pctx;
+	struct ext2_inode       inode;
+	int             file_type = 0;
+
+	clear_problem_context(&pctx);
+	pctx.ino = ino;
+
+	if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
+		if (e2fsck_get_lost_and_found(ctx, 1) == 0)
+			ctx->bad_lost_and_found++;
+	}
+	if (ctx->bad_lost_and_found) {
+		fix_problem(ctx, PR_3_NO_LPF, &pctx);
+		return 1;
+	}
+
+	sprintf(name, "#%u", ino);
+	if (ext2fs_read_inode(fs, ino, &inode) == 0)
+		file_type = ext2_file_type(inode.i_mode);
+	retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
+	if (retval == EXT2_ET_DIR_NO_SPACE) {
+		if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
+			return 1;
+		retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
+						 1, 0);
+		if (retval) {
+			pctx.errcode = retval;
+			fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
+			return 1;
+		}
+		retval = ext2fs_link(fs, ctx->lost_and_found, name,
+				     ino, file_type);
+	}
+	if (retval) {
+		pctx.errcode = retval;
+		fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
+		return 1;
+	}
+	e2fsck_adjust_inode_count(ctx, ino, 1);
+
+	return 0;
+}
+
+/*
+ * Utility routine to adjust the inode counts on an inode.
+ */
+errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
+{
+	ext2_filsys fs = ctx->fs;
+	errcode_t               retval;
+	struct ext2_inode       inode;
+
+	if (!ino)
+		return 0;
+
+	retval = ext2fs_read_inode(fs, ino, &inode);
+	if (retval)
+		return retval;
+
+	if (adj == 1) {
+		ext2fs_icount_increment(ctx->inode_count, ino, 0);
+		if (inode.i_links_count == (__u16) ~0)
+			return 0;
+		ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
+		inode.i_links_count++;
+	} else if (adj == -1) {
+		ext2fs_icount_decrement(ctx->inode_count, ino, 0);
+		if (inode.i_links_count == 0)
+			return 0;
+		ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
+		inode.i_links_count--;
+	}
+
+	retval = ext2fs_write_inode(fs, ino, &inode);
+	if (retval)
+		return retval;
+
+	return 0;
+}
+
+/*
+ * Fix parent --- this routine fixes up the parent of a directory.
+ */
+struct fix_dotdot_struct {
+	ext2_filsys     fs;
+	ext2_ino_t      parent;
+	int             done;
+	e2fsck_t        ctx;
+};
+
+static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
+			   int  offset FSCK_ATTR((unused)),
+			   int  blocksize FSCK_ATTR((unused)),
+			   char *buf FSCK_ATTR((unused)),
+			   void *priv_data)
+{
+	struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
+	errcode_t       retval;
+	struct problem_context pctx;
+
+	if ((dirent->name_len & 0xFF) != 2)
+		return 0;
+	if (strncmp(dirent->name, "..", 2))
+		return 0;
+
+	clear_problem_context(&pctx);
+
+	retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
+	if (retval) {
+		pctx.errcode = retval;
+		fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
+	}
+	retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
+	if (retval) {
+		pctx.errcode = retval;
+		fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
+	}
+	dirent->inode = fp->parent;
+
+	fp->done++;
+	return DIRENT_ABORT | DIRENT_CHANGED;
+}
+
+static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
+{
+	ext2_filsys fs = ctx->fs;
+	errcode_t       retval;
+	struct fix_dotdot_struct fp;
+	struct problem_context pctx;
+
+	fp.fs = fs;
+	fp.parent = parent;
+	fp.done = 0;
+	fp.ctx = ctx;
+
+	retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
+				    0, fix_dotdot_proc, &fp);
+	if (retval || !fp.done) {
+		clear_problem_context(&pctx);
+		pctx.ino = dir->ino;
+		pctx.errcode = retval;
+		fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
+			    PR_3_FIX_PARENT_NOFIND, &pctx);
+		ext2fs_unmark_valid(fs);
+	}
+	dir->dotdot = parent;
+
+	return;
+}
+
+/*
+ * These routines are responsible for expanding a /lost+found if it is
+ * too small.
+ */
+
+struct expand_dir_struct {
+	int                     num;
+	int                     guaranteed_size;
+	int                     newblocks;
+	int                     last_block;
+	errcode_t               err;
+	e2fsck_t                ctx;
+};
+
+static int expand_dir_proc(ext2_filsys fs,
+			   blk_t        *blocknr,
+			   e2_blkcnt_t  blockcnt,
+			   blk_t ref_block FSCK_ATTR((unused)),
+			   int ref_offset FSCK_ATTR((unused)),
+			   void *priv_data)
+{
+	struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
+	blk_t   new_blk;
+	static blk_t    last_blk = 0;
+	char            *block;
+	errcode_t       retval;
+	e2fsck_t        ctx;
+
+	ctx = es->ctx;
+
+	if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
+		return BLOCK_ABORT;
+
+	if (blockcnt > 0)
+		es->last_block = blockcnt;
+	if (*blocknr) {
+		last_blk = *blocknr;
+		return 0;
+	}
+	retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
+				  &new_blk);
+	if (retval) {
+		es->err = retval;
+		return BLOCK_ABORT;
+	}
+	if (blockcnt > 0) {
+		retval = ext2fs_new_dir_block(fs, 0, 0, &block);
+		if (retval) {
+			es->err = retval;
+			return BLOCK_ABORT;
+		}
+		es->num--;
+		retval = ext2fs_write_dir_block(fs, new_blk, block);
+	} else {
+		retval = ext2fs_get_mem(fs->blocksize, &block);
+		if (retval) {
+			es->err = retval;
+			return BLOCK_ABORT;
+		}
+		memset(block, 0, fs->blocksize);
+		retval = io_channel_write_blk(fs->io, new_blk, 1, block);
+	}
+	if (retval) {
+		es->err = retval;
+		return BLOCK_ABORT;
+	}
+	ext2fs_free_mem(&block);
+	*blocknr = new_blk;
+	ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
+	ext2fs_block_alloc_stats(fs, new_blk, +1);
+	es->newblocks++;
+
+	if (es->num == 0)
+		return (BLOCK_CHANGED | BLOCK_ABORT);
+	else
+		return BLOCK_CHANGED;
+}
+
+errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
+				  int num, int guaranteed_size)
+{
+	ext2_filsys fs = ctx->fs;
+	errcode_t       retval;
+	struct expand_dir_struct es;
+	struct ext2_inode       inode;
+
+	if (!(fs->flags & EXT2_FLAG_RW))
+		return EXT2_ET_RO_FILSYS;
+
+	/*
+	 * Read the inode and block bitmaps in; we'll be messing with
+	 * them.
+	 */
+	e2fsck_read_bitmaps(ctx);
+
+	retval = ext2fs_check_directory(fs, dir);
+	if (retval)
+		return retval;
+
+	es.num = num;
+	es.guaranteed_size = guaranteed_size;
+	es.last_block = 0;
+	es.err = 0;
+	es.newblocks = 0;
+	es.ctx = ctx;
+
+	retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
+				       0, expand_dir_proc, &es);
+
+	if (es.err)
+		return es.err;
+
+	/*
+	 * Update the size and block count fields in the inode.
+	 */
+	retval = ext2fs_read_inode(fs, dir, &inode);
+	if (retval)
+		return retval;
+
+	inode.i_size = (es.last_block + 1) * fs->blocksize;
+	inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
+
+	e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
+
+	return 0;
+}
+
+/*
+ * pass4.c -- pass #4 of e2fsck: Check reference counts
+ *
+ * Pass 4 frees the following data structures:
+ *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
+ */
+
+/*
+ * This routine is called when an inode is not connected to the
+ * directory tree.
+ *
+ * This subroutine returns 1 then the caller shouldn't bother with the
+ * rest of the pass 4 tests.
+ */
+static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
+{
+	ext2_filsys fs = ctx->fs;
+	struct ext2_inode       inode;
+	struct problem_context  pctx;
+
+	e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
+	clear_problem_context(&pctx);
+	pctx.ino = i;
+	pctx.inode = &inode;
+
+	/*
+	 * Offer to delete any zero-length files that does not have
+	 * blocks.  If there is an EA block, it might have useful
+	 * information, so we won't prompt to delete it, but let it be
+	 * reconnected to lost+found.
+	 */
+	if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
+				LINUX_S_ISDIR(inode.i_mode))) {
+		if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
+			ext2fs_icount_store(ctx->inode_link_info, i, 0);
+			inode.i_links_count = 0;
+			inode.i_dtime = time(0);
+			e2fsck_write_inode(ctx, i, &inode,
+					   "disconnect_inode");
+			/*
+			 * Fix up the bitmaps...
+			 */
+			e2fsck_read_bitmaps(ctx);
+			ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
+			ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
+			ext2fs_inode_alloc_stats2(fs, i, -1,
+						  LINUX_S_ISDIR(inode.i_mode));
+			return 0;
+		}
+	}
+
+	/*
+	 * Prompt to reconnect.
+	 */
+	if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
+		if (e2fsck_reconnect_file(ctx, i))
+			ext2fs_unmark_valid(fs);
+	} else {
+		/*
+		 * If we don't attach the inode, then skip the
+		 * i_links_test since there's no point in trying to
+		 * force i_links_count to zero.
+		 */
+		ext2fs_unmark_valid(fs);
+		return 1;
+	}
+	return 0;
+}
+
+
+static void e2fsck_pass4(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	ext2_ino_t      i;
+	struct ext2_inode       inode;
+	struct problem_context  pctx;
+	__u16   link_count, link_counted;
+	char    *buf = 0;
+	int     group, maxgroup;
+
+	/* Pass 4 */
+
+	clear_problem_context(&pctx);
+
+	if (!(ctx->options & E2F_OPT_PREEN))
+		fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
+
+	group = 0;
+	maxgroup = fs->group_desc_count;
+	if (ctx->progress)
+		if ((ctx->progress)(ctx, 4, 0, maxgroup))
+			return;
+
+	for (i=1; i <= fs->super->s_inodes_count; i++) {
+		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+			return;
+		if ((i % fs->super->s_inodes_per_group) == 0) {
+			group++;
+			if (ctx->progress)
+				if ((ctx->progress)(ctx, 4, group, maxgroup))
+					return;
+		}
+		if (i == EXT2_BAD_INO ||
+		    (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
+			continue;
+		if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
+		    (ctx->inode_imagic_map &&
+		     ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
+			continue;
+		ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
+		ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
+		if (link_counted == 0) {
+			if (!buf)
+				buf = e2fsck_allocate_memory(ctx,
+				     fs->blocksize, "bad_inode buffer");
+			if (e2fsck_process_bad_inode(ctx, 0, i, buf))
+				continue;
+			if (disconnect_inode(ctx, i))
+				continue;
+			ext2fs_icount_fetch(ctx->inode_link_info, i,
+					    &link_count);
+			ext2fs_icount_fetch(ctx->inode_count, i,
+					    &link_counted);
+		}
+		if (link_counted != link_count) {
+			e2fsck_read_inode(ctx, i, &inode, "pass4");
+			pctx.ino = i;
+			pctx.inode = &inode;
+			if (link_count != inode.i_links_count) {
+				pctx.num = link_count;
+				fix_problem(ctx,
+					    PR_4_INCONSISTENT_COUNT, &pctx);
+			}
+			pctx.num = link_counted;
+			if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
+				inode.i_links_count = link_counted;
+				e2fsck_write_inode(ctx, i, &inode, "pass4");
+			}
+		}
+	}
+	ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
+	ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
+	ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
+	ctx->inode_imagic_map = 0;
+	ext2fs_free_mem(&buf);
+}
+
+/*
+ * pass5.c --- check block and inode bitmaps against on-disk bitmaps
+ */
+
+#define NO_BLK ((blk_t) -1)
+
+static void print_bitmap_problem(e2fsck_t ctx, int problem,
+			    struct problem_context *pctx)
+{
+	switch (problem) {
+	case PR_5_BLOCK_UNUSED:
+		if (pctx->blk == pctx->blk2)
+			pctx->blk2 = 0;
+		else
+			problem = PR_5_BLOCK_RANGE_UNUSED;
+		break;
+	case PR_5_BLOCK_USED:
+		if (pctx->blk == pctx->blk2)
+			pctx->blk2 = 0;
+		else
+			problem = PR_5_BLOCK_RANGE_USED;
+		break;
+	case PR_5_INODE_UNUSED:
+		if (pctx->ino == pctx->ino2)
+			pctx->ino2 = 0;
+		else
+			problem = PR_5_INODE_RANGE_UNUSED;
+		break;
+	case PR_5_INODE_USED:
+		if (pctx->ino == pctx->ino2)
+			pctx->ino2 = 0;
+		else
+			problem = PR_5_INODE_RANGE_USED;
+		break;
+	}
+	fix_problem(ctx, problem, pctx);
+	pctx->blk = pctx->blk2 = NO_BLK;
+	pctx->ino = pctx->ino2 = 0;
+}
+
+static void check_block_bitmaps(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	blk_t   i;
+	int     *free_array;
+	int     group = 0;
+	unsigned int    blocks = 0;
+	unsigned int    free_blocks = 0;
+	int     group_free = 0;
+	int     actual, bitmap;
+	struct problem_context  pctx;
+	int     problem, save_problem, fixit, had_problem;
+	errcode_t       retval;
+
+	clear_problem_context(&pctx);
+	free_array = (int *) e2fsck_allocate_memory(ctx,
+	    fs->group_desc_count * sizeof(int), "free block count array");
+
+	if ((fs->super->s_first_data_block <
+	     ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
+	    (fs->super->s_blocks_count-1 >
+	     ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
+		pctx.num = 1;
+		pctx.blk = fs->super->s_first_data_block;
+		pctx.blk2 = fs->super->s_blocks_count -1;
+		pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
+		pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
+		fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
+
+		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
+		return;
+	}
+
+	if ((fs->super->s_first_data_block <
+	     ext2fs_get_block_bitmap_start(fs->block_map)) ||
+	    (fs->super->s_blocks_count-1 >
+	     ext2fs_get_block_bitmap_end(fs->block_map))) {
+		pctx.num = 2;
+		pctx.blk = fs->super->s_first_data_block;
+		pctx.blk2 = fs->super->s_blocks_count -1;
+		pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
+		pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
+		fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
+
+		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
+		return;
+	}
+
+redo_counts:
+	had_problem = 0;
+	save_problem = 0;
+	pctx.blk = pctx.blk2 = NO_BLK;
+	for (i = fs->super->s_first_data_block;
+	     i < fs->super->s_blocks_count;
+	     i++) {
+		actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
+		bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
+
+		if (actual == bitmap)
+			goto do_counts;
+
+		if (!actual && bitmap) {
+			/*
+			 * Block not used, but marked in use in the bitmap.
+			 */
+			problem = PR_5_BLOCK_UNUSED;
+		} else {
+			/*
+			 * Block used, but not marked in use in the bitmap.
+			 */
+			problem = PR_5_BLOCK_USED;
+		}
+		if (pctx.blk == NO_BLK) {
+			pctx.blk = pctx.blk2 = i;
+			save_problem = problem;
+		} else {
+			if ((problem == save_problem) &&
+			    (pctx.blk2 == i-1))
+				pctx.blk2++;
+			else {
+				print_bitmap_problem(ctx, save_problem, &pctx);
+				pctx.blk = pctx.blk2 = i;
+				save_problem = problem;
+			}
+		}
+		ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
+		had_problem++;
+
+	do_counts:
+		if (!bitmap) {
+			group_free++;
+			free_blocks++;
+		}
+		blocks ++;
+		if ((blocks == fs->super->s_blocks_per_group) ||
+		    (i == fs->super->s_blocks_count-1)) {
+			free_array[group] = group_free;
+			group ++;
+			blocks = 0;
+			group_free = 0;
+			if (ctx->progress)
+				if ((ctx->progress)(ctx, 5, group,
+						    fs->group_desc_count*2))
+					return;
+		}
+	}
+	if (pctx.blk != NO_BLK)
+		print_bitmap_problem(ctx, save_problem, &pctx);
+	if (had_problem)
+		fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
+	else
+		fixit = -1;
+	ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
+
+	if (fixit == 1) {
+		ext2fs_free_block_bitmap(fs->block_map);
+		retval = ext2fs_copy_bitmap(ctx->block_found_map,
+						  &fs->block_map);
+		if (retval) {
+			clear_problem_context(&pctx);
+			fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
+			ctx->flags |= E2F_FLAG_ABORT;
+			return;
+		}
+		ext2fs_set_bitmap_padding(fs->block_map);
+		ext2fs_mark_bb_dirty(fs);
+
+		/* Redo the counts */
+		blocks = 0; free_blocks = 0; group_free = 0; group = 0;
+		memset(free_array, 0, fs->group_desc_count * sizeof(int));
+		goto redo_counts;
+	} else if (fixit == 0)
+		ext2fs_unmark_valid(fs);
+
+	for (i = 0; i < fs->group_desc_count; i++) {
+		if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
+			pctx.group = i;
+			pctx.blk = fs->group_desc[i].bg_free_blocks_count;
+			pctx.blk2 = free_array[i];
+
+			if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
+					&pctx)) {
+				fs->group_desc[i].bg_free_blocks_count =
+					free_array[i];
+				ext2fs_mark_super_dirty(fs);
+			} else
+				ext2fs_unmark_valid(fs);
+		}
+	}
+	if (free_blocks != fs->super->s_free_blocks_count) {
+		pctx.group = 0;
+		pctx.blk = fs->super->s_free_blocks_count;
+		pctx.blk2 = free_blocks;
+
+		if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
+			fs->super->s_free_blocks_count = free_blocks;
+			ext2fs_mark_super_dirty(fs);
+		} else
+			ext2fs_unmark_valid(fs);
+	}
+	ext2fs_free_mem(&free_array);
+}
+
+static void check_inode_bitmaps(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	ext2_ino_t      i;
+	unsigned int    free_inodes = 0;
+	int             group_free = 0;
+	int             dirs_count = 0;
+	int             group = 0;
+	unsigned int    inodes = 0;
+	int             *free_array;
+	int             *dir_array;
+	int             actual, bitmap;
+	errcode_t       retval;
+	struct problem_context  pctx;
+	int             problem, save_problem, fixit, had_problem;
+
+	clear_problem_context(&pctx);
+	free_array = (int *) e2fsck_allocate_memory(ctx,
+	    fs->group_desc_count * sizeof(int), "free inode count array");
+
+	dir_array = (int *) e2fsck_allocate_memory(ctx,
+	   fs->group_desc_count * sizeof(int), "directory count array");
+
+	if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
+	    (fs->super->s_inodes_count >
+	     ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
+		pctx.num = 3;
+		pctx.blk = 1;
+		pctx.blk2 = fs->super->s_inodes_count;
+		pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
+		pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
+		fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
+
+		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
+		return;
+	}
+	if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
+	    (fs->super->s_inodes_count >
+	     ext2fs_get_inode_bitmap_end(fs->inode_map))) {
+		pctx.num = 4;
+		pctx.blk = 1;
+		pctx.blk2 = fs->super->s_inodes_count;
+		pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
+		pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
+		fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
+
+		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
+		return;
+	}
+
+redo_counts:
+	had_problem = 0;
+	save_problem = 0;
+	pctx.ino = pctx.ino2 = 0;
+	for (i = 1; i <= fs->super->s_inodes_count; i++) {
+		actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
+		bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
+
+		if (actual == bitmap)
+			goto do_counts;
+
+		if (!actual && bitmap) {
+			/*
+			 * Inode wasn't used, but marked in bitmap
+			 */
+			problem = PR_5_INODE_UNUSED;
+		} else /* if (actual && !bitmap) */ {
+			/*
+			 * Inode used, but not in bitmap
+			 */
+			problem = PR_5_INODE_USED;
+		}
+		if (pctx.ino == 0) {
+			pctx.ino = pctx.ino2 = i;
+			save_problem = problem;
+		} else {
+			if ((problem == save_problem) &&
+			    (pctx.ino2 == i-1))
+				pctx.ino2++;
+			else {
+				print_bitmap_problem(ctx, save_problem, &pctx);
+				pctx.ino = pctx.ino2 = i;
+				save_problem = problem;
+			}
+		}
+		ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
+		had_problem++;
+
+do_counts:
+		if (!bitmap) {
+			group_free++;
+			free_inodes++;
+		} else {
+			if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
+				dirs_count++;
+		}
+		inodes++;
+		if ((inodes == fs->super->s_inodes_per_group) ||
+		    (i == fs->super->s_inodes_count)) {
+			free_array[group] = group_free;
+			dir_array[group] = dirs_count;
+			group ++;
+			inodes = 0;
+			group_free = 0;
+			dirs_count = 0;
+			if (ctx->progress)
+				if ((ctx->progress)(ctx, 5,
+					    group + fs->group_desc_count,
+					    fs->group_desc_count*2))
+					return;
+		}
+	}
+	if (pctx.ino)
+		print_bitmap_problem(ctx, save_problem, &pctx);
+
+	if (had_problem)
+		fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
+	else
+		fixit = -1;
+	ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
+
+	if (fixit == 1) {
+		ext2fs_free_inode_bitmap(fs->inode_map);
+		retval = ext2fs_copy_bitmap(ctx->inode_used_map,
+						  &fs->inode_map);
+		if (retval) {
+			clear_problem_context(&pctx);
+			fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
+			ctx->flags |= E2F_FLAG_ABORT;
+			return;
+		}
+		ext2fs_set_bitmap_padding(fs->inode_map);
+		ext2fs_mark_ib_dirty(fs);
+
+		/* redo counts */
+		inodes = 0; free_inodes = 0; group_free = 0;
+		dirs_count = 0; group = 0;
+		memset(free_array, 0, fs->group_desc_count * sizeof(int));
+		memset(dir_array, 0, fs->group_desc_count * sizeof(int));
+		goto redo_counts;
+	} else if (fixit == 0)
+		ext2fs_unmark_valid(fs);
+
+	for (i = 0; i < fs->group_desc_count; i++) {
+		if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
+			pctx.group = i;
+			pctx.ino = fs->group_desc[i].bg_free_inodes_count;
+			pctx.ino2 = free_array[i];
+			if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
+					&pctx)) {
+				fs->group_desc[i].bg_free_inodes_count =
+					free_array[i];
+				ext2fs_mark_super_dirty(fs);
+			} else
+				ext2fs_unmark_valid(fs);
+		}
+		if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
+			pctx.group = i;
+			pctx.ino = fs->group_desc[i].bg_used_dirs_count;
+			pctx.ino2 = dir_array[i];
+
+			if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
+					&pctx)) {
+				fs->group_desc[i].bg_used_dirs_count =
+					dir_array[i];
+				ext2fs_mark_super_dirty(fs);
+			} else
+				ext2fs_unmark_valid(fs);
+		}
+	}
+	if (free_inodes != fs->super->s_free_inodes_count) {
+		pctx.group = -1;
+		pctx.ino = fs->super->s_free_inodes_count;
+		pctx.ino2 = free_inodes;
+
+		if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
+			fs->super->s_free_inodes_count = free_inodes;
+			ext2fs_mark_super_dirty(fs);
+		} else
+			ext2fs_unmark_valid(fs);
+	}
+	ext2fs_free_mem(&free_array);
+	ext2fs_free_mem(&dir_array);
+}
+
+static void check_inode_end(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	ext2_ino_t      end, save_inodes_count, i;
+	struct problem_context  pctx;
+
+	clear_problem_context(&pctx);
+
+	end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
+	pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
+						     &save_inodes_count);
+	if (pctx.errcode) {
+		pctx.num = 1;
+		fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
+		return;
+	}
+	if (save_inodes_count == end)
+		return;
+
+	for (i = save_inodes_count + 1; i <= end; i++) {
+		if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
+			if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
+				for (i = save_inodes_count + 1; i <= end; i++)
+					ext2fs_mark_inode_bitmap(fs->inode_map,
+								 i);
+				ext2fs_mark_ib_dirty(fs);
+			} else
+				ext2fs_unmark_valid(fs);
+			break;
+		}
+	}
+
+	pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
+						     save_inodes_count, 0);
+	if (pctx.errcode) {
+		pctx.num = 2;
+		fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
+		return;
+	}
+}
+
+static void check_block_end(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	blk_t   end, save_blocks_count, i;
+	struct problem_context  pctx;
+
+	clear_problem_context(&pctx);
+
+	end = fs->block_map->start +
+		(EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
+	pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
+						     &save_blocks_count);
+	if (pctx.errcode) {
+		pctx.num = 3;
+		fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
+		return;
+	}
+	if (save_blocks_count == end)
+		return;
+
+	for (i = save_blocks_count + 1; i <= end; i++) {
+		if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
+			if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
+				for (i = save_blocks_count + 1; i <= end; i++)
+					ext2fs_mark_block_bitmap(fs->block_map,
+								 i);
+				ext2fs_mark_bb_dirty(fs);
+			} else
+				ext2fs_unmark_valid(fs);
+			break;
+		}
+	}
+
+	pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
+						     save_blocks_count, 0);
+	if (pctx.errcode) {
+		pctx.num = 4;
+		fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
+		return;
+	}
+}
+
+static void e2fsck_pass5(e2fsck_t ctx)
+{
+	struct problem_context  pctx;
+
+	/* Pass 5 */
+
+	clear_problem_context(&pctx);
+
+	if (!(ctx->options & E2F_OPT_PREEN))
+		fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
+
+	if (ctx->progress)
+		if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
+			return;
+
+	e2fsck_read_bitmaps(ctx);
+
+	check_block_bitmaps(ctx);
+	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+		return;
+	check_inode_bitmaps(ctx);
+	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+		return;
+	check_inode_end(ctx);
+	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+		return;
+	check_block_end(ctx);
+	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+		return;
+
+	ext2fs_free_inode_bitmap(ctx->inode_used_map);
+	ctx->inode_used_map = 0;
+	ext2fs_free_inode_bitmap(ctx->inode_dir_map);
+	ctx->inode_dir_map = 0;
+	ext2fs_free_block_bitmap(ctx->block_found_map);
+	ctx->block_found_map = 0;
+}
+
+/*
+ * problem.c --- report filesystem problems to the user
+ */
+
+#define PR_PREEN_OK     0x000001 /* Don't need to do preenhalt */
+#define PR_NO_OK        0x000002 /* If user answers no, don't make fs invalid */
+#define PR_NO_DEFAULT   0x000004 /* Default to no */
+#define PR_MSG_ONLY     0x000008 /* Print message only */
+
+/* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
+
+#define PR_FATAL        0x001000 /* Fatal error */
+#define PR_AFTER_CODE   0x002000 /* After asking the first question, */
+				 /* ask another */
+#define PR_PREEN_NOMSG  0x004000 /* Don't print a message if we're preening */
+#define PR_NOCOLLATE    0x008000 /* Don't collate answers for this latch */
+#define PR_NO_NOMSG     0x010000 /* Don't print a message if e2fsck -n */
+#define PR_PREEN_NO     0x020000 /* Use No as an answer if preening */
+#define PR_PREEN_NOHDR  0x040000 /* Don't print the preen header */
+
+
+#define PROMPT_NONE     0
+#define PROMPT_FIX      1
+#define PROMPT_CLEAR    2
+#define PROMPT_RELOCATE 3
+#define PROMPT_ALLOCATE 4
+#define PROMPT_EXPAND   5
+#define PROMPT_CONNECT  6
+#define PROMPT_CREATE   7
+#define PROMPT_SALVAGE  8
+#define PROMPT_TRUNCATE 9
+#define PROMPT_CLEAR_INODE 10
+#define PROMPT_ABORT    11
+#define PROMPT_SPLIT    12
+#define PROMPT_CONTINUE 13
+#define PROMPT_CLONE    14
+#define PROMPT_DELETE   15
+#define PROMPT_SUPPRESS 16
+#define PROMPT_UNLINK   17
+#define PROMPT_CLEAR_HTREE 18
+#define PROMPT_RECREATE 19
+#define PROMPT_NULL     20
+
+struct e2fsck_problem {
+	problem_t       e2p_code;
+	const char *    e2p_description;
+	char            prompt;
+	int             flags;
+	problem_t       second_code;
+};
+
+struct latch_descr {
+	int             latch_code;
+	problem_t       question;
+	problem_t       end_message;
+	int             flags;
+};
+
+/*
+ * These are the prompts which are used to ask the user if they want
+ * to fix a problem.
+ */
+static const char * const prompt[] = {
+	N_("(no prompt)"),      /* 0 */
+	N_("Fix"),              /* 1 */
+	N_("Clear"),            /* 2 */
+	N_("Relocate"),         /* 3 */
+	N_("Allocate"),         /* 4 */
+	N_("Expand"),           /* 5 */
+	N_("Connect to /lost+found"), /* 6 */
+	N_("Create"),           /* 7 */
+	N_("Salvage"),          /* 8 */
+	N_("Truncate"),         /* 9 */
+	N_("Clear inode"),      /* 10 */
+	N_("Abort"),            /* 11 */
+	N_("Split"),            /* 12 */
+	N_("Continue"),         /* 13 */
+	N_("Clone multiply-claimed blocks"), /* 14 */
+	N_("Delete file"),      /* 15 */
+	N_("Suppress messages"),/* 16 */
+	N_("Unlink"),           /* 17 */
+	N_("Clear HTree index"),/* 18 */
+	N_("Recreate"),         /* 19 */
+	"",                     /* 20 */
+};
+
+/*
+ * These messages are printed when we are preen mode and we will be
+ * automatically fixing the problem.
+ */
+static const char * const preen_msg[] = {
+	N_("(NONE)"),           /* 0 */
+	N_("FIXED"),            /* 1 */
+	N_("CLEARED"),          /* 2 */
+	N_("RELOCATED"),        /* 3 */
+	N_("ALLOCATED"),        /* 4 */
+	N_("EXPANDED"),         /* 5 */
+	N_("RECONNECTED"),      /* 6 */
+	N_("CREATED"),          /* 7 */
+	N_("SALVAGED"),         /* 8 */
+	N_("TRUNCATED"),        /* 9 */
+	N_("INODE CLEARED"),    /* 10 */
+	N_("ABORTED"),          /* 11 */
+	N_("SPLIT"),            /* 12 */
+	N_("CONTINUING"),       /* 13 */
+	N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
+	N_("FILE DELETED"),     /* 15 */
+	N_("SUPPRESSED"),       /* 16 */
+	N_("UNLINKED"),         /* 17 */
+	N_("HTREE INDEX CLEARED"),/* 18 */
+	N_("WILL RECREATE"),    /* 19 */
+	"",                     /* 20 */
+};
+
+static const struct e2fsck_problem problem_table[] = {
+
+	/* Pre-Pass 1 errors */
+
+	/* Block bitmap not in group */
+	{ PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
+	  PROMPT_RELOCATE, PR_LATCH_RELOC },
+
+	/* Inode bitmap not in group */
+	{ PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
+	  PROMPT_RELOCATE, PR_LATCH_RELOC },
+
+	/* Inode table not in group */
+	{ PR_0_ITABLE_NOT_GROUP,
+	  N_("@i table for @g %g is not in @g.  (@b %b)\n"
+	  "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
+	  PROMPT_RELOCATE, PR_LATCH_RELOC },
+
+	/* Superblock corrupt */
+	{ PR_0_SB_CORRUPT,
+	  N_("\nThe @S could not be read or does not describe a correct ext2\n"
+	  "@f.  If the @v is valid and it really contains an ext2\n"
+	  "@f (and not swap or ufs or something else), then the @S\n"
+	  "is corrupt, and you might try running e2fsck with an alternate @S:\n"
+	  "    e2fsck -b %S <@v>\n\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Filesystem size is wrong */
+	{ PR_0_FS_SIZE_WRONG,
+	  N_("The @f size (according to the @S) is %b @bs\n"
+	  "The physical size of the @v is %c @bs\n"
+	  "Either the @S or the partition table is likely to be corrupt!\n"),
+	  PROMPT_ABORT, 0 },
+
+	/* Fragments not supported */
+	{ PR_0_NO_FRAGMENTS,
+	  N_("@S @b_size = %b, fragsize = %c.\n"
+	  "This version of e2fsck does not support fragment sizes different\n"
+	  "from the @b size.\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	  /* Bad blocks_per_group */
+	{ PR_0_BLOCKS_PER_GROUP,
+	  N_("@S @bs_per_group = %b, should have been %c\n"),
+	  PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
+
+	/* Bad first_data_block */
+	{ PR_0_FIRST_DATA_BLOCK,
+	  N_("@S first_data_ at b = %b, should have been %c\n"),
+	  PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
+
+	/* Adding UUID to filesystem */
+	{ PR_0_ADD_UUID,
+	  N_("@f did not have a UUID; generating one.\n\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Relocate hint */
+	{ PR_0_RELOCATE_HINT,
+	  N_("Note: if several inode or block bitmap blocks or part\n"
+	  "of the inode table require relocation, you may wish to try\n"
+	  "running e2fsck with the '-b %S' option first.  The problem\n"
+	  "may lie only with the primary block group descriptors, and\n"
+	  "the backup block group descriptors may be OK.\n\n"),
+	  PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
+
+	/* Miscellaneous superblock corruption */
+	{ PR_0_MISC_CORRUPT_SUPER,
+	  N_("Corruption found in @S.  (%s = %N).\n"),
+	  PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
+
+	/* Error determing physical device size of filesystem */
+	{ PR_0_GETSIZE_ERROR,
+	  N_("Error determining size of the physical @v: %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Inode count in superblock is incorrect */
+	{ PR_0_INODE_COUNT_WRONG,
+	  N_("@i count in @S is %i, @s %j.\n"),
+	  PROMPT_FIX, 0 },
+
+	{ PR_0_HURD_CLEAR_FILETYPE,
+	  N_("The Hurd does not support the filetype feature.\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* Journal inode is invalid */
+	{ PR_0_JOURNAL_BAD_INODE,
+	  N_("@S has an @n ext3 @j (@i %i).\n"),
+	  PROMPT_CLEAR, PR_PREEN_OK },
+
+	/* The external journal has (unsupported) multiple filesystems */
+	{ PR_0_JOURNAL_UNSUPP_MULTIFS,
+	  N_("External @j has multiple @f users (unsupported).\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Can't find external journal */
+	{ PR_0_CANT_FIND_JOURNAL,
+	  N_("Can't find external @j\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* External journal has bad superblock */
+	{ PR_0_EXT_JOURNAL_BAD_SUPER,
+	  N_("External @j has bad @S\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Superblock has a bad journal UUID */
+	{ PR_0_JOURNAL_BAD_UUID,
+	  N_("External @j does not support this @f\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Journal has an unknown superblock type */
+	{ PR_0_JOURNAL_UNSUPP_SUPER,
+	  N_("Ext3 @j @S is unknown type %N (unsupported).\n"
+	     "It is likely that your copy of e2fsck is old and/or doesn't "
+	     "support this @j format.\n"
+	     "It is also possible the @j @S is corrupt.\n"),
+	  PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
+
+	/* Journal superblock is corrupt */
+	{ PR_0_JOURNAL_BAD_SUPER,
+	  N_("Ext3 @j @S is corrupt.\n"),
+	  PROMPT_FIX, PR_PREEN_OK },
+
+	/* Superblock flag should be cleared */
+	{ PR_0_JOURNAL_HAS_JOURNAL,
+	  N_("@S doesn't have has_ at j flag, but has ext3 @j %s.\n"),
+	  PROMPT_CLEAR, PR_PREEN_OK },
+
+	/* Superblock flag is incorrect */
+	{ PR_0_JOURNAL_RECOVER_SET,
+	  N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
+	  PROMPT_CLEAR, PR_PREEN_OK },
+
+	/* Journal has data, but recovery flag is clear */
+	{ PR_0_JOURNAL_RECOVERY_CLEAR,
+	  N_("ext3 recovery flag is clear, but @j has data.\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Ask if we should clear the journal */
+	{ PR_0_JOURNAL_RESET_JOURNAL,
+	  N_("Clear @j"),
+	  PROMPT_NULL, PR_PREEN_NOMSG },
+
+	/* Ask if we should run the journal anyway */
+	{ PR_0_JOURNAL_RUN,
+	  N_("Run @j anyway"),
+	  PROMPT_NULL, 0 },
+
+	/* Run the journal by default */
+	{ PR_0_JOURNAL_RUN_DEFAULT,
+	  N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Clearing orphan inode */
+	{ PR_0_ORPHAN_CLEAR_INODE,
+	  N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Illegal block found in orphaned inode */
+	{ PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
+	   N_("@I @b #%B (%b) found in @o @i %i.\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Already cleared block found in orphaned inode */
+	{ PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
+	   N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Illegal orphan inode in superblock */
+	{ PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
+	  N_("@I @o @i %i in @S.\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Illegal inode in orphaned inode list */
+	{ PR_0_ORPHAN_ILLEGAL_INODE,
+	  N_("@I @i %i in @o @i list.\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Filesystem revision is 0, but feature flags are set */
+	{ PR_0_FS_REV_LEVEL,
+	  N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
+	  PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
+
+	/* Journal superblock has an unknown read-only feature flag set */
+	{ PR_0_JOURNAL_UNSUPP_ROCOMPAT,
+	  N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
+	  PROMPT_ABORT, 0 },
+
+	/* Journal superblock has an unknown incompatible feature flag set */
+	{ PR_0_JOURNAL_UNSUPP_INCOMPAT,
+	  N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
+	  PROMPT_ABORT, 0 },
+
+	/* Journal has unsupported version number */
+	{ PR_0_JOURNAL_UNSUPP_VERSION,
+	  N_("@j version not supported by this e2fsck.\n"),
+	  PROMPT_ABORT, 0 },
+
+	/* Moving journal to hidden file */
+	{ PR_0_MOVE_JOURNAL,
+	  N_("Moving @j from /%s to hidden @i.\n\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Error moving journal to hidden file */
+	{ PR_0_ERR_MOVE_JOURNAL,
+	  N_("Error moving @j: %m\n\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Clearing V2 journal superblock */
+	{ PR_0_CLEAR_V2_JOURNAL,
+	  N_("Found @n V2 @j @S fields (from V1 @j).\n"
+	     "Clearing fields beyond the V1 @j @S...\n\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Backup journal inode blocks */
+	{ PR_0_BACKUP_JNL,
+	  N_("Backing up @j @i @b information.\n\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Reserved blocks w/o resize_inode */
+	{ PR_0_NONZERO_RESERVED_GDT_BLOCKS,
+	  N_("@f does not have resize_ at i enabled, but s_reserved_gdt_ at bs\n"
+	     "is %N; @s zero.  "),
+	  PROMPT_FIX, 0 },
+
+	/* Resize_inode not enabled, but resize inode is non-zero */
+	{ PR_0_CLEAR_RESIZE_INODE,
+	  N_("Resize_ at i not enabled, but the resize @i is non-zero.  "),
+	  PROMPT_CLEAR, 0 },
+
+	/* Resize inode invalid */
+	{ PR_0_RESIZE_INODE_INVALID,
+	  N_("Resize @i not valid.  "),
+	  PROMPT_RECREATE, 0 },
+
+	/* Pass 1 errors */
+
+	/* Pass 1: Checking inodes, blocks, and sizes */
+	{ PR_1_PASS_HEADER,
+	  N_("Pass 1: Checking @is, @bs, and sizes\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Root directory is not an inode */
+	{ PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
+	  PROMPT_CLEAR, 0 },
+
+	/* Root directory has dtime set */
+	{ PR_1_ROOT_DTIME,
+	  N_("@r has dtime set (probably due to old mke2fs).  "),
+	  PROMPT_FIX, PR_PREEN_OK },
+
+	/* Reserved inode has bad mode */
+	{ PR_1_RESERVED_BAD_MODE,
+	  N_("Reserved @i %i (%Q) has @n mode.  "),
+	  PROMPT_CLEAR, PR_PREEN_OK },
+
+	/* Deleted inode has zero dtime */
+	{ PR_1_ZERO_DTIME,
+	  N_("@D @i %i has zero dtime.  "),
+	  PROMPT_FIX, PR_PREEN_OK },
+
+	/* Inode in use, but dtime set */
+	{ PR_1_SET_DTIME,
+	  N_("@i %i is in use, but has dtime set.  "),
+	  PROMPT_FIX, PR_PREEN_OK },
+
+	/* Zero-length directory */
+	{ PR_1_ZERO_LENGTH_DIR,
+	  N_("@i %i is a @z @d.  "),
+	  PROMPT_CLEAR, PR_PREEN_OK },
+
+	/* Block bitmap conflicts with some other fs block */
+	{ PR_1_BB_CONFLICT,
+	  N_("@g %g's @b @B at %b @C.\n"),
+	  PROMPT_RELOCATE, 0 },
+
+	/* Inode bitmap conflicts with some other fs block */
+	{ PR_1_IB_CONFLICT,
+	  N_("@g %g's @i @B at %b @C.\n"),
+	  PROMPT_RELOCATE, 0 },
+
+	/* Inode table conflicts with some other fs block */
+	{ PR_1_ITABLE_CONFLICT,
+	  N_("@g %g's @i table at %b @C.\n"),
+	  PROMPT_RELOCATE, 0 },
+
+	/* Block bitmap is on a bad block */
+	{ PR_1_BB_BAD_BLOCK,
+	  N_("@g %g's @b @B (%b) is bad.  "),
+	  PROMPT_RELOCATE, 0 },
+
+	/* Inode bitmap is on a bad block */
+	{ PR_1_IB_BAD_BLOCK,
+	  N_("@g %g's @i @B (%b) is bad.  "),
+	  PROMPT_RELOCATE, 0 },
+
+	/* Inode has incorrect i_size */
+	{ PR_1_BAD_I_SIZE,
+	  N_("@i %i, i_size is %Is, @s %N.  "),
+	  PROMPT_FIX, PR_PREEN_OK },
+
+	/* Inode has incorrect i_blocks */
+	{ PR_1_BAD_I_BLOCKS,
+	  N_("@i %i, i_ at bs is %Ib, @s %N.  "),
+	  PROMPT_FIX, PR_PREEN_OK },
+
+	/* Illegal blocknumber in inode */
+	{ PR_1_ILLEGAL_BLOCK_NUM,
+	  N_("@I @b #%B (%b) in @i %i.  "),
+	  PROMPT_CLEAR, PR_LATCH_BLOCK },
+
+	/* Block number overlaps fs metadata */
+	{ PR_1_BLOCK_OVERLAPS_METADATA,
+	  N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
+	  PROMPT_CLEAR, PR_LATCH_BLOCK },
+
+	/* Inode has illegal blocks (latch question) */
+	{ PR_1_INODE_BLOCK_LATCH,
+	  N_("@i %i has illegal @b(s).  "),
+	  PROMPT_CLEAR, 0 },
+
+	/* Too many bad blocks in inode */
+	{ PR_1_TOO_MANY_BAD_BLOCKS,
+	  N_("Too many illegal @bs in @i %i.\n"),
+	  PROMPT_CLEAR_INODE, PR_NO_OK },
+
+	/* Illegal block number in bad block inode */
+	{ PR_1_BB_ILLEGAL_BLOCK_NUM,
+	  N_("@I @b #%B (%b) in bad @b @i.  "),
+	  PROMPT_CLEAR, PR_LATCH_BBLOCK },
+
+	/* Bad block inode has illegal blocks (latch question) */
+	{ PR_1_INODE_BBLOCK_LATCH,
+	  N_("Bad @b @i has illegal @b(s).  "),
+	  PROMPT_CLEAR, 0 },
+
+	/* Duplicate or bad blocks in use! */
+	{ PR_1_DUP_BLOCKS_PREENSTOP,
+	  N_("Duplicate or bad @b in use!\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Bad block used as bad block indirect block */
+	{ PR_1_BBINODE_BAD_METABLOCK,
+	  N_("Bad @b %b used as bad @b @i indirect @b.  "),
+	  PROMPT_CLEAR, PR_LATCH_BBLOCK },
+
+	/* Inconsistency can't be fixed prompt */
+	{ PR_1_BBINODE_BAD_METABLOCK_PROMPT,
+	  N_("\nThe bad @b @i has probably been corrupted.  You probably\n"
+	     "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
+	     "in the @f.\n"),
+	  PROMPT_CONTINUE, PR_PREEN_NOMSG },
+
+	/* Bad primary block */
+	{ PR_1_BAD_PRIMARY_BLOCK,
+	  N_("\nIf the @b is really bad, the @f can not be fixed.\n"),
+	  PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
+
+	/* Bad primary block prompt */
+	{ PR_1_BAD_PRIMARY_BLOCK_PROMPT,
+	  N_("You can remove this @b from the bad @b list and hope\n"
+	     "that the @b is really OK.  But there are no guarantees.\n\n"),
+	  PROMPT_CLEAR, PR_PREEN_NOMSG },
+
+	/* Bad primary superblock */
+	{ PR_1_BAD_PRIMARY_SUPERBLOCK,
+	  N_("The primary @S (%b) is on the bad @b list.\n"),
+	  PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
+
+	/* Bad primary block group descriptors */
+	{ PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
+	  N_("Block %b in the primary @g descriptors "
+	  "is on the bad @b list\n"),
+	  PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
+
+	/* Bad superblock in group */
+	{ PR_1_BAD_SUPERBLOCK,
+	  N_("Warning: Group %g's @S (%b) is bad.\n"),
+	  PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Bad block group descriptors in group */
+	{ PR_1_BAD_GROUP_DESCRIPTORS,
+	  N_("Warning: Group %g's copy of the @g descriptors has a bad "
+	  "@b (%b).\n"),
+	  PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Block claimed for no reason */
+	{ PR_1_PROGERR_CLAIMED_BLOCK,
+	  N_("Programming error?  @b #%b claimed for no reason in "
+	  "process_bad_ at b.\n"),
+	  PROMPT_NONE, PR_PREEN_OK },
+
+	/* Error allocating blocks for relocating metadata */
+	{ PR_1_RELOC_BLOCK_ALLOCATE,
+	  N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
+	  PROMPT_NONE, PR_PREEN_OK },
+
+	/* Error allocating block buffer during relocation process */
+	{ PR_1_RELOC_MEMORY_ALLOCATE,
+	  N_("@A @b buffer for relocating %s\n"),
+	  PROMPT_NONE, PR_PREEN_OK },
+
+	/* Relocating metadata group information from X to Y */
+	{ PR_1_RELOC_FROM_TO,
+	  N_("Relocating @g %g's %s from %b to %c...\n"),
+	  PROMPT_NONE, PR_PREEN_OK },
+
+	/* Relocating metatdata group information to X */
+	{ PR_1_RELOC_TO,
+	  N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
+	  PROMPT_NONE, PR_PREEN_OK },
+
+	/* Block read error during relocation process */
+	{ PR_1_RELOC_READ_ERR,
+	  N_("Warning: could not read @b %b of %s: %m\n"),
+	  PROMPT_NONE, PR_PREEN_OK },
+
+	/* Block write error during relocation process */
+	{ PR_1_RELOC_WRITE_ERR,
+	  N_("Warning: could not write @b %b for %s: %m\n"),
+	  PROMPT_NONE, PR_PREEN_OK },
+
+	/* Error allocating inode bitmap */
+	{ PR_1_ALLOCATE_IBITMAP_ERROR,
+	  N_("@A @i @B (%N): %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error allocating block bitmap */
+	{ PR_1_ALLOCATE_BBITMAP_ERROR,
+	  N_("@A @b @B (%N): %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error allocating icount structure */
+	{ PR_1_ALLOCATE_ICOUNT,
+	  N_("@A icount link information: %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error allocating dbcount */
+	{ PR_1_ALLOCATE_DBCOUNT,
+	  N_("@A @d @b array: %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error while scanning inodes */
+	{ PR_1_ISCAN_ERROR,
+	  N_("Error while scanning @is (%i): %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error while iterating over blocks */
+	{ PR_1_BLOCK_ITERATE,
+	  N_("Error while iterating over @bs in @i %i: %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error while storing inode count information */
+	{ PR_1_ICOUNT_STORE,
+	  N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error while storing directory block information */
+	{ PR_1_ADD_DBLOCK,
+	  N_("Error storing @d @b information "
+	  "(@i=%i, @b=%b, num=%N): %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error while reading inode (for clearing) */
+	{ PR_1_READ_INODE,
+	  N_("Error reading @i %i: %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Suppress messages prompt */
+	{ PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
+
+	/* Imagic flag set on an inode when filesystem doesn't support it */
+	{ PR_1_SET_IMAGIC,
+	  N_("@i %i has imagic flag set.  "),
+	  PROMPT_CLEAR, 0 },
+
+	/* Immutable flag set on a device or socket inode */
+	{ PR_1_SET_IMMUTABLE,
+	  N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
+	     "or append-only flag set.  "),
+	  PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
+
+	/* Compression flag set on an inode when filesystem doesn't support it */
+	{ PR_1_COMPR_SET,
+	  N_("@i %i has @cion flag set on @f without @cion support.  "),
+	  PROMPT_CLEAR, 0 },
+
+	/* Non-zero size for device, fifo or socket inode */
+	{ PR_1_SET_NONZSIZE,
+	  N_("Special (@v/socket/fifo) @i %i has non-zero size.  "),
+	  PROMPT_FIX, PR_PREEN_OK },
+
+	/* Filesystem revision is 0, but feature flags are set */
+	{ PR_1_FS_REV_LEVEL,
+	  N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
+	  PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
+
+	/* Journal inode is not in use, but contains data */
+	{ PR_1_JOURNAL_INODE_NOT_CLEAR,
+	  N_("@j @i is not in use, but contains data.  "),
+	  PROMPT_CLEAR, PR_PREEN_OK },
+
+	/* Journal has bad mode */
+	{ PR_1_JOURNAL_BAD_MODE,
+	  N_("@j is not regular file.  "),
+	  PROMPT_FIX, PR_PREEN_OK },
+
+	/* Deal with inodes that were part of orphan linked list */
+	{ PR_1_LOW_DTIME,
+	  N_("@i %i was part of the @o @i list.  "),
+	  PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
+
+	/* Deal with inodes that were part of corrupted orphan linked
+	   list (latch question) */
+	{ PR_1_ORPHAN_LIST_REFUGEES,
+	  N_("@is that were part of a corrupted orphan linked list found.  "),
+	  PROMPT_FIX, 0 },
+
+	/* Error allocating refcount structure */
+	{ PR_1_ALLOCATE_REFCOUNT,
+	  N_("@A refcount structure (%N): %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error reading extended attribute block */
+	{ PR_1_READ_EA_BLOCK,
+	  N_("Error reading @a @b %b for @i %i.  "),
+	  PROMPT_CLEAR, 0 },
+
+	/* Invalid extended attribute block */
+	{ PR_1_BAD_EA_BLOCK,
+	  N_("@i %i has a bad @a @b %b.  "),
+	  PROMPT_CLEAR, 0 },
+
+	/* Error reading Extended Attribute block while fixing refcount */
+	{ PR_1_EXTATTR_READ_ABORT,
+	  N_("Error reading @a @b %b (%m).  "),
+	  PROMPT_ABORT, 0 },
+
+	/* Extended attribute reference count incorrect */
+	{ PR_1_EXTATTR_REFCOUNT,
+	  N_("@a @b %b has reference count %B, @s %N.  "),
+	  PROMPT_FIX, 0 },
+
+	/* Error writing Extended Attribute block while fixing refcount */
+	{ PR_1_EXTATTR_WRITE,
+	  N_("Error writing @a @b %b (%m).  "),
+	  PROMPT_ABORT, 0 },
+
+	/* Multiple EA blocks not supported */
+	{ PR_1_EA_MULTI_BLOCK,
+	  N_("@a @b %b has h_ at bs > 1.  "),
+	  PROMPT_CLEAR, 0},
+
+	/* Error allocating EA region allocation structure */
+	{ PR_1_EA_ALLOC_REGION,
+	  N_("@A @a @b %b.  "),
+	  PROMPT_ABORT, 0},
+
+	/* Error EA allocation collision */
+	{ PR_1_EA_ALLOC_COLLISION,
+	  N_("@a @b %b is corrupt (allocation collision).  "),
+	  PROMPT_CLEAR, 0},
+
+	/* Bad extended attribute name */
+	{ PR_1_EA_BAD_NAME,
+	  N_("@a @b %b is corrupt (@n name).  "),
+	  PROMPT_CLEAR, 0},
+
+	/* Bad extended attribute value */
+	{ PR_1_EA_BAD_VALUE,
+	  N_("@a @b %b is corrupt (@n value).  "),
+	  PROMPT_CLEAR, 0},
+
+	/* Inode too big (latch question) */
+	{ PR_1_INODE_TOOBIG,
+	  N_("@i %i is too big.  "), PROMPT_TRUNCATE, 0 },
+
+	/* Directory too big */
+	{ PR_1_TOOBIG_DIR,
+	  N_("@b #%B (%b) causes @d to be too big.  "),
+	  PROMPT_CLEAR, PR_LATCH_TOOBIG },
+
+	/* Regular file too big */
+	{ PR_1_TOOBIG_REG,
+	  N_("@b #%B (%b) causes file to be too big.  "),
+	  PROMPT_CLEAR, PR_LATCH_TOOBIG },
+
+	/* Symlink too big */
+	{ PR_1_TOOBIG_SYMLINK,
+	  N_("@b #%B (%b) causes symlink to be too big.  "),
+	  PROMPT_CLEAR, PR_LATCH_TOOBIG },
+
+	/* INDEX_FL flag set on a non-HTREE filesystem */
+	{ PR_1_HTREE_SET,
+	  N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
+	  PROMPT_CLEAR_HTREE, PR_PREEN_OK },
+
+	/* INDEX_FL flag set on a non-directory */
+	{ PR_1_HTREE_NODIR,
+	  N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
+	  PROMPT_CLEAR_HTREE, PR_PREEN_OK },
+
+	/* Invalid root node in HTREE directory */
+	{ PR_1_HTREE_BADROOT,
+	  N_("@h %i has an @n root node.\n"),
+	  PROMPT_CLEAR_HTREE, PR_PREEN_OK },
+
+	/* Unsupported hash version in HTREE directory */
+	{ PR_1_HTREE_HASHV,
+	  N_("@h %i has an unsupported hash version (%N)\n"),
+	  PROMPT_CLEAR_HTREE, PR_PREEN_OK },
+
+	/* Incompatible flag in HTREE root node */
+	{ PR_1_HTREE_INCOMPAT,
+	  N_("@h %i uses an incompatible htree root node flag.\n"),
+	  PROMPT_CLEAR_HTREE, PR_PREEN_OK },
+
+	/* HTREE too deep */
+	{ PR_1_HTREE_DEPTH,
+	  N_("@h %i has a tree depth (%N) which is too big\n"),
+	  PROMPT_CLEAR_HTREE, PR_PREEN_OK },
+
+	/* Bad block has indirect block that conflicts with filesystem block */
+	{ PR_1_BB_FS_BLOCK,
+	  N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
+	     "@f metadata.  "),
+	  PROMPT_CLEAR, PR_LATCH_BBLOCK },
+
+	/* Resize inode failed */
+	{ PR_1_RESIZE_INODE_CREATE,
+	  N_("Resize @i (re)creation failed: %m."),
+	  PROMPT_ABORT, 0 },
+
+	/* invalid inode->i_extra_isize */
+	{ PR_1_EXTRA_ISIZE,
+	  N_("@i %i has a extra size (%IS) which is @n\n"),
+	  PROMPT_FIX, PR_PREEN_OK },
+
+	/* invalid ea entry->e_name_len */
+	{ PR_1_ATTR_NAME_LEN,
+	  N_("@a in @i %i has a namelen (%N) which is @n\n"),
+	  PROMPT_CLEAR, PR_PREEN_OK },
+
+	/* invalid ea entry->e_value_size */
+	{ PR_1_ATTR_VALUE_SIZE,
+	  N_("@a in @i %i has a value size (%N) which is @n\n"),
+	  PROMPT_CLEAR, PR_PREEN_OK },
+
+	/* invalid ea entry->e_value_offs */
+	{ PR_1_ATTR_VALUE_OFFSET,
+	  N_("@a in @i %i has a value offset (%N) which is @n\n"),
+	  PROMPT_CLEAR, PR_PREEN_OK },
+
+	/* invalid ea entry->e_value_block */
+	{ PR_1_ATTR_VALUE_BLOCK,
+	  N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
+	  PROMPT_CLEAR, PR_PREEN_OK },
+
+	/* invalid ea entry->e_hash */
+	{ PR_1_ATTR_HASH,
+	  N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
+	  PROMPT_CLEAR, PR_PREEN_OK },
+
+	/* Pass 1b errors */
+
+	/* Pass 1B: Rescan for duplicate/bad blocks */
+	{ PR_1B_PASS_HEADER,
+	  N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
+	  "Pass 1B: Rescanning for @m @bs\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Duplicate/bad block(s) header */
+	{ PR_1B_DUP_BLOCK_HEADER,
+	  N_("@m @b(s) in @i %i:"),
+	  PROMPT_NONE, 0 },
+
+	/* Duplicate/bad block(s) in inode */
+	{ PR_1B_DUP_BLOCK,
+	  " %b",
+	  PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
+
+	/* Duplicate/bad block(s) end */
+	{ PR_1B_DUP_BLOCK_END,
+	  "\n",
+	  PROMPT_NONE, PR_PREEN_NOHDR },
+
+	/* Error while scanning inodes */
+	{ PR_1B_ISCAN_ERROR,
+	  N_("Error while scanning inodes (%i): %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error allocating inode bitmap */
+	{ PR_1B_ALLOCATE_IBITMAP_ERROR,
+	  N_("@A @i @B (@i_dup_map): %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error while iterating over blocks */
+	{ PR_1B_BLOCK_ITERATE,
+	  N_("Error while iterating over @bs in @i %i (%s): %m\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Error adjusting EA refcount */
+	{ PR_1B_ADJ_EA_REFCOUNT,
+	  N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
+	  PROMPT_NONE, 0 },
+
+
+	/* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
+	{ PR_1C_PASS_HEADER,
+	  N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
+	  PROMPT_NONE, 0 },
+
+
+	/* Pass 1D: Reconciling multiply-claimed blocks */
+	{ PR_1D_PASS_HEADER,
+	  N_("Pass 1D: Reconciling @m @bs\n"),
+	  PROMPT_NONE, 0 },
+
+	/* File has duplicate blocks */
+	{ PR_1D_DUP_FILE,
+	  N_("File %Q (@i #%i, mod time %IM) \n"
+	  "  has %B @m @b(s), shared with %N file(s):\n"),
+	  PROMPT_NONE, 0 },
+
+	/* List of files sharing duplicate blocks */
+	{ PR_1D_DUP_FILE_LIST,
+	  N_("\t%Q (@i #%i, mod time %IM)\n"),
+	  PROMPT_NONE, 0 },
+
+	/* File sharing blocks with filesystem metadata  */
+	{ PR_1D_SHARE_METADATA,
+	  N_("\t<@f metadata>\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Report of how many duplicate/bad inodes */
+	{ PR_1D_NUM_DUP_INODES,
+	  N_("(There are %N @is containing @m @bs.)\n\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Duplicated blocks already reassigned or cloned. */
+	{ PR_1D_DUP_BLOCKS_DEALT,
+	  N_("@m @bs already reassigned or cloned.\n\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Clone duplicate/bad blocks? */
+	{ PR_1D_CLONE_QUESTION,
+	  "", PROMPT_CLONE, PR_NO_OK },
+
+	/* Delete file? */
+	{ PR_1D_DELETE_QUESTION,
+	  "", PROMPT_DELETE, 0 },
+
+	/* Couldn't clone file (error) */
+	{ PR_1D_CLONE_ERROR,
+	  N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
+
+	/* Pass 2 errors */
+
+	/* Pass 2: Checking directory structure */
+	{ PR_2_PASS_HEADER,
+	  N_("Pass 2: Checking @d structure\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Bad inode number for '.' */
+	{ PR_2_BAD_INODE_DOT,
+	  N_("@n @i number for '.' in @d @i %i.\n"),
+	  PROMPT_FIX, 0 },
+
+	/* Directory entry has bad inode number */
+	{ PR_2_BAD_INO,
+	  N_("@E has @n @i #: %Di.\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* Directory entry has deleted or unused inode */
+	{ PR_2_UNUSED_INODE,
+	  N_("@E has @D/unused @i %Di.  "),
+	  PROMPT_CLEAR, PR_PREEN_OK },
+
+	/* Directry entry is link to '.' */
+	{ PR_2_LINK_DOT,
+	  N_("@E @L to '.'  "),
+	  PROMPT_CLEAR, 0 },
+
+	/* Directory entry points to inode now located in a bad block */
+	{ PR_2_BB_INODE,
+	  N_("@E points to @i (%Di) located in a bad @b.\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* Directory entry contains a link to a directory */
+	{ PR_2_LINK_DIR,
+	  N_("@E @L to @d %P (%Di).\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* Directory entry contains a link to the root directry */
+	{ PR_2_LINK_ROOT,
+	  N_("@E @L to the @r.\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* Directory entry has illegal characters in its name */
+	{ PR_2_BAD_NAME,
+	  N_("@E has illegal characters in its name.\n"),
+	  PROMPT_FIX, 0 },
+
+	/* Missing '.' in directory inode */
+	{ PR_2_MISSING_DOT,
+	  N_("Missing '.' in @d @i %i.\n"),
+	  PROMPT_FIX, 0 },
+
+	/* Missing '..' in directory inode */
+	{ PR_2_MISSING_DOT_DOT,
+	  N_("Missing '..' in @d @i %i.\n"),
+	  PROMPT_FIX, 0 },
+
+	/* First entry in directory inode doesn't contain '.' */
+	{ PR_2_1ST_NOT_DOT,
+	  N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
+	  PROMPT_FIX, 0 },
+
+	/* Second entry in directory inode doesn't contain '..' */
+	{ PR_2_2ND_NOT_DOT_DOT,
+	  N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
+	  PROMPT_FIX, 0 },
+
+	/* i_faddr should be zero */
+	{ PR_2_FADDR_ZERO,
+	  N_("i_faddr @F %IF, @s zero.\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* i_file_acl should be zero */
+	{ PR_2_FILE_ACL_ZERO,
+	  N_("i_file_acl @F %If, @s zero.\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* i_dir_acl should be zero */
+	{ PR_2_DIR_ACL_ZERO,
+	  N_("i_dir_acl @F %Id, @s zero.\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* i_frag should be zero */
+	{ PR_2_FRAG_ZERO,
+	  N_("i_frag @F %N, @s zero.\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* i_fsize should be zero */
+	{ PR_2_FSIZE_ZERO,
+	  N_("i_fsize @F %N, @s zero.\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* inode has bad mode */
+	{ PR_2_BAD_MODE,
+	  N_("@i %i (%Q) has @n mode (%Im).\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* directory corrupted */
+	{ PR_2_DIR_CORRUPTED,
+	  N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
+	  PROMPT_SALVAGE, 0 },
+
+	/* filename too long */
+	{ PR_2_FILENAME_LONG,
+	  N_("@d @i %i, @b %B, offset %N: filename too long\n"),
+	  PROMPT_TRUNCATE, 0 },
+
+	/* Directory inode has a missing block (hole) */
+	{ PR_2_DIRECTORY_HOLE,
+	  N_("@d @i %i has an unallocated @b #%B.  "),
+	  PROMPT_ALLOCATE, 0 },
+
+	/* '.' is not NULL terminated */
+	{ PR_2_DOT_NULL_TERM,
+	  N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
+	  PROMPT_FIX, 0 },
+
+	/* '..' is not NULL terminated */
+	{ PR_2_DOT_DOT_NULL_TERM,
+	  N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
+	  PROMPT_FIX, 0 },
+
+	/* Illegal character device inode */
+	{ PR_2_BAD_CHAR_DEV,
+	  N_("@i %i (%Q) is an @I character @v.\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* Illegal block device inode */
+	{ PR_2_BAD_BLOCK_DEV,
+	  N_("@i %i (%Q) is an @I @b @v.\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* Duplicate '.' entry */
+	{ PR_2_DUP_DOT,
+	  N_("@E is duplicate '.' @e.\n"),
+	  PROMPT_FIX, 0 },
+
+	/* Duplicate '..' entry */
+	{ PR_2_DUP_DOT_DOT,
+	  N_("@E is duplicate '..' @e.\n"),
+	  PROMPT_FIX, 0 },
+
+	/* Internal error: couldn't find dir_info */
+	{ PR_2_NO_DIRINFO,
+	  N_("Internal error: couldn't find dir_info for %i.\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Final rec_len is wrong */
+	{ PR_2_FINAL_RECLEN,
+	  N_("@E has rec_len of %Dr, @s %N.\n"),
+	  PROMPT_FIX, 0 },
+
+	/* Error allocating icount structure */
+	{ PR_2_ALLOCATE_ICOUNT,
+	  N_("@A icount structure: %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error iterating over directory blocks */
+	{ PR_2_DBLIST_ITERATE,
+	  N_("Error iterating over @d @bs: %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error reading directory block */
+	{ PR_2_READ_DIRBLOCK,
+	  N_("Error reading @d @b %b (@i %i): %m\n"),
+	  PROMPT_CONTINUE, 0 },
+
+	/* Error writing directory block */
+	{ PR_2_WRITE_DIRBLOCK,
+	  N_("Error writing @d @b %b (@i %i): %m\n"),
+	  PROMPT_CONTINUE, 0 },
+
+	/* Error allocating new directory block */
+	{ PR_2_ALLOC_DIRBOCK,
+	  N_("@A new @d @b for @i %i (%s): %m\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Error deallocating inode */
+	{ PR_2_DEALLOC_INODE,
+	  N_("Error deallocating @i %i: %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Directory entry for '.' is big.  Split? */
+	{ PR_2_SPLIT_DOT,
+	  N_("@d @e for '.' is big.  "),
+	  PROMPT_SPLIT, PR_NO_OK },
+
+	/* Illegal FIFO inode */
+	{ PR_2_BAD_FIFO,
+	  N_("@i %i (%Q) is an @I FIFO.\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* Illegal socket inode */
+	{ PR_2_BAD_SOCKET,
+	  N_("@i %i (%Q) is an @I socket.\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* Directory filetype not set */
+	{ PR_2_SET_FILETYPE,
+	  N_("Setting filetype for @E to %N.\n"),
+	  PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
+
+	/* Directory filetype incorrect */
+	{ PR_2_BAD_FILETYPE,
+	  N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
+	  PROMPT_FIX, 0 },
+
+	/* Directory filetype set on filesystem */
+	{ PR_2_CLEAR_FILETYPE,
+	  N_("@E has filetype set.\n"),
+	  PROMPT_CLEAR, PR_PREEN_OK },
+
+	/* Directory filename is null */
+	{ PR_2_NULL_NAME,
+	  N_("@E has a @z name.\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* Invalid symlink */
+	{ PR_2_INVALID_SYMLINK,
+	  N_("Symlink %Q (@i #%i) is @n.\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* i_file_acl (extended attribute block) is bad */
+	{ PR_2_FILE_ACL_BAD,
+	  N_("@a @b @F @n (%If).\n"),
+	  PROMPT_CLEAR, 0 },
+
+	/* Filesystem contains large files, but has no such flag in sb */
+	{ PR_2_FEATURE_LARGE_FILES,
+	  N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
+	  PROMPT_FIX, 0 },
+
+	/* Node in HTREE directory not referenced */
+	{ PR_2_HTREE_NOTREF,
+	  N_("@p @h %d: node (%B) not referenced\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Node in HTREE directory referenced twice */
+	{ PR_2_HTREE_DUPREF,
+	  N_("@p @h %d: node (%B) referenced twice\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Node in HTREE directory has bad min hash */
+	{ PR_2_HTREE_MIN_HASH,
+	  N_("@p @h %d: node (%B) has bad min hash\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Node in HTREE directory has bad max hash */
+	{ PR_2_HTREE_MAX_HASH,
+	  N_("@p @h %d: node (%B) has bad max hash\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Clear invalid HTREE directory */
+	{ PR_2_HTREE_CLEAR,
+	  N_("@n @h %d (%q).  "), PROMPT_CLEAR, 0 },
+
+	/* Bad block in htree interior node */
+	{ PR_2_HTREE_BADBLK,
+	  N_("@p @h %d (%q): bad @b number %b.\n"),
+	  PROMPT_CLEAR_HTREE, 0 },
+
+	/* Error adjusting EA refcount */
+	{ PR_2_ADJ_EA_REFCOUNT,
+	  N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Invalid HTREE root node */
+	{ PR_2_HTREE_BAD_ROOT,
+	  N_("@p @h %d: root node is @n\n"),
+	  PROMPT_CLEAR_HTREE, PR_PREEN_OK },
+
+	/* Invalid HTREE limit */
+	{ PR_2_HTREE_BAD_LIMIT,
+	  N_("@p @h %d: node (%B) has @n limit (%N)\n"),
+	  PROMPT_CLEAR_HTREE, PR_PREEN_OK },
+
+	/* Invalid HTREE count */
+	{ PR_2_HTREE_BAD_COUNT,
+	  N_("@p @h %d: node (%B) has @n count (%N)\n"),
+	  PROMPT_CLEAR_HTREE, PR_PREEN_OK },
+
+	/* HTREE interior node has out-of-order hashes in table */
+	{ PR_2_HTREE_HASH_ORDER,
+	  N_("@p @h %d: node (%B) has an unordered hash table\n"),
+	  PROMPT_CLEAR_HTREE, PR_PREEN_OK },
+
+	/* Node in HTREE directory has invalid depth */
+	{ PR_2_HTREE_BAD_DEPTH,
+	  N_("@p @h %d: node (%B) has @n depth\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Duplicate directory entry found */
+	{ PR_2_DUPLICATE_DIRENT,
+	  N_("Duplicate @E found.  "),
+	  PROMPT_CLEAR, 0 },
+
+	/* Non-unique filename found */
+	{ PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
+	  N_("@E has a non-unique filename.\nRename to %s"),
+	  PROMPT_NULL, 0 },
+
+	/* Duplicate directory entry found */
+	{ PR_2_REPORT_DUP_DIRENT,
+	  N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Pass 3 errors */
+
+	/* Pass 3: Checking directory connectivity */
+	{ PR_3_PASS_HEADER,
+	  N_("Pass 3: Checking @d connectivity\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Root inode not allocated */
+	{ PR_3_NO_ROOT_INODE,
+	  N_("@r not allocated.  "),
+	  PROMPT_ALLOCATE, 0 },
+
+	/* No room in lost+found */
+	{ PR_3_EXPAND_LF_DIR,
+	  N_("No room in @l @d.  "),
+	  PROMPT_EXPAND, 0 },
+
+	/* Unconnected directory inode */
+	{ PR_3_UNCONNECTED_DIR,
+	  N_("Unconnected @d @i %i (%p)\n"),
+	  PROMPT_CONNECT, 0 },
+
+	/* /lost+found not found */
+	{ PR_3_NO_LF_DIR,
+	  N_("/@l not found.  "),
+	  PROMPT_CREATE, PR_PREEN_OK },
+
+	/* .. entry is incorrect */
+	{ PR_3_BAD_DOT_DOT,
+	  N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
+	  PROMPT_FIX, 0 },
+
+	/* Bad or non-existent /lost+found.  Cannot reconnect */
+	{ PR_3_NO_LPF,
+	  N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Could not expand /lost+found */
+	{ PR_3_CANT_EXPAND_LPF,
+	  N_("Could not expand /@l: %m\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Could not reconnect inode */
+	{ PR_3_CANT_RECONNECT,
+	  N_("Could not reconnect %i: %m\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Error while trying to find /lost+found */
+	{ PR_3_ERR_FIND_LPF,
+	  N_("Error while trying to find /@l: %m\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Error in ext2fs_new_block while creating /lost+found */
+	{ PR_3_ERR_LPF_NEW_BLOCK,
+	  N_("ext2fs_new_ at b: %m while trying to create /@l @d\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Error in ext2fs_new_inode while creating /lost+found */
+	{ PR_3_ERR_LPF_NEW_INODE,
+	  N_("ext2fs_new_ at i: %m while trying to create /@l @d\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Error in ext2fs_new_dir_block while creating /lost+found */
+	{ PR_3_ERR_LPF_NEW_DIR_BLOCK,
+	  N_("ext2fs_new_dir_ at b: %m while creating new @d @b\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Error while writing directory block for /lost+found */
+	{ PR_3_ERR_LPF_WRITE_BLOCK,
+	  N_("ext2fs_write_dir_ at b: %m while writing the @d @b for /@l\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Error while adjusting inode count */
+	{ PR_3_ADJUST_INODE,
+	  N_("Error while adjusting @i count on @i %i\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Couldn't fix parent directory -- error */
+	{ PR_3_FIX_PARENT_ERR,
+	  N_("Couldn't fix parent of @i %i: %m\n\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Couldn't fix parent directory -- couldn't find it */
+	{ PR_3_FIX_PARENT_NOFIND,
+	  N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Error allocating inode bitmap */
+	{ PR_3_ALLOCATE_IBITMAP_ERROR,
+	  N_("@A @i @B (%N): %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error creating root directory */
+	{ PR_3_CREATE_ROOT_ERROR,
+	  N_("Error creating root @d (%s): %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error creating lost and found directory */
+	{ PR_3_CREATE_LPF_ERROR,
+	  N_("Error creating /@l @d (%s): %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Root inode is not directory; aborting */
+	{ PR_3_ROOT_NOT_DIR_ABORT,
+	  N_("@r is not a @d; aborting.\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Cannot proceed without a root inode. */
+	{ PR_3_NO_ROOT_INODE_ABORT,
+	  N_("Cannot proceed without a @r.\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Internal error: couldn't find dir_info */
+	{ PR_3_NO_DIRINFO,
+	  N_("Internal error: couldn't find dir_info for %i.\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Lost+found not a directory */
+	{ PR_3_LPF_NOTDIR,
+	  N_("/@l is not a @d (ino=%i)\n"),
+	  PROMPT_UNLINK, 0 },
+
+	/* Pass 3A Directory Optimization       */
+
+	/* Pass 3A: Optimizing directories */
+	{ PR_3A_PASS_HEADER,
+	  N_("Pass 3A: Optimizing directories\n"),
+	  PROMPT_NONE, PR_PREEN_NOMSG },
+
+	/* Error iterating over directories */
+	{ PR_3A_OPTIMIZE_ITER,
+	  N_("Failed to create dirs_to_hash iterator: %m"),
+	  PROMPT_NONE, 0 },
+
+	/* Error rehash directory */
+	{ PR_3A_OPTIMIZE_DIR_ERR,
+	  N_("Failed to optimize directory %q (%d): %m"),
+	  PROMPT_NONE, 0 },
+
+	/* Rehashing dir header */
+	{ PR_3A_OPTIMIZE_DIR_HEADER,
+	  N_("Optimizing directories: "),
+	  PROMPT_NONE, PR_MSG_ONLY },
+
+	/* Rehashing directory %d */
+	{ PR_3A_OPTIMIZE_DIR,
+	  " %d",
+	  PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
+
+	/* Rehashing dir end */
+	{ PR_3A_OPTIMIZE_DIR_END,
+	  "\n",
+	  PROMPT_NONE, PR_PREEN_NOHDR },
+
+	/* Pass 4 errors */
+
+	/* Pass 4: Checking reference counts */
+	{ PR_4_PASS_HEADER,
+	  N_("Pass 4: Checking reference counts\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Unattached zero-length inode */
+	{ PR_4_ZERO_LEN_INODE,
+	  N_("@u @z @i %i.  "),
+	  PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
+
+	/* Unattached inode */
+	{ PR_4_UNATTACHED_INODE,
+	  N_("@u @i %i\n"),
+	  PROMPT_CONNECT, 0 },
+
+	/* Inode ref count wrong */
+	{ PR_4_BAD_REF_COUNT,
+	  N_("@i %i ref count is %Il, @s %N.  "),
+	  PROMPT_FIX, PR_PREEN_OK },
+
+	{ PR_4_INCONSISTENT_COUNT,
+	  N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
+	  "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
+	  "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
+	  "They @s the same!\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Pass 5 errors */
+
+	/* Pass 5: Checking group summary information */
+	{ PR_5_PASS_HEADER,
+	  N_("Pass 5: Checking @g summary information\n"),
+	  PROMPT_NONE, 0 },
+
+	/* Padding at end of inode bitmap is not set. */
+	{ PR_5_INODE_BMAP_PADDING,
+	  N_("Padding at end of @i @B is not set. "),
+	  PROMPT_FIX, PR_PREEN_OK },
+
+	/* Padding at end of block bitmap is not set. */
+	{ PR_5_BLOCK_BMAP_PADDING,
+	  N_("Padding at end of @b @B is not set. "),
+	  PROMPT_FIX, PR_PREEN_OK },
+
+	/* Block bitmap differences header */
+	{ PR_5_BLOCK_BITMAP_HEADER,
+	  N_("@b @B differences: "),
+	  PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
+
+	/* Block not used, but marked in bitmap */
+	{ PR_5_BLOCK_UNUSED,
+	  " -%b",
+	  PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Block used, but not marked used in bitmap */
+	{ PR_5_BLOCK_USED,
+	  " +%b",
+	  PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Block bitmap differences end */
+	{ PR_5_BLOCK_BITMAP_END,
+	  "\n",
+	  PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Inode bitmap differences header */
+	{ PR_5_INODE_BITMAP_HEADER,
+	  N_("@i @B differences: "),
+	  PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Inode not used, but marked in bitmap */
+	{ PR_5_INODE_UNUSED,
+	  " -%i",
+	  PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Inode used, but not marked used in bitmap */
+	{ PR_5_INODE_USED,
+	  " +%i",
+	  PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Inode bitmap differences end */
+	{ PR_5_INODE_BITMAP_END,
+	  "\n",
+	  PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Free inodes count for group wrong */
+	{ PR_5_FREE_INODE_COUNT_GROUP,
+	  N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
+	  PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Directories count for group wrong */
+	{ PR_5_FREE_DIR_COUNT_GROUP,
+	  N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
+	  PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Free inodes count wrong */
+	{ PR_5_FREE_INODE_COUNT,
+	  N_("Free @is count wrong (%i, counted=%j).\n"),
+	  PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Free blocks count for group wrong */
+	{ PR_5_FREE_BLOCK_COUNT_GROUP,
+	  N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
+	  PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Free blocks count wrong */
+	{ PR_5_FREE_BLOCK_COUNT,
+	  N_("Free @bs count wrong (%b, counted=%c).\n"),
+	  PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Programming error: bitmap endpoints don't match */
+	{ PR_5_BMAP_ENDPOINTS,
+	  N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
+	  "match calculated @B endpoints (%i, %j)\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Internal error: fudging end of bitmap */
+	{ PR_5_FUDGE_BITMAP_ERROR,
+	  N_("Internal error: fudging end of bitmap (%N)\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error copying in replacement inode bitmap */
+	{ PR_5_COPY_IBITMAP_ERROR,
+	  N_("Error copying in replacement @i @B: %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Error copying in replacement block bitmap */
+	{ PR_5_COPY_BBITMAP_ERROR,
+	  N_("Error copying in replacement @b @B: %m\n"),
+	  PROMPT_NONE, PR_FATAL },
+
+	/* Block range not used, but marked in bitmap */
+	{ PR_5_BLOCK_RANGE_UNUSED,
+	  " -(%b--%c)",
+	  PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Block range used, but not marked used in bitmap */
+	{ PR_5_BLOCK_RANGE_USED,
+	  " +(%b--%c)",
+	  PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Inode range not used, but marked in bitmap */
+	{ PR_5_INODE_RANGE_UNUSED,
+	  " -(%i--%j)",
+	  PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	/* Inode range used, but not marked used in bitmap */
+	{ PR_5_INODE_RANGE_USED,
+	  " +(%i--%j)",
+	  PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
+
+	{ 0 }
+};
+
+/*
+ * This is the latch flags register.  It allows several problems to be
+ * "latched" together.  This means that the user has to answer but one
+ * question for the set of problems, and all of the associated
+ * problems will be either fixed or not fixed.
+ */
+static struct latch_descr pr_latch_info[] = {
+	{ PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
+	{ PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
+	{ PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
+	{ PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
+	{ PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
+	{ PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
+	{ PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
+	{ PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
+	{ PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
+	{ -1, 0, 0 },
+};
+
+static const struct e2fsck_problem *find_problem(problem_t code)
+{
+	int     i;
+
+	for (i=0; problem_table[i].e2p_code; i++) {
+		if (problem_table[i].e2p_code == code)
+			return &problem_table[i];
+	}
+	return 0;
+}
+
+static struct latch_descr *find_latch(int code)
+{
+	int     i;
+
+	for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
+		if (pr_latch_info[i].latch_code == code)
+			return &pr_latch_info[i];
+	}
+	return 0;
+}
+
+int end_problem_latch(e2fsck_t ctx, int mask)
+{
+	struct latch_descr *ldesc;
+	struct problem_context pctx;
+	int answer = -1;
+
+	ldesc = find_latch(mask);
+	if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
+		clear_problem_context(&pctx);
+		answer = fix_problem(ctx, ldesc->end_message, &pctx);
+	}
+	ldesc->flags &= ~(PRL_VARIABLE);
+	return answer;
+}
+
+int set_latch_flags(int mask, int setflags, int clearflags)
+{
+	struct latch_descr *ldesc;
+
+	ldesc = find_latch(mask);
+	if (!ldesc)
+		return -1;
+	ldesc->flags |= setflags;
+	ldesc->flags &= ~clearflags;
+	return 0;
+}
+
+void clear_problem_context(struct problem_context *ctx)
+{
+	memset(ctx, 0, sizeof(struct problem_context));
+	ctx->blkcount = -1;
+	ctx->group = -1;
+}
+
+int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
+{
+	ext2_filsys fs = ctx->fs;
+	const struct e2fsck_problem *ptr;
+	struct latch_descr *ldesc = 0;
+	const char *message;
+	int             def_yn, answer, ans;
+	int             print_answer = 0;
+	int             suppress = 0;
+
+	ptr = find_problem(code);
+	if (!ptr) {
+		printf(_("Unhandled error code (0x%x)!\n"), code);
+		return 0;
+	}
+	def_yn = 1;
+	if ((ptr->flags & PR_NO_DEFAULT) ||
+	    ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
+	    (ctx->options & E2F_OPT_NO))
+		def_yn= 0;
+
+	/*
+	 * Do special latch processing.  This is where we ask the
+	 * latch question, if it exists
+	 */
+	if (ptr->flags & PR_LATCH_MASK) {
+		ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
+		if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
+			ans = fix_problem(ctx, ldesc->question, pctx);
+			if (ans == 1)
+				ldesc->flags |= PRL_YES;
+			if (ans == 0)
+				ldesc->flags |= PRL_NO;
+			ldesc->flags |= PRL_LATCHED;
+		}
+		if (ldesc->flags & PRL_SUPPRESS)
+			suppress++;
+	}
+	if ((ptr->flags & PR_PREEN_NOMSG) &&
+	    (ctx->options & E2F_OPT_PREEN))
+		suppress++;
+	if ((ptr->flags & PR_NO_NOMSG) &&
+	    (ctx->options & E2F_OPT_NO))
+		suppress++;
+	if (!suppress) {
+		message = ptr->e2p_description;
+		if ((ctx->options & E2F_OPT_PREEN) &&
+		    !(ptr->flags & PR_PREEN_NOHDR)) {
+			printf("%s: ", ctx->device_name ?
+			       ctx->device_name : ctx->filesystem_name);
+		}
+		if (*message)
+			print_e2fsck_message(ctx, _(message), pctx, 1);
+	}
+	if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
+		preenhalt(ctx);
+
+	if (ptr->flags & PR_FATAL)
+		bb_error_msg_and_die(0);
+
+	if (ptr->prompt == PROMPT_NONE) {
+		if (ptr->flags & PR_NOCOLLATE)
+			answer = -1;
+		else
+			answer = def_yn;
+	} else {
+		if (ctx->options & E2F_OPT_PREEN) {
+			answer = def_yn;
+			if (!(ptr->flags & PR_PREEN_NOMSG))
+				print_answer = 1;
+		} else if ((ptr->flags & PR_LATCH_MASK) &&
+			   (ldesc->flags & (PRL_YES | PRL_NO))) {
+			if (!suppress)
+				print_answer = 1;
+			if (ldesc->flags & PRL_YES)
+				answer = 1;
+			else
+				answer = 0;
+		} else
+			answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
+		if (!answer && !(ptr->flags & PR_NO_OK))
+			ext2fs_unmark_valid(fs);
+
+		if (print_answer)
+			printf("%s.\n", answer ?
+			       _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
+
+	}
+
+	if ((ptr->prompt == PROMPT_ABORT) && answer)
+		bb_error_msg_and_die(0);
+
+	if (ptr->flags & PR_AFTER_CODE)
+		answer = fix_problem(ctx, ptr->second_code, pctx);
+
+	return answer;
+}
+
+/*
+ * linux/fs/recovery.c
+ *
+ * Written by Stephen C. Tweedie <sct at redhat.com>, 1999
+ */
+
+/*
+ * Maintain information about the progress of the recovery job, so that
+ * the different passes can carry information between them.
+ */
+struct recovery_info
+{
+	tid_t           start_transaction;
+	tid_t           end_transaction;
+
+	int             nr_replays;
+	int             nr_revokes;
+	int             nr_revoke_hits;
+};
+
+enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
+static int do_one_pass(journal_t *journal,
+				struct recovery_info *info, enum passtype pass);
+static int scan_revoke_records(journal_t *, struct buffer_head *,
+				tid_t, struct recovery_info *);
+
+/*
+ * Read a block from the journal
+ */
+
+static int jread(struct buffer_head **bhp, journal_t *journal,
+		 unsigned int offset)
+{
+	int err;
+	unsigned long blocknr;
+	struct buffer_head *bh;
+
+	*bhp = NULL;
+
+	err = journal_bmap(journal, offset, &blocknr);
+
+	if (err) {
+		printf ("JBD: bad block at offset %u\n", offset);
+		return err;
+	}
+
+	bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
+	if (!bh)
+		return -ENOMEM;
+
+	if (!buffer_uptodate(bh)) {
+		/* If this is a brand new buffer, start readahead.
+		   Otherwise, we assume we are already reading it.  */
+		if (!buffer_req(bh))
+			do_readahead(journal, offset);
+		wait_on_buffer(bh);
+	}
+
+	if (!buffer_uptodate(bh)) {
+		printf ("JBD: Failed to read block at offset %u\n", offset);
+		brelse(bh);
+		return -EIO;
+	}
+
+	*bhp = bh;
+	return 0;
+}
+
+
+/*
+ * Count the number of in-use tags in a journal descriptor block.
+ */
+
+static int count_tags(struct buffer_head *bh, int size)
+{
+	char *                  tagp;
+	journal_block_tag_t *   tag;
+	int                     nr = 0;
+
+	tagp = &bh->b_data[sizeof(journal_header_t)];
+
+	while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
+		tag = (journal_block_tag_t *) tagp;
+
+		nr++;
+		tagp += sizeof(journal_block_tag_t);
+		if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
+			tagp += 16;
+
+		if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
+			break;
+	}
+
+	return nr;
+}
+
+
+/* Make sure we wrap around the log correctly! */
+#define wrap(journal, var)					      \
+do {					                            \
+	if (var >= (journal)->j_last)                                   \
+		var -= ((journal)->j_last - (journal)->j_first);        \
+} while (0)
+
+/**
+ * int journal_recover(journal_t *journal) - recovers a on-disk journal
+ * @journal: the journal to recover
+ *
+ * The primary function for recovering the log contents when mounting a
+ * journaled device.
+ *
+ * Recovery is done in three passes.  In the first pass, we look for the
+ * end of the log.  In the second, we assemble the list of revoke
+ * blocks.  In the third and final pass, we replay any un-revoked blocks
+ * in the log.
+ */
+int journal_recover(journal_t *journal)
+{
+	int                     err;
+	journal_superblock_t *  sb;
+
+	struct recovery_info    info;
+
+	memset(&info, 0, sizeof(info));
+	sb = journal->j_superblock;
+
+	/*
+	 * The journal superblock's s_start field (the current log head)
+	 * is always zero if, and only if, the journal was cleanly
+	 * unmounted.
+	 */
+
+	if (!sb->s_start) {
+		journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
+		return 0;
+	}
+
+	err = do_one_pass(journal, &info, PASS_SCAN);
+	if (!err)
+		err = do_one_pass(journal, &info, PASS_REVOKE);
+	if (!err)
+		err = do_one_pass(journal, &info, PASS_REPLAY);
+
+	/* Restart the log at the next transaction ID, thus invalidating
+	 * any existing commit records in the log. */
+	journal->j_transaction_sequence = ++info.end_transaction;
+
+	journal_clear_revoke(journal);
+	sync_blockdev(journal->j_fs_dev);
+	return err;
+}
+
+static int do_one_pass(journal_t *journal,
+			struct recovery_info *info, enum passtype pass)
+{
+	unsigned int            first_commit_ID, next_commit_ID;
+	unsigned long           next_log_block;
+	int                     err, success = 0;
+	journal_superblock_t *  sb;
+	journal_header_t *      tmp;
+	struct buffer_head *    bh;
+	unsigned int            sequence;
+	int                     blocktype;
+
+	/* Precompute the maximum metadata descriptors in a descriptor block */
+	int                     MAX_BLOCKS_PER_DESC;
+	MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
+			       / sizeof(journal_block_tag_t));
+
+	/*
+	 * First thing is to establish what we expect to find in the log
+	 * (in terms of transaction IDs), and where (in terms of log
+	 * block offsets): query the superblock.
+	 */
+
+	sb = journal->j_superblock;
+	next_commit_ID = ntohl(sb->s_sequence);
+	next_log_block = ntohl(sb->s_start);
+
+	first_commit_ID = next_commit_ID;
+	if (pass == PASS_SCAN)
+		info->start_transaction = first_commit_ID;
+
+	/*
+	 * Now we walk through the log, transaction by transaction,
+	 * making sure that each transaction has a commit block in the
+	 * expected place.  Each complete transaction gets replayed back
+	 * into the main filesystem.
+	 */
+
+	while (1) {
+		int                     flags;
+		char *                  tagp;
+		journal_block_tag_t *   tag;
+		struct buffer_head *    obh;
+		struct buffer_head *    nbh;
+
+		/* If we already know where to stop the log traversal,
+		 * check right now that we haven't gone past the end of
+		 * the log. */
+
+		if (pass != PASS_SCAN)
+			if (tid_geq(next_commit_ID, info->end_transaction))
+				break;
+
+		/* Skip over each chunk of the transaction looking
+		 * either the next descriptor block or the final commit
+		 * record. */
+
+		err = jread(&bh, journal, next_log_block);
+		if (err)
+			goto failed;
+
+		next_log_block++;
+		wrap(journal, next_log_block);
+
+		/* What kind of buffer is it?
+		 *
+		 * If it is a descriptor block, check that it has the
+		 * expected sequence number.  Otherwise, we're all done
+		 * here. */
+
+		tmp = (journal_header_t *)bh->b_data;
+
+		if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
+			brelse(bh);
+			break;
+		}
+
+		blocktype = ntohl(tmp->h_blocktype);
+		sequence = ntohl(tmp->h_sequence);
+
+		if (sequence != next_commit_ID) {
+			brelse(bh);
+			break;
+		}
+
+		/* OK, we have a valid descriptor block which matches
+		 * all of the sequence number checks.  What are we going
+		 * to do with it?  That depends on the pass... */
+
+		switch(blocktype) {
+		case JFS_DESCRIPTOR_BLOCK:
+			/* If it is a valid descriptor block, replay it
+			 * in pass REPLAY; otherwise, just skip over the
+			 * blocks it describes. */
+			if (pass != PASS_REPLAY) {
+				next_log_block +=
+					count_tags(bh, journal->j_blocksize);
+				wrap(journal, next_log_block);
+				brelse(bh);
+				continue;
+			}
+
+			/* A descriptor block: we can now write all of
+			 * the data blocks.  Yay, useful work is finally
+			 * getting done here! */
+
+			tagp = &bh->b_data[sizeof(journal_header_t)];
+			while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
+			       <= journal->j_blocksize) {
+				unsigned long io_block;
+
+				tag = (journal_block_tag_t *) tagp;
+				flags = ntohl(tag->t_flags);
+
+				io_block = next_log_block++;
+				wrap(journal, next_log_block);
+				err = jread(&obh, journal, io_block);
+				if (err) {
+					/* Recover what we can, but
+					 * report failure at the end. */
+					success = err;
+					printf ("JBD: IO error %d recovering "
+						"block %ld in log\n",
+						err, io_block);
+				} else {
+					unsigned long blocknr;
+
+					blocknr = ntohl(tag->t_blocknr);
+
+					/* If the block has been
+					 * revoked, then we're all done
+					 * here. */
+					if (journal_test_revoke
+					    (journal, blocknr,
+					     next_commit_ID)) {
+						brelse(obh);
+						++info->nr_revoke_hits;
+						goto skip_write;
+					}
+
+					/* Find a buffer for the new
+					 * data being restored */
+					nbh = getblk(journal->j_fs_dev,
+						       blocknr,
+						     journal->j_blocksize);
+					if (nbh == NULL) {
+						printf ("JBD: Out of memory "
+						       "during recovery.\n");
+						err = -ENOMEM;
+						brelse(bh);
+						brelse(obh);
+						goto failed;
+					}
+
+					lock_buffer(nbh);
+					memcpy(nbh->b_data, obh->b_data,
+							journal->j_blocksize);
+					if (flags & JFS_FLAG_ESCAPE) {
+						*((unsigned int *)bh->b_data) =
+							htonl(JFS_MAGIC_NUMBER);
+					}
+
+					mark_buffer_uptodate(nbh, 1);
+					mark_buffer_dirty(nbh);
+					++info->nr_replays;
+					/* ll_rw_block(WRITE, 1, &nbh); */
+					unlock_buffer(nbh);
+					brelse(obh);
+					brelse(nbh);
+				}
+
+			skip_write:
+				tagp += sizeof(journal_block_tag_t);
+				if (!(flags & JFS_FLAG_SAME_UUID))
+					tagp += 16;
+
+				if (flags & JFS_FLAG_LAST_TAG)
+					break;
+			}
+
+			brelse(bh);
+			continue;
+
+		case JFS_COMMIT_BLOCK:
+			/* Found an expected commit block: not much to
+			 * do other than move on to the next sequence
+			 * number. */
+			brelse(bh);
+			next_commit_ID++;
+			continue;
+
+		case JFS_REVOKE_BLOCK:
+			/* If we aren't in the REVOKE pass, then we can
+			 * just skip over this block. */
+			if (pass != PASS_REVOKE) {
+				brelse(bh);
+				continue;
+			}
+
+			err = scan_revoke_records(journal, bh,
+						  next_commit_ID, info);
+			brelse(bh);
+			if (err)
+				goto failed;
+			continue;
+
+		default:
+			goto done;
+		}
+	}
+
+ done:
+	/*
+	 * We broke out of the log scan loop: either we came to the
+	 * known end of the log or we found an unexpected block in the
+	 * log.  If the latter happened, then we know that the "current"
+	 * transaction marks the end of the valid log.
+	 */
+
+	if (pass == PASS_SCAN)
+		info->end_transaction = next_commit_ID;
+	else {
+		/* It's really bad news if different passes end up at
+		 * different places (but possible due to IO errors). */
+		if (info->end_transaction != next_commit_ID) {
+			printf ("JBD: recovery pass %d ended at "
+				"transaction %u, expected %u\n",
+				pass, next_commit_ID, info->end_transaction);
+			if (!success)
+				success = -EIO;
+		}
+	}
+
+	return success;
+
+ failed:
+	return err;
+}
+
+
+/* Scan a revoke record, marking all blocks mentioned as revoked. */
+
+static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
+			       tid_t sequence, struct recovery_info *info)
+{
+	journal_revoke_header_t *header;
+	int offset, max;
+
+	header = (journal_revoke_header_t *) bh->b_data;
+	offset = sizeof(journal_revoke_header_t);
+	max = ntohl(header->r_count);
+
+	while (offset < max) {
+		unsigned long blocknr;
+		int err;
+
+		blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
+		offset += 4;
+		err = journal_set_revoke(journal, blocknr, sequence);
+		if (err)
+			return err;
+		++info->nr_revokes;
+	}
+	return 0;
+}
+
+
+/*
+ * rehash.c --- rebuild hash tree directories
+ *
+ * This algorithm is designed for simplicity of implementation and to
+ * pack the directory as much as possible.  It however requires twice
+ * as much memory as the size of the directory.  The maximum size
+ * directory supported using a 4k blocksize is roughly a gigabyte, and
+ * so there may very well be problems with machines that don't have
+ * virtual memory, and obscenely large directories.
+ *
+ * An alternate algorithm which is much more disk intensive could be
+ * written, and probably will need to be written in the future.  The
+ * design goals of such an algorithm are: (a) use (roughly) constant
+ * amounts of memory, no matter how large the directory, (b) the
+ * directory must be safe at all times, even if e2fsck is interrupted
+ * in the middle, (c) we must use minimal amounts of extra disk
+ * blocks.  This pretty much requires an incremental approach, where
+ * we are reading from one part of the directory, and inserting into
+ * the front half.  So the algorithm will have to keep track of a
+ * moving block boundary between the new tree and the old tree, and
+ * files will need to be moved from the old directory and inserted
+ * into the new tree.  If the new directory requires space which isn't
+ * yet available, blocks from the beginning part of the old directory
+ * may need to be moved to the end of the directory to make room for
+ * the new tree:
+ *
+ *    --------------------------------------------------------
+ *    |  new tree   |        | old tree                      |
+ *    --------------------------------------------------------
+ *                  ^ ptr    ^ptr
+ *                tail new   head old
+ *
+ * This is going to be a pain in the tuckus to implement, and will
+ * require a lot more disk accesses.  So I'm going to skip it for now;
+ * it's only really going to be an issue for really, really big
+ * filesystems (when we reach the level of tens of millions of files
+ * in a single directory).  It will probably be easier to simply
+ * require that e2fsck use VM first.
+ */
+
+struct fill_dir_struct {
+	char *buf;
+	struct ext2_inode *inode;
+	int err;
+	e2fsck_t ctx;
+	struct hash_entry *harray;
+	int max_array, num_array;
+	int dir_size;
+	int compress;
+	ino_t parent;
+};
+
+struct hash_entry {
+	ext2_dirhash_t  hash;
+	ext2_dirhash_t  minor_hash;
+	struct ext2_dir_entry   *dir;
+};
+
+struct out_dir {
+	int             num;
+	int             max;
+	char            *buf;
+	ext2_dirhash_t  *hashes;
+};
+
+static int fill_dir_block(ext2_filsys fs,
+			  blk_t *block_nr,
+			  e2_blkcnt_t blockcnt,
+			  blk_t ref_block FSCK_ATTR((unused)),
+			  int ref_offset FSCK_ATTR((unused)),
+			  void *priv_data)
+{
+	struct fill_dir_struct  *fd = (struct fill_dir_struct *) priv_data;
+	struct hash_entry       *new_array, *ent;
+	struct ext2_dir_entry   *dirent;
+	char                    *dir;
+	unsigned int            offset, dir_offset;
+
+	if (blockcnt < 0)
+		return 0;
+
+	offset = blockcnt * fs->blocksize;
+	if (offset + fs->blocksize > fd->inode->i_size) {
+		fd->err = EXT2_ET_DIR_CORRUPTED;
+		return BLOCK_ABORT;
+	}
+	dir = (fd->buf+offset);
+	if (HOLE_BLKADDR(*block_nr)) {
+		memset(dir, 0, fs->blocksize);
+		dirent = (struct ext2_dir_entry *) dir;
+		dirent->rec_len = fs->blocksize;
+	} else {
+		fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
+		if (fd->err)
+			return BLOCK_ABORT;
+	}
+	/* While the directory block is "hot", index it. */
+	dir_offset = 0;
+	while (dir_offset < fs->blocksize) {
+		dirent = (struct ext2_dir_entry *) (dir + dir_offset);
+		if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
+		    (dirent->rec_len < 8) ||
+		    ((dirent->rec_len % 4) != 0) ||
+		    (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
+			fd->err = EXT2_ET_DIR_CORRUPTED;
+			return BLOCK_ABORT;
+		}
+		dir_offset += dirent->rec_len;
+		if (dirent->inode == 0)
+			continue;
+		if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
+		    (dirent->name[0] == '.'))
+			continue;
+		if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
+		    (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
+			fd->parent = dirent->inode;
+			continue;
+		}
+		if (fd->num_array >= fd->max_array) {
+			new_array = realloc(fd->harray,
+			    sizeof(struct hash_entry) * (fd->max_array+500));
+			if (!new_array) {
+				fd->err = ENOMEM;
+				return BLOCK_ABORT;
+			}
+			fd->harray = new_array;
+			fd->max_array += 500;
+		}
+		ent = fd->harray + fd->num_array++;
+		ent->dir = dirent;
+		fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
+		if (fd->compress)
+			ent->hash = ent->minor_hash = 0;
+		else {
+			fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
+						 dirent->name,
+						 dirent->name_len & 0xFF,
+						 fs->super->s_hash_seed,
+						 &ent->hash, &ent->minor_hash);
+			if (fd->err)
+				return BLOCK_ABORT;
+		}
+	}
+
+	return 0;
+}
+
+/* Used for sorting the hash entry */
+static int name_cmp(const void *a, const void *b)
+{
+	const struct hash_entry *he_a = (const struct hash_entry *) a;
+	const struct hash_entry *he_b = (const struct hash_entry *) b;
+	int     ret;
+	int     min_len;
+
+	min_len = he_a->dir->name_len;
+	if (min_len > he_b->dir->name_len)
+		min_len = he_b->dir->name_len;
+
+	ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
+	if (ret == 0) {
+		if (he_a->dir->name_len > he_b->dir->name_len)
+			ret = 1;
+		else if (he_a->dir->name_len < he_b->dir->name_len)
+			ret = -1;
+		else
+			ret = he_b->dir->inode - he_a->dir->inode;
+	}
+	return ret;
+}
+
+/* Used for sorting the hash entry */
+static int hash_cmp(const void *a, const void *b)
+{
+	const struct hash_entry *he_a = (const struct hash_entry *) a;
+	const struct hash_entry *he_b = (const struct hash_entry *) b;
+	int     ret;
+
+	if (he_a->hash > he_b->hash)
+		ret = 1;
+	else if (he_a->hash < he_b->hash)
+		ret = -1;
+	else {
+		if (he_a->minor_hash > he_b->minor_hash)
+			ret = 1;
+		else if (he_a->minor_hash < he_b->minor_hash)
+			ret = -1;
+		else
+			ret = name_cmp(a, b);
+	}
+	return ret;
+}
+
+static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
+				int blocks)
+{
+	void                    *new_mem;
+
+	if (outdir->max) {
+		new_mem = realloc(outdir->buf, blocks * fs->blocksize);
+		if (!new_mem)
+			return ENOMEM;
+		outdir->buf = new_mem;
+		new_mem = realloc(outdir->hashes,
+				  blocks * sizeof(ext2_dirhash_t));
+		if (!new_mem)
+			return ENOMEM;
+		outdir->hashes = new_mem;
+	} else {
+		outdir->buf = malloc(blocks * fs->blocksize);
+		outdir->hashes = malloc(blocks * sizeof(ext2_dirhash_t));
+		outdir->num = 0;
+	}
+	outdir->max = blocks;
+	return 0;
+}
+
+static void free_out_dir(struct out_dir *outdir)
+{
+	free(outdir->buf);
+	free(outdir->hashes);
+	outdir->max = 0;
+	outdir->num =0;
+}
+
+static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
+			 char ** ret)
+{
+	errcode_t       retval;
+
+	if (outdir->num >= outdir->max) {
+		retval = alloc_size_dir(fs, outdir, outdir->max + 50);
+		if (retval)
+			return retval;
+	}
+	*ret = outdir->buf + (outdir->num++ * fs->blocksize);
+	memset(*ret, 0, fs->blocksize);
+	return 0;
+}
+
+/*
+ * This function is used to make a unique filename.  We do this by
+ * appending ~0, and then incrementing the number.  However, we cannot
+ * expand the length of the filename beyond the padding available in
+ * the directory entry.
+ */
+static void mutate_name(char *str, __u16 *len)
+{
+	int     i;
+	__u16   l = *len & 0xFF, h = *len & 0xff00;
+
+	/*
+	 * First check to see if it looks the name has been mutated
+	 * already
+	 */
+	for (i = l-1; i > 0; i--) {
+		if (!isdigit(str[i]))
+			break;
+	}
+	if ((i == l-1) || (str[i] != '~')) {
+		if (((l-1) & 3) < 2)
+			l += 2;
+		else
+			l = (l+3) & ~3;
+		str[l-2] = '~';
+		str[l-1] = '0';
+		*len = l | h;
+		return;
+	}
+	for (i = l-1; i >= 0; i--) {
+		if (isdigit(str[i])) {
+			if (str[i] == '9')
+				str[i] = '0';
+			else {
+				str[i]++;
+				return;
+			}
+			continue;
+		}
+		if (i == 1) {
+			if (str[0] == 'z')
+				str[0] = 'A';
+			else if (str[0] == 'Z') {
+				str[0] = '~';
+				str[1] = '0';
+			} else
+				str[0]++;
+		} else if (i > 0) {
+			str[i] = '1';
+			str[i-1] = '~';
+		} else {
+			if (str[0] == '~')
+				str[0] = 'a';
+			else
+				str[0]++;
+		}
+		break;
+	}
+}
+
+static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
+				    ext2_ino_t ino,
+				    struct fill_dir_struct *fd)
+{
+	struct problem_context  pctx;
+	struct hash_entry       *ent, *prev;
+	int                     i, j;
+	int                     fixed = 0;
+	char                    new_name[256];
+	__u16                   new_len;
+
+	clear_problem_context(&pctx);
+	pctx.ino = ino;
+
+	for (i=1; i < fd->num_array; i++) {
+		ent = fd->harray + i;
+		prev = ent - 1;
+		if (!ent->dir->inode ||
+		    ((ent->dir->name_len & 0xFF) !=
+		     (prev->dir->name_len & 0xFF)) ||
+		    (strncmp(ent->dir->name, prev->dir->name,
+			     ent->dir->name_len & 0xFF)))
+			continue;
+		pctx.dirent = ent->dir;
+		if ((ent->dir->inode == prev->dir->inode) &&
+		    fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
+			e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
+			ent->dir->inode = 0;
+			fixed++;
+			continue;
+		}
+		memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
+		new_len = ent->dir->name_len;
+		mutate_name(new_name, &new_len);
+		for (j=0; j < fd->num_array; j++) {
+			if ((i==j) ||
+			    ((ent->dir->name_len & 0xFF) !=
+			     (fd->harray[j].dir->name_len & 0xFF)) ||
+			    (strncmp(new_name, fd->harray[j].dir->name,
+				     new_len & 0xFF)))
+				continue;
+			mutate_name(new_name, &new_len);
+
+			j = -1;
+		}
+		new_name[new_len & 0xFF] = 0;
+		pctx.str = new_name;
+		if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
+			memcpy(ent->dir->name, new_name, new_len & 0xFF);
+			ent->dir->name_len = new_len;
+			ext2fs_dirhash(fs->super->s_def_hash_version,
+				       ent->dir->name,
+				       ent->dir->name_len & 0xFF,
+				       fs->super->s_hash_seed,
+				       &ent->hash, &ent->minor_hash);
+			fixed++;
+		}
+	}
+	return fixed;
+}
+
+
+static errcode_t copy_dir_entries(ext2_filsys fs,
+				  struct fill_dir_struct *fd,
+				  struct out_dir *outdir)
+{
+	errcode_t               retval;
+	char                    *block_start;
+	struct hash_entry       *ent;
+	struct ext2_dir_entry   *dirent;
+	int                     i, rec_len, left;
+	ext2_dirhash_t          prev_hash;
+	int                     offset;
+
+	outdir->max = 0;
+	retval = alloc_size_dir(fs, outdir,
+				(fd->dir_size / fs->blocksize) + 2);
+	if (retval)
+		return retval;
+	outdir->num = fd->compress ? 0 : 1;
+	offset = 0;
+	outdir->hashes[0] = 0;
+	prev_hash = 1;
+	if ((retval = get_next_block(fs, outdir, &block_start)))
+		return retval;
+	dirent = (struct ext2_dir_entry *) block_start;
+	left = fs->blocksize;
+	for (i=0; i < fd->num_array; i++) {
+		ent = fd->harray + i;
+		if (ent->dir->inode == 0)
+			continue;
+		rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
+		if (rec_len > left) {
+			if (left)
+				dirent->rec_len += left;
+			if ((retval = get_next_block(fs, outdir,
+						      &block_start)))
+				return retval;
+			offset = 0;
+		}
+		left = fs->blocksize - offset;
+		dirent = (struct ext2_dir_entry *) (block_start + offset);
+		if (offset == 0) {
+			if (ent->hash == prev_hash)
+				outdir->hashes[outdir->num-1] = ent->hash | 1;
+			else
+				outdir->hashes[outdir->num-1] = ent->hash;
+		}
+		dirent->inode = ent->dir->inode;
+		dirent->name_len = ent->dir->name_len;
+		dirent->rec_len = rec_len;
+		memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
+		offset += rec_len;
+		left -= rec_len;
+		if (left < 12) {
+			dirent->rec_len += left;
+			offset += left;
+			left = 0;
+		}
+		prev_hash = ent->hash;
+	}
+	if (left)
+		dirent->rec_len += left;
+
+	return 0;
+}
+
+
+static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
+				    ext2_ino_t ino, ext2_ino_t parent)
+{
+	struct ext2_dir_entry           *dir;
+	struct ext2_dx_root_info        *root;
+	struct ext2_dx_countlimit       *limits;
+	int                             filetype = 0;
+
+	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
+		filetype = EXT2_FT_DIR << 8;
+
+	memset(buf, 0, fs->blocksize);
+	dir = (struct ext2_dir_entry *) buf;
+	dir->inode = ino;
+	dir->name[0] = '.';
+	dir->name_len = 1 | filetype;
+	dir->rec_len = 12;
+	dir = (struct ext2_dir_entry *) (buf + 12);
+	dir->inode = parent;
+	dir->name[0] = '.';
+	dir->name[1] = '.';
+	dir->name_len = 2 | filetype;
+	dir->rec_len = fs->blocksize - 12;
+
+	root = (struct ext2_dx_root_info *) (buf+24);
+	root->reserved_zero = 0;
+	root->hash_version = fs->super->s_def_hash_version;
+	root->info_length = 8;
+	root->indirect_levels = 0;
+	root->unused_flags = 0;
+
+	limits = (struct ext2_dx_countlimit *) (buf+32);
+	limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
+	limits->count = 0;
+
+	return root;
+}
+
+
+static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
+{
+	struct ext2_dir_entry           *dir;
+	struct ext2_dx_countlimit       *limits;
+
+	memset(buf, 0, fs->blocksize);
+	dir = (struct ext2_dir_entry *) buf;
+	dir->inode = 0;
+	dir->rec_len = fs->blocksize;
+
+	limits = (struct ext2_dx_countlimit *) (buf+8);
+	limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
+	limits->count = 0;
+
+	return (struct ext2_dx_entry *) limits;
+}
+
+/*
+ * This function takes the leaf nodes which have been written in
+ * outdir, and populates the root node and any necessary interior nodes.
+ */
+static errcode_t calculate_tree(ext2_filsys fs,
+				struct out_dir *outdir,
+				ext2_ino_t ino,
+				ext2_ino_t parent)
+{
+	struct ext2_dx_root_info        *root_info;
+	struct ext2_dx_entry            *root, *dx_ent = 0;
+	struct ext2_dx_countlimit       *root_limit, *limit;
+	errcode_t                       retval;
+	char                            * block_start;
+	int                             i, c1, c2, nblks;
+	int                             limit_offset, root_offset;
+
+	root_info = set_root_node(fs, outdir->buf, ino, parent);
+	root_offset = limit_offset = ((char *) root_info - outdir->buf) +
+		root_info->info_length;
+	root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
+	c1 = root_limit->limit;
+	nblks = outdir->num;
+
+	/* Write out the pointer blocks */
+	if (nblks-1 <= c1) {
+		/* Just write out the root block, and we're done */
+		root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
+		for (i=1; i < nblks; i++) {
+			root->block = ext2fs_cpu_to_le32(i);
+			if (i != 1)
+				root->hash =
+					ext2fs_cpu_to_le32(outdir->hashes[i]);
+			root++;
+			c1--;
+		}
+	} else {
+		c2 = 0;
+		limit = 0;
+		root_info->indirect_levels = 1;
+		for (i=1; i < nblks; i++) {
+			if (c1 == 0)
+				return ENOSPC;
+			if (c2 == 0) {
+				if (limit)
+					limit->limit = limit->count =
+		ext2fs_cpu_to_le16(limit->limit);
+				root = (struct ext2_dx_entry *)
+					(outdir->buf + root_offset);
+				root->block = ext2fs_cpu_to_le32(outdir->num);
+				if (i != 1)
+					root->hash =
+			ext2fs_cpu_to_le32(outdir->hashes[i]);
+				if ((retval =  get_next_block(fs, outdir,
+							      &block_start)))
+					return retval;
+				dx_ent = set_int_node(fs, block_start);
+				limit = (struct ext2_dx_countlimit *) dx_ent;
+				c2 = limit->limit;
+				root_offset += sizeof(struct ext2_dx_entry);
+				c1--;
+			}
+			dx_ent->block = ext2fs_cpu_to_le32(i);
+			if (c2 != limit->limit)
+				dx_ent->hash =
+					ext2fs_cpu_to_le32(outdir->hashes[i]);
+			dx_ent++;
+			c2--;
+		}
+		limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
+		limit->limit = ext2fs_cpu_to_le16(limit->limit);
+	}
+	root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
+	root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
+	root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
+
+	return 0;
+}
+
+struct write_dir_struct {
+	struct out_dir *outdir;
+	errcode_t       err;
+	e2fsck_t        ctx;
+	int             cleared;
+};
+
+/*
+ * Helper function which writes out a directory block.
+ */
+static int write_dir_block(ext2_filsys fs,
+			   blk_t        *block_nr,
+			   e2_blkcnt_t blockcnt,
+			   blk_t ref_block FSCK_ATTR((unused)),
+			   int ref_offset FSCK_ATTR((unused)),
+			   void *priv_data)
+{
+	struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
+	blk_t   blk;
+	char    *dir;
+
+	if (*block_nr == 0)
+		return 0;
+	if (blockcnt >= wd->outdir->num) {
+		e2fsck_read_bitmaps(wd->ctx);
+		blk = *block_nr;
+		ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
+		ext2fs_block_alloc_stats(fs, blk, -1);
+		*block_nr = 0;
+		wd->cleared++;
+		return BLOCK_CHANGED;
+	}
+	if (blockcnt < 0)
+		return 0;
+
+	dir = wd->outdir->buf + (blockcnt * fs->blocksize);
+	wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
+	if (wd->err)
+		return BLOCK_ABORT;
+	return 0;
+}
+
+static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
+				 struct out_dir *outdir,
+				 ext2_ino_t ino, int compress)
+{
+	struct write_dir_struct wd;
+	errcode_t       retval;
+	struct ext2_inode       inode;
+
+	retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
+	if (retval)
+		return retval;
+
+	wd.outdir = outdir;
+	wd.err = 0;
+	wd.ctx = ctx;
+	wd.cleared = 0;
+
+	retval = ext2fs_block_iterate2(fs, ino, 0, 0,
+				       write_dir_block, &wd);
+	if (retval)
+		return retval;
+	if (wd.err)
+		return wd.err;
+
+	e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
+	if (compress)
+		inode.i_flags &= ~EXT2_INDEX_FL;
+	else
+		inode.i_flags |= EXT2_INDEX_FL;
+	inode.i_size = outdir->num * fs->blocksize;
+	inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
+	e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
+
+	return 0;
+}
+
+static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
+{
+	ext2_filsys             fs = ctx->fs;
+	errcode_t               retval;
+	struct ext2_inode       inode;
+	char                    *dir_buf = 0;
+	struct fill_dir_struct  fd;
+	struct out_dir          outdir;
+
+	outdir.max = outdir.num = 0;
+	outdir.buf = 0;
+	outdir.hashes = 0;
+	e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
+
+	retval = ENOMEM;
+	fd.harray = 0;
+	dir_buf = malloc(inode.i_size);
+	if (!dir_buf)
+		goto errout;
+
+	fd.max_array = inode.i_size / 32;
+	fd.num_array = 0;
+	fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
+	if (!fd.harray)
+		goto errout;
+
+	fd.ctx = ctx;
+	fd.buf = dir_buf;
+	fd.inode = &inode;
+	fd.err = 0;
+	fd.dir_size = 0;
+	fd.compress = 0;
+	if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
+	    (inode.i_size / fs->blocksize) < 2)
+		fd.compress = 1;
+	fd.parent = 0;
+
+	/* Read in the entire directory into memory */
+	retval = ext2fs_block_iterate2(fs, ino, 0, 0,
+				       fill_dir_block, &fd);
+	if (fd.err) {
+		retval = fd.err;
+		goto errout;
+	}
+
+	/* Sort the list */
+resort:
+	if (fd.compress)
+		qsort(fd.harray+2, fd.num_array-2,
+		      sizeof(struct hash_entry), name_cmp);
+	else
+		qsort(fd.harray, fd.num_array,
+		      sizeof(struct hash_entry), hash_cmp);
+
+	/*
+	 * Look for duplicates
+	 */
+	if (duplicate_search_and_fix(ctx, fs, ino, &fd))
+		goto resort;
+
+	if (ctx->options & E2F_OPT_NO) {
+		retval = 0;
+		goto errout;
+	}
+
+	/*
+	 * Copy the directory entries.  In a htree directory these
+	 * will become the leaf nodes.
+	 */
+	retval = copy_dir_entries(fs, &fd, &outdir);
+	if (retval)
+		goto errout;
+
+	free(dir_buf); dir_buf = 0;
+
+	if (!fd.compress) {
+		/* Calculate the interior nodes */
+		retval = calculate_tree(fs, &outdir, ino, fd.parent);
+		if (retval)
+			goto errout;
+	}
+
+	retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
+
+errout:
+	free(dir_buf);
+	free(fd.harray);
+
+	free_out_dir(&outdir);
+	return retval;
+}
+
+void e2fsck_rehash_directories(e2fsck_t ctx)
+{
+	struct problem_context  pctx;
+	struct dir_info         *dir;
+	ext2_u32_iterate        iter;
+	ext2_ino_t              ino;
+	errcode_t               retval;
+	int                     i, cur, max, all_dirs, dir_index, first = 1;
+
+	all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
+
+	if (!ctx->dirs_to_hash && !all_dirs)
+		return;
+
+	e2fsck_get_lost_and_found(ctx, 0);
+
+	clear_problem_context(&pctx);
+
+	dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
+	cur = 0;
+	if (all_dirs) {
+		i = 0;
+		max = e2fsck_get_num_dirinfo(ctx);
+	} else {
+		retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
+						       &iter);
+		if (retval) {
+			pctx.errcode = retval;
+			fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
+			return;
+		}
+		max = ext2fs_u32_list_count(ctx->dirs_to_hash);
+	}
+	while (1) {
+		if (all_dirs) {
+			if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
+				break;
+			ino = dir->ino;
+		} else {
+			if (!ext2fs_u32_list_iterate(iter, &ino))
+				break;
+		}
+		if (ino == ctx->lost_and_found)
+			continue;
+		pctx.dir = ino;
+		if (first) {
+			fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
+			first = 0;
+		}
+		pctx.errcode = e2fsck_rehash_dir(ctx, ino);
+		if (pctx.errcode) {
+			end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
+			fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
+		}
+		if (ctx->progress && !ctx->progress_fd)
+			e2fsck_simple_progress(ctx, "Rebuilding directory",
+			       100.0 * (float) (++cur) / (float) max, ino);
+	}
+	end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
+	if (!all_dirs)
+		ext2fs_u32_list_iterate_end(iter);
+
+	ext2fs_u32_list_free(ctx->dirs_to_hash);
+	ctx->dirs_to_hash = 0;
+}
+
+/*
+ * linux/fs/revoke.c
+ *
+ * Journal revoke routines for the generic filesystem journaling code;
+ * part of the ext2fs journaling system.
+ *
+ * Revoke is the mechanism used to prevent old log records for deleted
+ * metadata from being replayed on top of newer data using the same
+ * blocks.  The revoke mechanism is used in two separate places:
+ *
+ * + Commit: during commit we write the entire list of the current
+ *   transaction's revoked blocks to the journal
+ *
+ * + Recovery: during recovery we record the transaction ID of all
+ *   revoked blocks.  If there are multiple revoke records in the log
+ *   for a single block, only the last one counts, and if there is a log
+ *   entry for a block beyond the last revoke, then that log entry still
+ *   gets replayed.
+ *
+ * We can get interactions between revokes and new log data within a
+ * single transaction:
+ *
+ * Block is revoked and then journaled:
+ *   The desired end result is the journaling of the new block, so we
+ *   cancel the revoke before the transaction commits.
+ *
+ * Block is journaled and then revoked:
+ *   The revoke must take precedence over the write of the block, so we
+ *   need either to cancel the journal entry or to write the revoke
+ *   later in the log than the log block.  In this case, we choose the
+ *   latter: journaling a block cancels any revoke record for that block
+ *   in the current transaction, so any revoke for that block in the
+ *   transaction must have happened after the block was journaled and so
+ *   the revoke must take precedence.
+ *
+ * Block is revoked and then written as data:
+ *   The data write is allowed to succeed, but the revoke is _not_
+ *   cancelled.  We still need to prevent old log records from
+ *   overwriting the new data.  We don't even need to clear the revoke
+ *   bit here.
+ *
+ * Revoke information on buffers is a tri-state value:
+ *
+ * RevokeValid clear:   no cached revoke status, need to look it up
+ * RevokeValid set, Revoked clear:
+ *                      buffer has not been revoked, and cancel_revoke
+ *                      need do nothing.
+ * RevokeValid set, Revoked set:
+ *                      buffer has been revoked.
+ */
+
+static kmem_cache_t *revoke_record_cache;
+static kmem_cache_t *revoke_table_cache;
+
+/* Each revoke record represents one single revoked block.  During
+   journal replay, this involves recording the transaction ID of the
+   last transaction to revoke this block. */
+
+struct jbd_revoke_record_s
+{
+	struct list_head  hash;
+	tid_t             sequence;     /* Used for recovery only */
+	unsigned long     blocknr;
+};
+
+
+/* The revoke table is just a simple hash table of revoke records. */
+struct jbd_revoke_table_s
+{
+	/* It is conceivable that we might want a larger hash table
+	 * for recovery.  Must be a power of two. */
+	int               hash_size;
+	int               hash_shift;
+	struct list_head *hash_table;
+};
+
+
+/* Utility functions to maintain the revoke table */
+
+/* Borrowed from buffer.c: this is a tried and tested block hash function */
+static inline int hash(journal_t *journal, unsigned long block)
+{
+	struct jbd_revoke_table_s *table = journal->j_revoke;
+	int hash_shift = table->hash_shift;
+
+	return ((block << (hash_shift - 6)) ^
+		(block >> 13) ^
+		(block << (hash_shift - 12))) & (table->hash_size - 1);
+}
+
+static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
+			      tid_t seq)
+{
+	struct list_head *hash_list;
+	struct jbd_revoke_record_s *record;
+
+	record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
+	if (!record)
+		goto oom;
+
+	record->sequence = seq;
+	record->blocknr = blocknr;
+	hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
+	list_add(&record->hash, hash_list);
+	return 0;
+
+oom:
+	return -ENOMEM;
+}
+
+/* Find a revoke record in the journal's hash table. */
+
+static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
+						      unsigned long blocknr)
+{
+	struct list_head *hash_list;
+	struct jbd_revoke_record_s *record;
+
+	hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
+
+	record = (struct jbd_revoke_record_s *) hash_list->next;
+	while (&(record->hash) != hash_list) {
+		if (record->blocknr == blocknr)
+			return record;
+		record = (struct jbd_revoke_record_s *) record->hash.next;
+	}
+	return NULL;
+}
+
+int journal_init_revoke_caches(void)
+{
+	revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
+	if (revoke_record_cache == 0)
+		return -ENOMEM;
+
+	revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
+	if (revoke_table_cache == 0) {
+		do_cache_destroy(revoke_record_cache);
+		revoke_record_cache = NULL;
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+void journal_destroy_revoke_caches(void)
+{
+	do_cache_destroy(revoke_record_cache);
+	revoke_record_cache = 0;
+	do_cache_destroy(revoke_table_cache);
+	revoke_table_cache = 0;
+}
+
+/* Initialise the revoke table for a given journal to a given size. */
+
+int journal_init_revoke(journal_t *journal, int hash_size)
+{
+	int shift, tmp;
+
+	journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
+	if (!journal->j_revoke)
+		return -ENOMEM;
+
+	/* Check that the hash_size is a power of two */
+	journal->j_revoke->hash_size = hash_size;
+
+	shift = 0;
+	tmp = hash_size;
+	while((tmp >>= 1UL) != 0UL)
+		shift++;
+	journal->j_revoke->hash_shift = shift;
+
+	journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
+	if (!journal->j_revoke->hash_table) {
+		free(journal->j_revoke);
+		journal->j_revoke = NULL;
+		return -ENOMEM;
+	}
+
+	for (tmp = 0; tmp < hash_size; tmp++)
+		INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
+
+	return 0;
+}
+
+/* Destoy a journal's revoke table.  The table must already be empty! */
+
+void journal_destroy_revoke(journal_t *journal)
+{
+	struct jbd_revoke_table_s *table;
+	struct list_head *hash_list;
+	int i;
+
+	table = journal->j_revoke;
+	if (!table)
+		return;
+
+	for (i=0; i<table->hash_size; i++) {
+		hash_list = &table->hash_table[i];
+	}
+
+	free(table->hash_table);
+	free(table);
+	journal->j_revoke = NULL;
+}
+
+/*
+ * Revoke support for recovery.
+ *
+ * Recovery needs to be able to:
+ *
+ *  record all revoke records, including the tid of the latest instance
+ *  of each revoke in the journal
+ *
+ *  check whether a given block in a given transaction should be replayed
+ *  (ie. has not been revoked by a revoke record in that or a subsequent
+ *  transaction)
+ *
+ *  empty the revoke table after recovery.
+ */
+
+/*
+ * First, setting revoke records.  We create a new revoke record for
+ * every block ever revoked in the log as we scan it for recovery, and
+ * we update the existing records if we find multiple revokes for a
+ * single block.
+ */
+
+int journal_set_revoke(journal_t *journal, unsigned long blocknr,
+		       tid_t sequence)
+{
+	struct jbd_revoke_record_s *record;
+
+	record = find_revoke_record(journal, blocknr);
+	if (record) {
+		/* If we have multiple occurences, only record the
+		 * latest sequence number in the hashed record */
+		if (tid_gt(sequence, record->sequence))
+			record->sequence = sequence;
+		return 0;
+	}
+	return insert_revoke_hash(journal, blocknr, sequence);
+}
+
+/*
+ * Test revoke records.  For a given block referenced in the log, has
+ * that block been revoked?  A revoke record with a given transaction
+ * sequence number revokes all blocks in that transaction and earlier
+ * ones, but later transactions still need replayed.
+ */
+
+int journal_test_revoke(journal_t *journal, unsigned long blocknr,
+			tid_t sequence)
+{
+	struct jbd_revoke_record_s *record;
+
+	record = find_revoke_record(journal, blocknr);
+	if (!record)
+		return 0;
+	if (tid_gt(sequence, record->sequence))
+		return 0;
+	return 1;
+}
+
+/*
+ * Finally, once recovery is over, we need to clear the revoke table so
+ * that it can be reused by the running filesystem.
+ */
+
+void journal_clear_revoke(journal_t *journal)
+{
+	int i;
+	struct list_head *hash_list;
+	struct jbd_revoke_record_s *record;
+	struct jbd_revoke_table_s *revoke_var;
+
+	revoke_var = journal->j_revoke;
+
+	for (i = 0; i < revoke_var->hash_size; i++) {
+		hash_list = &revoke_var->hash_table[i];
+		while (!list_empty(hash_list)) {
+			record = (struct jbd_revoke_record_s*) hash_list->next;
+			list_del(&record->hash);
+			free(record);
+		}
+	}
+}
+
+/*
+ * e2fsck.c - superblock checks
+ */
+
+#define MIN_CHECK 1
+#define MAX_CHECK 2
+
+static void check_super_value(e2fsck_t ctx, const char *descr,
+			      unsigned long value, int flags,
+			      unsigned long min_val, unsigned long max_val)
+{
+	struct          problem_context pctx;
+
+	if (((flags & MIN_CHECK) && (value < min_val)) ||
+	    ((flags & MAX_CHECK) && (value > max_val))) {
+		clear_problem_context(&pctx);
+		pctx.num = value;
+		pctx.str = descr;
+		fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
+	}
+}
+
+/*
+ * This routine may get stubbed out in special compilations of the
+ * e2fsck code..
+ */
+#ifndef EXT2_SPECIAL_DEVICE_SIZE
+static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
+{
+	return (ext2fs_get_device_size(ctx->filesystem_name,
+				       EXT2_BLOCK_SIZE(ctx->fs->super),
+				       &ctx->num_blocks));
+}
+#endif
+
+/*
+ * helper function to release an inode
+ */
+struct process_block_struct {
+	e2fsck_t        ctx;
+	char            *buf;
+	struct problem_context *pctx;
+	int             truncating;
+	int             truncate_offset;
+	e2_blkcnt_t     truncate_block;
+	int             truncated_blocks;
+	int             abort;
+	errcode_t       errcode;
+};
+
+static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
+			       e2_blkcnt_t blockcnt,
+			       blk_t    ref_blk FSCK_ATTR((unused)),
+			       int      ref_offset FSCK_ATTR((unused)),
+			       void *priv_data)
+{
+	struct process_block_struct *pb;
+	e2fsck_t                ctx;
+	struct problem_context  *pctx;
+	blk_t                   blk = *block_nr;
+	int                     retval = 0;
+
+	pb = (struct process_block_struct *) priv_data;
+	ctx = pb->ctx;
+	pctx = pb->pctx;
+
+	pctx->blk = blk;
+	pctx->blkcount = blockcnt;
+
+	if (HOLE_BLKADDR(blk))
+		return 0;
+
+	if ((blk < fs->super->s_first_data_block) ||
+	    (blk >= fs->super->s_blocks_count)) {
+		fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
+	return_abort:
+		pb->abort = 1;
+		return BLOCK_ABORT;
+	}
+
+	if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
+		fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
+		goto return_abort;
+	}
+
+	/*
+	 * If we are deleting an orphan, then we leave the fields alone.
+	 * If we are truncating an orphan, then update the inode fields
+	 * and clean up any partial block data.
+	 */
+	if (pb->truncating) {
+		/*
+		 * We only remove indirect blocks if they are
+		 * completely empty.
+		 */
+		if (blockcnt < 0) {
+			int     i, limit;
+			blk_t   *bp;
+
+			pb->errcode = io_channel_read_blk(fs->io, blk, 1,
+							pb->buf);
+			if (pb->errcode)
+				goto return_abort;
+
+			limit = fs->blocksize >> 2;
+			for (i = 0, bp = (blk_t *) pb->buf;
+			     i < limit;  i++, bp++)
+				if (*bp)
+					return 0;
+		}
+		/*
+		 * We don't remove direct blocks until we've reached
+		 * the truncation block.
+		 */
+		if (blockcnt >= 0 && blockcnt < pb->truncate_block)
+			return 0;
+		/*
+		 * If part of the last block needs truncating, we do
+		 * it here.
+		 */
+		if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
+			pb->errcode = io_channel_read_blk(fs->io, blk, 1,
+							pb->buf);
+			if (pb->errcode)
+				goto return_abort;
+			memset(pb->buf + pb->truncate_offset, 0,
+			       fs->blocksize - pb->truncate_offset);
+			pb->errcode = io_channel_write_blk(fs->io, blk, 1,
+							 pb->buf);
+			if (pb->errcode)
+				goto return_abort;
+		}
+		pb->truncated_blocks++;
+		*block_nr = 0;
+		retval |= BLOCK_CHANGED;
+	}
+
+	ext2fs_block_alloc_stats(fs, blk, -1);
+	return retval;
+}
+
+/*
+ * This function releases an inode.  Returns 1 if an inconsistency was
+ * found.  If the inode has a link count, then it is being truncated and
+ * not deleted.
+ */
+static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
+				struct ext2_inode *inode, char *block_buf,
+				struct problem_context *pctx)
+{
+	struct process_block_struct     pb;
+	ext2_filsys                     fs = ctx->fs;
+	errcode_t                       retval;
+	__u32                           count;
+
+	if (!ext2fs_inode_has_valid_blocks(inode))
+		return 0;
+
+	pb.buf = block_buf + 3 * ctx->fs->blocksize;
+	pb.ctx = ctx;
+	pb.abort = 0;
+	pb.errcode = 0;
+	pb.pctx = pctx;
+	if (inode->i_links_count) {
+		pb.truncating = 1;
+		pb.truncate_block = (e2_blkcnt_t)
+			((((long long)inode->i_size_high << 32) +
+			  inode->i_size + fs->blocksize - 1) /
+			 fs->blocksize);
+		pb.truncate_offset = inode->i_size % fs->blocksize;
+	} else {
+		pb.truncating = 0;
+		pb.truncate_block = 0;
+		pb.truncate_offset = 0;
+	}
+	pb.truncated_blocks = 0;
+	retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
+				      block_buf, release_inode_block, &pb);
+	if (retval) {
+		bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
+			ino);
+		return 1;
+	}
+	if (pb.abort)
+		return 1;
+
+	/* Refresh the inode since ext2fs_block_iterate may have changed it */
+	e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
+
+	if (pb.truncated_blocks)
+		inode->i_blocks -= pb.truncated_blocks *
+			(fs->blocksize / 512);
+
+	if (inode->i_file_acl) {
+		retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
+						   block_buf, -1, &count);
+		if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
+			retval = 0;
+			count = 1;
+		}
+		if (retval) {
+			bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
+				ino);
+			return 1;
+		}
+		if (count == 0)
+			ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
+		inode->i_file_acl = 0;
+	}
+	return 0;
+}
+
+/*
+ * This function releases all of the orphan inodes.  It returns 1 if
+ * it hit some error, and 0 on success.
+ */
+static int release_orphan_inodes(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	ext2_ino_t      ino, next_ino;
+	struct ext2_inode inode;
+	struct problem_context pctx;
+	char *block_buf;
+
+	if ((ino = fs->super->s_last_orphan) == 0)
+		return 0;
+
+	/*
+	 * Win or lose, we won't be using the head of the orphan inode
+	 * list again.
+	 */
+	fs->super->s_last_orphan = 0;
+	ext2fs_mark_super_dirty(fs);
+
+	/*
+	 * If the filesystem contains errors, don't run the orphan
+	 * list, since the orphan list can't be trusted; and we're
+	 * going to be running a full e2fsck run anyway...
+	 */
+	if (fs->super->s_state & EXT2_ERROR_FS)
+		return 0;
+
+	if ((ino < EXT2_FIRST_INODE(fs->super)) ||
+	    (ino > fs->super->s_inodes_count)) {
+		clear_problem_context(&pctx);
+		pctx.ino = ino;
+		fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
+		return 1;
+	}
+
+	block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
+						    "block iterate buffer");
+	e2fsck_read_bitmaps(ctx);
+
+	while (ino) {
+		e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
+		clear_problem_context(&pctx);
+		pctx.ino = ino;
+		pctx.inode = &inode;
+		pctx.str = inode.i_links_count ? _("Truncating") :
+			_("Clearing");
+
+		fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
+
+		next_ino = inode.i_dtime;
+		if (next_ino &&
+		    ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
+		     (next_ino > fs->super->s_inodes_count))) {
+			pctx.ino = next_ino;
+			fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
+			goto return_abort;
+		}
+
+		if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
+			goto return_abort;
+
+		if (!inode.i_links_count) {
+			ext2fs_inode_alloc_stats2(fs, ino, -1,
+						  LINUX_S_ISDIR(inode.i_mode));
+			inode.i_dtime = time(0);
+		} else {
+			inode.i_dtime = 0;
+		}
+		e2fsck_write_inode(ctx, ino, &inode, "delete_file");
+		ino = next_ino;
+	}
+	ext2fs_free_mem(&block_buf);
+	return 0;
+return_abort:
+	ext2fs_free_mem(&block_buf);
+	return 1;
+}
+
+/*
+ * Check the resize inode to make sure it is sane.  We check both for
+ * the case where on-line resizing is not enabled (in which case the
+ * resize inode should be cleared) as well as the case where on-line
+ * resizing is enabled.
+ */
+static void check_resize_inode(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	struct ext2_inode inode;
+	struct problem_context  pctx;
+	int             i, j, gdt_off, ind_off;
+	blk_t           blk, pblk, expect;
+	__u32           *dind_buf = 0, *ind_buf;
+	errcode_t       retval;
+
+	clear_problem_context(&pctx);
+
+	/*
+	 * If the resize inode feature isn't set, then
+	 * s_reserved_gdt_blocks must be zero.
+	 */
+	if (!(fs->super->s_feature_compat &
+	      EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
+		if (fs->super->s_reserved_gdt_blocks) {
+			pctx.num = fs->super->s_reserved_gdt_blocks;
+			if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
+					&pctx)) {
+				fs->super->s_reserved_gdt_blocks = 0;
+				ext2fs_mark_super_dirty(fs);
+			}
+		}
+	}
+
+	/* Read the resize inode */
+	pctx.ino = EXT2_RESIZE_INO;
+	retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
+	if (retval) {
+		if (fs->super->s_feature_compat &
+		    EXT2_FEATURE_COMPAT_RESIZE_INODE)
+			ctx->flags |= E2F_FLAG_RESIZE_INODE;
+		return;
+	}
+
+	/*
+	 * If the resize inode feature isn't set, check to make sure
+	 * the resize inode is cleared; then we're done.
+	 */
+	if (!(fs->super->s_feature_compat &
+	      EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
+		for (i=0; i < EXT2_N_BLOCKS; i++) {
+			if (inode.i_block[i])
+				break;
+		}
+		if ((i < EXT2_N_BLOCKS) &&
+		    fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
+			memset(&inode, 0, sizeof(inode));
+			e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
+					   "clear_resize");
+		}
+		return;
+	}
+
+	/*
+	 * The resize inode feature is enabled; check to make sure the
+	 * only block in use is the double indirect block
+	 */
+	blk = inode.i_block[EXT2_DIND_BLOCK];
+	for (i=0; i < EXT2_N_BLOCKS; i++) {
+		if (i != EXT2_DIND_BLOCK && inode.i_block[i])
+			break;
+	}
+	if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
+	    !(inode.i_mode & LINUX_S_IFREG) ||
+	    (blk < fs->super->s_first_data_block ||
+	     blk >= fs->super->s_blocks_count)) {
+	resize_inode_invalid:
+		if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
+			memset(&inode, 0, sizeof(inode));
+			e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
+					   "clear_resize");
+			ctx->flags |= E2F_FLAG_RESIZE_INODE;
+		}
+		if (!(ctx->options & E2F_OPT_READONLY)) {
+			fs->super->s_state &= ~EXT2_VALID_FS;
+			ext2fs_mark_super_dirty(fs);
+		}
+		goto cleanup;
+	}
+	dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
+						    "resize dind buffer");
+	ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
+
+	retval = ext2fs_read_ind_block(fs, blk, dind_buf);
+	if (retval)
+		goto resize_inode_invalid;
+
+	gdt_off = fs->desc_blocks;
+	pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
+	for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
+	     i++, gdt_off++, pblk++) {
+		gdt_off %= fs->blocksize/4;
+		if (dind_buf[gdt_off] != pblk)
+			goto resize_inode_invalid;
+		retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
+		if (retval)
+			goto resize_inode_invalid;
+		ind_off = 0;
+		for (j = 1; j < fs->group_desc_count; j++) {
+			if (!ext2fs_bg_has_super(fs, j))
+				continue;
+			expect = pblk + (j * fs->super->s_blocks_per_group);
+			if (ind_buf[ind_off] != expect)
+				goto resize_inode_invalid;
+			ind_off++;
+		}
+	}
+
+cleanup:
+	ext2fs_free_mem(&dind_buf);
+
+ }
+
+static void check_super_block(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	blk_t   first_block, last_block;
+	struct ext2_super_block *sb = fs->super;
+	struct ext2_group_desc *gd;
+	blk_t   blocks_per_group = fs->super->s_blocks_per_group;
+	blk_t   bpg_max;
+	int     inodes_per_block;
+	int     ipg_max;
+	int     inode_size;
+	dgrp_t  i;
+	blk_t   should_be;
+	struct problem_context  pctx;
+	__u32   free_blocks = 0, free_inodes = 0;
+
+	inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
+	ipg_max = inodes_per_block * (blocks_per_group - 4);
+	if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
+		ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
+	bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
+	if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
+		bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
+
+	ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
+		 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
+	ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
+		 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
+	ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
+		sizeof(int) * fs->group_desc_count, "invalid_inode_table");
+
+	clear_problem_context(&pctx);
+
+	/*
+	 * Verify the super block constants...
+	 */
+	check_super_value(ctx, "inodes_count", sb->s_inodes_count,
+			  MIN_CHECK, 1, 0);
+	check_super_value(ctx, "blocks_count", sb->s_blocks_count,
+			  MIN_CHECK, 1, 0);
+	check_super_value(ctx, "first_data_block", sb->s_first_data_block,
+			  MAX_CHECK, 0, sb->s_blocks_count);
+	check_super_value(ctx, "log_block_size", sb->s_log_block_size,
+			  MIN_CHECK | MAX_CHECK, 0,
+			  EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
+	check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
+			  MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
+	check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
+			  MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
+			  bpg_max);
+	check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
+			  MIN_CHECK | MAX_CHECK, 8, bpg_max);
+	check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
+			  MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
+	check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
+			  MAX_CHECK, 0, sb->s_blocks_count / 2);
+	check_super_value(ctx, "reserved_gdt_blocks",
+			  sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
+			  fs->blocksize/4);
+	inode_size = EXT2_INODE_SIZE(sb);
+	check_super_value(ctx, "inode_size",
+			  inode_size, MIN_CHECK | MAX_CHECK,
+			  EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
+	if (inode_size & (inode_size - 1)) {
+		pctx.num = inode_size;
+		pctx.str = "inode_size";
+		fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
+		return;
+	}
+
+	if (!ctx->num_blocks) {
+		pctx.errcode = e2fsck_get_device_size(ctx);
+		if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
+			fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
+			ctx->flags |= E2F_FLAG_ABORT;
+			return;
+		}
+		if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
+		    (ctx->num_blocks < sb->s_blocks_count)) {
+			pctx.blk = sb->s_blocks_count;
+			pctx.blk2 = ctx->num_blocks;
+			if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
+				ctx->flags |= E2F_FLAG_ABORT;
+				return;
+			}
+		}
+	}
+
+	if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
+		pctx.blk = EXT2_BLOCK_SIZE(sb);
+		pctx.blk2 = EXT2_FRAG_SIZE(sb);
+		fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+
+	should_be = sb->s_frags_per_group >>
+		(sb->s_log_block_size - sb->s_log_frag_size);
+	if (sb->s_blocks_per_group != should_be) {
+		pctx.blk = sb->s_blocks_per_group;
+		pctx.blk2 = should_be;
+		fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+
+	should_be = (sb->s_log_block_size == 0) ? 1 : 0;
+	if (sb->s_first_data_block != should_be) {
+		pctx.blk = sb->s_first_data_block;
+		pctx.blk2 = should_be;
+		fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+
+	should_be = sb->s_inodes_per_group * fs->group_desc_count;
+	if (sb->s_inodes_count != should_be) {
+		pctx.ino = sb->s_inodes_count;
+		pctx.ino2 = should_be;
+		if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
+			sb->s_inodes_count = should_be;
+			ext2fs_mark_super_dirty(fs);
+		}
+	}
+
+	/*
+	 * Verify the group descriptors....
+	 */
+	first_block =  sb->s_first_data_block;
+	last_block = first_block + blocks_per_group;
+
+	for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
+		pctx.group = i;
+
+		if (i == fs->group_desc_count - 1)
+			last_block = sb->s_blocks_count;
+		if ((gd->bg_block_bitmap < first_block) ||
+		    (gd->bg_block_bitmap >= last_block)) {
+			pctx.blk = gd->bg_block_bitmap;
+			if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
+				gd->bg_block_bitmap = 0;
+		}
+		if (gd->bg_block_bitmap == 0) {
+			ctx->invalid_block_bitmap_flag[i]++;
+			ctx->invalid_bitmaps++;
+		}
+		if ((gd->bg_inode_bitmap < first_block) ||
+		    (gd->bg_inode_bitmap >= last_block)) {
+			pctx.blk = gd->bg_inode_bitmap;
+			if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
+				gd->bg_inode_bitmap = 0;
+		}
+		if (gd->bg_inode_bitmap == 0) {
+			ctx->invalid_inode_bitmap_flag[i]++;
+			ctx->invalid_bitmaps++;
+		}
+		if ((gd->bg_inode_table < first_block) ||
+		    ((gd->bg_inode_table +
+		      fs->inode_blocks_per_group - 1) >= last_block)) {
+			pctx.blk = gd->bg_inode_table;
+			if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
+				gd->bg_inode_table = 0;
+		}
+		if (gd->bg_inode_table == 0) {
+			ctx->invalid_inode_table_flag[i]++;
+			ctx->invalid_bitmaps++;
+		}
+		free_blocks += gd->bg_free_blocks_count;
+		free_inodes += gd->bg_free_inodes_count;
+		first_block += sb->s_blocks_per_group;
+		last_block += sb->s_blocks_per_group;
+
+		if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
+		    (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
+		    (gd->bg_used_dirs_count > sb->s_inodes_per_group))
+			ext2fs_unmark_valid(fs);
+
+	}
+
+	/*
+	 * Update the global counts from the block group counts.  This
+	 * is needed for an experimental patch which eliminates
+	 * locking the entire filesystem when allocating blocks or
+	 * inodes; if the filesystem is not unmounted cleanly, the
+	 * global counts may not be accurate.
+	 */
+	if ((free_blocks != sb->s_free_blocks_count) ||
+	    (free_inodes != sb->s_free_inodes_count)) {
+		if (ctx->options & E2F_OPT_READONLY)
+			ext2fs_unmark_valid(fs);
+		else {
+			sb->s_free_blocks_count = free_blocks;
+			sb->s_free_inodes_count = free_inodes;
+			ext2fs_mark_super_dirty(fs);
+		}
+	}
+
+	if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
+	    (sb->s_free_inodes_count > sb->s_inodes_count))
+		ext2fs_unmark_valid(fs);
+
+
+	/*
+	 * If we have invalid bitmaps, set the error state of the
+	 * filesystem.
+	 */
+	if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
+		sb->s_state &= ~EXT2_VALID_FS;
+		ext2fs_mark_super_dirty(fs);
+	}
+
+	clear_problem_context(&pctx);
+
+	/*
+	 * If the UUID field isn't assigned, assign it.
+	 */
+	if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
+		if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
+			uuid_generate(sb->s_uuid);
+			ext2fs_mark_super_dirty(fs);
+			fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
+		}
+	}
+
+	/* FIXME - HURD support?
+	 * For the Hurd, check to see if the filetype option is set,
+	 * since it doesn't support it.
+	 */
+	if (!(ctx->options & E2F_OPT_READONLY) &&
+	    fs->super->s_creator_os == EXT2_OS_HURD &&
+	    (fs->super->s_feature_incompat &
+	     EXT2_FEATURE_INCOMPAT_FILETYPE)) {
+		if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
+			fs->super->s_feature_incompat &=
+				~EXT2_FEATURE_INCOMPAT_FILETYPE;
+			ext2fs_mark_super_dirty(fs);
+
+		}
+	}
+
+	/*
+	 * If we have any of the compatibility flags set, we need to have a
+	 * revision 1 filesystem.  Most kernels will not check the flags on
+	 * a rev 0 filesystem and we may have corruption issues because of
+	 * the incompatible changes to the filesystem.
+	 */
+	if (!(ctx->options & E2F_OPT_READONLY) &&
+	    fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
+	    (fs->super->s_feature_compat ||
+	     fs->super->s_feature_ro_compat ||
+	     fs->super->s_feature_incompat) &&
+	    fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
+		ext2fs_update_dynamic_rev(fs);
+		ext2fs_mark_super_dirty(fs);
+	}
+
+	check_resize_inode(ctx);
+
+	/*
+	 * Clean up any orphan inodes, if present.
+	 */
+	if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
+		fs->super->s_state &= ~EXT2_VALID_FS;
+		ext2fs_mark_super_dirty(fs);
+	}
+
+	/*
+	 * Move the ext3 journal file, if necessary.
+	 */
+	e2fsck_move_ext3_journal(ctx);
+	return;
+}
+
+/*
+ * swapfs.c --- byte-swap an ext2 filesystem
+ */
+
+#ifdef ENABLE_SWAPFS
+
+struct swap_block_struct {
+	ext2_ino_t      ino;
+	int             isdir;
+	errcode_t       errcode;
+	char            *dir_buf;
+	struct ext2_inode *inode;
+};
+
+/*
+ * This is a helper function for block_iterate.  We mark all of the
+ * indirect and direct blocks as changed, so that block_iterate will
+ * write them out.
+ */
+static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
+		      void *priv_data)
+{
+	errcode_t       retval;
+
+	struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
+
+	if (sb->isdir && (blockcnt >= 0) && *block_nr) {
+		retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
+		if (retval) {
+			sb->errcode = retval;
+			return BLOCK_ABORT;
+		}
+		retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
+		if (retval) {
+			sb->errcode = retval;
+			return BLOCK_ABORT;
+		}
+	}
+	if (blockcnt >= 0) {
+		if (blockcnt < EXT2_NDIR_BLOCKS)
+			return 0;
+		return BLOCK_CHANGED;
+	}
+	if (blockcnt == BLOCK_COUNT_IND) {
+		if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
+			return 0;
+		return BLOCK_CHANGED;
+	}
+	if (blockcnt == BLOCK_COUNT_DIND) {
+		if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
+			return 0;
+		return BLOCK_CHANGED;
+	}
+	if (blockcnt == BLOCK_COUNT_TIND) {
+		if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
+			return 0;
+		return BLOCK_CHANGED;
+	}
+	return BLOCK_CHANGED;
+}
+
+/*
+ * This function is responsible for byte-swapping all of the indirect,
+ * block pointers.  It is also responsible for byte-swapping directories.
+ */
+static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
+			      struct ext2_inode *inode)
+{
+	errcode_t                       retval;
+	struct swap_block_struct        sb;
+
+	sb.ino = ino;
+	sb.inode = inode;
+	sb.dir_buf = block_buf + ctx->fs->blocksize*3;
+	sb.errcode = 0;
+	sb.isdir = 0;
+	if (LINUX_S_ISDIR(inode->i_mode))
+		sb.isdir = 1;
+
+	retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
+				      swap_block, &sb);
+	if (retval) {
+		bb_error_msg(_("while calling ext2fs_block_iterate"));
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+	if (sb.errcode) {
+		bb_error_msg(_("while calling iterator function"));
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+}
+
+static void swap_inodes(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	dgrp_t                  group;
+	unsigned int            i;
+	ext2_ino_t              ino = 1;
+	char                    *buf, *block_buf;
+	errcode_t               retval;
+	struct ext2_inode *     inode;
+
+	e2fsck_use_inode_shortcuts(ctx, 1);
+
+	retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
+				&buf);
+	if (retval) {
+		bb_error_msg(_("while allocating inode buffer"));
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+	block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
+						    "block interate buffer");
+	for (group = 0; group < fs->group_desc_count; group++) {
+		retval = io_channel_read_blk(fs->io,
+		      fs->group_desc[group].bg_inode_table,
+		      fs->inode_blocks_per_group, buf);
+		if (retval) {
+			bb_error_msg(_("while reading inode table (group %d)"),
+				group);
+			ctx->flags |= E2F_FLAG_ABORT;
+			return;
+		}
+		inode = (struct ext2_inode *) buf;
+		for (i=0; i < fs->super->s_inodes_per_group;
+		     i++, ino++, inode++) {
+			ctx->stashed_ino = ino;
+			ctx->stashed_inode = inode;
+
+			if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
+				ext2fs_swap_inode(fs, inode, inode, 0);
+
+			/*
+			 * Skip deleted files.
+			 */
+			if (inode->i_links_count == 0)
+				continue;
+
+			if (LINUX_S_ISDIR(inode->i_mode) ||
+			    ((inode->i_block[EXT2_IND_BLOCK] ||
+			      inode->i_block[EXT2_DIND_BLOCK] ||
+			      inode->i_block[EXT2_TIND_BLOCK]) &&
+			     ext2fs_inode_has_valid_blocks(inode)))
+				swap_inode_blocks(ctx, ino, block_buf, inode);
+
+			if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+				return;
+
+			if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
+				ext2fs_swap_inode(fs, inode, inode, 1);
+		}
+		retval = io_channel_write_blk(fs->io,
+		      fs->group_desc[group].bg_inode_table,
+		      fs->inode_blocks_per_group, buf);
+		if (retval) {
+			bb_error_msg(_("while writing inode table (group %d)"),
+				group);
+			ctx->flags |= E2F_FLAG_ABORT;
+			return;
+		}
+	}
+	ext2fs_free_mem(&buf);
+	ext2fs_free_mem(&block_buf);
+	e2fsck_use_inode_shortcuts(ctx, 0);
+	ext2fs_flush_icache(fs);
+}
+
+#if defined(__powerpc__) && BB_BIG_ENDIAN
+/*
+ * On the PowerPC, the big-endian variant of the ext2 filesystem
+ * has its bitmaps stored as 32-bit words with bit 0 as the LSB
+ * of each word.  Thus a bitmap with only bit 0 set would be, as
+ * a string of bytes, 00 00 00 01 00 ...
+ * To cope with this, we byte-reverse each word of a bitmap if
+ * we have a big-endian filesystem, that is, if we are *not*
+ * byte-swapping other word-sized numbers.
+ */
+#define EXT2_BIG_ENDIAN_BITMAPS
+#endif
+
+#ifdef EXT2_BIG_ENDIAN_BITMAPS
+static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
+{
+	__u32 *p = (__u32 *) bmap->bitmap;
+	int n, nbytes = (bmap->end - bmap->start + 7) / 8;
+
+	for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
+		*p = ext2fs_swab32(*p);
+}
+#endif
+
+
+#ifdef ENABLE_SWAPFS
+static void swap_filesys(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	if (!(ctx->options & E2F_OPT_PREEN))
+		printf(_("Pass 0: Doing byte-swap of filesystem\n"));
+
+	/* Byte swap */
+
+	if (fs->super->s_mnt_count) {
+		fprintf(stderr, _("%s: the filesystem must be freshly "
+			"checked using fsck\n"
+			"and not mounted before trying to "
+			"byte-swap it.\n"), ctx->device_name);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
+	}
+	if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
+		fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
+			       EXT2_FLAG_SWAP_BYTES_WRITE);
+		fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
+	} else {
+		fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
+		fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
+	}
+	swap_inodes(ctx);
+	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+		return;
+	if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
+		fs->flags |= EXT2_FLAG_SWAP_BYTES;
+	fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
+		       EXT2_FLAG_SWAP_BYTES_WRITE);
+
+#ifdef EXT2_BIG_ENDIAN_BITMAPS
+	e2fsck_read_bitmaps(ctx);
+	ext2fs_swap_bitmap(fs->inode_map);
+	ext2fs_swap_bitmap(fs->block_map);
+	fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
+#endif
+	fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
+	ext2fs_flush(fs);
+	fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
+}
+#endif  /* ENABLE_SWAPFS */
+
+#endif
+
+/*
+ * util.c --- miscellaneous utilities
+ */
+
+
+void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
+			     const char *description)
+{
+	void *ret;
+	char buf[256];
+
+	ret = malloc(size);
+	if (!ret) {
+		sprintf(buf, "Can't allocate %s\n", description);
+		bb_error_msg_and_die(buf);
+	}
+	memset(ret, 0, size);
+	return ret;
+}
+
+static char *string_copy(const char *str, int len)
+{
+	char    *ret;
+
+	if (!str)
+		return NULL;
+	if (!len)
+		len = strlen(str);
+	ret = malloc(len+1);
+	if (ret) {
+		strncpy(ret, str, len);
+		ret[len] = 0;
+	}
+	return ret;
+}
+
+#ifndef HAVE_CONIO_H
+static int read_a_char(void)
+{
+	char    c;
+	int     r;
+	int     fail = 0;
+
+	while(1) {
+		if (e2fsck_global_ctx &&
+		    (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
+			return 3;
+		}
+		r = read(0, &c, 1);
+		if (r == 1)
+			return c;
+		if (fail++ > 100)
+			break;
+	}
+	return EOF;
+}
+#endif
+
+static int ask_yn(const char * string, int def)
+{
+	int             c;
+	const char      *defstr;
+	static const char short_yes[] = "yY";
+	static const char short_no[] = "nN";
+
+#ifdef HAVE_TERMIOS_H
+	struct termios  termios, tmp;
+
+	tcgetattr (0, &termios);
+	tmp = termios;
+	tmp.c_lflag &= ~(ICANON | ECHO);
+	tmp.c_cc[VMIN] = 1;
+	tmp.c_cc[VTIME] = 0;
+	tcsetattr (0, TCSANOW, &tmp);
+#endif
+
+	if (def == 1)
+		defstr = "<y>";
+	else if (def == 0)
+		defstr = "<n>";
+	else
+		defstr = " (y/n)";
+	printf("%s%s? ", string, defstr);
+	while (1) {
+		fflush (stdout);
+		if ((c = read_a_char()) == EOF)
+			break;
+		if (c == 3) {
+#ifdef HAVE_TERMIOS_H
+			tcsetattr (0, TCSANOW, &termios);
+#endif
+			if (e2fsck_global_ctx &&
+			    e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
+				puts("\n");
+				longjmp(e2fsck_global_ctx->abort_loc, 1);
+			}
+			puts(_("cancelled!\n"));
+			return 0;
+		}
+		if (strchr(short_yes, (char) c)) {
+			def = 1;
+			break;
+		}
+		else if (strchr(short_no, (char) c)) {
+			def = 0;
+			break;
+		}
+		else if ((c == ' ' || c == '\n') && (def != -1))
+			break;
+	}
+	if (def)
+		puts("yes\n");
+	else
+		puts ("no\n");
+#ifdef HAVE_TERMIOS_H
+	tcsetattr (0, TCSANOW, &termios);
+#endif
+	return def;
+}
+
+int ask (e2fsck_t ctx, const char * string, int def)
+{
+	if (ctx->options & E2F_OPT_NO) {
+		printf (_("%s? no\n\n"), string);
+		return 0;
+	}
+	if (ctx->options & E2F_OPT_YES) {
+		printf (_("%s? yes\n\n"), string);
+		return 1;
+	}
+	if (ctx->options & E2F_OPT_PREEN) {
+		printf ("%s? %s\n\n", string, def ? _("yes") : _("no"));
+		return def;
+	}
+	return ask_yn(string, def);
+}
+
+void e2fsck_read_bitmaps(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	errcode_t       retval;
+
+	if (ctx->invalid_bitmaps) {
+		bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
+			ctx->device_name);
+		bb_error_msg_and_die(0);
+	}
+
+	ehandler_operation(_("reading inode and block bitmaps"));
+	retval = ext2fs_read_bitmaps(fs);
+	ehandler_operation(0);
+	if (retval) {
+		bb_error_msg(_("while retrying to read bitmaps for %s"),
+			ctx->device_name);
+		bb_error_msg_and_die(0);
+	}
+}
+
+static void e2fsck_write_bitmaps(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	errcode_t       retval;
+
+	if (ext2fs_test_bb_dirty(fs)) {
+		ehandler_operation(_("writing block bitmaps"));
+		retval = ext2fs_write_block_bitmap(fs);
+		ehandler_operation(0);
+		if (retval) {
+			bb_error_msg(_("while retrying to write block bitmaps for %s"),
+				ctx->device_name);
+			bb_error_msg_and_die(0);
+		}
+	}
+
+	if (ext2fs_test_ib_dirty(fs)) {
+		ehandler_operation(_("writing inode bitmaps"));
+		retval = ext2fs_write_inode_bitmap(fs);
+		ehandler_operation(0);
+		if (retval) {
+			bb_error_msg(_("while retrying to write inode bitmaps for %s"),
+				ctx->device_name);
+			bb_error_msg_and_die(0);
+		}
+	}
+}
+
+void preenhalt(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+
+	if (!(ctx->options & E2F_OPT_PREEN))
+		return;
+	fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
+		"RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
+	       ctx->device_name);
+	if (fs != NULL) {
+		fs->super->s_state |= EXT2_ERROR_FS;
+		ext2fs_mark_super_dirty(fs);
+		ext2fs_close(fs);
+	}
+	exit(EXIT_UNCORRECTED);
+}
+
+void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
+			      struct ext2_inode * inode, const char *proc)
+{
+	int retval;
+
+	retval = ext2fs_read_inode(ctx->fs, ino, inode);
+	if (retval) {
+		bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
+		bb_error_msg_and_die(0);
+	}
+}
+
+extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
+			       struct ext2_inode * inode, int bufsize,
+			       const char *proc)
+{
+	int retval;
+
+	retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
+	if (retval) {
+		bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
+		bb_error_msg_and_die(0);
+	}
+}
+
+extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
+			       struct ext2_inode * inode, const char *proc)
+{
+	int retval;
+
+	retval = ext2fs_write_inode(ctx->fs, ino, inode);
+	if (retval) {
+		bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
+		bb_error_msg_and_die(0);
+	}
+}
+
+blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
+		   io_manager manager)
+{
+	struct ext2_super_block *sb;
+	io_channel              io = NULL;
+	void                    *buf = NULL;
+	int                     blocksize;
+	blk_t                   superblock, ret_sb = 8193;
+
+	if (fs && fs->super) {
+		ret_sb = (fs->super->s_blocks_per_group +
+			  fs->super->s_first_data_block);
+		if (ctx) {
+			ctx->superblock = ret_sb;
+			ctx->blocksize = fs->blocksize;
+		}
+		return ret_sb;
+	}
+
+	if (ctx) {
+		if (ctx->blocksize) {
+			ret_sb = ctx->blocksize * 8;
+			if (ctx->blocksize == 1024)
+				ret_sb++;
+			ctx->superblock = ret_sb;
+			return ret_sb;
+		}
+		ctx->superblock = ret_sb;
+		ctx->blocksize = 1024;
+	}
+
+	if (!name || !manager)
+		goto cleanup;
+
+	if (manager->open(name, 0, &io) != 0)
+		goto cleanup;
+
+	if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
+		goto cleanup;
+	sb = (struct ext2_super_block *) buf;
+
+	for (blocksize = EXT2_MIN_BLOCK_SIZE;
+	     blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
+		superblock = blocksize*8;
+		if (blocksize == 1024)
+			superblock++;
+		io_channel_set_blksize(io, blocksize);
+		if (io_channel_read_blk(io, superblock,
+					-SUPERBLOCK_SIZE, buf))
+			continue;
+#if BB_BIG_ENDIAN
+		if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
+			ext2fs_swap_super(sb);
+#endif
+		if (sb->s_magic == EXT2_SUPER_MAGIC) {
+			ret_sb = superblock;
+			if (ctx) {
+				ctx->superblock = superblock;
+				ctx->blocksize = blocksize;
+			}
+			break;
+		}
+	}
+
+cleanup:
+	if (io)
+		io_channel_close(io);
+	ext2fs_free_mem(&buf);
+	return (ret_sb);
+}
+
+
+/*
+ * This function runs through the e2fsck passes and calls them all,
+ * returning restart, abort, or cancel as necessary...
+ */
+typedef void (*pass_t)(e2fsck_t ctx);
+
+static const pass_t e2fsck_passes[] = {
+	e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
+	e2fsck_pass5, 0 };
+
+#define E2F_FLAG_RUN_RETURN     (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
+
+static int e2fsck_run(e2fsck_t ctx)
+{
+	int     i;
+	pass_t  e2fsck_pass;
+
+	if (setjmp(ctx->abort_loc)) {
+		ctx->flags &= ~E2F_FLAG_SETJMP_OK;
+		return (ctx->flags & E2F_FLAG_RUN_RETURN);
+	}
+	ctx->flags |= E2F_FLAG_SETJMP_OK;
+
+	for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
+		if (ctx->flags & E2F_FLAG_RUN_RETURN)
+			break;
+		e2fsck_pass(ctx);
+		if (ctx->progress)
+			(void) (ctx->progress)(ctx, 0, 0, 0);
+	}
+	ctx->flags &= ~E2F_FLAG_SETJMP_OK;
+
+	if (ctx->flags & E2F_FLAG_RUN_RETURN)
+		return (ctx->flags & E2F_FLAG_RUN_RETURN);
+	return 0;
+}
+
+
+/*
+ * unix.c - The unix-specific code for e2fsck
+ */
+
+
+/* Command line options */
+static int swapfs;
+#ifdef ENABLE_SWAPFS
+static int normalize_swapfs;
+#endif
+static int cflag;               /* check disk */
+static int show_version_only;
+static int verbose;
+
+#define P_E2(singular, plural, n)       n, ((n) == 1 ? singular : plural)
+
+static void show_stats(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	int inodes, inodes_used, blocks, blocks_used;
+	int dir_links;
+	int num_files, num_links;
+	int frag_percent;
+
+	dir_links = 2 * ctx->fs_directory_count - 1;
+	num_files = ctx->fs_total_count - dir_links;
+	num_links = ctx->fs_links_count - dir_links;
+	inodes = fs->super->s_inodes_count;
+	inodes_used = (fs->super->s_inodes_count -
+		       fs->super->s_free_inodes_count);
+	blocks = fs->super->s_blocks_count;
+	blocks_used = (fs->super->s_blocks_count -
+		       fs->super->s_free_blocks_count);
+
+	frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
+	frag_percent = (frag_percent + 5) / 10;
+
+	if (!verbose) {
+		printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
+		       ctx->device_name, inodes_used, inodes,
+		       frag_percent / 10, frag_percent % 10,
+		       blocks_used, blocks);
+		return;
+	}
+	printf ("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
+		100 * inodes_used / inodes);
+	printf ("%8d non-contiguous inode%s (%0d.%d%%)\n",
+		P_E2("", "s", ctx->fs_fragmented),
+		frag_percent / 10, frag_percent % 10);
+	printf (_("         # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
+		ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
+	printf ("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
+		(int) ((long long) 100 * blocks_used / blocks));
+	printf ("%8d large file%s\n", P_E2("", "s", ctx->large_files));
+	printf ("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
+	printf ("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
+	printf ("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
+	printf ("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
+	printf ("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
+	printf ("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
+	printf ("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
+	printf (" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
+	printf ("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
+	printf ("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
+}
+
+static void check_mount(e2fsck_t ctx)
+{
+	errcode_t       retval;
+	int             cont;
+
+	retval = ext2fs_check_if_mounted(ctx->filesystem_name,
+					 &ctx->mount_flags);
+	if (retval) {
+		bb_error_msg(_("while determining whether %s is mounted."),
+			ctx->filesystem_name);
+		return;
+	}
+
+	/*
+	 * If the filesystem isn't mounted, or it's the root filesystem
+	 * and it's mounted read-only, then everything's fine.
+	 */
+	if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
+	    ((ctx->mount_flags & EXT2_MF_ISROOT) &&
+	     (ctx->mount_flags & EXT2_MF_READONLY)))
+		return;
+
+	if (ctx->options & E2F_OPT_READONLY) {
+		printf(_("Warning!  %s is mounted.\n"), ctx->filesystem_name);
+		return;
+	}
+
+	printf(_("%s is mounted.  "), ctx->filesystem_name);
+	if (!ctx->interactive)
+		bb_error_msg_and_die(_("Cannot continue, aborting.\n\n"));
+	printf(_("\n\n\007\007\007\007WARNING!!!  "
+	       "Running e2fsck on a mounted filesystem may cause\n"
+	       "SEVERE filesystem damage.\007\007\007\n\n"));
+	cont = ask_yn(_("Do you really want to continue"), -1);
+	if (!cont) {
+		printf (_("check aborted.\n"));
+		exit (0);
+	}
+	return;
+}
+
+static int is_on_batt(void)
+{
+	FILE    *f;
+	DIR     *d;
+	char    tmp[80], tmp2[80], fname[80];
+	unsigned int    acflag;
+	struct dirent*  de;
+
+	f = fopen("/proc/apm", "r");
+	if (f) {
+		if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
+			acflag = 1;
+		fclose(f);
+		return (acflag != 1);
+	}
+	d = opendir("/proc/acpi/ac_adapter");
+	if (d) {
+		while ((de=readdir(d)) != NULL) {
+			if (!strncmp(".", de->d_name, 1))
+				continue;
+			snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
+				 de->d_name);
+			f = fopen(fname, "r");
+			if (!f)
+				continue;
+			if (fscanf(f, "%s %s", tmp2, tmp) != 2)
+				tmp[0] = 0;
+			fclose(f);
+			if (strncmp(tmp, "off-line", 8) == 0) {
+				closedir(d);
+				return 1;
+			}
+		}
+		closedir(d);
+	}
+	return 0;
+}
+
+/*
+ * This routine checks to see if a filesystem can be skipped; if so,
+ * it will exit with EXIT_OK.  Under some conditions it will print a
+ * message explaining why a check is being forced.
+ */
+static void check_if_skip(e2fsck_t ctx)
+{
+	ext2_filsys fs = ctx->fs;
+	const char *reason = NULL;
+	unsigned int reason_arg = 0;
+	long next_check;
+	int batt = is_on_batt();
+	time_t now = time(0);
+
+	if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
+		return;
+
+	if ((fs->super->s_state & EXT2_ERROR_FS) ||
+	    !ext2fs_test_valid(fs))
+		reason = _(" contains a file system with errors");
+	else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
+		reason = _(" was not cleanly unmounted");
+	else if ((fs->super->s_max_mnt_count > 0) &&
+		 (fs->super->s_mnt_count >=
+		  (unsigned) fs->super->s_max_mnt_count)) {
+		reason = _(" has been mounted %u times without being checked");
+		reason_arg = fs->super->s_mnt_count;
+		if (batt && (fs->super->s_mnt_count <
+			     (unsigned) fs->super->s_max_mnt_count*2))
+			reason = 0;
+	} else if (fs->super->s_checkinterval &&
+		   ((now - fs->super->s_lastcheck) >=
+		    fs->super->s_checkinterval)) {
+		reason = _(" has gone %u days without being checked");
+		reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
+		if (batt && ((now - fs->super->s_lastcheck) <
+			     fs->super->s_checkinterval*2))
+			reason = 0;
+	}
+	if (reason) {
+		fputs(ctx->device_name, stdout);
+		printf(reason, reason_arg);
+		fputs(_(", check forced.\n"), stdout);
+		return;
+	}
+	printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
+	       fs->super->s_inodes_count - fs->super->s_free_inodes_count,
+	       fs->super->s_inodes_count,
+	       fs->super->s_blocks_count - fs->super->s_free_blocks_count,
+	       fs->super->s_blocks_count);
+	next_check = 100000;
+	if (fs->super->s_max_mnt_count > 0) {
+		next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
+		if (next_check <= 0)
+			next_check = 1;
+	}
+	if (fs->super->s_checkinterval &&
+	    ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
+		next_check = 1;
+	if (next_check <= 5) {
+		if (next_check == 1)
+			fputs(_(" (check after next mount)"), stdout);
+		else
+			printf(_(" (check in %ld mounts)"), next_check);
+	}
+	fputc('\n', stdout);
+	ext2fs_close(fs);
+	ctx->fs = NULL;
+	e2fsck_free_context(ctx);
+	exit(EXIT_OK);
+}
+
+/*
+ * For completion notice
+ */
+struct percent_tbl {
+	int     max_pass;
+	int     table[32];
+};
+static const struct percent_tbl e2fsck_tbl = {
+	5, { 0, 70, 90, 92,  95, 100 }
+};
+
+static char bar[128], spaces[128];
+
+static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
+			  int max)
+{
+	float   percent;
+
+	if (pass <= 0)
+		return 0.0;
+	if (pass > tbl->max_pass || max == 0)
+		return 100.0;
+	percent = ((float) curr) / ((float) max);
+	return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
+		+ tbl->table[pass-1]);
+}
+
+void e2fsck_clear_progbar(e2fsck_t ctx)
+{
+	if (!(ctx->flags & E2F_FLAG_PROG_BAR))
+		return;
+
+	printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
+	       ctx->stop_meta);
+	fflush(stdout);
+	ctx->flags &= ~E2F_FLAG_PROG_BAR;
+}
+
+int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
+			   unsigned int dpynum)
+{
+	static const char spinner[] = "\\|/-";
+	int     i;
+	unsigned int    tick;
+	struct timeval  tv;
+	int dpywidth;
+	int fixed_percent;
+
+	if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
+		return 0;
+
+	/*
+	 * Calculate the new progress position.  If the
+	 * percentage hasn't changed, then we skip out right
+	 * away.
+	 */
+	fixed_percent = (int) ((10 * percent) + 0.5);
+	if (ctx->progress_last_percent == fixed_percent)
+		return 0;
+	ctx->progress_last_percent = fixed_percent;
+
+	/*
+	 * If we've already updated the spinner once within
+	 * the last 1/8th of a second, no point doing it
+	 * again.
+	 */
+	gettimeofday(&tv, NULL);
+	tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
+	if ((tick == ctx->progress_last_time) &&
+	    (fixed_percent != 0) && (fixed_percent != 1000))
+		return 0;
+	ctx->progress_last_time = tick;
+
+	/*
+	 * Advance the spinner, and note that the progress bar
+	 * will be on the screen
+	 */
+	ctx->progress_pos = (ctx->progress_pos+1) & 3;
+	ctx->flags |= E2F_FLAG_PROG_BAR;
+
+	dpywidth = 66 - strlen(label);
+	dpywidth = 8 * (dpywidth / 8);
+	if (dpynum)
+		dpywidth -= 8;
+
+	i = ((percent * dpywidth) + 50) / 100;
+	printf("%s%s: |%s%s", ctx->start_meta, label,
+	       bar + (sizeof(bar) - (i+1)),
+	       spaces + (sizeof(spaces) - (dpywidth - i + 1)));
+	if (fixed_percent == 1000)
+		fputc('|', stdout);
+	else
+		fputc(spinner[ctx->progress_pos & 3], stdout);
+	printf(" %4.1f%%  ", percent);
+	if (dpynum)
+		printf("%u\r", dpynum);
+	else
+		fputs(" \r", stdout);
+	fputs(ctx->stop_meta, stdout);
+
+	if (fixed_percent == 1000)
+		e2fsck_clear_progbar(ctx);
+	fflush(stdout);
+
+	return 0;
+}
+
+static int e2fsck_update_progress(e2fsck_t ctx, int pass,
+				  unsigned long cur, unsigned long max)
+{
+	char buf[80];
+	float percent;
+
+	if (pass == 0)
+		return 0;
+
+	if (ctx->progress_fd) {
+		sprintf(buf, "%d %lu %lu\n", pass, cur, max);
+		write(ctx->progress_fd, buf, strlen(buf));
+	} else {
+		percent = calc_percent(&e2fsck_tbl, pass, cur, max);
+		e2fsck_simple_progress(ctx, ctx->device_name,
+				       percent, 0);
+	}
+	return 0;
+}
+
+static void reserve_stdio_fds(void)
+{
+	int     fd;
+
+	while (1) {
+		fd = open(bb_dev_null, O_RDWR);
+		if (fd > 2)
+			break;
+		if (fd < 0) {
+			fprintf(stderr, _("ERROR: Couldn't open "
+				"/dev/null (%s)\n"),
+				strerror(errno));
+			break;
+		}
+	}
+	close(fd);
+}
+
+static void signal_progress_on(int sig FSCK_ATTR((unused)))
+{
+	e2fsck_t ctx = e2fsck_global_ctx;
+
+	if (!ctx)
+		return;
+
+	ctx->progress = e2fsck_update_progress;
+	ctx->progress_fd = 0;
+}
+
+static void signal_progress_off(int sig FSCK_ATTR((unused)))
+{
+	e2fsck_t ctx = e2fsck_global_ctx;
+
+	if (!ctx)
+		return;
+
+	e2fsck_clear_progbar(ctx);
+	ctx->progress = 0;
+}
+
+static void signal_cancel(int sig FSCK_ATTR((unused)))
+{
+	e2fsck_t ctx = e2fsck_global_ctx;
+
+	if (!ctx)
+		exit(FSCK_CANCELED);
+
+	ctx->flags |= E2F_FLAG_CANCEL;
+}
+
+static void parse_extended_opts(e2fsck_t ctx, const char *opts)
+{
+	char    *buf, *token, *next, *p, *arg;
+	int     ea_ver;
+	int     extended_usage = 0;
+
+	buf = string_copy(opts, 0);
+	for (token = buf; token && *token; token = next) {
+		p = strchr(token, ',');
+		next = 0;
+		if (p) {
+			*p = 0;
+			next = p+1;
+		}
+		arg = strchr(token, '=');
+		if (arg) {
+			*arg = 0;
+			arg++;
+		}
+		if (strcmp(token, "ea_ver") == 0) {
+			if (!arg) {
+				extended_usage++;
+				continue;
+			}
+			ea_ver = strtoul(arg, &p, 0);
+			if (*p ||
+			    ((ea_ver != 1) && (ea_ver != 2))) {
+				fprintf(stderr,
+					_("Invalid EA version.\n"));
+				extended_usage++;
+				continue;
+			}
+			ctx->ext_attr_ver = ea_ver;
+		} else {
+			fprintf(stderr, _("Unknown extended option: %s\n"),
+				token);
+			extended_usage++;
+		}
+	}
+	if (extended_usage) {
+		bb_error_msg_and_die(
+			"Extended options are separated by commas, "
+			"and may take an argument which\n"
+			"is set off by an equals ('=') sign.  "
+			"Valid extended options are:\n"
+			"\tea_ver=<ea_version (1 or 2)>\n\n");
+	}
+}
+
+
+static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
+{
+	int             flush = 0;
+	int             c, fd;
+	e2fsck_t        ctx;
+	errcode_t       retval;
+	struct sigaction        sa;
+	char            *extended_opts = 0;
+
+	retval = e2fsck_allocate_context(&ctx);
+	if (retval)
+		return retval;
+
+	*ret_ctx = ctx;
+
+	setvbuf(stdout, NULL, _IONBF, BUFSIZ);
+	setvbuf(stderr, NULL, _IONBF, BUFSIZ);
+	if (isatty(0) && isatty(1)) {
+		ctx->interactive = 1;
+	} else {
+		ctx->start_meta[0] = '\001';
+		ctx->stop_meta[0] = '\002';
+	}
+	memset(bar, '=', sizeof(bar)-1);
+	memset(spaces, ' ', sizeof(spaces)-1);
+	blkid_get_cache(&ctx->blkid, NULL);
+
+	if (argc && *argv)
+		ctx->program_name = *argv;
+	else
+		ctx->program_name = "e2fsck";
+	while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
+		switch (c) {
+		case 'C':
+			ctx->progress = e2fsck_update_progress;
+			ctx->progress_fd = atoi(optarg);
+			if (!ctx->progress_fd)
+				break;
+			/* Validate the file descriptor to avoid disasters */
+			fd = dup(ctx->progress_fd);
+			if (fd < 0) {
+				fprintf(stderr,
+				_("Error validating file descriptor %d: %s\n"),
+					ctx->progress_fd,
+					error_message(errno));
+				bb_error_msg_and_die(_("Invalid completion information file descriptor"));
+			} else
+				close(fd);
+			break;
+		case 'D':
+			ctx->options |= E2F_OPT_COMPRESS_DIRS;
+			break;
+		case 'E':
+			extended_opts = optarg;
+			break;
+		case 'p':
+		case 'a':
+			if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
+			conflict_opt:
+				bb_error_msg_and_die(_("Only one the options -p/-a, -n or -y may be specified."));
+			}
+			ctx->options |= E2F_OPT_PREEN;
+			break;
+		case 'n':
+			if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
+				goto conflict_opt;
+			ctx->options |= E2F_OPT_NO;
+			break;
+		case 'y':
+			if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
+				goto conflict_opt;
+			ctx->options |= E2F_OPT_YES;
+			break;
+		case 't':
+			/* FIXME - This needs to go away in a future path - will change binary */
+			fprintf(stderr, _("The -t option is not "
+				"supported on this version of e2fsck.\n"));
+			break;
+		case 'c':
+			if (cflag++)
+				ctx->options |= E2F_OPT_WRITECHECK;
+			ctx->options |= E2F_OPT_CHECKBLOCKS;
+			break;
+		case 'r':
+			/* What we do by default, anyway! */
+			break;
+		case 'b':
+			ctx->use_superblock = atoi(optarg);
+			ctx->flags |= E2F_FLAG_SB_SPECIFIED;
+			break;
+		case 'B':
+			ctx->blocksize = atoi(optarg);
+			break;
+		case 'I':
+			ctx->inode_buffer_blocks = atoi(optarg);
+			break;
+		case 'j':
+			ctx->journal_name = string_copy(optarg, 0);
+			break;
+		case 'P':
+			ctx->process_inode_size = atoi(optarg);
+			break;
+		case 'd':
+			ctx->options |= E2F_OPT_DEBUG;
+			break;
+		case 'f':
+			ctx->options |= E2F_OPT_FORCE;
+			break;
+		case 'F':
+			flush = 1;
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case 'V':
+			show_version_only = 1;
+			break;
+		case 'N':
+			ctx->device_name = optarg;
+			break;
+#ifdef ENABLE_SWAPFS
+		case 's':
+			normalize_swapfs = 1;
+		case 'S':
+			swapfs = 1;
+			break;
+#else
+		case 's':
+		case 'S':
+			fprintf(stderr, _("Byte-swapping filesystems "
+					  "not compiled in this version "
+					  "of e2fsck\n"));
+			exit(1);
+#endif
+		default:
+			bb_show_usage();
+		}
+	if (show_version_only)
+		return 0;
+	if (optind != argc - 1)
+		bb_show_usage();
+	if ((ctx->options & E2F_OPT_NO) &&
+	    !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
+		ctx->options |= E2F_OPT_READONLY;
+	ctx->io_options = strchr(argv[optind], '?');
+	if (ctx->io_options)
+		*ctx->io_options++ = 0;
+	ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
+	if (!ctx->filesystem_name) {
+		bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
+		bb_error_msg_and_die(0);
+	}
+	if (extended_opts)
+		parse_extended_opts(ctx, extended_opts);
+
+	if (flush) {
+		fd = open(ctx->filesystem_name, O_RDONLY, 0);
+		if (fd < 0) {
+			bb_error_msg(_("while opening %s for flushing"),
+				ctx->filesystem_name);
+			bb_error_msg_and_die(0);
+		}
+		if ((retval = ext2fs_sync_device(fd, 1))) {
+			bb_error_msg(_("while trying to flush %s"),
+				ctx->filesystem_name);
+			bb_error_msg_and_die(0);
+		}
+		close(fd);
+	}
+#ifdef ENABLE_SWAPFS
+	if (swapfs && cflag) {
+			fprintf(stderr, _("Incompatible options not "
+					  "allowed when byte-swapping.\n"));
+			exit(EXIT_USAGE);
+	}
+#endif
+	/*
+	 * Set up signal action
+	 */
+	memset(&sa, 0, sizeof(struct sigaction));
+	sa.sa_handler = signal_cancel;
+	sigaction(SIGINT, &sa, 0);
+	sigaction(SIGTERM, &sa, 0);
+#ifdef SA_RESTART
+	sa.sa_flags = SA_RESTART;
+#endif
+	e2fsck_global_ctx = ctx;
+	sa.sa_handler = signal_progress_on;
+	sigaction(SIGUSR1, &sa, 0);
+	sa.sa_handler = signal_progress_off;
+	sigaction(SIGUSR2, &sa, 0);
+
+	/* Update our PATH to include /sbin if we need to run badblocks  */
+	if (cflag)
+		e2fs_set_sbin_path();
+	return 0;
+}
+
+static const char my_ver_string[] = E2FSPROGS_VERSION;
+static const char my_ver_date[] = E2FSPROGS_DATE;
+
+int e2fsck_main (int argc, char *argv[])
+{
+	errcode_t       retval;
+	int             exit_value = EXIT_OK;
+	ext2_filsys     fs = 0;
+	io_manager      io_ptr;
+	struct ext2_super_block *sb;
+	const char      *lib_ver_date;
+	int             my_ver, lib_ver;
+	e2fsck_t        ctx;
+	struct problem_context pctx;
+	int flags, run_result;
+
+	clear_problem_context(&pctx);
+
+	my_ver = ext2fs_parse_version_string(my_ver_string);
+	lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
+	if (my_ver > lib_ver) {
+		fprintf( stderr, _("Error: ext2fs library version "
+			"out of date!\n"));
+		show_version_only++;
+	}
+
+	retval = PRS(argc, argv, &ctx);
+	if (retval) {
+		bb_error_msg(_("while trying to initialize program"));
+		exit(EXIT_ERROR);
+	}
+	reserve_stdio_fds();
+
+	if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
+		fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
+			 my_ver_date);
+
+	if (show_version_only) {
+		fprintf(stderr, _("\tUsing %s, %s\n"),
+			error_message(EXT2_ET_BASE), lib_ver_date);
+		exit(EXIT_OK);
+	}
+
+	check_mount(ctx);
+
+	if (!(ctx->options & E2F_OPT_PREEN) &&
+	    !(ctx->options & E2F_OPT_NO) &&
+	    !(ctx->options & E2F_OPT_YES)) {
+		if (!ctx->interactive)
+			bb_error_msg_and_die(_("need terminal for interactive repairs"));
+	}
+	ctx->superblock = ctx->use_superblock;
+restart:
+#ifdef CONFIG_TESTIO_DEBUG
+	io_ptr = test_io_manager;
+	test_io_backing_manager = unix_io_manager;
+#else
+	io_ptr = unix_io_manager;
+#endif
+	flags = 0;
+	if ((ctx->options & E2F_OPT_READONLY) == 0)
+		flags |= EXT2_FLAG_RW;
+
+	if (ctx->superblock && ctx->blocksize) {
+		retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
+				      flags, ctx->superblock, ctx->blocksize,
+				      io_ptr, &fs);
+	} else if (ctx->superblock) {
+		int blocksize;
+		for (blocksize = EXT2_MIN_BLOCK_SIZE;
+		     blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
+			retval = ext2fs_open2(ctx->filesystem_name,
+					      ctx->io_options, flags,
+					      ctx->superblock, blocksize,
+					      io_ptr, &fs);
+			if (!retval)
+				break;
+		}
+	} else
+		retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
+				      flags, 0, 0, io_ptr, &fs);
+	if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
+	    !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
+	    ((retval == EXT2_ET_BAD_MAGIC) ||
+	     ((retval == 0) && ext2fs_check_desc(fs)))) {
+		if (!fs || (fs->group_desc_count > 1)) {
+			printf(_("%s trying backup blocks...\n"),
+			       retval ? _("Couldn't find ext2 superblock,") :
+			       _("Group descriptors look bad..."));
+			get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
+			if (fs)
+				ext2fs_close(fs);
+			goto restart;
+		}
+	}
+	if (retval) {
+		bb_error_msg(_("while trying to open %s"),
+			ctx->filesystem_name);
+		if (retval == EXT2_ET_REV_TOO_HIGH) {
+			printf(_("The filesystem revision is apparently "
+			       "too high for this version of e2fsck.\n"
+			       "(Or the filesystem superblock "
+			       "is corrupt)\n\n"));
+			fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
+		} else if (retval == EXT2_ET_SHORT_READ)
+			printf(_("Could this be a zero-length partition?\n"));
+		else if ((retval == EPERM) || (retval == EACCES))
+			printf(_("You must have %s access to the "
+			       "filesystem or be root\n"),
+			       (ctx->options & E2F_OPT_READONLY) ?
+			       "r/o" : "r/w");
+		else if (retval == ENXIO)
+			printf(_("Possibly non-existent or swap device?\n"));
+#ifdef EROFS
+		else if (retval == EROFS)
+			printf(_("Disk write-protected; use the -n option "
+			       "to do a read-only\n"
+			       "check of the device.\n"));
+#endif
+		else
+			fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
+		bb_error_msg_and_die(0);
+	}
+	ctx->fs = fs;
+	fs->priv_data = ctx;
+	sb = fs->super;
+	if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
+		bb_error_msg(_("while trying to open %s"),
+			ctx->filesystem_name);
+	get_newer:
+		bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
+	}
+
+	/*
+	 * Set the device name, which is used whenever we print error
+	 * or informational messages to the user.
+	 */
+	if (ctx->device_name == 0 &&
+	    (sb->s_volume_name[0] != 0)) {
+		ctx->device_name = string_copy(sb->s_volume_name,
+					       sizeof(sb->s_volume_name));
+	}
+	if (ctx->device_name == 0)
+		ctx->device_name = ctx->filesystem_name;
+
+	/*
+	 * Make sure the ext3 superblock fields are consistent.
+	 */
+	retval = e2fsck_check_ext3_journal(ctx);
+	if (retval) {
+		bb_error_msg(_("while checking ext3 journal for %s"),
+			ctx->device_name);
+		bb_error_msg_and_die(0);
+	}
+
+	/*
+	 * Check to see if we need to do ext3-style recovery.  If so,
+	 * do it, and then restart the fsck.
+	 */
+	if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
+		if (ctx->options & E2F_OPT_READONLY) {
+			printf(_("Warning: skipping journal recovery "
+				 "because doing a read-only filesystem "
+				 "check.\n"));
+			io_channel_flush(ctx->fs->io);
+		} else {
+			if (ctx->flags & E2F_FLAG_RESTARTED) {
+				/*
+				 * Whoops, we attempted to run the
+				 * journal twice.  This should never
+				 * happen, unless the hardware or
+				 * device driver is being bogus.
+				 */
+				bb_error_msg(_("unable to set superblock flags on %s\n"), ctx->device_name);
+				bb_error_msg_and_die(0);
+			}
+			retval = e2fsck_run_ext3_journal(ctx);
+			if (retval) {
+				bb_error_msg(_("while recovering ext3 journal of %s"),
+					ctx->device_name);
+				bb_error_msg_and_die(0);
+			}
+			ext2fs_close(ctx->fs);
+			ctx->fs = 0;
+			ctx->flags |= E2F_FLAG_RESTARTED;
+			goto restart;
+		}
+	}
+
+	/*
+	 * Check for compatibility with the feature sets.  We need to
+	 * be more stringent than ext2fs_open().
+	 */
+	if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
+	    (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
+		bb_error_msg("(%s)", ctx->device_name);
+		goto get_newer;
+	}
+	if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
+		bb_error_msg("(%s)", ctx->device_name);
+		goto get_newer;
+	}
+#ifdef ENABLE_COMPRESSION
+	/* FIXME - do we support this at all? */
+	if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
+		bb_error_msg(_("Warning: compression support is experimental.\n"));
+#endif
+#ifndef ENABLE_HTREE
+	if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
+		bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
+			  "but filesystem %s has HTREE directories.\n"),
+			ctx->device_name);
+		goto get_newer;
+	}
+#endif
+
+	/*
+	 * If the user specified a specific superblock, presumably the
+	 * master superblock has been trashed.  So we mark the
+	 * superblock as dirty, so it can be written out.
+	 */
+	if (ctx->superblock &&
+	    !(ctx->options & E2F_OPT_READONLY))
+		ext2fs_mark_super_dirty(fs);
+
+	/*
+	 * We only update the master superblock because (a) paranoia;
+	 * we don't want to corrupt the backup superblocks, and (b) we
+	 * don't need to update the mount count and last checked
+	 * fields in the backup superblock (the kernel doesn't
+	 * update the backup superblocks anyway).
+	 */
+	fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
+
+	ehandler_init(fs->io);
+
+	if (ctx->superblock)
+		set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
+	ext2fs_mark_valid(fs);
+	check_super_block(ctx);
+	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+		bb_error_msg_and_die(0);
+	check_if_skip(ctx);
+	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+		bb_error_msg_and_die(0);
+#ifdef ENABLE_SWAPFS
+
+#ifdef WORDS_BIGENDIAN
+#define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
+#else
+#define NATIVE_FLAG 0
+#endif
+
+
+	if (normalize_swapfs) {
+		if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
+			fprintf(stderr, _("%s: Filesystem byte order "
+				"already normalized.\n"), ctx->device_name);
+			bb_error_msg_and_die(0);
+		}
+	}
+	if (swapfs) {
+		swap_filesys(ctx);
+		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+			bb_error_msg_and_die(0);
+	}
+#endif
+
+	/*
+	 * Mark the system as valid, 'til proven otherwise
+	 */
+	ext2fs_mark_valid(fs);
+
+	retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
+	if (retval) {
+		bb_error_msg(_("while reading bad blocks inode"));
+		preenhalt(ctx);
+		printf(_("This doesn't bode well,"
+			 " but we'll try to go on...\n"));
+	}
+
+	run_result = e2fsck_run(ctx);
+	e2fsck_clear_progbar(ctx);
+	if (run_result == E2F_FLAG_RESTART) {
+		printf(_("Restarting e2fsck from the beginning...\n"));
+		retval = e2fsck_reset_context(ctx);
+		if (retval) {
+			bb_error_msg(_("while resetting context"));
+			bb_error_msg_and_die(0);
+		}
+		ext2fs_close(fs);
+		goto restart;
+	}
+	if (run_result & E2F_FLAG_CANCEL) {
+		printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
+		       ctx->device_name : ctx->filesystem_name);
+		exit_value |= FSCK_CANCELED;
+	}
+	if (run_result & E2F_FLAG_ABORT)
+		bb_error_msg_and_die(_("aborted"));
+
+	/* Cleanup */
+	if (ext2fs_test_changed(fs)) {
+		exit_value |= EXIT_NONDESTRUCT;
+		if (!(ctx->options & E2F_OPT_PREEN))
+		    printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
+			       ctx->device_name);
+		if (ctx->mount_flags & EXT2_MF_ISROOT) {
+			printf(_("%s: ***** REBOOT LINUX *****\n"),
+			       ctx->device_name);
+			exit_value |= EXIT_DESTRUCT;
+		}
+	}
+	if (!ext2fs_test_valid(fs)) {
+		printf(_("\n%s: ********** WARNING: Filesystem still has "
+			 "errors **********\n\n"), ctx->device_name);
+		exit_value |= EXIT_UNCORRECTED;
+		exit_value &= ~EXIT_NONDESTRUCT;
+	}
+	if (exit_value & FSCK_CANCELED)
+		exit_value &= ~EXIT_NONDESTRUCT;
+	else {
+		show_stats(ctx);
+		if (!(ctx->options & E2F_OPT_READONLY)) {
+			if (ext2fs_test_valid(fs)) {
+				if (!(sb->s_state & EXT2_VALID_FS))
+					exit_value |= EXIT_NONDESTRUCT;
+				sb->s_state = EXT2_VALID_FS;
+			} else
+				sb->s_state &= ~EXT2_VALID_FS;
+			sb->s_mnt_count = 0;
+			sb->s_lastcheck = time(NULL);
+			ext2fs_mark_super_dirty(fs);
+		}
+	}
+
+	e2fsck_write_bitmaps(ctx);
+
+	ext2fs_close(fs);
+	ctx->fs = NULL;
+	free(ctx->filesystem_name);
+	free(ctx->journal_name);
+	e2fsck_free_context(ctx);
+
+	return exit_value;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2fsck.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2fsck.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2fsck.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,644 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <time.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <setjmp.h>
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
+#include <stddef.h>
+#include <assert.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <mntent.h>
+#include <dirent.h>
+#include "ext2fs/kernel-list.h"
+#include <sys/types.h>
+#include <linux/types.h>
+
+/*
+ * Now pull in the real linux/jfs.h definitions.
+ */
+#include "ext2fs/kernel-jbd.h"
+
+
+
+#include "fsck.h"
+
+#include "ext2fs/ext2_fs.h"
+#include "blkid/blkid.h"
+#include "ext2fs/ext2_ext_attr.h"
+#include "uuid/uuid.h"
+#include "busybox.h"
+
+#ifdef HAVE_CONIO_H
+#undef HAVE_TERMIOS_H
+#include <conio.h>
+#define read_a_char()   getch()
+#else
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+#endif
+
+
+/*
+ * The last ext2fs revision level that this version of e2fsck is able to
+ * support
+ */
+#define E2FSCK_CURRENT_REV      1
+
+/* Used by the region allocation code */
+typedef __u32 region_addr_t;
+typedef struct region_struct *region_t;
+
+struct dx_dirblock_info {
+	int             type;
+	blk_t           phys;
+	int             flags;
+	blk_t           parent;
+	ext2_dirhash_t  min_hash;
+	ext2_dirhash_t  max_hash;
+	ext2_dirhash_t  node_min_hash;
+	ext2_dirhash_t  node_max_hash;
+};
+
+/*
+These defines are used in the type field of dx_dirblock_info
+*/
+
+#define DX_DIRBLOCK_ROOT        1
+#define DX_DIRBLOCK_LEAF        2
+#define DX_DIRBLOCK_NODE        3
+
+
+/*
+The following defines are used in the 'flags' field of a dx_dirblock_info
+*/
+#define DX_FLAG_REFERENCED      1
+#define DX_FLAG_DUP_REF         2
+#define DX_FLAG_FIRST           4
+#define DX_FLAG_LAST            8
+
+/*
+ * E2fsck options
+ */
+#define E2F_OPT_READONLY        0x0001
+#define E2F_OPT_PREEN           0x0002
+#define E2F_OPT_YES             0x0004
+#define E2F_OPT_NO              0x0008
+#define E2F_OPT_TIME            0x0010
+#define E2F_OPT_CHECKBLOCKS     0x0040
+#define E2F_OPT_DEBUG           0x0080
+#define E2F_OPT_FORCE           0x0100
+#define E2F_OPT_WRITECHECK      0x0200
+#define E2F_OPT_COMPRESS_DIRS   0x0400
+
+/*
+ * E2fsck flags
+ */
+#define E2F_FLAG_ABORT          0x0001 /* Abort signaled */
+#define E2F_FLAG_CANCEL         0x0002 /* Cancel signaled */
+#define E2F_FLAG_SIGNAL_MASK    0x0003
+#define E2F_FLAG_RESTART        0x0004 /* Restart signaled */
+
+#define E2F_FLAG_SETJMP_OK      0x0010 /* Setjmp valid for abort */
+
+#define E2F_FLAG_PROG_BAR       0x0020 /* Progress bar on screen */
+#define E2F_FLAG_PROG_SUPPRESS  0x0040 /* Progress suspended */
+#define E2F_FLAG_JOURNAL_INODE  0x0080 /* Create a new ext3 journal inode */
+#define E2F_FLAG_SB_SPECIFIED   0x0100 /* The superblock was explicitly
+					* specified by the user */
+#define E2F_FLAG_RESTARTED      0x0200 /* E2fsck has been restarted */
+#define E2F_FLAG_RESIZE_INODE   0x0400 /* Request to recreate resize inode */
+
+
+/*Don't know where these come from*/
+#define READ 0
+#define WRITE 1
+#define cpu_to_be32(n) htonl(n)
+#define be32_to_cpu(n) ntohl(n)
+
+/*
+ * We define a set of "latch groups"; these are problems which are
+ * handled as a set.  The user answers once for a particular latch
+ * group.
+ */
+#define PR_LATCH_MASK         0x0ff0 /* Latch mask */
+#define PR_LATCH_BLOCK        0x0010 /* Latch for illegal blocks (pass 1) */
+#define PR_LATCH_BBLOCK       0x0020 /* Latch for bad block inode blocks (pass 1) */
+#define PR_LATCH_IBITMAP      0x0030 /* Latch for pass 5 inode bitmap proc. */
+#define PR_LATCH_BBITMAP      0x0040 /* Latch for pass 5 inode bitmap proc. */
+#define PR_LATCH_RELOC        0x0050 /* Latch for superblock relocate hint */
+#define PR_LATCH_DBLOCK       0x0060 /* Latch for pass 1b dup block headers */
+#define PR_LATCH_LOW_DTIME    0x0070 /* Latch for pass1 orphaned list refugees */
+#define PR_LATCH_TOOBIG       0x0080 /* Latch for file to big errors */
+#define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */
+
+#define PR_LATCH(x)     ((((x) & PR_LATCH_MASK) >> 4) - 1)
+
+/*
+ * Latch group descriptor flags
+ */
+#define PRL_YES         0x0001  /* Answer yes */
+#define PRL_NO          0x0002  /* Answer no */
+#define PRL_LATCHED     0x0004  /* The latch group is latched */
+#define PRL_SUPPRESS    0x0008  /* Suppress all latch group questions */
+
+#define PRL_VARIABLE    0x000f  /* All the flags that need to be reset */
+
+/*
+ * Pre-Pass 1 errors
+ */
+
+#define PR_0_BB_NOT_GROUP       0x000001  /* Block bitmap not in group */
+#define PR_0_IB_NOT_GROUP       0x000002  /* Inode bitmap not in group */
+#define PR_0_ITABLE_NOT_GROUP   0x000003  /* Inode table not in group */
+#define PR_0_SB_CORRUPT         0x000004  /* Superblock corrupt */
+#define PR_0_FS_SIZE_WRONG      0x000005  /* Filesystem size is wrong */
+#define PR_0_NO_FRAGMENTS       0x000006  /* Fragments not supported */
+#define PR_0_BLOCKS_PER_GROUP   0x000007  /* Bad blocks_per_group */
+#define PR_0_FIRST_DATA_BLOCK   0x000008  /* Bad first_data_block */
+#define PR_0_ADD_UUID           0x000009  /* Adding UUID to filesystem */
+#define PR_0_RELOCATE_HINT      0x00000A  /* Relocate hint */
+#define PR_0_MISC_CORRUPT_SUPER 0x00000B  /* Miscellaneous superblock corruption */
+#define PR_0_GETSIZE_ERROR      0x00000C  /* Error determing physical device size of filesystem */
+#define PR_0_INODE_COUNT_WRONG  0x00000D  /* Inode count in the superblock incorrect */
+#define PR_0_HURD_CLEAR_FILETYPE 0x00000E /* The Hurd does not support the filetype feature */
+#define PR_0_JOURNAL_BAD_INODE  0x00000F  /* The Hurd does not support the filetype feature */
+#define PR_0_JOURNAL_UNSUPP_MULTIFS 0x000010 /* The external journal has multiple filesystems (which we can't handle yet) */
+#define PR_0_CANT_FIND_JOURNAL  0x000011  /* Can't find external journal */
+#define PR_0_EXT_JOURNAL_BAD_SUPER 0x000012/* External journal has bad superblock */
+#define PR_0_JOURNAL_BAD_UUID   0x000013  /* Superblock has a bad journal UUID */
+#define PR_0_JOURNAL_UNSUPP_SUPER 0x000014 /* Journal has an unknown superblock type */
+#define PR_0_JOURNAL_BAD_SUPER  0x000015  /* Journal superblock is corrupt */
+#define PR_0_JOURNAL_HAS_JOURNAL 0x000016 /* Journal superblock is corrupt */
+#define PR_0_JOURNAL_RECOVER_SET 0x000017 /* Superblock has recovery flag set but no journal */
+#define PR_0_JOURNAL_RECOVERY_CLEAR 0x000018 /* Journal has data, but recovery flag is clear */
+#define PR_0_JOURNAL_RESET_JOURNAL 0x000019 /* Ask if we should clear the journal */
+#define PR_0_FS_REV_LEVEL       0x00001A  /* Filesystem revision is 0, but feature flags are set */
+#define PR_0_ORPHAN_CLEAR_INODE             0x000020 /* Clearing orphan inode */
+#define PR_0_ORPHAN_ILLEGAL_BLOCK_NUM       0x000021 /* Illegal block found in orphaned inode */
+#define PR_0_ORPHAN_ALREADY_CLEARED_BLOCK   0x000022 /* Already cleared block found in orphaned inode */
+#define PR_0_ORPHAN_ILLEGAL_HEAD_INODE      0x000023 /* Illegal orphan inode in superblock */
+#define PR_0_ORPHAN_ILLEGAL_INODE           0x000024 /* Illegal inode in orphaned inode list */
+#define PR_0_JOURNAL_UNSUPP_ROCOMPAT        0x000025 /* Journal has unsupported read-only feature - abort */
+#define PR_0_JOURNAL_UNSUPP_INCOMPAT        0x000026 /* Journal has unsupported incompatible feature - abort */
+#define PR_0_JOURNAL_UNSUPP_VERSION         0x000027 /* Journal has unsupported version number */
+#define PR_0_MOVE_JOURNAL                   0x000028 /* Moving journal to hidden file */
+#define PR_0_ERR_MOVE_JOURNAL               0x000029 /* Error moving journal */
+#define PR_0_CLEAR_V2_JOURNAL               0x00002A /* Clearing V2 journal superblock */
+#define PR_0_JOURNAL_RUN                    0x00002B /* Run journal anyway */
+#define PR_0_JOURNAL_RUN_DEFAULT            0x00002C /* Run journal anyway by default */
+#define PR_0_BACKUP_JNL                     0x00002D /* Backup journal inode blocks */
+#define PR_0_NONZERO_RESERVED_GDT_BLOCKS    0x00002E /* Reserved blocks w/o resize_inode */
+#define PR_0_CLEAR_RESIZE_INODE             0x00002F /* Resize_inode not enabled, but resize inode is non-zero */
+#define PR_0_RESIZE_INODE_INVALID           0x000030 /* Resize inode invalid */
+
+/*
+ * Pass 1 errors
+ */
+
+#define PR_1_PASS_HEADER              0x010000  /* Pass 1: Checking inodes, blocks, and sizes */
+#define PR_1_ROOT_NO_DIR              0x010001  /* Root directory is not an inode */
+#define PR_1_ROOT_DTIME               0x010002  /* Root directory has dtime set */
+#define PR_1_RESERVED_BAD_MODE        0x010003  /* Reserved inode has bad mode */
+#define PR_1_ZERO_DTIME               0x010004  /* Deleted inode has zero dtime */
+#define PR_1_SET_DTIME                0x010005  /* Inode in use, but dtime set */
+#define PR_1_ZERO_LENGTH_DIR          0x010006  /* Zero-length directory */
+#define PR_1_BB_CONFLICT              0x010007  /* Block bitmap conflicts with some other fs block */
+#define PR_1_IB_CONFLICT              0x010008  /* Inode bitmap conflicts with some other fs block */
+#define PR_1_ITABLE_CONFLICT          0x010009  /* Inode table conflicts with some other fs block */
+#define PR_1_BB_BAD_BLOCK             0x01000A  /* Block bitmap is on a bad block */
+#define PR_1_IB_BAD_BLOCK             0x01000B  /* Inode bitmap is on a bad block */
+#define PR_1_BAD_I_SIZE               0x01000C  /* Inode has incorrect i_size */
+#define PR_1_BAD_I_BLOCKS             0x01000D  /* Inode has incorrect i_blocks */
+#define PR_1_ILLEGAL_BLOCK_NUM        0x01000E  /* Illegal block number in inode */
+#define PR_1_BLOCK_OVERLAPS_METADATA  0x01000F  /* Block number overlaps fs metadata */
+#define PR_1_INODE_BLOCK_LATCH        0x010010  /* Inode has illegal blocks (latch question) */
+#define PR_1_TOO_MANY_BAD_BLOCKS      0x010011  /* Too many bad blocks in inode */
+#define PR_1_BB_ILLEGAL_BLOCK_NUM     0x010012  /* Illegal block number in bad block inode */
+#define PR_1_INODE_BBLOCK_LATCH       0x010013  /* Bad block inode has illegal blocks (latch question) */
+#define PR_1_DUP_BLOCKS_PREENSTOP     0x010014  /* Duplicate or bad blocks in use! */
+#define PR_1_BBINODE_BAD_METABLOCK    0x010015  /* Bad block used as bad block indirect block */
+#define PR_1_BBINODE_BAD_METABLOCK_PROMPT 0x010016 /* Inconsistency can't be fixed prompt */
+#define PR_1_BAD_PRIMARY_BLOCK        0x010017  /* Bad primary block */
+#define PR_1_BAD_PRIMARY_BLOCK_PROMPT 0x010018  /* Bad primary block prompt */
+#define PR_1_BAD_PRIMARY_SUPERBLOCK   0x010019  /* Bad primary superblock */
+#define PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR 0x01001A /* Bad primary block group descriptors */
+#define PR_1_BAD_SUPERBLOCK           0x01001B  /* Bad superblock in group */
+#define PR_1_BAD_GROUP_DESCRIPTORS    0x01001C  /* Bad block group descriptors in group */
+#define PR_1_PROGERR_CLAIMED_BLOCK    0x01001D  /* Block claimed for no reason */
+#define PR_1_RELOC_BLOCK_ALLOCATE     0x01001E  /* Error allocating blocks for relocating metadata */
+#define PR_1_RELOC_MEMORY_ALLOCATE    0x01001F  /* Error allocating block buffer during relocation process */
+#define PR_1_RELOC_FROM_TO            0x010020  /* Relocating metadata group information from X to Y */
+#define PR_1_RELOC_TO                 0x010021  /* Relocating metatdata group information to X */
+#define PR_1_RELOC_READ_ERR           0x010022  /* Block read error during relocation process */
+#define PR_1_RELOC_WRITE_ERR          0x010023  /* Block write error during relocation process */
+#define PR_1_ALLOCATE_IBITMAP_ERROR   0x010024  /* Error allocating inode bitmap */
+#define PR_1_ALLOCATE_BBITMAP_ERROR   0x010025  /* Error allocating block bitmap */
+#define PR_1_ALLOCATE_ICOUNT          0x010026  /* Error allocating icount structure */
+#define PR_1_ALLOCATE_DBCOUNT         0x010027  /* Error allocating dbcount */
+#define PR_1_ISCAN_ERROR              0x010028  /* Error while scanning inodes */
+#define PR_1_BLOCK_ITERATE            0x010029  /* Error while iterating over blocks */
+#define PR_1_ICOUNT_STORE             0x01002A  /* Error while storing inode count information */
+#define PR_1_ADD_DBLOCK               0x01002B  /* Error while storing directory block information */
+#define PR_1_READ_INODE               0x01002C  /* Error while reading inode (for clearing) */
+#define PR_1_SUPPRESS_MESSAGES        0x01002D  /* Suppress messages prompt */
+#define PR_1_SET_IMAGIC    0x01002F  /* Imagic flag set on an inode when filesystem doesn't support it */
+#define PR_1_SET_IMMUTABLE            0x010030  /* Immutable flag set on a device or socket inode */
+#define PR_1_COMPR_SET                0x010031  /* Compression flag set on a non-compressed filesystem */
+#define PR_1_SET_NONZSIZE             0x010032  /* Non-zero size on on device, fifo or socket inode */
+#define PR_1_FS_REV_LEVEL             0x010033  /* Filesystem revision is 0, but feature flags are set */
+#define PR_1_JOURNAL_INODE_NOT_CLEAR  0x010034  /* Journal inode not in use, needs clearing */
+#define PR_1_JOURNAL_BAD_MODE         0x010035  /* Journal inode has wrong mode */
+#define PR_1_LOW_DTIME                0x010036  /* Inode that was part of orphan linked list */
+#define PR_1_ORPHAN_LIST_REFUGEES     0x010037  /* Latch question which asks how to deal with low dtime inodes */
+#define PR_1_ALLOCATE_REFCOUNT        0x010038  /* Error allocating refcount structure */
+#define PR_1_READ_EA_BLOCK            0x010039  /* Error reading Extended Attribute block */
+#define PR_1_BAD_EA_BLOCK             0x01003A  /* Invalid Extended Attribute block */
+#define PR_1_EXTATTR_READ_ABORT   0x01003B  /* Error reading Extended Attribute block while fixing refcount -- abort */
+#define PR_1_EXTATTR_REFCOUNT         0x01003C  /* Extended attribute reference count incorrect */
+#define PR_1_EXTATTR_WRITE            0x01003D  /* Error writing Extended Attribute block while fixing refcount */
+#define PR_1_EA_MULTI_BLOCK           0x01003E  /* Multiple EA blocks not supported */
+#define PR_1_EA_ALLOC_REGION          0x01003F  /* Error allocating EA region allocation structure */
+#define PR_1_EA_ALLOC_COLLISION       0x010040  /* Error EA allocation collision */
+#define PR_1_EA_BAD_NAME              0x010041  /* Bad extended attribute name */
+#define PR_1_EA_BAD_VALUE             0x010042  /* Bad extended attribute value */
+#define PR_1_INODE_TOOBIG             0x010043  /* Inode too big (latch question) */
+#define PR_1_TOOBIG_DIR               0x010044  /* Directory too big */
+#define PR_1_TOOBIG_REG               0x010045  /* Regular file too big */
+#define PR_1_TOOBIG_SYMLINK           0x010046  /* Symlink too big */
+#define PR_1_HTREE_SET                0x010047  /* INDEX_FL flag set on a non-HTREE filesystem */
+#define PR_1_HTREE_NODIR              0x010048  /* INDEX_FL flag set on a non-directory */
+#define PR_1_HTREE_BADROOT            0x010049  /* Invalid root node in HTREE directory */
+#define PR_1_HTREE_HASHV              0x01004A  /* Unsupported hash version in HTREE directory */
+#define PR_1_HTREE_INCOMPAT           0x01004B  /* Incompatible flag in HTREE root node */
+#define PR_1_HTREE_DEPTH              0x01004C  /* HTREE too deep */
+#define PR_1_BB_FS_BLOCK   0x01004D  /* Bad block has indirect block that conflicts with filesystem block */
+#define PR_1_RESIZE_INODE_CREATE      0x01004E  /* Resize inode failed */
+#define PR_1_EXTRA_ISIZE              0x01004F  /* inode->i_size is too long */
+#define PR_1_ATTR_NAME_LEN            0x010050  /* attribute name is too long */
+#define PR_1_ATTR_VALUE_OFFSET        0x010051  /* wrong EA value offset */
+#define PR_1_ATTR_VALUE_BLOCK         0x010052  /* wrong EA blocknumber */
+#define PR_1_ATTR_VALUE_SIZE          0x010053  /* wrong EA value size */
+#define PR_1_ATTR_HASH                0x010054  /* wrong EA hash value */
+
+/*
+ * Pass 1b errors
+ */
+
+#define PR_1B_PASS_HEADER       0x011000  /* Pass 1B: Rescan for duplicate/bad blocks */
+#define PR_1B_DUP_BLOCK_HEADER  0x011001  /* Duplicate/bad block(s) header */
+#define PR_1B_DUP_BLOCK         0x011002  /* Duplicate/bad block(s) in inode */
+#define PR_1B_DUP_BLOCK_END     0x011003  /* Duplicate/bad block(s) end */
+#define PR_1B_ISCAN_ERROR       0x011004  /* Error while scanning inodes */
+#define PR_1B_ALLOCATE_IBITMAP_ERROR 0x011005  /* Error allocating inode bitmap */
+#define PR_1B_BLOCK_ITERATE     0x0110006  /* Error while iterating over blocks */
+#define PR_1B_ADJ_EA_REFCOUNT   0x0110007  /* Error adjusting EA refcount */
+#define PR_1C_PASS_HEADER       0x012000  /* Pass 1C: Scan directories for inodes with dup blocks. */
+#define PR_1D_PASS_HEADER       0x013000  /* Pass 1D: Reconciling duplicate blocks */
+#define PR_1D_DUP_FILE          0x013001  /* File has duplicate blocks */
+#define PR_1D_DUP_FILE_LIST     0x013002  /* List of files sharing duplicate blocks */
+#define PR_1D_SHARE_METADATA    0x013003  /* File sharing blocks with filesystem metadata  */
+#define PR_1D_NUM_DUP_INODES    0x013004  /* Report of how many duplicate/bad inodes */
+#define PR_1D_DUP_BLOCKS_DEALT  0x013005  /* Duplicated blocks already reassigned or cloned. */
+#define PR_1D_CLONE_QUESTION    0x013006  /* Clone duplicate/bad blocks? */
+#define PR_1D_DELETE_QUESTION   0x013007  /* Delete file? */
+#define PR_1D_CLONE_ERROR       0x013008  /* Couldn't clone file (error) */
+
+/*
+ * Pass 2 errors
+ */
+
+#define PR_2_PASS_HEADER        0x020000  /* Pass 2: Checking directory structure */
+#define PR_2_BAD_INODE_DOT      0x020001  /* Bad inode number for '.' */
+#define PR_2_BAD_INO            0x020002  /* Directory entry has bad inode number */
+#define PR_2_UNUSED_INODE       0x020003  /* Directory entry has deleted or unused inode */
+#define PR_2_LINK_DOT           0x020004  /* Directry entry is link to '.' */
+#define PR_2_BB_INODE           0x020005  /* Directory entry points to inode now located in a bad block */
+#define PR_2_LINK_DIR           0x020006  /* Directory entry contains a link to a directory */
+#define PR_2_LINK_ROOT          0x020007  /* Directory entry contains a link to the root directry */
+#define PR_2_BAD_NAME           0x020008  /* Directory entry has illegal characters in its name */
+#define PR_2_MISSING_DOT        0x020009  /* Missing '.' in directory inode */
+#define PR_2_MISSING_DOT_DOT    0x02000A  /* Missing '..' in directory inode */
+#define PR_2_1ST_NOT_DOT        0x02000B  /* First entry in directory inode doesn't contain '.' */
+#define PR_2_2ND_NOT_DOT_DOT    0x02000C  /* Second entry in directory inode doesn't contain '..' */
+#define PR_2_FADDR_ZERO         0x02000D  /* i_faddr should be zero */
+#define PR_2_FILE_ACL_ZERO      0x02000E  /* i_file_acl should be zero */
+#define PR_2_DIR_ACL_ZERO       0x02000F  /* i_dir_acl should be zero */
+#define PR_2_FRAG_ZERO          0x020010  /* i_frag should be zero */
+#define PR_2_FSIZE_ZERO         0x020011  /* i_fsize should be zero */
+#define PR_2_BAD_MODE           0x020012  /* inode has bad mode */
+#define PR_2_DIR_CORRUPTED      0x020013  /* directory corrupted */
+#define PR_2_FILENAME_LONG      0x020014  /* filename too long */
+#define PR_2_DIRECTORY_HOLE     0x020015  /* Directory inode has a missing block (hole) */
+#define PR_2_DOT_NULL_TERM      0x020016  /* '.' is not NULL terminated */
+#define PR_2_DOT_DOT_NULL_TERM  0x020017  /* '..' is not NULL terminated */
+#define PR_2_BAD_CHAR_DEV       0x020018  /* Illegal character device in inode */
+#define PR_2_BAD_BLOCK_DEV      0x020019  /* Illegal block device in inode */
+#define PR_2_DUP_DOT            0x02001A  /* Duplicate '.' entry */
+#define PR_2_DUP_DOT_DOT        0x02001B  /* Duplicate '..' entry */
+#define PR_2_NO_DIRINFO         0x02001C  /* Internal error: couldn't find dir_info */
+#define PR_2_FINAL_RECLEN       0x02001D  /* Final rec_len is wrong */
+#define PR_2_ALLOCATE_ICOUNT    0x02001E  /* Error allocating icount structure */
+#define PR_2_DBLIST_ITERATE     0x02001F  /* Error iterating over directory blocks */
+#define PR_2_READ_DIRBLOCK      0x020020  /* Error reading directory block */
+#define PR_2_WRITE_DIRBLOCK     0x020021  /* Error writing directory block */
+#define PR_2_ALLOC_DIRBOCK      0x020022  /* Error allocating new directory block */
+#define PR_2_DEALLOC_INODE      0x020023  /* Error deallocating inode */
+#define PR_2_SPLIT_DOT          0x020024  /* Directory entry for '.' is big.  Split? */
+#define PR_2_BAD_FIFO           0x020025  /* Illegal FIFO */
+#define PR_2_BAD_SOCKET         0x020026  /* Illegal socket */
+#define PR_2_SET_FILETYPE       0x020027  /* Directory filetype not set */
+#define PR_2_BAD_FILETYPE       0x020028  /* Directory filetype incorrect */
+#define PR_2_CLEAR_FILETYPE     0x020029  /* Directory filetype set when it shouldn't be */
+#define PR_2_NULL_NAME          0x020030  /* Directory filename can't be zero-length  */
+#define PR_2_INVALID_SYMLINK    0x020031  /* Invalid symlink */
+#define PR_2_FILE_ACL_BAD       0x020032  /* i_file_acl (extended attribute) is bad */
+#define PR_2_FEATURE_LARGE_FILES 0x020033  /* Filesystem contains large files, but has no such flag in sb */
+#define PR_2_HTREE_NOTREF       0x020034  /* Node in HTREE directory not referenced */
+#define PR_2_HTREE_DUPREF       0x020035  /* Node in HTREE directory referenced twice */
+#define PR_2_HTREE_MIN_HASH     0x020036  /* Node in HTREE directory has bad min hash */
+#define PR_2_HTREE_MAX_HASH     0x020037  /* Node in HTREE directory has bad max hash */
+#define PR_2_HTREE_CLEAR        0x020038  /* Clear invalid HTREE directory */
+#define PR_2_HTREE_BADBLK       0x02003A  /* Bad block in htree interior node */
+#define PR_2_ADJ_EA_REFCOUNT    0x02003B  /* Error adjusting EA refcount */
+#define PR_2_HTREE_BAD_ROOT     0x02003C  /* Invalid HTREE root node */
+#define PR_2_HTREE_BAD_LIMIT    0x02003D  /* Invalid HTREE limit */
+#define PR_2_HTREE_BAD_COUNT    0x02003E  /* Invalid HTREE count */
+#define PR_2_HTREE_HASH_ORDER   0x02003F  /* HTREE interior node has out-of-order hashes in table */
+#define PR_2_HTREE_BAD_DEPTH    0x020040  /* Node in HTREE directory has bad depth */
+#define PR_2_DUPLICATE_DIRENT   0x020041  /* Duplicate directory entry found */
+#define PR_2_NON_UNIQUE_FILE    0x020042  /* Non-unique filename found */
+#define PR_2_REPORT_DUP_DIRENT  0x020043  /* Duplicate directory entry found */
+
+/*
+ * Pass 3 errors
+ */
+
+#define PR_3_PASS_HEADER            0x030000  /* Pass 3: Checking directory connectivity */
+#define PR_3_NO_ROOT_INODE          0x030001  /* Root inode not allocated */
+#define PR_3_EXPAND_LF_DIR          0x030002  /* No room in lost+found */
+#define PR_3_UNCONNECTED_DIR        0x030003  /* Unconnected directory inode */
+#define PR_3_NO_LF_DIR              0x030004  /* /lost+found not found */
+#define PR_3_BAD_DOT_DOT            0x030005  /* .. entry is incorrect */
+#define PR_3_NO_LPF                 0x030006  /* Bad or non-existent /lost+found.  Cannot reconnect */
+#define PR_3_CANT_EXPAND_LPF        0x030007  /* Could not expand /lost+found */
+#define PR_3_CANT_RECONNECT         0x030008  /* Could not reconnect inode */
+#define PR_3_ERR_FIND_LPF           0x030009  /* Error while trying to find /lost+found */
+#define PR_3_ERR_LPF_NEW_BLOCK      0x03000A  /* Error in ext2fs_new_block while creating /lost+found */
+#define PR_3_ERR_LPF_NEW_INODE      0x03000B  /* Error in ext2fs_new_inode while creating /lost+found */
+#define PR_3_ERR_LPF_NEW_DIR_BLOCK  0x03000C  /* Error in ext2fs_new_dir_block while creating /lost+found */
+#define PR_3_ERR_LPF_WRITE_BLOCK    0x03000D  /* Error while writing directory block for /lost+found */
+#define PR_3_ADJUST_INODE           0x03000E  /* Error while adjusting inode count */
+#define PR_3_FIX_PARENT_ERR         0x03000F  /* Couldn't fix parent directory -- error */
+#define PR_3_FIX_PARENT_NOFIND      0x030010  /* Couldn't fix parent directory -- couldn't find it */
+#define PR_3_ALLOCATE_IBITMAP_ERROR 0x030011  /* Error allocating inode bitmap */
+#define PR_3_CREATE_ROOT_ERROR      0x030012  /* Error creating root directory */
+#define PR_3_CREATE_LPF_ERROR       0x030013  /* Error creating lost and found directory */
+#define PR_3_ROOT_NOT_DIR_ABORT     0x030014  /* Root inode is not directory; aborting */
+#define PR_3_NO_ROOT_INODE_ABORT    0x030015  /* Cannot proceed without a root inode. */
+#define PR_3_NO_DIRINFO             0x030016  /* Internal error: couldn't find dir_info */
+#define PR_3_LPF_NOTDIR             0x030017  /* Lost+found is not a directory */
+
+/*
+ * Pass 3a --- rehashing diretories
+ */
+#define PR_3A_PASS_HEADER         0x031000  /* Pass 3a: Reindexing directories */
+#define PR_3A_OPTIMIZE_ITER       0x031001  /* Error iterating over directories */
+#define PR_3A_OPTIMIZE_DIR_ERR    0x031002  /* Error rehash directory */
+#define PR_3A_OPTIMIZE_DIR_HEADER 0x031003  /* Rehashing dir header */
+#define PR_3A_OPTIMIZE_DIR        0x031004  /* Rehashing directory %d */
+#define PR_3A_OPTIMIZE_DIR_END    0x031005  /* Rehashing dir end */
+
+/*
+ * Pass 4 errors
+ */
+
+#define PR_4_PASS_HEADER        0x040000  /* Pass 4: Checking reference counts */
+#define PR_4_ZERO_LEN_INODE     0x040001  /* Unattached zero-length inode */
+#define PR_4_UNATTACHED_INODE   0x040002  /* Unattached inode */
+#define PR_4_BAD_REF_COUNT      0x040003  /* Inode ref count wrong */
+#define PR_4_INCONSISTENT_COUNT 0x040004  /* Inconsistent inode count information cached */
+
+/*
+ * Pass 5 errors
+ */
+
+#define PR_5_PASS_HEADER            0x050000  /* Pass 5: Checking group summary information */
+#define PR_5_INODE_BMAP_PADDING     0x050001  /* Padding at end of inode bitmap is not set. */
+#define PR_5_BLOCK_BMAP_PADDING     0x050002  /* Padding at end of block bitmap is not set. */
+#define PR_5_BLOCK_BITMAP_HEADER    0x050003  /* Block bitmap differences header */
+#define PR_5_BLOCK_UNUSED           0x050004  /* Block not used, but marked in bitmap */
+#define PR_5_BLOCK_USED             0x050005  /* Block used, but not marked used in bitmap */
+#define PR_5_BLOCK_BITMAP_END       0x050006  /* Block bitmap differences end */
+#define PR_5_INODE_BITMAP_HEADER    0x050007  /* Inode bitmap differences header */
+#define PR_5_INODE_UNUSED           0x050008  /* Inode not used, but marked in bitmap */
+#define PR_5_INODE_USED             0x050009  /* Inode used, but not marked used in bitmap */
+#define PR_5_INODE_BITMAP_END       0x05000A  /* Inode bitmap differences end */
+#define PR_5_FREE_INODE_COUNT_GROUP 0x05000B  /* Free inodes count for group wrong */
+#define PR_5_FREE_DIR_COUNT_GROUP   0x05000C  /* Directories count for group wrong */
+#define PR_5_FREE_INODE_COUNT       0x05000D  /* Free inodes count wrong */
+#define PR_5_FREE_BLOCK_COUNT_GROUP 0x05000E  /* Free blocks count for group wrong */
+#define PR_5_FREE_BLOCK_COUNT       0x05000F  /* Free blocks count wrong */
+#define PR_5_BMAP_ENDPOINTS         0x050010  /* Programming error: bitmap endpoints don't match */
+#define PR_5_FUDGE_BITMAP_ERROR     0x050011  /* Internal error: fudging end of bitmap */
+#define PR_5_COPY_IBITMAP_ERROR     0x050012  /* Error copying in replacement inode bitmap */
+#define PR_5_COPY_BBITMAP_ERROR     0x050013  /* Error copying in replacement block bitmap */
+#define PR_5_BLOCK_RANGE_UNUSED     0x050014  /* Block range not used, but marked in bitmap */
+#define PR_5_BLOCK_RANGE_USED       0x050015  /* Block range used, but not marked used in bitmap */
+#define PR_5_INODE_RANGE_UNUSED     0x050016  /* Inode range not used, but marked in bitmap */
+#define PR_5_INODE_RANGE_USED       0x050017  /* Inode rangeused, but not marked used in bitmap */
+
+
+/*
+ * The directory information structure; stores directory information
+ * collected in earlier passes, to avoid disk i/o in fetching the
+ * directory information.
+ */
+struct dir_info {
+	ext2_ino_t              ino;    /* Inode number */
+	ext2_ino_t              dotdot; /* Parent according to '..' */
+	ext2_ino_t              parent; /* Parent according to treewalk */
+};
+
+
+
+/*
+ * The indexed directory information structure; stores information for
+ * directories which contain a hash tree index.
+ */
+struct dx_dir_info {
+	ext2_ino_t              ino;            /* Inode number */
+	int                     numblocks;      /* number of blocks */
+	int                     hashversion;
+	short                   depth;          /* depth of tree */
+	struct dx_dirblock_info *dx_block;      /* Array of size numblocks */
+};
+
+/*
+ * Define the extended attribute refcount structure
+ */
+typedef struct ea_refcount *ext2_refcount_t;
+
+struct e2fsck_struct {
+	ext2_filsys fs;
+	const char *program_name;
+	char *filesystem_name;
+	char *device_name;
+	char *io_options;
+	int     flags;          /* E2fsck internal flags */
+	int     options;
+	blk_t   use_superblock; /* sb requested by user */
+	blk_t   superblock;     /* sb used to open fs */
+	int     blocksize;      /* blocksize */
+	blk_t   num_blocks;     /* Total number of blocks */
+	int     mount_flags;
+	blkid_cache blkid;      /* blkid cache */
+
+	jmp_buf abort_loc;
+
+	unsigned long abort_code;
+
+	int (*progress)(e2fsck_t ctx, int pass, unsigned long cur,
+			unsigned long max);
+
+	ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */
+	ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */
+	ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */
+	ext2fs_inode_bitmap inode_imagic_map; /* AFS inodes */
+	ext2fs_inode_bitmap inode_reg_map; /* Inodes which are regular files*/
+
+	ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
+	ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */
+	ext2fs_block_bitmap block_ea_map; /* Blocks which are used by EA's */
+
+	/*
+	 * Inode count arrays
+	 */
+	ext2_icount_t   inode_count;
+	ext2_icount_t inode_link_info;
+
+	ext2_refcount_t refcount;
+	ext2_refcount_t refcount_extra;
+
+	/*
+	 * Array of flags indicating whether an inode bitmap, block
+	 * bitmap, or inode table is invalid
+	 */
+	int *invalid_inode_bitmap_flag;
+	int *invalid_block_bitmap_flag;
+	int *invalid_inode_table_flag;
+	int invalid_bitmaps;    /* There are invalid bitmaps/itable */
+
+	/*
+	 * Block buffer
+	 */
+	char *block_buf;
+
+	/*
+	 * For pass1_check_directory and pass1_get_blocks
+	 */
+	ext2_ino_t stashed_ino;
+	struct ext2_inode *stashed_inode;
+
+	/*
+	 * Location of the lost and found directory
+	 */
+	ext2_ino_t lost_and_found;
+	int bad_lost_and_found;
+
+	/*
+	 * Directory information
+	 */
+	int             dir_info_count;
+	int             dir_info_size;
+	struct dir_info *dir_info;
+
+	/*
+	 * Indexed directory information
+	 */
+	int             dx_dir_info_count;
+	int             dx_dir_info_size;
+	struct dx_dir_info *dx_dir_info;
+
+	/*
+	 * Directories to hash
+	 */
+	ext2_u32_list   dirs_to_hash;
+
+	/*
+	 * Tuning parameters
+	 */
+	int process_inode_size;
+	int inode_buffer_blocks;
+
+	/*
+	 * ext3 journal support
+	 */
+	io_channel      journal_io;
+	char    *journal_name;
+
+	/*
+	 * How we display the progress update (for unix)
+	 */
+	int progress_fd;
+	int progress_pos;
+	int progress_last_percent;
+	unsigned int progress_last_time;
+	int interactive;        /* Are we connected directly to a tty? */
+	char start_meta[2], stop_meta[2];
+
+	/* File counts */
+	int fs_directory_count;
+	int fs_regular_count;
+	int fs_blockdev_count;
+	int fs_chardev_count;
+	int fs_links_count;
+	int fs_symlinks_count;
+	int fs_fast_symlinks_count;
+	int fs_fifo_count;
+	int fs_total_count;
+	int fs_sockets_count;
+	int fs_ind_count;
+	int fs_dind_count;
+	int fs_tind_count;
+	int fs_fragmented;
+	int large_files;
+	int fs_ext_attr_inodes;
+	int fs_ext_attr_blocks;
+
+	int ext_attr_ver;
+
+	/*
+	 * For the use of callers of the e2fsck functions; not used by
+	 * e2fsck functions themselves.
+	 */
+	void *priv_data;
+};
+
+
+
+static inline int tid_gt(tid_t x, tid_t y)
+{
+	int difference = (x - y);
+	return (difference > 0);
+}
+
+static inline int tid_geq(tid_t x, tid_t y)
+{
+	int difference = (x - y);
+	return (difference >= 0);
+}
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/e2p.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/e2p.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/e2p.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,63 @@
+#include "busybox.h"
+#include <sys/types.h>		/* Needed by dirent.h on netbsd */
+#include <stdio.h>
+#include <dirent.h>
+
+#include "../ext2fs/ext2_fs.h"
+
+#define E2P_FEATURE_COMPAT	0
+#define E2P_FEATURE_INCOMPAT	1
+#define E2P_FEATURE_RO_INCOMPAT	2
+#ifndef EXT3_FEATURE_INCOMPAT_EXTENTS
+#define EXT3_FEATURE_INCOMPAT_EXTENTS           0x0040
+#endif
+
+/* `options' for print_flags() */
+
+#define PFOPT_LONG  1 /* Must be 1 for compatibility with `int long_format'. */
+
+/*int fgetversion (const char * name, unsigned long * version);*/
+/*int fsetversion (const char * name, unsigned long version);*/
+int fgetsetversion(const char * name, unsigned long * get_version, unsigned long set_version);
+#define fgetversion(name, version) fgetsetversion(name, version, 0)
+#define fsetversion(name, version) fgetsetversion(name, NULL, version)
+
+/*int fgetflags (const char * name, unsigned long * flags);*/
+/*int fsetflags (const char * name, unsigned long flags);*/
+int fgetsetflags(const char * name, unsigned long * get_flags, unsigned long set_flags);
+#define fgetflags(name, flags) fgetsetflags(name, flags, 0)
+#define fsetflags(name, flags) fgetsetflags(name, NULL, flags)
+
+int getflags (int fd, unsigned long * flags);
+int getversion (int fd, unsigned long * version);
+int iterate_on_dir (const char * dir_name,
+		    int (*func) (const char *, struct dirent *, void *),
+		    void * private);
+/*void list_super(struct ext2_super_block * s);*/
+void list_super2(struct ext2_super_block * s, FILE *f);
+#define list_super(s) list_super2(s, stdout)
+void print_fs_errors (FILE * f, unsigned short errors);
+void print_flags (FILE * f, unsigned long flags, unsigned options);
+void print_fs_state (FILE * f, unsigned short state);
+int setflags (int fd, unsigned long flags);
+int setversion (int fd, unsigned long version);
+
+const char *e2p_feature2string(int compat, unsigned int mask);
+int e2p_string2feature(char *string, int *compat, unsigned int *mask);
+int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array);
+
+int e2p_is_null_uuid(void *uu);
+void e2p_uuid_to_str(void *uu, char *out);
+const char *e2p_uuid2str(void *uu);
+
+const char *e2p_hash2string(int num);
+int e2p_string2hash(char *string);
+
+const char *e2p_mntopt2string(unsigned int mask);
+int e2p_string2mntopt(char *string, unsigned int *mask);
+int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok);
+
+unsigned long parse_num_blocks(const char *arg, int log_block_size);
+
+char *e2p_os2string(int os_type);
+int e2p_string2os(char *str);

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/feature.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/feature.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/feature.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,186 @@
+/*
+ * feature.c --- convert between features and strings
+ *
+ * Copyright (C) 1999  Theodore Ts'o <tytso at mit.edu>
+ *
+ * This file can be redistributed under the terms of the GNU Library General
+ * Public License
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "e2p.h"
+
+struct feature {
+	int		compat;
+	unsigned int	mask;
+	const char	*string;
+};
+
+static const struct feature feature_list[] = {
+	{	E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_PREALLOC,
+			"dir_prealloc" },
+	{	E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL,
+			"has_journal" },
+	{	E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_IMAGIC_INODES,
+			"imagic_inodes" },
+	{	E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXT_ATTR,
+			"ext_attr" },
+	{	E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX,
+			"dir_index" },
+	{	E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INODE,
+			"resize_inode" },
+	{	E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER,
+			"sparse_super" },
+	{	E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE,
+			"large_file" },
+	{	E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION,
+			"compression" },
+	{	E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_FILETYPE,
+			"filetype" },
+	{	E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_RECOVER,
+			"needs_recovery" },
+	{	E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV,
+			"journal_dev" },
+	{	E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS,
+			"extents" },
+	{	E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG,
+			"meta_bg" },
+	{	0, 0, 0 },
+};
+
+const char *e2p_feature2string(int compat, unsigned int mask)
+{
+	const struct feature *f;
+	static char buf[20];
+	char fchar;
+	int fnum;
+
+	for (f = feature_list; f->string; f++) {
+		if ((compat == f->compat) &&
+		    (mask == f->mask))
+			return f->string;
+	}
+	switch (compat) {
+	case E2P_FEATURE_COMPAT:
+		fchar = 'C';
+		break;
+	case E2P_FEATURE_INCOMPAT:
+		fchar = 'I';
+		break;
+	case E2P_FEATURE_RO_INCOMPAT:
+		fchar = 'R';
+		break;
+	default:
+		fchar = '?';
+		break;
+	}
+	for (fnum = 0; mask >>= 1; fnum++);
+		sprintf(buf, "FEATURE_%c%d", fchar, fnum);
+	return buf;
+}
+
+int e2p_string2feature(char *string, int *compat_type, unsigned int *mask)
+{
+	const struct feature *f;
+	char *eptr;
+	int num;
+
+	for (f = feature_list; f->string; f++) {
+		if (!strcasecmp(string, f->string)) {
+			*compat_type = f->compat;
+			*mask = f->mask;
+			return 0;
+		}
+	}
+	if (strncasecmp(string, "FEATURE_", 8))
+		return 1;
+
+	switch (string[8]) {
+	case 'c':
+	case 'C':
+		*compat_type = E2P_FEATURE_COMPAT;
+		break;
+	case 'i':
+	case 'I':
+		*compat_type = E2P_FEATURE_INCOMPAT;
+		break;
+	case 'r':
+	case 'R':
+		*compat_type = E2P_FEATURE_RO_INCOMPAT;
+		break;
+	default:
+		return 1;
+	}
+	if (string[9] == 0)
+		return 1;
+	num = strtol(string+9, &eptr, 10);
+	if (num > 32 || num < 0)
+		return 1;
+	if (*eptr)
+		return 1;
+	*mask = 1 << num;
+	return 0;
+}
+
+static inline char *skip_over_blanks(char *cp)
+{
+	while (*cp && isspace(*cp))
+		cp++;
+	return cp;
+}
+
+static inline char *skip_over_word(char *cp)
+{
+	while (*cp && !isspace(*cp) && *cp != ',')
+		cp++;
+	return cp;
+}
+
+/*
+ * Edit a feature set array as requested by the user.  The ok_array,
+ * if set, allows the application to limit what features the user is
+ * allowed to set or clear using this function.
+ */
+int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array)
+{
+	char	*cp, *buf, *next;
+	int	neg;
+	unsigned int	mask;
+	int		compat_type;
+
+	buf = bb_xstrdup(str);
+	cp = buf;
+	while (cp && *cp) {
+		neg = 0;
+		cp = skip_over_blanks(cp);
+		next = skip_over_word(cp);
+		if (*next == 0)
+			next = 0;
+		else
+			*next = 0;
+		switch (*cp) {
+		case '-':
+		case '^':
+			neg++;
+		case '+':
+			cp++;
+			break;
+		}
+		if (e2p_string2feature(cp, &compat_type, &mask))
+			return 1;
+		if (ok_array && !(ok_array[compat_type] & mask))
+			return 1;
+		if (neg)
+			compat_array[compat_type] &= ~mask;
+		else
+			compat_array[compat_type] |= mask;
+		cp = next ? next+1 : 0;
+	}
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/fgetsetflags.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/fgetsetflags.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/fgetsetflags.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,69 @@
+/*
+ * fgetflags.c		- Get a file flags on an ext2 file system
+ * fsetflags.c		- Set a file flags on an ext2 file system
+ *
+ * Copyright (C) 1993, 1994  Remy Card <card at masi.ibp.fr>
+ *                           Laboratoire MASI, Institut Blaise Pascal
+ *                           Universite Pierre et Marie Curie (Paris VI)
+ *
+ * This file can be redistributed under the terms of the GNU Library General
+ * Public License
+ */
+
+/*
+ * History:
+ * 93/10/30	- Creation
+ */
+
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#if HAVE_EXT2_IOCTLS
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#endif
+
+#include "e2p.h"
+
+#ifdef O_LARGEFILE
+#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
+#else
+#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
+#endif
+
+int fgetsetflags (const char * name, unsigned long * get_flags, unsigned long set_flags)
+{
+#if HAVE_EXT2_IOCTLS
+	struct stat buf;
+	int fd, r, f, save_errno = 0;
+
+	if (!stat(name, &buf) &&
+	    !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
+		goto notsupp;
+	}
+	fd = open (name, OPEN_FLAGS);
+	if (fd == -1)
+		return -1;
+	if (!get_flags) {
+		f = (int) set_flags;
+		r = ioctl (fd, EXT2_IOC_SETFLAGS, &f);
+	} else {
+		r = ioctl (fd, EXT2_IOC_GETFLAGS, &f);
+		*get_flags = f;
+	}
+	if (r == -1)
+		save_errno = errno;
+	close (fd);
+	if (save_errno)
+		errno = save_errno;
+	return r;
+#endif /* HAVE_EXT2_IOCTLS */
+notsupp:
+	errno = EOPNOTSUPP;
+	return -1;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/fgetsetversion.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/fgetsetversion.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/fgetsetversion.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,69 @@
+/*
+ * fgetversion.c	- Get a file version on an ext2 file system
+ * fsetversion.c	- Set a file version on an ext2 file system
+ *
+ *
+ * Copyright (C) 1993, 1994  Remy Card <card at masi.ibp.fr>
+ *                           Laboratoire MASI, Institut Blaise Pascal
+ *                           Universite Pierre et Marie Curie (Paris VI)
+ *
+ * This file can be redistributed under the terms of the GNU Library General
+ * Public License
+ */
+
+/*
+ * History:
+ * 93/10/30	- Creation
+ */
+
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include "e2p.h"
+
+#ifdef O_LARGEFILE
+#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
+#else
+#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
+#endif
+
+/*
+   To do fsetversion:     unsigned long *ptr_version must be set to NULL.
+		      and unsigned long version must be set to a value
+   To do fgetversion:     unsigned long *ptr_version must NOT be set to NULL
+		      and unsigned long version is ignored.
+	TITO.
+*/
+
+int fgetsetversion (const char * name, unsigned long * get_version, unsigned long set_version)
+{
+#if HAVE_EXT2_IOCTLS
+	int fd, r, ver, save_errno = 0;
+
+	fd = open (name, OPEN_FLAGS);
+	if (fd == -1)
+		return -1;
+	if (!get_version) {
+		ver = (int) set_version;
+		r = ioctl (fd, EXT2_IOC_SETVERSION, &ver);
+	} else {
+		r = ioctl (fd, EXT2_IOC_GETVERSION, &ver);
+		*get_version = ver;
+	}
+	if (r == -1)
+		save_errno = errno;
+	close (fd);
+	if (save_errno)
+		errno = save_errno;
+	return r;
+#else /* ! HAVE_EXT2_IOCTLS */
+	errno = EOPNOTSUPP;
+	return -1;
+#endif /* ! HAVE_EXT2_IOCTLS */
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/hashstr.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/hashstr.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/hashstr.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,69 @@
+/*
+ * feature.c --- convert between features and strings
+ *
+ * Copyright (C) 1999  Theodore Ts'o <tytso at mit.edu>
+ *
+ * This file can be redistributed under the terms of the GNU Library General
+ * Public License
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "e2p.h"
+
+struct hash {
+	int num;
+	const char *string;
+};
+
+static const struct hash hash_list[] = {
+	{ EXT2_HASH_LEGACY,   "legacy" },
+	{ EXT2_HASH_HALF_MD4, "half_md4" },
+	{ EXT2_HASH_TEA,      "tea" },
+	{ 0, 0 },
+};
+
+const char *e2p_hash2string(int num)
+{
+	const struct hash *p;
+	static char buf[20];
+
+	for (p = hash_list; p->string; p++) {
+		if (num == p->num)
+			return p->string;
+	}
+	sprintf(buf, "HASHALG_%d", num);
+	return buf;
+}
+
+/*
+ * Returns the hash algorithm, or -1 on error
+ */
+int e2p_string2hash(char *string)
+{
+	const struct hash *p;
+	char *eptr;
+	int num;
+
+	for (p = hash_list; p->string; p++) {
+		if (!strcasecmp(string, p->string)) {
+			return p->num;
+		}
+	}
+	if (strncasecmp(string, "HASHALG_", 8))
+		return -1;
+
+	if (string[8] == 0)
+		return -1;
+	num = strtol(string+8, &eptr, 10);
+	if (num > 255 || num < 0)
+		return -1;
+	if (*eptr)
+		return -1;
+	return num;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/iod.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/iod.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/iod.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,51 @@
+/*
+ * iod.c		- Iterate a function on each entry of a directory
+ *
+ * Copyright (C) 1993, 1994  Remy Card <card at masi.ibp.fr>
+ *                           Laboratoire MASI, Institut Blaise Pascal
+ *                           Universite Pierre et Marie Curie (Paris VI)
+ *
+ * This file can be redistributed under the terms of the GNU Library General
+ * Public License
+ */
+
+/*
+ * History:
+ * 93/10/30	- Creation
+ */
+
+#include "e2p.h"
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+int iterate_on_dir (const char * dir_name,
+		    int (*func) (const char *, struct dirent *, void *),
+		    void * private)
+{
+	DIR * dir;
+	struct dirent *de, *dep;
+	int	max_len, len;
+
+	max_len = PATH_MAX + sizeof(struct dirent);
+	de = (struct dirent *)xmalloc(max_len+1);
+	memset(de, 0, max_len+1);
+
+	dir = opendir (dir_name);
+	if (dir == NULL) {
+		free(de);
+		return -1;
+	}
+	while ((dep = readdir (dir))) {
+		len = sizeof(struct dirent);
+		if (len < dep->d_reclen)
+			len = dep->d_reclen;
+		if (len > max_len)
+			len = max_len;
+		memcpy(de, dep, len);
+		(*func) (dir_name, de, private);
+	}
+	free(de);
+	closedir(dir);
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/ls.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/ls.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/ls.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,272 @@
+/*
+ * ls.c			- List the contents of an ext2fs superblock
+ *
+ * Copyright (C) 1992, 1993, 1994  Remy Card <card at masi.ibp.fr>
+ *                                 Laboratoire MASI, Institut Blaise Pascal
+ *                                 Universite Pierre et Marie Curie (Paris VI)
+ *
+ * Copyright (C) 1995, 1996, 1997  Theodore Ts'o <tytso at mit.edu>
+ *
+ * This file can be redistributed under the terms of the GNU Library General
+ * Public License
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <grp.h>
+#include <pwd.h>
+#include <time.h>
+
+#include "e2p.h"
+
+static void print_user(unsigned short uid, FILE *f)
+{
+	struct passwd *pw = getpwuid(uid);
+	fprintf(f, "%u (user %s)\n", uid,
+	        (pw == NULL ? "unknown" : pw->pw_name));
+}
+
+static void print_group(unsigned short gid, FILE *f)
+{
+	struct group *gr = getgrgid(gid);
+	fprintf(f, "%u (group %s)\n", gid,
+	        (gr == NULL ? "unknown" : gr->gr_name));
+}
+
+#define MONTH_INT (86400 * 30)
+#define WEEK_INT (86400 * 7)
+#define DAY_INT	(86400)
+#define HOUR_INT (60 * 60)
+#define MINUTE_INT (60)
+
+static const char *interval_string(unsigned int secs)
+{
+	static char buf[256], tmp[80];
+	int		hr, min, num;
+
+	buf[0] = 0;
+
+	if (secs == 0)
+		return "<none>";
+
+	if (secs >= MONTH_INT) {
+		num = secs / MONTH_INT;
+		secs -= num*MONTH_INT;
+		sprintf(buf, "%d month%s", num, (num>1) ? "s" : "");
+	}
+	if (secs >= WEEK_INT) {
+		num = secs / WEEK_INT;
+		secs -= num*WEEK_INT;
+		sprintf(tmp, "%s%d week%s", buf[0] ? ", " : "",
+			num, (num>1) ? "s" : "");
+		strcat(buf, tmp);
+	}
+	if (secs >= DAY_INT) {
+		num = secs / DAY_INT;
+		secs -= num*DAY_INT;
+		sprintf(tmp, "%s%d day%s", buf[0] ? ", " : "",
+			num, (num>1) ? "s" : "");
+		strcat(buf, tmp);
+	}
+	if (secs > 0) {
+		hr = secs / HOUR_INT;
+		secs -= hr*HOUR_INT;
+		min = secs / MINUTE_INT;
+		secs -= min*MINUTE_INT;
+		sprintf(tmp, "%s%d:%02d:%02d", buf[0] ? ", " : "",
+			hr, min, secs);
+		strcat(buf, tmp);
+	}
+	return buf;
+}
+
+static void print_features(struct ext2_super_block * s, FILE *f)
+{
+#ifdef EXT2_DYNAMIC_REV
+	int	i, j, printed=0;
+	__u32	*mask = &s->s_feature_compat, m;
+
+	fprintf(f, "Filesystem features:     ");
+	for (i=0; i <3; i++,mask++) {
+		for (j=0,m=1; j < 32; j++, m<<=1) {
+			if (*mask & m) {
+				fprintf(f, " %s", e2p_feature2string(i, m));
+				printed++;
+			}
+		}
+	}
+	if (printed == 0)
+		fprintf(f, " (none)");
+	fprintf(f, "\n");
+#endif
+}
+
+static void print_mntopts(struct ext2_super_block * s, FILE *f)
+{
+#ifdef EXT2_DYNAMIC_REV
+	int	i, printed=0;
+	__u32	mask = s->s_default_mount_opts, m;
+
+	fprintf(f, "Default mount options:   ");
+	if (mask & EXT3_DEFM_JMODE) {
+		fprintf(f, " %s", e2p_mntopt2string(mask & EXT3_DEFM_JMODE));
+		printed++;
+	}
+	for (i=0,m=1; i < 32; i++, m<<=1) {
+		if (m & EXT3_DEFM_JMODE)
+			continue;
+		if (mask & m) {
+			fprintf(f, " %s", e2p_mntopt2string(m));
+			printed++;
+		}
+	}
+	if (printed == 0)
+		fprintf(f, " (none)");
+	fprintf(f, "\n");
+#endif
+}
+
+
+#ifndef EXT2_INODE_SIZE
+#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode)
+#endif
+
+#ifndef EXT2_GOOD_OLD_REV
+#define EXT2_GOOD_OLD_REV 0
+#endif
+
+void list_super2(struct ext2_super_block * sb, FILE *f)
+{
+	int inode_blocks_per_group;
+	char buf[80], *str;
+	time_t	tm;
+
+	inode_blocks_per_group = (((sb->s_inodes_per_group *
+				    EXT2_INODE_SIZE(sb)) +
+				   EXT2_BLOCK_SIZE(sb) - 1) /
+				  EXT2_BLOCK_SIZE(sb));
+	if (sb->s_volume_name[0]) {
+		memset(buf, 0, sizeof(buf));
+		strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name));
+	} else
+		strcpy(buf, "<none>");
+	fprintf(f, "Filesystem volume name:   %s\n", buf);
+	if (sb->s_last_mounted[0]) {
+		memset(buf, 0, sizeof(buf));
+		strncpy(buf, sb->s_last_mounted, sizeof(sb->s_last_mounted));
+	} else
+		strcpy(buf, "<not available>");
+	fprintf(f,
+		"Last mounted on:          %s\n"
+		"Filesystem UUID:          %s\n"
+		"Filesystem magic number:  0x%04X\n"
+		"Filesystem revision #:    %d",
+		buf, e2p_uuid2str(sb->s_uuid), sb->s_magic, sb->s_rev_level);
+	if (sb->s_rev_level == EXT2_GOOD_OLD_REV) {
+		fprintf(f, " (original)\n");
+#ifdef EXT2_DYNAMIC_REV
+	} else if (sb->s_rev_level == EXT2_DYNAMIC_REV) {
+		fprintf(f, " (dynamic)\n");
+#endif
+	} else
+		fprintf(f, " (unknown)\n");
+	print_features(sb, f);
+	print_mntopts(sb, f);
+	fprintf(f, "Filesystem state:        ");
+	print_fs_state (f, sb->s_state);
+	fprintf(f, "\nErrors behavior:          ");
+	print_fs_errors(f, sb->s_errors);
+	str = e2p_os2string(sb->s_creator_os);
+	fprintf(f,
+		"\n"
+		"Filesystem OS type:       %s\n"
+		"Inode count:              %u\n"
+		"Block count:              %u\n"
+		"Reserved block count:     %u\n"
+		"Free blocks:              %u\n"
+		"Free inodes:              %u\n"
+		"First block:              %u\n"
+		"Block size:               %u\n"
+		"Fragment size:            %u\n",
+		str, sb->s_inodes_count, sb->s_blocks_count, sb->s_r_blocks_count,
+		sb->s_free_blocks_count, sb->s_free_inodes_count,
+		sb->s_first_data_block, EXT2_BLOCK_SIZE(sb), EXT2_FRAG_SIZE(sb));
+	free(str);
+	if (sb->s_reserved_gdt_blocks)
+		fprintf(f, "Reserved GDT blocks:      %u\n",
+			sb->s_reserved_gdt_blocks);
+	fprintf(f,
+		"Blocks per group:         %u\n"
+		"Fragments per group:      %u\n"
+		"Inodes per group:         %u\n"
+		"Inode blocks per group:   %u\n",
+		sb->s_blocks_per_group, sb->s_frags_per_group,
+		sb->s_inodes_per_group, inode_blocks_per_group);
+	if (sb->s_first_meta_bg)
+		fprintf(f, "First meta block group:   %u\n",
+			sb->s_first_meta_bg);
+	if (sb->s_mkfs_time) {
+		tm = sb->s_mkfs_time;
+		fprintf(f, "Filesystem created:       %s", ctime(&tm));
+	}
+	tm = sb->s_mtime;
+	fprintf(f, "Last mount time:          %s",
+		sb->s_mtime ? ctime(&tm) : "n/a\n");
+	tm = sb->s_wtime;
+	fprintf(f,
+		"Last write time:          %s"
+		"Mount count:              %u\n"
+		"Maximum mount count:      %d\n",
+		ctime(&tm), sb->s_mnt_count, sb->s_max_mnt_count);
+	tm = sb->s_lastcheck;
+	fprintf(f,
+		"Last checked:             %s"
+		"Check interval:           %u (%s)\n",
+		ctime(&tm),
+		sb->s_checkinterval, interval_string(sb->s_checkinterval));
+	if (sb->s_checkinterval)
+	{
+		time_t next;
+
+		next = sb->s_lastcheck + sb->s_checkinterval;
+		fprintf(f, "Next check after:         %s", ctime(&next));
+	}
+	fprintf(f, "Reserved blocks uid:      ");
+	print_user(sb->s_def_resuid, f);
+	fprintf(f, "Reserved blocks gid:      ");
+	print_group(sb->s_def_resgid, f);
+	if (sb->s_rev_level >= EXT2_DYNAMIC_REV) {
+		fprintf(f,
+			"First inode:              %d\n"
+			"Inode size:		  %d\n",
+			sb->s_first_ino, sb->s_inode_size);
+	}
+	if (!e2p_is_null_uuid(sb->s_journal_uuid))
+		fprintf(f, "Journal UUID:             %s\n",
+			e2p_uuid2str(sb->s_journal_uuid));
+	if (sb->s_journal_inum)
+		fprintf(f, "Journal inode:            %u\n",
+			sb->s_journal_inum);
+	if (sb->s_journal_dev)
+		fprintf(f, "Journal device:	          0x%04x\n",
+			sb->s_journal_dev);
+	if (sb->s_last_orphan)
+		fprintf(f, "First orphan inode:       %u\n",
+			sb->s_last_orphan);
+	if ((sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
+	    sb->s_def_hash_version)
+		fprintf(f, "Default directory hash:   %s\n",
+			e2p_hash2string(sb->s_def_hash_version));
+	if (!e2p_is_null_uuid(sb->s_hash_seed))
+		fprintf(f, "Directory Hash Seed:      %s\n",
+			e2p_uuid2str(sb->s_hash_seed));
+	if (sb->s_jnl_backup_type) {
+		fprintf(f, "Journal backup:           ");
+		if (sb->s_jnl_backup_type == 1)
+			fprintf(f, "inode blocks\n");
+		else
+			fprintf(f, "type %u\n", sb->s_jnl_backup_type);
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/mntopts.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/mntopts.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/mntopts.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,133 @@
+/*
+ * mountopts.c --- convert between default mount options and strings
+ *
+ * Copyright (C) 2002  Theodore Ts'o <tytso at mit.edu>
+ *
+ * This file can be redistributed under the terms of the GNU Library General
+ * Public License
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "e2p.h"
+
+struct mntopt {
+	unsigned int	mask;
+	const char	*string;
+};
+
+static const struct mntopt mntopt_list[] = {
+	{ EXT2_DEFM_DEBUG,	"debug" },
+	{ EXT2_DEFM_BSDGROUPS,	"bsdgroups" },
+	{ EXT2_DEFM_XATTR_USER,	"user_xattr" },
+	{ EXT2_DEFM_ACL,	"acl" },
+	{ EXT2_DEFM_UID16,	"uid16" },
+	{ EXT3_DEFM_JMODE_DATA, "journal_data" },
+	{ EXT3_DEFM_JMODE_ORDERED, "journal_data_ordered" },
+	{ EXT3_DEFM_JMODE_WBACK, "journal_data_writeback" },
+	{ 0, 0 },
+};
+
+const char *e2p_mntopt2string(unsigned int mask)
+{
+	const struct mntopt  *f;
+	static char buf[20];
+	int	fnum;
+
+	for (f = mntopt_list; f->string; f++) {
+		if (mask == f->mask)
+			return f->string;
+	}
+	for (fnum = 0; mask >>= 1; fnum++);
+	sprintf(buf, "MNTOPT_%d", fnum);
+	return buf;
+}
+
+int e2p_string2mntopt(char *string, unsigned int *mask)
+{
+	const struct mntopt  *f;
+	char		*eptr;
+	int		num;
+
+	for (f = mntopt_list; f->string; f++) {
+		if (!strcasecmp(string, f->string)) {
+			*mask = f->mask;
+			return 0;
+		}
+	}
+	if (strncasecmp(string, "MNTOPT_", 8))
+		return 1;
+
+	if (string[8] == 0)
+		return 1;
+	num = strtol(string+8, &eptr, 10);
+	if (num > 32 || num < 0)
+		return 1;
+	if (*eptr)
+		return 1;
+	*mask = 1 << num;
+	return 0;
+}
+
+static char *skip_over_blanks(char *cp)
+{
+	while (*cp && isspace(*cp))
+		cp++;
+	return cp;
+}
+
+static char *skip_over_word(char *cp)
+{
+	while (*cp && !isspace(*cp) && *cp != ',')
+		cp++;
+	return cp;
+}
+
+/*
+ * Edit a mntopt set array as requested by the user.  The ok
+ * parameter, if non-zero, allows the application to limit what
+ * mntopts the user is allowed to set or clear using this function.
+ */
+int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok)
+{
+	char	*cp, *buf, *next;
+	int	neg;
+	unsigned int	mask;
+
+	buf = bb_xstrdup(str);
+	cp = buf;
+	while (cp && *cp) {
+		neg = 0;
+		cp = skip_over_blanks(cp);
+		next = skip_over_word(cp);
+		if (*next == 0)
+			next = 0;
+		else
+			*next = 0;
+		switch (*cp) {
+		case '-':
+		case '^':
+			neg++;
+		case '+':
+			cp++;
+			break;
+		}
+		if (e2p_string2mntopt(cp, &mask))
+			return 1;
+		if (ok && !(ok & mask))
+			return 1;
+		if (mask & EXT3_DEFM_JMODE)
+			*mntopts &= ~EXT3_DEFM_JMODE;
+		if (neg)
+			*mntopts &= ~mask;
+		else
+			*mntopts |= mask;
+		cp = next ? next+1 : 0;
+	}
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/ostype.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/ostype.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/ostype.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,73 @@
+/*
+ * getostype.c          - Get the Filesystem OS type
+ *
+ * Copyright (C) 2004,2005  Theodore Ts'o <tytso at mit.edu>
+ *
+ * This file can be redistributed under the terms of the GNU Library General
+ * Public License
+ */
+
+#include "e2p.h"
+#include <string.h>
+#include <stdlib.h>
+
+static const char * const os_tab[] =
+	{ "Linux",
+	  "Hurd",
+	  "Masix",
+	  "FreeBSD",
+	  "Lites",
+	  0 };
+
+/*
+ * Convert an os_type to a string
+ */
+char *e2p_os2string(int os_type)
+{
+	const char *os;
+	char *ret;
+
+	if (os_type <= EXT2_OS_LITES)
+		os = os_tab[os_type];
+	else
+		os = "(unknown os)";
+
+	ret = bb_xstrdup(os);
+	return ret;
+}
+
+/*
+ * Convert an os_type to a string
+ */
+int e2p_string2os(char *str)
+{
+	const char * const *cpp;
+	int i = 0;
+
+	for (cpp = os_tab; *cpp; cpp++, i++) {
+		if (!strcasecmp(str, *cpp))
+			return i;
+	}
+	return -1;
+}
+
+#ifdef TEST_PROGRAM
+int main(int argc, char **argv)
+{
+	char	*s;
+	int	i, os;
+
+	for (i=0; i <= EXT2_OS_LITES; i++) {
+		s = e2p_os2string(i);
+		os = e2p_string2os(s);
+		printf("%d: %s (%d)\n", i, s, os);
+		if (i != os) {
+			fprintf(stderr, "Failure!\n");
+			exit(1);
+		}
+	}
+	exit(0);
+}
+#endif
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/parse_num.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/parse_num.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/parse_num.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,64 @@
+/*
+ * parse_num.c		- Parse the number of blocks
+ *
+ * Copyright (C) 2004,2005  Theodore Ts'o <tytso at mit.edu>
+ *
+ * This file can be redistributed under the terms of the GNU Library General
+ * Public License
+ */
+
+#include "e2p.h"
+
+#include <stdlib.h>
+
+unsigned long parse_num_blocks(const char *arg, int log_block_size)
+{
+	char *p;
+	unsigned long long num;
+
+	num = strtoull(arg, &p, 0);
+
+	if (p[0] && p[1])
+		return 0;
+
+	switch (*p) {		/* Using fall-through logic */
+	case 'T': case 't':
+		num <<= 10;
+	case 'G': case 'g':
+		num <<= 10;
+	case 'M': case 'm':
+		num <<= 10;
+	case 'K': case 'k':
+		num >>= log_block_size;
+		break;
+	case 's':
+		num >>= 1;
+		break;
+	case '\0':
+		break;
+	default:
+		return 0;
+	}
+	return num;
+}
+
+#ifdef DEBUG
+#include <unistd.h>
+#include <stdio.h>
+
+main(int argc, char **argv)
+{
+	unsigned long num;
+	int log_block_size = 0;
+
+	if (argc != 2) {
+		fprintf(stderr, "Usage: %s arg\n", argv[0]);
+		exit(1);
+	}
+
+	num = parse_num_blocks(argv[1], log_block_size);
+
+	printf("Parsed number: %lu\n", num);
+	exit(0);
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/pe.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/pe.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/pe.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,31 @@
+/*
+ * pe.c			- Print a second extended filesystem errors behavior
+ *
+ * Copyright (C) 1992, 1993, 1994  Remy Card <card at masi.ibp.fr>
+ *                                 Laboratoire MASI, Institut Blaise Pascal
+ *                                 Universite Pierre et Marie Curie (Paris VI)
+ *
+ * This file can be redistributed under the terms of the GNU Library General
+ * Public License
+ */
+
+/*
+ * History:
+ * 94/01/09	- Creation
+ */
+
+#include <stdio.h>
+
+#include "e2p.h"
+
+void print_fs_errors(FILE *f, unsigned short errors)
+{
+	char *disp = NULL;
+	switch (errors) {
+	case EXT2_ERRORS_CONTINUE: disp = "Continue"; break;
+	case EXT2_ERRORS_RO:       disp = "Remount read-only"; break;
+	case EXT2_ERRORS_PANIC:    disp = "Panic"; break;
+	default:                   disp = "Unknown (continue)";
+	}
+	fprintf(f, disp);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/pf.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/pf.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/pf.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,73 @@
+/*
+ * pf.c			- Print file attributes on an ext2 file system
+ *
+ * Copyright (C) 1993, 1994  Remy Card <card at masi.ibp.fr>
+ *                           Laboratoire MASI, Institut Blaise Pascal
+ *                           Universite Pierre et Marie Curie (Paris VI)
+ *
+ * This file can be redistributed under the terms of the GNU Library General
+ * Public License
+ */
+
+/*
+ * History:
+ * 93/10/30	- Creation
+ */
+
+#include <stdio.h>
+
+#include "e2p.h"
+
+struct flags_name {
+	unsigned long	flag;
+	const char	*short_name;
+	const char	*long_name;
+};
+
+static const struct flags_name flags_array[] = {
+	{ EXT2_SECRM_FL, "s", "Secure_Deletion" },
+	{ EXT2_UNRM_FL, "u" , "Undelete" },
+	{ EXT2_SYNC_FL, "S", "Synchronous_Updates" },
+	{ EXT2_DIRSYNC_FL, "D", "Synchronous_Directory_Updates" },
+	{ EXT2_IMMUTABLE_FL, "i", "Immutable" },
+	{ EXT2_APPEND_FL, "a", "Append_Only" },
+	{ EXT2_NODUMP_FL, "d", "No_Dump" },
+	{ EXT2_NOATIME_FL, "A", "No_Atime" },
+	{ EXT2_COMPR_FL, "c", "Compression_Requested" },
+#ifdef ENABLE_COMPRESSION
+	{ EXT2_COMPRBLK_FL, "B", "Compressed_File" },
+	{ EXT2_DIRTY_FL, "Z", "Compressed_Dirty_File" },
+	{ EXT2_NOCOMPR_FL, "X", "Compression_Raw_Access" },
+	{ EXT2_ECOMPR_FL, "E", "Compression_Error" },
+#endif
+	{ EXT3_JOURNAL_DATA_FL, "j", "Journaled_Data" },
+	{ EXT2_INDEX_FL, "I", "Indexed_direcctory" },
+	{ EXT2_NOTAIL_FL, "t", "No_Tailmerging" },
+	{ EXT2_TOPDIR_FL, "T", "Top_of_Directory_Hierarchies" },
+	{ 0, NULL, NULL }
+};
+
+void print_flags (FILE * f, unsigned long flags, unsigned options)
+{
+	int long_opt = (options & PFOPT_LONG);
+	const struct flags_name *fp;
+	int	first = 1;
+
+	for (fp = flags_array; fp->flag != 0; fp++) {
+		if (flags & fp->flag) {
+			if (long_opt) {
+				if (first)
+					first = 0;
+				else
+					fputs(", ", f);
+				fputs(fp->long_name, f);
+			} else
+				fputs(fp->short_name, f);
+		} else {
+			if (!long_opt)
+				fputs("-", f);
+		}
+	}
+	if (long_opt && first)
+		fputs("---", f);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/ps.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/ps.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/ps.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,26 @@
+/*
+ * ps.c			- Print filesystem state
+ *
+ * Copyright (C) 1993, 1994  Remy Card <card at masi.ibp.fr>
+ *                           Laboratoire MASI, Institut Blaise Pascal
+ *                           Universite Pierre et Marie Curie (Paris VI)
+ *
+ * This file can be redistributed under the terms of the GNU Library General
+ * Public License
+ */
+
+/*
+ * History:
+ * 93/12/22	- Creation
+ */
+
+#include <stdio.h>
+
+#include "e2p.h"
+
+void print_fs_state(FILE *f, unsigned short state)
+{
+	fprintf(f, (state & EXT2_VALID_FS ? " clean" : " not clean"));
+	if (state & EXT2_ERROR_FS)
+		fprintf (f, " with errors");
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/uuid.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/uuid.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/e2p/uuid.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,77 @@
+/*
+ * uuid.c -- utility routines for manipulating UUID's.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "../ext2fs/ext2_types.h"
+
+#include "e2p.h"
+
+struct uuid {
+	__u32	time_low;
+	__u16	time_mid;
+	__u16	time_hi_and_version;
+	__u16	clock_seq;
+	__u8	node[6];
+};
+
+/* Returns 1 if the uuid is the NULL uuid */
+int e2p_is_null_uuid(void *uu)
+{
+	__u8	*cp;
+	int	i;
+
+	for (i=0, cp = uu; i < 16; i++)
+		if (*cp)
+			return 0;
+	return 1;
+}
+
+static void e2p_unpack_uuid(void *in, struct uuid *uu)
+{
+	__u8	*ptr = in;
+	__u32	tmp;
+
+	tmp = *ptr++;
+	tmp = (tmp << 8) | *ptr++;
+	tmp = (tmp << 8) | *ptr++;
+	tmp = (tmp << 8) | *ptr++;
+	uu->time_low = tmp;
+
+	tmp = *ptr++;
+	tmp = (tmp << 8) | *ptr++;
+	uu->time_mid = tmp;
+
+	tmp = *ptr++;
+	tmp = (tmp << 8) | *ptr++;
+	uu->time_hi_and_version = tmp;
+
+	tmp = *ptr++;
+	tmp = (tmp << 8) | *ptr++;
+	uu->clock_seq = tmp;
+
+	memcpy(uu->node, ptr, 6);
+}
+
+void e2p_uuid_to_str(void *uu, char *out)
+{
+	struct uuid uuid;
+
+	e2p_unpack_uuid(uu, &uuid);
+	sprintf(out,
+		"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+		uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
+		uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
+		uuid.node[0], uuid.node[1], uuid.node[2],
+		uuid.node[3], uuid.node[4], uuid.node[5]);
+}
+
+const char *e2p_uuid2str(void *uu)
+{
+	static char buf[80];
+	if (e2p_is_null_uuid(uu))
+		return "<none>";
+	e2p_uuid_to_str(uu, buf);
+	return buf;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/alloc.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/alloc.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/alloc.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,173 @@
+/*
+ * alloc.c --- allocate new inodes, blocks for ext2fs
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ *
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <time.h>
+#include <string.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * Right now, just search forward from the parent directory's block
+ * group to find the next free inode.
+ *
+ * Should have a special policy for directories.
+ */
+errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir,
+			   int mode EXT2FS_ATTR((unused)),
+			   ext2fs_inode_bitmap map, ext2_ino_t *ret)
+{
+	ext2_ino_t	dir_group = 0;
+	ext2_ino_t	i;
+	ext2_ino_t	start_inode;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (!map)
+		map = fs->inode_map;
+	if (!map)
+		return EXT2_ET_NO_INODE_BITMAP;
+
+	if (dir > 0)
+		dir_group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super);
+
+	start_inode = (dir_group * EXT2_INODES_PER_GROUP(fs->super)) + 1;
+	if (start_inode < EXT2_FIRST_INODE(fs->super))
+		start_inode = EXT2_FIRST_INODE(fs->super);
+	i = start_inode;
+
+	do {
+		if (!ext2fs_fast_test_inode_bitmap(map, i))
+			break;
+		i++;
+		if (i > fs->super->s_inodes_count)
+			i = EXT2_FIRST_INODE(fs->super);
+	} while (i != start_inode);
+
+	if (ext2fs_test_inode_bitmap(map, i))
+		return EXT2_ET_INODE_ALLOC_FAIL;
+	*ret = i;
+	return 0;
+}
+
+/*
+ * Stupid algorithm --- we now just search forward starting from the
+ * goal.  Should put in a smarter one someday....
+ */
+errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
+			   ext2fs_block_bitmap map, blk_t *ret)
+{
+	blk_t	i;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (!map)
+		map = fs->block_map;
+	if (!map)
+		return EXT2_ET_NO_BLOCK_BITMAP;
+	if (!goal || (goal >= fs->super->s_blocks_count))
+		goal = fs->super->s_first_data_block;
+	i = goal;
+	do {
+		if (!ext2fs_fast_test_block_bitmap(map, i)) {
+			*ret = i;
+			return 0;
+		}
+		i++;
+		if (i >= fs->super->s_blocks_count)
+			i = fs->super->s_first_data_block;
+	} while (i != goal);
+	return EXT2_ET_BLOCK_ALLOC_FAIL;
+}
+
+/*
+ * This function zeros out the allocated block, and updates all of the
+ * appropriate filesystem records.
+ */
+errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
+			     char *block_buf, blk_t *ret)
+{
+	errcode_t	retval;
+	blk_t		block;
+	char		*buf = 0;
+
+	if (!block_buf) {
+		retval = ext2fs_get_mem(fs->blocksize, &buf);
+		if (retval)
+			return retval;
+		block_buf = buf;
+	}
+	memset(block_buf, 0, fs->blocksize);
+
+	if (!fs->block_map) {
+		retval = ext2fs_read_block_bitmap(fs);
+		if (retval)
+			goto fail;
+	}
+
+	retval = ext2fs_new_block(fs, goal, 0, &block);
+	if (retval)
+		goto fail;
+
+	retval = io_channel_write_blk(fs->io, block, 1, block_buf);
+	if (retval)
+		goto fail;
+
+	ext2fs_block_alloc_stats(fs, block, +1);
+	*ret = block;
+	return 0;
+
+fail:
+	if (buf)
+		ext2fs_free_mem(&buf);
+	return retval;
+}
+
+errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
+				 int num, ext2fs_block_bitmap map, blk_t *ret)
+{
+	blk_t	b = start;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (!map)
+		map = fs->block_map;
+	if (!map)
+		return EXT2_ET_NO_BLOCK_BITMAP;
+	if (!b)
+		b = fs->super->s_first_data_block;
+	if (!finish)
+		finish = start;
+	if (!num)
+		num = 1;
+	do {
+		if (b+num-1 > fs->super->s_blocks_count)
+			b = fs->super->s_first_data_block;
+		if (ext2fs_fast_test_block_bitmap_range(map, b, num)) {
+			*ret = b;
+			return 0;
+		}
+		b++;
+	} while (b != finish);
+	return EXT2_ET_BLOCK_ALLOC_FAIL;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/alloc_sb.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/alloc_sb.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/alloc_sb.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,57 @@
+/*
+ * alloc_sb.c --- Allocate the superblock and block group descriptors for a
+ * newly initialized filesystem.  Used by mke2fs when initializing a filesystem
+ *
+ * Copyright (C) 1994, 1995, 1996, 2003 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
+				 dgrp_t group,
+				 ext2fs_block_bitmap bmap)
+{
+	blk_t	super_blk, old_desc_blk, new_desc_blk;
+	int	j, old_desc_blocks, num_blocks;
+
+	num_blocks = ext2fs_super_and_bgd_loc(fs, group, &super_blk,
+					      &old_desc_blk, &new_desc_blk, 0);
+
+	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
+		old_desc_blocks = fs->super->s_first_meta_bg;
+	else
+		old_desc_blocks =
+			fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
+
+	if (super_blk || (group == 0))
+		ext2fs_mark_block_bitmap(bmap, super_blk);
+
+	if (old_desc_blk) {
+		for (j=0; j < old_desc_blocks; j++)
+			ext2fs_mark_block_bitmap(bmap, old_desc_blk + j);
+	}
+	if (new_desc_blk)
+		ext2fs_mark_block_bitmap(bmap, new_desc_blk);
+
+	return num_blocks;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/alloc_stats.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/alloc_stats.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/alloc_stats.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,52 @@
+/*
+ * alloc_stats.c --- Update allocation statistics for ext2fs
+ *
+ * Copyright (C) 2001 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ *
+ */
+
+#include <stdio.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
+			       int inuse, int isdir)
+{
+	int	group = ext2fs_group_of_ino(fs, ino);
+
+	if (inuse > 0)
+		ext2fs_mark_inode_bitmap(fs->inode_map, ino);
+	else
+		ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
+	fs->group_desc[group].bg_free_inodes_count -= inuse;
+	if (isdir)
+		fs->group_desc[group].bg_used_dirs_count += inuse;
+	fs->super->s_free_inodes_count -= inuse;
+	ext2fs_mark_super_dirty(fs);
+	ext2fs_mark_ib_dirty(fs);
+}
+
+void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse)
+{
+	ext2fs_inode_alloc_stats2(fs, ino, inuse, 0);
+}
+
+void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse)
+{
+	int	group = ext2fs_group_of_blk(fs, blk);
+
+	if (inuse > 0)
+		ext2fs_mark_block_bitmap(fs->block_map, blk);
+	else
+		ext2fs_unmark_block_bitmap(fs->block_map, blk);
+	fs->group_desc[group].bg_free_blocks_count -= inuse;
+	fs->super->s_free_blocks_count -= inuse;
+	ext2fs_mark_super_dirty(fs);
+	ext2fs_mark_bb_dirty(fs);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/alloc_tables.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/alloc_tables.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/alloc_tables.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,117 @@
+/*
+ * alloc_tables.c --- Allocate tables for a newly initialized
+ * filesystem.  Used by mke2fs when initializing a filesystem
+ *
+ * Copyright (C) 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
+				      ext2fs_block_bitmap bmap)
+{
+	errcode_t	retval;
+	blk_t		group_blk, start_blk, last_blk, new_blk, blk;
+	int		j;
+
+	group_blk = fs->super->s_first_data_block +
+		(group * fs->super->s_blocks_per_group);
+
+	last_blk = group_blk + fs->super->s_blocks_per_group;
+	if (last_blk >= fs->super->s_blocks_count)
+		last_blk = fs->super->s_blocks_count - 1;
+
+	if (!bmap)
+		bmap = fs->block_map;
+
+	/*
+	 * Allocate the block and inode bitmaps, if necessary
+	 */
+	if (fs->stride) {
+		start_blk = group_blk + fs->inode_blocks_per_group;
+		start_blk += ((fs->stride * group) %
+			      (last_blk - start_blk));
+		if (start_blk > last_blk)
+			start_blk = group_blk;
+	} else
+		start_blk = group_blk;
+
+	if (!fs->group_desc[group].bg_block_bitmap) {
+		retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
+						1, bmap, &new_blk);
+		if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
+			retval = ext2fs_get_free_blocks(fs, group_blk,
+					last_blk, 1, bmap, &new_blk);
+		if (retval)
+			return retval;
+		ext2fs_mark_block_bitmap(bmap, new_blk);
+		fs->group_desc[group].bg_block_bitmap = new_blk;
+	}
+
+	if (!fs->group_desc[group].bg_inode_bitmap) {
+		retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
+						1, bmap, &new_blk);
+		if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
+			retval = ext2fs_get_free_blocks(fs, group_blk,
+					last_blk, 1, bmap, &new_blk);
+		if (retval)
+			return retval;
+		ext2fs_mark_block_bitmap(bmap, new_blk);
+		fs->group_desc[group].bg_inode_bitmap = new_blk;
+	}
+
+	/*
+	 * Allocate the inode table
+	 */
+	if (!fs->group_desc[group].bg_inode_table) {
+		retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
+						fs->inode_blocks_per_group,
+						bmap, &new_blk);
+		if (retval)
+			return retval;
+		for (j=0, blk = new_blk;
+		     j < fs->inode_blocks_per_group;
+		     j++, blk++)
+			ext2fs_mark_block_bitmap(bmap, blk);
+		fs->group_desc[group].bg_inode_table = new_blk;
+	}
+
+
+	return 0;
+}
+
+
+
+errcode_t ext2fs_allocate_tables(ext2_filsys fs)
+{
+	errcode_t	retval;
+	dgrp_t		i;
+
+	for (i = 0; i < fs->group_desc_count; i++) {
+		retval = ext2fs_allocate_group_table(fs, i, fs->block_map);
+		if (retval)
+			return retval;
+	}
+	return 0;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/badblocks.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/badblocks.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/badblocks.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,327 @@
+/*
+ * badblocks.c --- routines to manipulate the bad block structure
+ *
+ * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+/*
+ * Helper function for making a badblocks list
+ */
+static errcode_t make_u32_list(int size, int num, __u32 *list,
+			       ext2_u32_list *ret)
+{
+	ext2_u32_list	bb;
+	errcode_t	retval;
+
+	retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_list), &bb);
+	if (retval)
+		return retval;
+	memset(bb, 0, sizeof(struct ext2_struct_u32_list));
+	bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
+	bb->size = size ? size : 10;
+	bb->num = num;
+	retval = ext2fs_get_mem(bb->size * sizeof(blk_t), &bb->list);
+	if (!bb->list) {
+		ext2fs_free_mem(&bb);
+		return retval;
+	}
+	if (list)
+		memcpy(bb->list, list, bb->size * sizeof(blk_t));
+	else
+		memset(bb->list, 0, bb->size * sizeof(blk_t));
+	*ret = bb;
+	return 0;
+}
+
+
+/*
+ * This procedure creates an empty u32 list.
+ */
+errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size)
+{
+	return make_u32_list(size, 0, 0, ret);
+}
+
+/*
+ * This procedure creates an empty badblocks list.
+ */
+errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size)
+{
+	return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret);
+}
+
+
+/*
+ * This procedure copies a badblocks list
+ */
+errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest)
+{
+	errcode_t	retval;
+
+	retval = make_u32_list(src->size, src->num, src->list, dest);
+	if (retval)
+		return retval;
+	(*dest)->badblocks_flags = src->badblocks_flags;
+	return 0;
+}
+
+errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
+				ext2_badblocks_list *dest)
+{
+	return ext2fs_u32_copy((ext2_u32_list) src,
+			       (ext2_u32_list *) dest);
+}
+
+/*
+ * This procedure frees a badblocks list.
+ *
+ * (note: moved to closefs.c)
+ */
+
+
+/*
+ * This procedure adds a block to a badblocks list.
+ */
+errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk)
+{
+	errcode_t	retval;
+	int		i, j;
+	unsigned long	old_size;
+
+	EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
+
+	if (bb->num >= bb->size) {
+		old_size = bb->size * sizeof(__u32);
+		bb->size += 100;
+		retval = ext2fs_resize_mem(old_size, bb->size * sizeof(__u32),
+					   &bb->list);
+		if (retval) {
+			bb->size -= 100;
+			return retval;
+		}
+	}
+
+	/*
+	 * Add special case code for appending to the end of the list
+	 */
+	i = bb->num-1;
+	if ((bb->num != 0) && (bb->list[i] == blk))
+		return 0;
+	if ((bb->num == 0) || (bb->list[i] < blk)) {
+		bb->list[bb->num++] = blk;
+		return 0;
+	}
+
+	j = bb->num;
+	for (i=0; i < bb->num; i++) {
+		if (bb->list[i] == blk)
+			return 0;
+		if (bb->list[i] > blk) {
+			j = i;
+			break;
+		}
+	}
+	for (i=bb->num; i > j; i--)
+		bb->list[i] = bb->list[i-1];
+	bb->list[j] = blk;
+	bb->num++;
+	return 0;
+}
+
+errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
+{
+	return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk);
+}
+
+/*
+ * This procedure finds a particular block is on a badblocks
+ * list.
+ */
+int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk)
+{
+	int	low, high, mid;
+
+	if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
+		return -1;
+
+	if (bb->num == 0)
+		return -1;
+
+	low = 0;
+	high = bb->num-1;
+	if (blk == bb->list[low])
+		return low;
+	if (blk == bb->list[high])
+		return high;
+
+	while (low < high) {
+		mid = (low+high)/2;
+		if (mid == low || mid == high)
+			break;
+		if (blk == bb->list[mid])
+			return mid;
+		if (blk < bb->list[mid])
+			high = mid;
+		else
+			low = mid;
+	}
+	return -1;
+}
+
+/*
+ * This procedure tests to see if a particular block is on a badblocks
+ * list.
+ */
+int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk)
+{
+	if (ext2fs_u32_list_find(bb, blk) < 0)
+		return 0;
+	else
+		return 1;
+}
+
+int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
+{
+	return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk);
+}
+
+
+/*
+ * Remove a block from the badblock list
+ */
+int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk)
+{
+	int	remloc, i;
+
+	if (bb->num == 0)
+		return -1;
+
+	remloc = ext2fs_u32_list_find(bb, blk);
+	if (remloc < 0)
+		return -1;
+
+	for (i = remloc ; i < bb->num-1; i++)
+		bb->list[i] = bb->list[i+1];
+	bb->num--;
+	return 0;
+}
+
+void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk)
+{
+	ext2fs_u32_list_del(bb, blk);
+}
+
+errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
+					ext2_u32_iterate *ret)
+{
+	ext2_u32_iterate iter;
+	errcode_t		retval;
+
+	EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
+
+	retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_iterate), &iter);
+	if (retval)
+		return retval;
+
+	iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE;
+	iter->bb = bb;
+	iter->ptr = 0;
+	*ret = iter;
+	return 0;
+}
+
+errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
+					      ext2_badblocks_iterate *ret)
+{
+	return ext2fs_u32_list_iterate_begin((ext2_u32_list) bb,
+					      (ext2_u32_iterate *) ret);
+}
+
+
+int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk)
+{
+	ext2_u32_list	bb;
+
+	if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
+		return 0;
+
+	bb = iter->bb;
+
+	if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
+		return 0;
+
+	if (iter->ptr < bb->num) {
+		*blk = bb->list[iter->ptr++];
+		return 1;
+	}
+	*blk = 0;
+	return 0;
+}
+
+int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
+{
+	return ext2fs_u32_list_iterate((ext2_u32_iterate) iter,
+				       (__u32 *) blk);
+}
+
+
+void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter)
+{
+	if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
+		return;
+
+	iter->bb = 0;
+	ext2fs_free_mem(&iter);
+}
+
+void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter)
+{
+	ext2fs_u32_list_iterate_end((ext2_u32_iterate) iter);
+}
+
+
+int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2)
+{
+	EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST);
+	EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST);
+
+	if (bb1->num != bb2->num)
+		return 0;
+
+	if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0)
+		return 0;
+	return 1;
+}
+
+int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2)
+{
+	return ext2fs_u32_list_equal((ext2_u32_list) bb1,
+				     (ext2_u32_list) bb2);
+}
+
+int ext2fs_u32_list_count(ext2_u32_list bb)
+{
+	return bb->num;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bb_compat.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bb_compat.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bb_compat.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,63 @@
+/*
+ * bb_compat.c --- compatibility badblocks routines
+ *
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+errcode_t badblocks_list_create(badblocks_list *ret, int size)
+{
+	return ext2fs_badblocks_list_create(ret, size);
+}
+
+void badblocks_list_free(badblocks_list bb)
+{
+	ext2fs_badblocks_list_free(bb);
+}
+
+errcode_t badblocks_list_add(badblocks_list bb, blk_t blk)
+{
+	return ext2fs_badblocks_list_add(bb, blk);
+}
+
+int badblocks_list_test(badblocks_list bb, blk_t blk)
+{
+	return ext2fs_badblocks_list_test(bb, blk);
+}
+
+errcode_t badblocks_list_iterate_begin(badblocks_list bb,
+				       badblocks_iterate *ret)
+{
+	return ext2fs_badblocks_list_iterate_begin(bb, ret);
+}
+
+int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk)
+{
+	return ext2fs_badblocks_list_iterate(iter, blk);
+}
+
+void badblocks_list_iterate_end(badblocks_iterate iter)
+{
+	ext2fs_badblocks_list_iterate_end(iter);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bb_inode.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bb_inode.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bb_inode.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,267 @@
+/*
+ * bb_inode.c --- routines to update the bad block inode.
+ *
+ * WARNING: This routine modifies a lot of state in the filesystem; if
+ * this routine returns an error, the bad block inode may be in an
+ * inconsistent state.
+ *
+ * Copyright (C) 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct set_badblock_record {
+	ext2_badblocks_iterate	bb_iter;
+	int		bad_block_count;
+	blk_t		*ind_blocks;
+	int		max_ind_blocks;
+	int		ind_blocks_size;
+	int		ind_blocks_ptr;
+	char		*block_buf;
+	errcode_t	err;
+};
+
+static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
+			      e2_blkcnt_t blockcnt,
+			      blk_t ref_block, int ref_offset,
+			      void *priv_data);
+static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
+				e2_blkcnt_t blockcnt,
+				blk_t ref_block, int ref_offset,
+				void *priv_data);
+
+/*
+ * Given a bad blocks bitmap, update the bad blocks inode to reflect
+ * the map.
+ */
+errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
+{
+	errcode_t			retval;
+	struct set_badblock_record	rec;
+	struct ext2_inode		inode;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (!fs->block_map)
+		return EXT2_ET_NO_BLOCK_BITMAP;
+
+	rec.bad_block_count = 0;
+	rec.ind_blocks_size = rec.ind_blocks_ptr = 0;
+	rec.max_ind_blocks = 10;
+	retval = ext2fs_get_mem(rec.max_ind_blocks * sizeof(blk_t),
+				&rec.ind_blocks);
+	if (retval)
+		return retval;
+	memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t));
+	retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf);
+	if (retval)
+		goto cleanup;
+	memset(rec.block_buf, 0, fs->blocksize);
+	rec.err = 0;
+
+	/*
+	 * First clear the old bad blocks (while saving the indirect blocks)
+	 */
+	retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
+				       BLOCK_FLAG_DEPTH_TRAVERSE, 0,
+				       clear_bad_block_proc, &rec);
+	if (retval)
+		goto cleanup;
+	if (rec.err) {
+		retval = rec.err;
+		goto cleanup;
+	}
+
+	/*
+	 * Now set the bad blocks!
+	 *
+	 * First, mark the bad blocks as used.  This prevents a bad
+	 * block from being used as an indirecto block for the bad
+	 * block inode (!).
+	 */
+	if (bb_list) {
+		retval = ext2fs_badblocks_list_iterate_begin(bb_list,
+							     &rec.bb_iter);
+		if (retval)
+			goto cleanup;
+		retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
+					       BLOCK_FLAG_APPEND, 0,
+					       set_bad_block_proc, &rec);
+		ext2fs_badblocks_list_iterate_end(rec.bb_iter);
+		if (retval)
+			goto cleanup;
+		if (rec.err) {
+			retval = rec.err;
+			goto cleanup;
+		}
+	}
+
+	/*
+	 * Update the bad block inode's mod time and block count
+	 * field.
+	 */
+	retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
+	if (retval)
+		goto cleanup;
+
+	inode.i_atime = inode.i_mtime = time(0);
+	if (!inode.i_ctime)
+		inode.i_ctime = time(0);
+	inode.i_blocks = rec.bad_block_count * (fs->blocksize / 512);
+	inode.i_size = rec.bad_block_count * fs->blocksize;
+
+	retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode);
+	if (retval)
+		goto cleanup;
+
+cleanup:
+	ext2fs_free_mem(&rec.ind_blocks);
+	ext2fs_free_mem(&rec.block_buf);
+	return retval;
+}
+
+/*
+ * Helper function for update_bb_inode()
+ *
+ * Clear the bad blocks in the bad block inode, while saving the
+ * indirect blocks.
+ */
+#ifdef __TURBOC__
+# pragma argsused
+#endif
+static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
+				e2_blkcnt_t blockcnt,
+				blk_t ref_block EXT2FS_ATTR((unused)),
+				int ref_offset EXT2FS_ATTR((unused)),
+				void *priv_data)
+{
+	struct set_badblock_record *rec = (struct set_badblock_record *)
+		priv_data;
+	errcode_t	retval;
+	unsigned long	old_size;
+
+	if (!*block_nr)
+		return 0;
+
+	/*
+	 * If the block number is outrageous, clear it and ignore it.
+	 */
+	if (*block_nr >= fs->super->s_blocks_count ||
+	    *block_nr < fs->super->s_first_data_block) {
+		*block_nr = 0;
+		return BLOCK_CHANGED;
+	}
+
+	if (blockcnt < 0) {
+		if (rec->ind_blocks_size >= rec->max_ind_blocks) {
+			old_size = rec->max_ind_blocks * sizeof(blk_t);
+			rec->max_ind_blocks += 10;
+			retval = ext2fs_resize_mem(old_size,
+				   rec->max_ind_blocks * sizeof(blk_t),
+				   &rec->ind_blocks);
+			if (retval) {
+				rec->max_ind_blocks -= 10;
+				rec->err = retval;
+				return BLOCK_ABORT;
+			}
+		}
+		rec->ind_blocks[rec->ind_blocks_size++] = *block_nr;
+	}
+
+	/*
+	 * Mark the block as unused, and update accounting information
+	 */
+	ext2fs_block_alloc_stats(fs, *block_nr, -1);
+
+	*block_nr = 0;
+	return BLOCK_CHANGED;
+}
+
+
+/*
+ * Helper function for update_bb_inode()
+ *
+ * Set the block list in the bad block inode, using the supplied bitmap.
+ */
+#ifdef __TURBOC__
+ #pragma argsused
+#endif
+static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
+			      e2_blkcnt_t blockcnt,
+			      blk_t ref_block EXT2FS_ATTR((unused)),
+			      int ref_offset EXT2FS_ATTR((unused)),
+			      void *priv_data)
+{
+	struct set_badblock_record *rec = (struct set_badblock_record *)
+		priv_data;
+	errcode_t	retval;
+	blk_t		blk;
+
+	if (blockcnt >= 0) {
+		/*
+		 * Get the next bad block.
+		 */
+		if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk))
+			return BLOCK_ABORT;
+		rec->bad_block_count++;
+	} else {
+		/*
+		 * An indirect block; fetch a block from the
+		 * previously used indirect block list.  The block
+		 * most be not marked as used; if so, get another one.
+		 * If we run out of reserved indirect blocks, allocate
+		 * a new one.
+		 */
+	retry:
+		if (rec->ind_blocks_ptr < rec->ind_blocks_size) {
+			blk = rec->ind_blocks[rec->ind_blocks_ptr++];
+			if (ext2fs_test_block_bitmap(fs->block_map, blk))
+				goto retry;
+		} else {
+			retval = ext2fs_new_block(fs, 0, 0, &blk);
+			if (retval) {
+				rec->err = retval;
+				return BLOCK_ABORT;
+			}
+		}
+		retval = io_channel_write_blk(fs->io, blk, 1, rec->block_buf);
+		if (retval) {
+			rec->err = retval;
+			return BLOCK_ABORT;
+		}
+	}
+
+	/*
+	 * Update block counts
+	 */
+	ext2fs_block_alloc_stats(fs, blk, +1);
+
+	*block_nr = blk;
+	return BLOCK_CHANGED;
+}
+
+
+
+
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bitmaps.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bitmaps.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bitmaps.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,212 @@
+/*
+ * bitmaps.c --- routines to read, write, and manipulate the inode and
+ * block bitmaps.
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+static errcode_t make_bitmap(__u32 start, __u32 end, __u32 real_end,
+			     const char *descr, char *init_map,
+			     ext2fs_generic_bitmap *ret)
+{
+	ext2fs_generic_bitmap	bitmap;
+	errcode_t		retval;
+	size_t			size;
+
+	retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap),
+				&bitmap);
+	if (retval)
+		return retval;
+
+	bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
+	bitmap->fs = NULL;
+	bitmap->start = start;
+	bitmap->end = end;
+	bitmap->real_end = real_end;
+	bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
+	if (descr) {
+		retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
+		if (retval) {
+			ext2fs_free_mem(&bitmap);
+			return retval;
+		}
+		strcpy(bitmap->description, descr);
+	} else
+		bitmap->description = 0;
+
+	size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
+	retval = ext2fs_get_mem(size, &bitmap->bitmap);
+	if (retval) {
+		ext2fs_free_mem(&bitmap->description);
+		ext2fs_free_mem(&bitmap);
+		return retval;
+	}
+
+	if (init_map)
+		memcpy(bitmap->bitmap, init_map, size);
+	else
+		memset(bitmap->bitmap, 0, size);
+	*ret = bitmap;
+	return 0;
+}
+
+errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
+					 __u32 end,
+					 __u32 real_end,
+					 const char *descr,
+					 ext2fs_generic_bitmap *ret)
+{
+	return make_bitmap(start, end, real_end, descr, 0, ret);
+}
+
+errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
+			     ext2fs_generic_bitmap *dest)
+{
+	errcode_t		retval;
+	ext2fs_generic_bitmap	new_map;
+
+	retval = make_bitmap(src->start, src->end, src->real_end,
+			     src->description, src->bitmap, &new_map);
+	if (retval)
+		return retval;
+	new_map->magic = src->magic;
+	new_map->fs = src->fs;
+	new_map->base_error_code = src->base_error_code;
+	*dest = new_map;
+	return 0;
+}
+
+void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map)
+{
+	__u32	i, j;
+
+	for (i=map->end+1, j = i - map->start; i <= map->real_end; i++, j++)
+		ext2fs_set_bit(j, map->bitmap);
+
+	return;
+}
+
+errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
+				       const char *descr,
+				       ext2fs_inode_bitmap *ret)
+{
+	ext2fs_inode_bitmap bitmap;
+	errcode_t	retval;
+	__u32		start, end, real_end;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	fs->write_bitmaps = ext2fs_write_bitmaps;
+
+	start = 1;
+	end = fs->super->s_inodes_count;
+	real_end = (EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count);
+
+	retval = ext2fs_allocate_generic_bitmap(start, end, real_end,
+						descr, &bitmap);
+	if (retval)
+		return retval;
+
+	bitmap->magic = EXT2_ET_MAGIC_INODE_BITMAP;
+	bitmap->fs = fs;
+	bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
+
+	*ret = bitmap;
+	return 0;
+}
+
+errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
+				       const char *descr,
+				       ext2fs_block_bitmap *ret)
+{
+	ext2fs_block_bitmap bitmap;
+	errcode_t	retval;
+	__u32		start, end, real_end;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	fs->write_bitmaps = ext2fs_write_bitmaps;
+
+	start = fs->super->s_first_data_block;
+	end = fs->super->s_blocks_count-1;
+	real_end = (EXT2_BLOCKS_PER_GROUP(fs->super)
+		    * fs->group_desc_count)-1 + start;
+
+	retval = ext2fs_allocate_generic_bitmap(start, end, real_end,
+						descr, &bitmap);
+	if (retval)
+		return retval;
+
+	bitmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP;
+	bitmap->fs = fs;
+	bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
+
+	*ret = bitmap;
+	return 0;
+}
+
+errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
+					ext2_ino_t end, ext2_ino_t *oend)
+{
+	EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP);
+
+	if (end > bitmap->real_end)
+		return EXT2_ET_FUDGE_INODE_BITMAP_END;
+	if (oend)
+		*oend = bitmap->end;
+	bitmap->end = end;
+	return 0;
+}
+
+errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
+					blk_t end, blk_t *oend)
+{
+	EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
+
+	if (end > bitmap->real_end)
+		return EXT2_ET_FUDGE_BLOCK_BITMAP_END;
+	if (oend)
+		*oend = bitmap->end;
+	bitmap->end = end;
+	return 0;
+}
+
+void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap)
+{
+	if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP))
+		return;
+
+	memset(bitmap->bitmap, 0,
+	       (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
+}
+
+void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap)
+{
+	if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP))
+		return;
+
+	memset(bitmap->bitmap, 0,
+	       (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bitops.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bitops.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bitops.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,90 @@
+/*
+ * bitops.c --- Bitmap frobbing code.  See bitops.h for the inlined
+ *	routines.
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#ifndef _EXT2_HAVE_ASM_BITOPS_
+
+/*
+ * For the benefit of those who are trying to port Linux to another
+ * architecture, here are some C-language equivalents.  You should
+ * recode these in the native assmebly language, if at all possible.
+ *
+ * C language equivalents written by Theodore Ts'o, 9/26/92.
+ * Modified by Pete A. Zaitcev 7/14/95 to be portable to big endian
+ * systems, as well as non-32 bit systems.
+ */
+
+int ext2fs_set_bit(unsigned int nr,void * addr)
+{
+	int		mask, retval;
+	unsigned char	*ADDR = (unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	retval = mask & *ADDR;
+	*ADDR |= mask;
+	return retval;
+}
+
+int ext2fs_clear_bit(unsigned int nr, void * addr)
+{
+	int		mask, retval;
+	unsigned char	*ADDR = (unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	retval = mask & *ADDR;
+	*ADDR &= ~mask;
+	return retval;
+}
+
+int ext2fs_test_bit(unsigned int nr, const void * addr)
+{
+	int			mask;
+	const unsigned char	*ADDR = (const unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	return (mask & *ADDR);
+}
+
+#endif	/* !_EXT2_HAVE_ASM_BITOPS_ */
+
+void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
+			const char *description)
+{
+#ifndef OMIT_COM_ERR
+	if (description)
+		bb_error_msg("#%lu for %s", arg, description);
+	else
+		bb_error_msg("#%lu", arg);
+#endif
+}
+
+void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
+			    int code, unsigned long arg)
+{
+#ifndef OMIT_COM_ERR
+	if (bitmap->description)
+		bb_error_msg("#%lu for %s", arg, bitmap->description);
+	else
+		bb_error_msg("#%lu", arg);
+#endif
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bitops.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bitops.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bitops.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,106 @@
+/*
+ * bitops.h --- Bitmap frobbing code.  The byte swapping routines are
+ *	also included here.
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ *
+ * i386 bitops operations taken from <asm/bitops.h>, Copyright 1992,
+ * Linus Torvalds.
+ */
+
+#include <string.h>
+#include <strings.h>
+
+extern int ext2fs_set_bit(unsigned int nr,void * addr);
+extern int ext2fs_clear_bit(unsigned int nr, void * addr);
+extern int ext2fs_test_bit(unsigned int nr, const void * addr);
+extern __u16 ext2fs_swab16(__u16 val);
+extern __u32 ext2fs_swab32(__u32 val);
+
+#ifdef WORDS_BIGENDIAN
+#define ext2fs_cpu_to_le32(x) ext2fs_swab32((x))
+#define ext2fs_le32_to_cpu(x) ext2fs_swab32((x))
+#define ext2fs_cpu_to_le16(x) ext2fs_swab16((x))
+#define ext2fs_le16_to_cpu(x) ext2fs_swab16((x))
+#define ext2fs_cpu_to_be32(x) ((__u32)(x))
+#define ext2fs_be32_to_cpu(x) ((__u32)(x))
+#define ext2fs_cpu_to_be16(x) ((__u16)(x))
+#define ext2fs_be16_to_cpu(x) ((__u16)(x))
+#else
+#define ext2fs_cpu_to_le32(x) ((__u32)(x))
+#define ext2fs_le32_to_cpu(x) ((__u32)(x))
+#define ext2fs_cpu_to_le16(x) ((__u16)(x))
+#define ext2fs_le16_to_cpu(x) ((__u16)(x))
+#define ext2fs_cpu_to_be32(x) ext2fs_swab32((x))
+#define ext2fs_be32_to_cpu(x) ext2fs_swab32((x))
+#define ext2fs_cpu_to_be16(x) ext2fs_swab16((x))
+#define ext2fs_be16_to_cpu(x) ext2fs_swab16((x))
+#endif
+
+/*
+ * EXT2FS bitmap manipulation routines.
+ */
+
+/* Support for sending warning messages from the inline subroutines */
+extern const char *ext2fs_block_string;
+extern const char *ext2fs_inode_string;
+extern const char *ext2fs_mark_string;
+extern const char *ext2fs_unmark_string;
+extern const char *ext2fs_test_string;
+extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
+			       const char *description);
+extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
+				int code, unsigned long arg);
+
+extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
+extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
+				       blk_t block);
+extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
+
+extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
+extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+				       ext2_ino_t inode);
+extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
+
+extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
+					  blk_t block);
+extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
+					    blk_t block);
+extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
+					 blk_t block);
+
+extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+					  ext2_ino_t inode);
+extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+					    ext2_ino_t inode);
+extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
+					 ext2_ino_t inode);
+extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
+extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
+extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
+extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
+
+extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+					   blk_t block, int num);
+extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+					     blk_t block, int num);
+extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
+					  blk_t block, int num);
+extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+						blk_t block, int num);
+extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+						  blk_t block, int num);
+extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
+					       blk_t block, int num);
+extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map);
+
+/* These two routines moved to gen_bitmap.c */
+extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
+					 __u32 bitno);
+extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
+					   blk_t bitno);

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/block.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/block.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/block.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,437 @@
+/*
+ * block.c --- iterate over all blocks in an inode
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct block_context {
+	ext2_filsys	fs;
+	int (*func)(ext2_filsys	fs,
+		    blk_t	*blocknr,
+		    e2_blkcnt_t	bcount,
+		    blk_t	ref_blk,
+		    int		ref_offset,
+		    void	*priv_data);
+	e2_blkcnt_t	bcount;
+	int		bsize;
+	int		flags;
+	errcode_t	errcode;
+	char	*ind_buf;
+	char	*dind_buf;
+	char	*tind_buf;
+	void	*priv_data;
+};
+
+static int block_iterate_ind(blk_t *ind_block, blk_t ref_block,
+			     int ref_offset, struct block_context *ctx)
+{
+	int	ret = 0, changed = 0;
+	int	i, flags, limit, offset;
+	blk_t	*block_nr;
+
+	limit = ctx->fs->blocksize >> 2;
+	if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
+	    !(ctx->flags & BLOCK_FLAG_DATA_ONLY))
+		ret = (*ctx->func)(ctx->fs, ind_block,
+				   BLOCK_COUNT_IND, ref_block,
+				   ref_offset, ctx->priv_data);
+	if (!*ind_block || (ret & BLOCK_ABORT)) {
+		ctx->bcount += limit;
+		return ret;
+	}
+	if (*ind_block >= ctx->fs->super->s_blocks_count ||
+	    *ind_block < ctx->fs->super->s_first_data_block) {
+		ctx->errcode = EXT2_ET_BAD_IND_BLOCK;
+		ret |= BLOCK_ERROR;
+		return ret;
+	}
+	ctx->errcode = ext2fs_read_ind_block(ctx->fs, *ind_block,
+					     ctx->ind_buf);
+	if (ctx->errcode) {
+		ret |= BLOCK_ERROR;
+		return ret;
+	}
+
+	block_nr = (blk_t *) ctx->ind_buf;
+	offset = 0;
+	if (ctx->flags & BLOCK_FLAG_APPEND) {
+		for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
+			flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
+					     *ind_block, offset,
+					     ctx->priv_data);
+			changed	|= flags;
+			if (flags & BLOCK_ABORT) {
+				ret |= BLOCK_ABORT;
+				break;
+			}
+			offset += sizeof(blk_t);
+		}
+	} else {
+		for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
+			if (*block_nr == 0)
+				continue;
+			flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
+					     *ind_block, offset,
+					     ctx->priv_data);
+			changed	|= flags;
+			if (flags & BLOCK_ABORT) {
+				ret |= BLOCK_ABORT;
+				break;
+			}
+			offset += sizeof(blk_t);
+		}
+	}
+	if (changed & BLOCK_CHANGED) {
+		ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block,
+						      ctx->ind_buf);
+		if (ctx->errcode)
+			ret |= BLOCK_ERROR | BLOCK_ABORT;
+	}
+	if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
+	    !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
+	    !(ret & BLOCK_ABORT))
+		ret |= (*ctx->func)(ctx->fs, ind_block,
+				    BLOCK_COUNT_IND, ref_block,
+				    ref_offset, ctx->priv_data);
+	return ret;
+}
+
+static int block_iterate_dind(blk_t *dind_block, blk_t ref_block,
+			      int ref_offset, struct block_context *ctx)
+{
+	int	ret = 0, changed = 0;
+	int	i, flags, limit, offset;
+	blk_t	*block_nr;
+
+	limit = ctx->fs->blocksize >> 2;
+	if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
+			    BLOCK_FLAG_DATA_ONLY)))
+		ret = (*ctx->func)(ctx->fs, dind_block,
+				   BLOCK_COUNT_DIND, ref_block,
+				   ref_offset, ctx->priv_data);
+	if (!*dind_block || (ret & BLOCK_ABORT)) {
+		ctx->bcount += limit*limit;
+		return ret;
+	}
+	if (*dind_block >= ctx->fs->super->s_blocks_count ||
+	    *dind_block < ctx->fs->super->s_first_data_block) {
+		ctx->errcode = EXT2_ET_BAD_DIND_BLOCK;
+		ret |= BLOCK_ERROR;
+		return ret;
+	}
+	ctx->errcode = ext2fs_read_ind_block(ctx->fs, *dind_block,
+					     ctx->dind_buf);
+	if (ctx->errcode) {
+		ret |= BLOCK_ERROR;
+		return ret;
+	}
+
+	block_nr = (blk_t *) ctx->dind_buf;
+	offset = 0;
+	if (ctx->flags & BLOCK_FLAG_APPEND) {
+		for (i = 0; i < limit; i++, block_nr++) {
+			flags = block_iterate_ind(block_nr,
+						  *dind_block, offset,
+						  ctx);
+			changed |= flags;
+			if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
+				ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
+				break;
+			}
+			offset += sizeof(blk_t);
+		}
+	} else {
+		for (i = 0; i < limit; i++, block_nr++) {
+			if (*block_nr == 0) {
+				ctx->bcount += limit;
+				continue;
+			}
+			flags = block_iterate_ind(block_nr,
+						  *dind_block, offset,
+						  ctx);
+			changed |= flags;
+			if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
+				ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
+				break;
+			}
+			offset += sizeof(blk_t);
+		}
+	}
+	if (changed & BLOCK_CHANGED) {
+		ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block,
+						      ctx->dind_buf);
+		if (ctx->errcode)
+			ret |= BLOCK_ERROR | BLOCK_ABORT;
+	}
+	if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
+	    !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
+	    !(ret & BLOCK_ABORT))
+		ret |= (*ctx->func)(ctx->fs, dind_block,
+				    BLOCK_COUNT_DIND, ref_block,
+				    ref_offset, ctx->priv_data);
+	return ret;
+}
+
+static int block_iterate_tind(blk_t *tind_block, blk_t ref_block,
+			      int ref_offset, struct block_context *ctx)
+{
+	int	ret = 0, changed = 0;
+	int	i, flags, limit, offset;
+	blk_t	*block_nr;
+
+	limit = ctx->fs->blocksize >> 2;
+	if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
+			    BLOCK_FLAG_DATA_ONLY)))
+		ret = (*ctx->func)(ctx->fs, tind_block,
+				   BLOCK_COUNT_TIND, ref_block,
+				   ref_offset, ctx->priv_data);
+	if (!*tind_block || (ret & BLOCK_ABORT)) {
+		ctx->bcount += limit*limit*limit;
+		return ret;
+	}
+	if (*tind_block >= ctx->fs->super->s_blocks_count ||
+	    *tind_block < ctx->fs->super->s_first_data_block) {
+		ctx->errcode = EXT2_ET_BAD_TIND_BLOCK;
+		ret |= BLOCK_ERROR;
+		return ret;
+	}
+	ctx->errcode = ext2fs_read_ind_block(ctx->fs, *tind_block,
+					     ctx->tind_buf);
+	if (ctx->errcode) {
+		ret |= BLOCK_ERROR;
+		return ret;
+	}
+
+	block_nr = (blk_t *) ctx->tind_buf;
+	offset = 0;
+	if (ctx->flags & BLOCK_FLAG_APPEND) {
+		for (i = 0; i < limit; i++, block_nr++) {
+			flags = block_iterate_dind(block_nr,
+						   *tind_block,
+						   offset, ctx);
+			changed |= flags;
+			if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
+				ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
+				break;
+			}
+			offset += sizeof(blk_t);
+		}
+	} else {
+		for (i = 0; i < limit; i++, block_nr++) {
+			if (*block_nr == 0) {
+				ctx->bcount += limit*limit;
+				continue;
+			}
+			flags = block_iterate_dind(block_nr,
+						   *tind_block,
+						   offset, ctx);
+			changed |= flags;
+			if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
+				ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
+				break;
+			}
+			offset += sizeof(blk_t);
+		}
+	}
+	if (changed & BLOCK_CHANGED) {
+		ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block,
+						      ctx->tind_buf);
+		if (ctx->errcode)
+			ret |= BLOCK_ERROR | BLOCK_ABORT;
+	}
+	if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
+	    !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
+	    !(ret & BLOCK_ABORT))
+		ret |= (*ctx->func)(ctx->fs, tind_block,
+				    BLOCK_COUNT_TIND, ref_block,
+				    ref_offset, ctx->priv_data);
+
+	return ret;
+}
+
+errcode_t ext2fs_block_iterate2(ext2_filsys fs,
+				ext2_ino_t ino,
+				int	flags,
+				char *block_buf,
+				int (*func)(ext2_filsys fs,
+					    blk_t	*blocknr,
+					    e2_blkcnt_t	blockcnt,
+					    blk_t	ref_blk,
+					    int		ref_offset,
+					    void	*priv_data),
+				void *priv_data)
+{
+	int	i;
+	int	got_inode = 0;
+	int	ret = 0;
+	blk_t	blocks[EXT2_N_BLOCKS];	/* directory data blocks */
+	struct ext2_inode inode;
+	errcode_t	retval;
+	struct block_context ctx;
+	int	limit;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	/*
+	 * Check to see if we need to limit large files
+	 */
+	if (flags & BLOCK_FLAG_NO_LARGE) {
+		ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
+		if (ctx.errcode)
+			return ctx.errcode;
+		got_inode = 1;
+		if (!LINUX_S_ISDIR(inode.i_mode) &&
+		    (inode.i_size_high != 0))
+			return EXT2_ET_FILE_TOO_BIG;
+	}
+
+	retval = ext2fs_get_blocks(fs, ino, blocks);
+	if (retval)
+		return retval;
+
+	limit = fs->blocksize >> 2;
+
+	ctx.fs = fs;
+	ctx.func = func;
+	ctx.priv_data = priv_data;
+	ctx.flags = flags;
+	ctx.bcount = 0;
+	if (block_buf) {
+		ctx.ind_buf = block_buf;
+	} else {
+		retval = ext2fs_get_mem(fs->blocksize * 3, &ctx.ind_buf);
+		if (retval)
+			return retval;
+	}
+	ctx.dind_buf = ctx.ind_buf + fs->blocksize;
+	ctx.tind_buf = ctx.dind_buf + fs->blocksize;
+
+	/*
+	 * Iterate over the HURD translator block (if present)
+	 */
+	if ((fs->super->s_creator_os == EXT2_OS_HURD) &&
+	    !(flags & BLOCK_FLAG_DATA_ONLY)) {
+		ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
+		if (ctx.errcode)
+			goto abort_exit;
+		got_inode = 1;
+		if (inode.osd1.hurd1.h_i_translator) {
+			ret |= (*ctx.func)(fs,
+					   &inode.osd1.hurd1.h_i_translator,
+					   BLOCK_COUNT_TRANSLATOR,
+					   0, 0, priv_data);
+			if (ret & BLOCK_ABORT)
+				goto abort_exit;
+		}
+	}
+
+	/*
+	 * Iterate over normal data blocks
+	 */
+	for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) {
+		if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) {
+			ret |= (*ctx.func)(fs, &blocks[i],
+					    ctx.bcount, 0, i, priv_data);
+			if (ret & BLOCK_ABORT)
+				goto abort_exit;
+		}
+	}
+	if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
+		ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK,
+					 0, EXT2_IND_BLOCK, &ctx);
+		if (ret & BLOCK_ABORT)
+			goto abort_exit;
+	} else
+		ctx.bcount += limit;
+	if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
+		ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK,
+					  0, EXT2_DIND_BLOCK, &ctx);
+		if (ret & BLOCK_ABORT)
+			goto abort_exit;
+	} else
+		ctx.bcount += limit * limit;
+	if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
+		ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK,
+					  0, EXT2_TIND_BLOCK, &ctx);
+		if (ret & BLOCK_ABORT)
+			goto abort_exit;
+	}
+
+abort_exit:
+	if (ret & BLOCK_CHANGED) {
+		if (!got_inode) {
+			retval = ext2fs_read_inode(fs, ino, &inode);
+			if (retval)
+				return retval;
+		}
+		for (i=0; i < EXT2_N_BLOCKS; i++)
+			inode.i_block[i] = blocks[i];
+		retval = ext2fs_write_inode(fs, ino, &inode);
+		if (retval)
+			return retval;
+	}
+
+	if (!block_buf)
+		ext2fs_free_mem(&ctx.ind_buf);
+
+	return (ret & BLOCK_ERROR) ? ctx.errcode : 0;
+}
+
+/*
+ * Emulate the old ext2fs_block_iterate function!
+ */
+
+struct xlate {
+	int (*func)(ext2_filsys	fs,
+		    blk_t	*blocknr,
+		    int		bcount,
+		    void	*priv_data);
+	void *real_private;
+};
+
+#ifdef __TURBOC__
+# pragma argsused
+#endif
+static int xlate_func(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt,
+		      blk_t ref_block EXT2FS_ATTR((unused)),
+		      int ref_offset EXT2FS_ATTR((unused)),
+		      void *priv_data)
+{
+	struct xlate *xl = (struct xlate *) priv_data;
+
+	return (*xl->func)(fs, blocknr, (int) blockcnt, xl->real_private);
+}
+
+errcode_t ext2fs_block_iterate(ext2_filsys fs,
+			       ext2_ino_t ino,
+			       int	flags,
+			       char *block_buf,
+			       int (*func)(ext2_filsys fs,
+					   blk_t	*blocknr,
+					   int	blockcnt,
+					   void	*priv_data),
+			       void *priv_data)
+{
+	struct xlate xl;
+
+	xl.real_private = priv_data;
+	xl.func = func;
+
+	return ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_NO_LARGE | flags,
+				     block_buf, xlate_func, &xl);
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bmap.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bmap.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bmap.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,263 @@
+/*
+ * bmap.c --- logical to physical block mapping
+ *
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
+			     struct ext2_inode *inode,
+			     char *block_buf, int bmap_flags,
+			     blk_t block, blk_t *phys_blk);
+
+#define inode_bmap(inode, nr) ((inode)->i_block[(nr)])
+
+static errcode_t block_ind_bmap(ext2_filsys fs, int flags,
+					      blk_t ind, char *block_buf,
+					      int *blocks_alloc,
+					      blk_t nr, blk_t *ret_blk)
+{
+	errcode_t	retval;
+	blk_t		b;
+
+	if (!ind) {
+		if (flags & BMAP_SET)
+			return EXT2_ET_SET_BMAP_NO_IND;
+		*ret_blk = 0;
+		return 0;
+	}
+	retval = io_channel_read_blk(fs->io, ind, 1, block_buf);
+	if (retval)
+		return retval;
+
+	if (flags & BMAP_SET) {
+		b = *ret_blk;
+#if BB_BIG_ENDIAN
+		if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+		    (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
+			b = ext2fs_swab32(b);
+#endif
+		((blk_t *) block_buf)[nr] = b;
+		return io_channel_write_blk(fs->io, ind, 1, block_buf);
+	}
+
+	b = ((blk_t *) block_buf)[nr];
+
+#if BB_BIG_ENDIAN
+	if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+	    (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
+		b = ext2fs_swab32(b);
+#endif
+
+	if (!b && (flags & BMAP_ALLOC)) {
+		b = nr ? ((blk_t *) block_buf)[nr-1] : 0;
+		retval = ext2fs_alloc_block(fs, b,
+					    block_buf + fs->blocksize, &b);
+		if (retval)
+			return retval;
+
+#if BB_BIG_ENDIAN
+		if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+		    (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
+			((blk_t *) block_buf)[nr] = ext2fs_swab32(b);
+		else
+#endif
+			((blk_t *) block_buf)[nr] = b;
+
+		retval = io_channel_write_blk(fs->io, ind, 1, block_buf);
+		if (retval)
+			return retval;
+
+		(*blocks_alloc)++;
+	}
+
+	*ret_blk = b;
+	return 0;
+}
+
+static errcode_t block_dind_bmap(ext2_filsys fs, int flags,
+					       blk_t dind, char *block_buf,
+					       int *blocks_alloc,
+					       blk_t nr, blk_t *ret_blk)
+{
+	blk_t		b;
+	errcode_t	retval;
+	blk_t		addr_per_block;
+
+	addr_per_block = (blk_t) fs->blocksize >> 2;
+
+	retval = block_ind_bmap(fs, flags & ~BMAP_SET, dind, block_buf,
+				blocks_alloc, nr / addr_per_block, &b);
+	if (retval)
+		return retval;
+	retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
+				nr % addr_per_block, ret_blk);
+	return retval;
+}
+
+static errcode_t block_tind_bmap(ext2_filsys fs, int flags,
+					       blk_t tind, char *block_buf,
+					       int *blocks_alloc,
+					       blk_t nr, blk_t *ret_blk)
+{
+	blk_t		b;
+	errcode_t	retval;
+	blk_t		addr_per_block;
+
+	addr_per_block = (blk_t) fs->blocksize >> 2;
+
+	retval = block_dind_bmap(fs, flags & ~BMAP_SET, tind, block_buf,
+				 blocks_alloc, nr / addr_per_block, &b);
+	if (retval)
+		return retval;
+	retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
+				nr % addr_per_block, ret_blk);
+	return retval;
+}
+
+errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
+		      char *block_buf, int bmap_flags, blk_t block,
+		      blk_t *phys_blk)
+{
+	struct ext2_inode inode_buf;
+	blk_t addr_per_block;
+	blk_t	b;
+	char	*buf = 0;
+	errcode_t	retval = 0;
+	int		blocks_alloc = 0, inode_dirty = 0;
+
+	if (!(bmap_flags & BMAP_SET))
+		*phys_blk = 0;
+
+	/* Read inode structure if necessary */
+	if (!inode) {
+		retval = ext2fs_read_inode(fs, ino, &inode_buf);
+		if (retval)
+			return retval;
+		inode = &inode_buf;
+	}
+	addr_per_block = (blk_t) fs->blocksize >> 2;
+
+	if (!block_buf) {
+		retval = ext2fs_get_mem(fs->blocksize * 2, &buf);
+		if (retval)
+			return retval;
+		block_buf = buf;
+	}
+
+	if (block < EXT2_NDIR_BLOCKS) {
+		if (bmap_flags & BMAP_SET) {
+			b = *phys_blk;
+#if BB_BIG_ENDIAN
+			if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+			    (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
+				b = ext2fs_swab32(b);
+#endif
+			inode_bmap(inode, block) = b;
+			inode_dirty++;
+			goto done;
+		}
+
+		*phys_blk = inode_bmap(inode, block);
+		b = block ? inode_bmap(inode, block-1) : 0;
+
+		if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) {
+			retval = ext2fs_alloc_block(fs, b, block_buf, &b);
+			if (retval)
+				goto done;
+			inode_bmap(inode, block) = b;
+			blocks_alloc++;
+			*phys_blk = b;
+		}
+		goto done;
+	}
+
+	/* Indirect block */
+	block -= EXT2_NDIR_BLOCKS;
+	if (block < addr_per_block) {
+		b = inode_bmap(inode, EXT2_IND_BLOCK);
+		if (!b) {
+			if (!(bmap_flags & BMAP_ALLOC)) {
+				if (bmap_flags & BMAP_SET)
+					retval = EXT2_ET_SET_BMAP_NO_IND;
+				goto done;
+			}
+
+			b = inode_bmap(inode, EXT2_IND_BLOCK-1);
+			retval = ext2fs_alloc_block(fs, b, block_buf, &b);
+			if (retval)
+				goto done;
+			inode_bmap(inode, EXT2_IND_BLOCK) = b;
+			blocks_alloc++;
+		}
+		retval = block_ind_bmap(fs, bmap_flags, b, block_buf,
+					&blocks_alloc, block, phys_blk);
+		goto done;
+	}
+
+	/* Doubly indirect block  */
+	block -= addr_per_block;
+	if (block < addr_per_block * addr_per_block) {
+		b = inode_bmap(inode, EXT2_DIND_BLOCK);
+		if (!b) {
+			if (!(bmap_flags & BMAP_ALLOC)) {
+				if (bmap_flags & BMAP_SET)
+					retval = EXT2_ET_SET_BMAP_NO_IND;
+				goto done;
+			}
+
+			b = inode_bmap(inode, EXT2_IND_BLOCK);
+			retval = ext2fs_alloc_block(fs, b, block_buf, &b);
+			if (retval)
+				goto done;
+			inode_bmap(inode, EXT2_DIND_BLOCK) = b;
+			blocks_alloc++;
+		}
+		retval = block_dind_bmap(fs, bmap_flags, b, block_buf,
+					 &blocks_alloc, block, phys_blk);
+		goto done;
+	}
+
+	/* Triply indirect block */
+	block -= addr_per_block * addr_per_block;
+	b = inode_bmap(inode, EXT2_TIND_BLOCK);
+	if (!b) {
+		if (!(bmap_flags & BMAP_ALLOC)) {
+			if (bmap_flags & BMAP_SET)
+				retval = EXT2_ET_SET_BMAP_NO_IND;
+			goto done;
+		}
+
+		b = inode_bmap(inode, EXT2_DIND_BLOCK);
+		retval = ext2fs_alloc_block(fs, b, block_buf, &b);
+		if (retval)
+			goto done;
+		inode_bmap(inode, EXT2_TIND_BLOCK) = b;
+		blocks_alloc++;
+	}
+	retval = block_tind_bmap(fs, bmap_flags, b, block_buf,
+				 &blocks_alloc, block, phys_blk);
+done:
+	ext2fs_free_mem(&buf);
+	if ((retval == 0) && (blocks_alloc || inode_dirty)) {
+		inode->i_blocks += (blocks_alloc * fs->blocksize) / 512;
+		retval = ext2fs_write_inode(fs, ino, inode);
+	}
+	return retval;
+}
+
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bmove.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bmove.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/bmove.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,155 @@
+/*
+ * bmove.c --- Move blocks around to make way for a particular
+ *	filesystem structure.
+ *
+ * Copyright (C) 1997 Theodore Ts'o.  This file may be redistributed
+ * under the terms of the GNU Public License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+struct process_block_struct {
+	ext2_ino_t		ino;
+	struct ext2_inode *	inode;
+	ext2fs_block_bitmap	reserve;
+	ext2fs_block_bitmap	alloc_map;
+	errcode_t		error;
+	char			*buf;
+	int			add_dir;
+	int			flags;
+};
+
+static int process_block(ext2_filsys fs, blk_t	*block_nr,
+			 e2_blkcnt_t blockcnt, blk_t ref_block,
+			 int ref_offset, void *priv_data)
+{
+	struct process_block_struct *pb;
+	errcode_t	retval;
+	int		ret;
+	blk_t		block, orig;
+
+	pb = (struct process_block_struct *) priv_data;
+	block = orig = *block_nr;
+	ret = 0;
+
+	/*
+	 * Let's see if this is one which we need to relocate
+	 */
+	if (ext2fs_test_block_bitmap(pb->reserve, block)) {
+		do {
+			if (++block >= fs->super->s_blocks_count)
+				block = fs->super->s_first_data_block;
+			if (block == orig) {
+				pb->error = EXT2_ET_BLOCK_ALLOC_FAIL;
+				return BLOCK_ABORT;
+			}
+		} while (ext2fs_test_block_bitmap(pb->reserve, block) ||
+			 ext2fs_test_block_bitmap(pb->alloc_map, block));
+
+		retval = io_channel_read_blk(fs->io, orig, 1, pb->buf);
+		if (retval) {
+			pb->error = retval;
+			return BLOCK_ABORT;
+		}
+		retval = io_channel_write_blk(fs->io, block, 1, pb->buf);
+		if (retval) {
+			pb->error = retval;
+			return BLOCK_ABORT;
+		}
+		*block_nr = block;
+		ext2fs_mark_block_bitmap(pb->alloc_map, block);
+		ret = BLOCK_CHANGED;
+		if (pb->flags & EXT2_BMOVE_DEBUG)
+			printf("ino=%ld, blockcnt=%lld, %d->%d\n", pb->ino,
+			       blockcnt, orig, block);
+	}
+	if (pb->add_dir) {
+		retval = ext2fs_add_dir_block(fs->dblist, pb->ino,
+					      block, (int) blockcnt);
+		if (retval) {
+			pb->error = retval;
+			ret |= BLOCK_ABORT;
+		}
+	}
+	return ret;
+}
+
+errcode_t ext2fs_move_blocks(ext2_filsys fs,
+			     ext2fs_block_bitmap reserve,
+			     ext2fs_block_bitmap alloc_map,
+			     int flags)
+{
+	ext2_ino_t	ino;
+	struct ext2_inode inode;
+	errcode_t	retval;
+	struct process_block_struct pb;
+	ext2_inode_scan	scan;
+	char		*block_buf;
+
+	retval = ext2fs_open_inode_scan(fs, 0, &scan);
+	if (retval)
+		return retval;
+
+	pb.reserve = reserve;
+	pb.error = 0;
+	pb.alloc_map = alloc_map ? alloc_map : fs->block_map;
+	pb.flags = flags;
+
+	retval = ext2fs_get_mem(fs->blocksize * 4, &block_buf);
+	if (retval)
+		return retval;
+	pb.buf = block_buf + fs->blocksize * 3;
+
+	/*
+	 * If GET_DBLIST is set in the flags field, then we should
+	 * gather directory block information while we're doing the
+	 * block move.
+	 */
+	if (flags & EXT2_BMOVE_GET_DBLIST) {
+		ext2fs_free_dblist(fs->dblist);
+		fs->dblist = NULL;
+		retval = ext2fs_init_dblist(fs, 0);
+		if (retval)
+			return retval;
+	}
+
+	retval = ext2fs_get_next_inode(scan, &ino, &inode);
+	if (retval)
+		return retval;
+
+	while (ino) {
+		if ((inode.i_links_count == 0) ||
+		    !ext2fs_inode_has_valid_blocks(&inode))
+			goto next;
+
+		pb.ino = ino;
+		pb.inode = &inode;
+
+		pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) &&
+			      flags & EXT2_BMOVE_GET_DBLIST);
+
+		retval = ext2fs_block_iterate2(fs, ino, 0, block_buf,
+					      process_block, &pb);
+		if (retval)
+			return retval;
+		if (pb.error)
+			return pb.error;
+
+	next:
+		retval = ext2fs_get_next_inode(scan, &ino, &inode);
+		if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
+			goto next;
+	}
+	return 0;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/brel.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/brel.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/brel.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,86 @@
+/*
+ * brel.h
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+struct ext2_block_relocate_entry {
+	blk_t	new;
+	__s16	offset;
+	__u16	flags;
+	union {
+		blk_t		block_ref;
+		ext2_ino_t	inode_ref;
+	} owner;
+};
+
+#define RELOCATE_TYPE_REF  0x0007
+#define RELOCATE_BLOCK_REF 0x0001
+#define RELOCATE_INODE_REF 0x0002
+
+typedef struct ext2_block_relocation_table *ext2_brel;
+
+struct ext2_block_relocation_table {
+	__u32	magic;
+	char	*name;
+	blk_t	current;
+	void	*priv_data;
+
+	/*
+	 * Add a block relocation entry.
+	 */
+	errcode_t (*put)(ext2_brel brel, blk_t old,
+			      struct ext2_block_relocate_entry *ent);
+
+	/*
+	 * Get a block relocation entry.
+	 */
+	errcode_t (*get)(ext2_brel brel, blk_t old,
+			      struct ext2_block_relocate_entry *ent);
+
+	/*
+	 * Initialize for iterating over the block relocation entries.
+	 */
+	errcode_t (*start_iter)(ext2_brel brel);
+
+	/*
+	 * The iterator function for the inode relocation entries.
+	 * Returns an inode number of 0 when out of entries.
+	 */
+	errcode_t (*next)(ext2_brel brel, blk_t *old,
+			  struct ext2_block_relocate_entry *ent);
+
+	/*
+	 * Move the inode relocation table from one block number to
+	 * another.
+	 */
+	errcode_t (*move)(ext2_brel brel, blk_t old, blk_t new);
+
+	/*
+	 * Remove a block relocation entry.
+	 */
+	errcode_t (*delete)(ext2_brel brel, blk_t old);
+
+
+	/*
+	 * Free the block relocation table.
+	 */
+	errcode_t (*free)(ext2_brel brel);
+};
+
+errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
+				    ext2_brel *brel);
+
+#define ext2fs_brel_put(brel, old, ent) ((brel)->put((brel), old, ent))
+#define ext2fs_brel_get(brel, old, ent) ((brel)->get((brel), old, ent))
+#define ext2fs_brel_start_iter(brel) ((brel)->start_iter((brel)))
+#define ext2fs_brel_next(brel, old, ent) ((brel)->next((brel), old, ent))
+#define ext2fs_brel_move(brel, old, new) ((brel)->move((brel), old, new))
+#define ext2fs_brel_delete(brel, old) ((brel)->delete((brel), old))
+#define ext2fs_brel_free(brel) ((brel)->free((brel)))
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/brel_ma.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/brel_ma.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/brel_ma.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,195 @@
+/*
+ * brel_ma.c
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * TODO: rewrite to not use a direct array!!!  (Fortunately this
+ * module isn't really used yet.)
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+#include "brel.h"
+
+static errcode_t bma_put(ext2_brel brel, blk_t old,
+			struct ext2_block_relocate_entry *ent);
+static errcode_t bma_get(ext2_brel brel, blk_t old,
+			struct ext2_block_relocate_entry *ent);
+static errcode_t bma_start_iter(ext2_brel brel);
+static errcode_t bma_next(ext2_brel brel, blk_t *old,
+			 struct ext2_block_relocate_entry *ent);
+static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new);
+static errcode_t bma_delete(ext2_brel brel, blk_t old);
+static errcode_t bma_free(ext2_brel brel);
+
+struct brel_ma {
+	__u32 magic;
+	blk_t max_block;
+	struct ext2_block_relocate_entry *entries;
+};
+
+errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
+				      ext2_brel *new_brel)
+{
+	ext2_brel		brel = 0;
+	errcode_t	retval;
+	struct brel_ma	*ma = 0;
+	size_t		size;
+
+	*new_brel = 0;
+
+	/*
+	 * Allocate memory structures
+	 */
+	retval = ext2fs_get_mem(sizeof(struct ext2_block_relocation_table),
+				&brel);
+	if (retval)
+		goto errout;
+	memset(brel, 0, sizeof(struct ext2_block_relocation_table));
+
+	retval = ext2fs_get_mem(strlen(name)+1, &brel->name);
+	if (retval)
+		goto errout;
+	strcpy(brel->name, name);
+
+	retval = ext2fs_get_mem(sizeof(struct brel_ma), &ma);
+	if (retval)
+		goto errout;
+	memset(ma, 0, sizeof(struct brel_ma));
+	brel->priv_data = ma;
+
+	size = (size_t) (sizeof(struct ext2_block_relocate_entry) *
+			 (max_block+1));
+	retval = ext2fs_get_mem(size, &ma->entries);
+	if (retval)
+		goto errout;
+	memset(ma->entries, 0, size);
+	ma->max_block = max_block;
+
+	/*
+	 * Fill in the brel data structure
+	 */
+	brel->put = bma_put;
+	brel->get = bma_get;
+	brel->start_iter = bma_start_iter;
+	brel->next = bma_next;
+	brel->move = bma_move;
+	brel->delete = bma_delete;
+	brel->free = bma_free;
+
+	*new_brel = brel;
+	return 0;
+
+errout:
+	bma_free(brel);
+	return retval;
+}
+
+static errcode_t bma_put(ext2_brel brel, blk_t old,
+			struct ext2_block_relocate_entry *ent)
+{
+	struct brel_ma	*ma;
+
+	ma = brel->priv_data;
+	if (old > ma->max_block)
+		return EXT2_ET_INVALID_ARGUMENT;
+	ma->entries[(unsigned)old] = *ent;
+	return 0;
+}
+
+static errcode_t bma_get(ext2_brel brel, blk_t old,
+			struct ext2_block_relocate_entry *ent)
+{
+	struct brel_ma	*ma;
+
+	ma = brel->priv_data;
+	if (old > ma->max_block)
+		return EXT2_ET_INVALID_ARGUMENT;
+	if (ma->entries[(unsigned)old].new == 0)
+		return ENOENT;
+	*ent = ma->entries[old];
+	return 0;
+}
+
+static errcode_t bma_start_iter(ext2_brel brel)
+{
+	brel->current = 0;
+	return 0;
+}
+
+static errcode_t bma_next(ext2_brel brel, blk_t *old,
+			  struct ext2_block_relocate_entry *ent)
+{
+	struct brel_ma	*ma;
+
+	ma = brel->priv_data;
+	while (++brel->current < ma->max_block) {
+		if (ma->entries[(unsigned)brel->current].new == 0)
+			continue;
+		*old = brel->current;
+		*ent = ma->entries[(unsigned)brel->current];
+		return 0;
+	}
+	*old = 0;
+	return 0;
+}
+
+static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new)
+{
+	struct brel_ma	*ma;
+
+	ma = brel->priv_data;
+	if ((old > ma->max_block) || (new > ma->max_block))
+		return EXT2_ET_INVALID_ARGUMENT;
+	if (ma->entries[(unsigned)old].new == 0)
+		return ENOENT;
+	ma->entries[(unsigned)new] = ma->entries[old];
+	ma->entries[(unsigned)old].new = 0;
+	return 0;
+}
+
+static errcode_t bma_delete(ext2_brel brel, blk_t old)
+{
+	struct brel_ma	*ma;
+
+	ma = brel->priv_data;
+	if (old > ma->max_block)
+		return EXT2_ET_INVALID_ARGUMENT;
+	if (ma->entries[(unsigned)old].new == 0)
+		return ENOENT;
+	ma->entries[(unsigned)old].new = 0;
+	return 0;
+}
+
+static errcode_t bma_free(ext2_brel brel)
+{
+	struct brel_ma	*ma;
+
+	if (!brel)
+		return 0;
+
+	ma = brel->priv_data;
+
+	if (ma) {
+		ext2fs_free_mem(&ma->entries);
+		ext2fs_free_mem(&ma);
+	}
+	ext2fs_free_mem(&brel->name);
+	ext2fs_free_mem(&brel);
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/check_desc.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/check_desc.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/check_desc.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,68 @@
+/*
+ * check_desc.c --- Check the group descriptors of an ext2 filesystem
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * This routine sanity checks the group descriptors
+ */
+errcode_t ext2fs_check_desc(ext2_filsys fs)
+{
+	dgrp_t i;
+	blk_t block = fs->super->s_first_data_block;
+	blk_t next;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	for (i = 0; i < fs->group_desc_count; i++) {
+		next = block + fs->super->s_blocks_per_group;
+		/*
+		 * Check to make sure block bitmap for group is
+		 * located within the group.
+		 */
+		if (fs->group_desc[i].bg_block_bitmap < block ||
+		    fs->group_desc[i].bg_block_bitmap >= next)
+			return EXT2_ET_GDESC_BAD_BLOCK_MAP;
+		/*
+		 * Check to make sure inode bitmap for group is
+		 * located within the group
+		 */
+		if (fs->group_desc[i].bg_inode_bitmap < block ||
+		    fs->group_desc[i].bg_inode_bitmap >= next)
+			return EXT2_ET_GDESC_BAD_INODE_MAP;
+		/*
+		 * Check to make sure inode table for group is located
+		 * within the group
+		 */
+		if (fs->group_desc[i].bg_inode_table < block ||
+		    ((fs->group_desc[i].bg_inode_table +
+		      fs->inode_blocks_per_group) >= next))
+			return EXT2_ET_GDESC_BAD_INODE_TABLE;
+
+		block = next;
+	}
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/closefs.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/closefs.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/closefs.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,384 @@
+/*
+ * closefs.c --- close an ext2 filesystem
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <time.h>
+#include <string.h>
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+static int test_root(int a, int b)
+{
+	if (a == 0)
+		return 1;
+	while (1) {
+		if (a == 1)
+			return 1;
+		if (a % b)
+			return 0;
+		a = a / b;
+	}
+}
+
+int ext2fs_bg_has_super(ext2_filsys fs, int group_block)
+{
+	if (!(fs->super->s_feature_ro_compat &
+	      EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
+		return 1;
+
+	if (test_root(group_block, 3) || (test_root(group_block, 5)) ||
+	    test_root(group_block, 7))
+		return 1;
+
+	return 0;
+}
+
+int ext2fs_super_and_bgd_loc(ext2_filsys fs,
+			     dgrp_t group,
+			     blk_t *ret_super_blk,
+			     blk_t *ret_old_desc_blk,
+			     blk_t *ret_new_desc_blk,
+			     int *ret_meta_bg)
+{
+	blk_t	group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0;
+	unsigned int meta_bg, meta_bg_size;
+	int	numblocks, has_super;
+	int	old_desc_blocks;
+
+	group_block = fs->super->s_first_data_block +
+		(group * fs->super->s_blocks_per_group);
+
+	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
+		old_desc_blocks = fs->super->s_first_meta_bg;
+	else
+		old_desc_blocks =
+			fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
+
+	if (group == fs->group_desc_count-1) {
+		numblocks = (fs->super->s_blocks_count -
+			     fs->super->s_first_data_block) %
+			fs->super->s_blocks_per_group;
+		if (!numblocks)
+			numblocks = fs->super->s_blocks_per_group;
+	} else
+		numblocks = fs->super->s_blocks_per_group;
+
+	has_super = ext2fs_bg_has_super(fs, group);
+
+	if (has_super) {
+		super_blk = group_block;
+		numblocks--;
+	}
+	meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc));
+	meta_bg = group / meta_bg_size;
+
+	if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
+	    (meta_bg < fs->super->s_first_meta_bg)) {
+		if (has_super) {
+			old_desc_blk = group_block + 1;
+			numblocks -= old_desc_blocks;
+		}
+	} else {
+		if (((group % meta_bg_size) == 0) ||
+		    ((group % meta_bg_size) == 1) ||
+		    ((group % meta_bg_size) == (meta_bg_size-1))) {
+			if (has_super)
+				has_super = 1;
+			new_desc_blk = group_block + has_super;
+			numblocks--;
+		}
+	}
+
+	numblocks -= 2 + fs->inode_blocks_per_group;
+
+	if (ret_super_blk)
+		*ret_super_blk = super_blk;
+	if (ret_old_desc_blk)
+		*ret_old_desc_blk = old_desc_blk;
+	if (ret_new_desc_blk)
+		*ret_new_desc_blk = new_desc_blk;
+	if (ret_meta_bg)
+		*ret_meta_bg = meta_bg;
+	return (numblocks);
+}
+
+
+/*
+ * This function forces out the primary superblock.  We need to only
+ * write out those fields which we have changed, since if the
+ * filesystem is mounted, it may have changed some of the other
+ * fields.
+ *
+ * It takes as input a superblock which has already been byte swapped
+ * (if necessary).
+ *
+ */
+static errcode_t write_primary_superblock(ext2_filsys fs,
+					  struct ext2_super_block *super)
+{
+	__u16		*old_super, *new_super;
+	int		check_idx, write_idx, size;
+	errcode_t	retval;
+
+	if (!fs->io->manager->write_byte || !fs->orig_super) {
+		io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
+		retval = io_channel_write_blk(fs->io, 1, -SUPERBLOCK_SIZE,
+					      super);
+		io_channel_set_blksize(fs->io, fs->blocksize);
+		return retval;
+	}
+
+	old_super = (__u16 *) fs->orig_super;
+	new_super = (__u16 *) super;
+
+	for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) {
+		if (old_super[check_idx] == new_super[check_idx])
+			continue;
+		write_idx = check_idx;
+		for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++)
+			if (old_super[check_idx] == new_super[check_idx])
+				break;
+		size = 2 * (check_idx - write_idx);
+#if 0
+		printf("Writing %d bytes starting at %d\n",
+		       size, write_idx*2);
+#endif
+		retval = io_channel_write_byte(fs->io,
+			       SUPERBLOCK_OFFSET + (2 * write_idx), size,
+					       new_super + write_idx);
+		if (retval)
+			return retval;
+	}
+	memcpy(fs->orig_super, super, SUPERBLOCK_SIZE);
+	return 0;
+}
+
+
+/*
+ * Updates the revision to EXT2_DYNAMIC_REV
+ */
+void ext2fs_update_dynamic_rev(ext2_filsys fs)
+{
+	struct ext2_super_block *sb = fs->super;
+
+	if (sb->s_rev_level > EXT2_GOOD_OLD_REV)
+		return;
+
+	sb->s_rev_level = EXT2_DYNAMIC_REV;
+	sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
+	sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
+	/* s_uuid is handled by e2fsck already */
+	/* other fields should be left alone */
+}
+
+static errcode_t write_backup_super(ext2_filsys fs, dgrp_t group,
+				    blk_t group_block,
+				    struct ext2_super_block *super_shadow)
+{
+	dgrp_t	sgrp = group;
+
+	if (sgrp > ((1 << 16) - 1))
+		sgrp = (1 << 16) - 1;
+#if BB_BIG_ENDIAN
+	if (fs->flags & EXT2_FLAG_SWAP_BYTES)
+		super_shadow->s_block_group_nr = ext2fs_swab16(sgrp);
+	else
+#endif
+		fs->super->s_block_group_nr = sgrp;
+
+	return io_channel_write_blk(fs->io, group_block, -SUPERBLOCK_SIZE,
+				    super_shadow);
+}
+
+
+errcode_t ext2fs_flush(ext2_filsys fs)
+{
+	dgrp_t		i;
+	blk_t		group_block;
+	errcode_t	retval;
+	unsigned long	fs_state;
+	struct ext2_super_block *super_shadow = 0;
+	struct ext2_group_desc *group_shadow = 0;
+	char	*group_ptr;
+	int	old_desc_blocks;
+#if BB_BIG_ENDIAN
+	dgrp_t		j;
+	struct ext2_group_desc *s, *t;
+#endif
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	fs_state = fs->super->s_state;
+
+	fs->super->s_wtime = time(NULL);
+	fs->super->s_block_group_nr = 0;
+#if BB_BIG_ENDIAN
+	if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
+		retval = EXT2_ET_NO_MEMORY;
+		retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow);
+		if (retval)
+			goto errout;
+		retval = ext2fs_get_mem((size_t)(fs->blocksize *
+						 fs->desc_blocks),
+					&group_shadow);
+		if (retval)
+			goto errout;
+		memset(group_shadow, 0, (size_t) fs->blocksize *
+		       fs->desc_blocks);
+
+		/* swap the group descriptors */
+		for (j=0, s=fs->group_desc, t=group_shadow;
+		     j < fs->group_desc_count; j++, t++, s++) {
+			*t = *s;
+			ext2fs_swap_group_desc(t);
+		}
+	} else {
+		super_shadow = fs->super;
+		group_shadow = fs->group_desc;
+	}
+#else
+	super_shadow = fs->super;
+	group_shadow = fs->group_desc;
+#endif
+
+	/*
+	 * If this is an external journal device, don't write out the
+	 * block group descriptors or any of the backup superblocks
+	 */
+	if (fs->super->s_feature_incompat &
+	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
+		goto write_primary_superblock_only;
+
+	/*
+	 * Set the state of the FS to be non-valid.  (The state has
+	 * already been backed up earlier, and will be restored after
+	 * we write out the backup superblocks.)
+	 */
+	fs->super->s_state &= ~EXT2_VALID_FS;
+#if BB_BIG_ENDIAN
+	if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
+		*super_shadow = *fs->super;
+		ext2fs_swap_super(super_shadow);
+	}
+#endif
+
+	/*
+	 * Write out the master group descriptors, and the backup
+	 * superblocks and group descriptors.
+	 */
+	group_block = fs->super->s_first_data_block;
+	group_ptr = (char *) group_shadow;
+	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
+		old_desc_blocks = fs->super->s_first_meta_bg;
+	else
+		old_desc_blocks = fs->desc_blocks;
+
+	for (i = 0; i < fs->group_desc_count; i++) {
+		blk_t	super_blk, old_desc_blk, new_desc_blk;
+		int	meta_bg;
+
+		ext2fs_super_and_bgd_loc(fs, i, &super_blk, &old_desc_blk,
+					 &new_desc_blk, &meta_bg);
+
+		if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) {
+			retval = write_backup_super(fs, i, super_blk,
+						    super_shadow);
+			if (retval)
+				goto errout;
+		}
+		if (fs->flags & EXT2_FLAG_SUPER_ONLY)
+			continue;
+		if ((old_desc_blk) &&
+		    (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) {
+			retval = io_channel_write_blk(fs->io,
+			      old_desc_blk, old_desc_blocks, group_ptr);
+			if (retval)
+				goto errout;
+		}
+		if (new_desc_blk) {
+			retval = io_channel_write_blk(fs->io, new_desc_blk,
+				1, group_ptr + (meta_bg*fs->blocksize));
+			if (retval)
+				goto errout;
+		}
+	}
+	fs->super->s_block_group_nr = 0;
+	fs->super->s_state = fs_state;
+#if BB_BIG_ENDIAN
+	if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
+		*super_shadow = *fs->super;
+		ext2fs_swap_super(super_shadow);
+	}
+#endif
+
+	/*
+	 * If the write_bitmaps() function is present, call it to
+	 * flush the bitmaps.  This is done this way so that a simple
+	 * program that doesn't mess with the bitmaps doesn't need to
+	 * drag in the bitmaps.c code.
+	 */
+	if (fs->write_bitmaps) {
+		retval = fs->write_bitmaps(fs);
+		if (retval)
+			goto errout;
+	}
+
+write_primary_superblock_only:
+	/*
+	 * Write out master superblock.  This has to be done
+	 * separately, since it is located at a fixed location
+	 * (SUPERBLOCK_OFFSET).  We flush all other pending changes
+	 * out to disk first, just to avoid a race condition with an
+	 * insy-tinsy window....
+	 */
+	retval = io_channel_flush(fs->io);
+	retval = write_primary_superblock(fs, super_shadow);
+	if (retval)
+		goto errout;
+
+	fs->flags &= ~EXT2_FLAG_DIRTY;
+
+	retval = io_channel_flush(fs->io);
+errout:
+	fs->super->s_state = fs_state;
+	if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
+		if (super_shadow)
+			ext2fs_free_mem(&super_shadow);
+		if (group_shadow)
+			ext2fs_free_mem(&group_shadow);
+	}
+	return retval;
+}
+
+errcode_t ext2fs_close(ext2_filsys fs)
+{
+	errcode_t	retval;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (fs->flags & EXT2_FLAG_DIRTY) {
+		retval = ext2fs_flush(fs);
+		if (retval)
+			return retval;
+	}
+	if (fs->write_bitmaps) {
+		retval = fs->write_bitmaps(fs);
+		if (retval)
+			return retval;
+	}
+	ext2fs_free(fs);
+	return 0;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/cmp_bitmaps.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/cmp_bitmaps.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/cmp_bitmaps.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,72 @@
+/*
+ * cmp_bitmaps.c --- routines to compare inode and block bitmaps.
+ *
+ * Copyright (C) 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
+				      ext2fs_block_bitmap bm2)
+{
+	blk_t	i;
+
+	EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_BLOCK_BITMAP);
+	EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_BLOCK_BITMAP);
+
+	if ((bm1->start != bm2->start) ||
+	    (bm1->end != bm2->end) ||
+	    (memcmp(bm1->bitmap, bm2->bitmap,
+		    (size_t) (bm1->end - bm1->start)/8)))
+		return EXT2_ET_NEQ_BLOCK_BITMAP;
+
+	for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
+		if (ext2fs_fast_test_block_bitmap(bm1, i) !=
+		    ext2fs_fast_test_block_bitmap(bm2, i))
+			return EXT2_ET_NEQ_BLOCK_BITMAP;
+
+	return 0;
+}
+
+errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
+				      ext2fs_inode_bitmap bm2)
+{
+	ext2_ino_t	i;
+
+	EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_INODE_BITMAP);
+	EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_INODE_BITMAP);
+
+	if ((bm1->start != bm2->start) ||
+	    (bm1->end != bm2->end) ||
+	    (memcmp(bm1->bitmap, bm2->bitmap,
+		    (size_t) (bm1->end - bm1->start)/8)))
+		return EXT2_ET_NEQ_INODE_BITMAP;
+
+	for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
+		if (ext2fs_fast_test_inode_bitmap(bm1, i) !=
+		    ext2fs_fast_test_inode_bitmap(bm2, i))
+			return EXT2_ET_NEQ_INODE_BITMAP;
+
+	return 0;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dblist.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dblist.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dblist.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,259 @@
+/*
+ * dblist.c -- directory block list functions
+ *
+ * Copyright 1997 by Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ *
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <time.h>
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+static int dir_block_cmp(const void *a, const void *b);
+
+/*
+ * Returns the number of directories in the filesystem as reported by
+ * the group descriptors.  Of course, the group descriptors could be
+ * wrong!
+ */
+errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs)
+{
+	dgrp_t	i;
+	ext2_ino_t	num_dirs, max_dirs;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	num_dirs = 0;
+	max_dirs = fs->super->s_inodes_per_group;
+	for (i = 0; i < fs->group_desc_count; i++) {
+		if (fs->group_desc[i].bg_used_dirs_count > max_dirs)
+			num_dirs += max_dirs / 8;
+		else
+			num_dirs += fs->group_desc[i].bg_used_dirs_count;
+	}
+	if (num_dirs > fs->super->s_inodes_count)
+		num_dirs = fs->super->s_inodes_count;
+
+	*ret_num_dirs = num_dirs;
+
+	return 0;
+}
+
+/*
+ * helper function for making a new directory block list (for
+ * initialize and copy).
+ */
+static errcode_t make_dblist(ext2_filsys fs, ext2_ino_t size, ext2_ino_t count,
+			     struct ext2_db_entry *list,
+			     ext2_dblist *ret_dblist)
+{
+	ext2_dblist	dblist;
+	errcode_t	retval;
+	size_t		len;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if ((ret_dblist == 0) && fs->dblist &&
+	    (fs->dblist->magic == EXT2_ET_MAGIC_DBLIST))
+		return 0;
+
+	retval = ext2fs_get_mem(sizeof(struct ext2_struct_dblist), &dblist);
+	if (retval)
+		return retval;
+	memset(dblist, 0, sizeof(struct ext2_struct_dblist));
+
+	dblist->magic = EXT2_ET_MAGIC_DBLIST;
+	dblist->fs = fs;
+	if (size)
+		dblist->size = size;
+	else {
+		retval = ext2fs_get_num_dirs(fs, &dblist->size);
+		if (retval)
+			goto cleanup;
+		dblist->size = (dblist->size * 2) + 12;
+	}
+	len = (size_t) sizeof(struct ext2_db_entry) * dblist->size;
+	dblist->count = count;
+	retval = ext2fs_get_mem(len, &dblist->list);
+	if (retval)
+		goto cleanup;
+
+	if (list)
+		memcpy(dblist->list, list, len);
+	else
+		memset(dblist->list, 0, len);
+	if (ret_dblist)
+		*ret_dblist = dblist;
+	else
+		fs->dblist = dblist;
+	return 0;
+cleanup:
+	ext2fs_free_mem(&dblist);
+	return retval;
+}
+
+/*
+ * Initialize a directory block list
+ */
+errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist)
+{
+	ext2_dblist	dblist;
+	errcode_t	retval;
+
+	retval = make_dblist(fs, 0, 0, 0, &dblist);
+	if (retval)
+		return retval;
+
+	dblist->sorted = 1;
+	if (ret_dblist)
+		*ret_dblist = dblist;
+	else
+		fs->dblist = dblist;
+
+	return 0;
+}
+
+/*
+ * Copy a directory block list
+ */
+errcode_t ext2fs_copy_dblist(ext2_dblist src, ext2_dblist *dest)
+{
+	ext2_dblist	dblist;
+	errcode_t	retval;
+
+	retval = make_dblist(src->fs, src->size, src->count, src->list,
+			     &dblist);
+	if (retval)
+		return retval;
+	dblist->sorted = src->sorted;
+	*dest = dblist;
+	return 0;
+}
+
+/*
+ * Close a directory block list
+ *
+ * (moved to closefs.c)
+ */
+
+
+/*
+ * Add a directory block to the directory block list
+ */
+errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
+			       int blockcnt)
+{
+	struct ext2_db_entry	*new_entry;
+	errcode_t		retval;
+	unsigned long		old_size;
+
+	EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
+
+	if (dblist->count >= dblist->size) {
+		old_size = dblist->size * sizeof(struct ext2_db_entry);
+		dblist->size += 100;
+		retval = ext2fs_resize_mem(old_size, (size_t) dblist->size *
+					   sizeof(struct ext2_db_entry),
+					   &dblist->list);
+		if (retval) {
+			dblist->size -= 100;
+			return retval;
+		}
+	}
+	new_entry = dblist->list + ( (int) dblist->count++);
+	new_entry->blk = blk;
+	new_entry->ino = ino;
+	new_entry->blockcnt = blockcnt;
+
+	dblist->sorted = 0;
+
+	return 0;
+}
+
+/*
+ * Change the directory block to the directory block list
+ */
+errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk,
+			       int blockcnt)
+{
+	dgrp_t			i;
+
+	EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
+
+	for (i=0; i < dblist->count; i++) {
+		if ((dblist->list[i].ino != ino) ||
+		    (dblist->list[i].blockcnt != blockcnt))
+			continue;
+		dblist->list[i].blk = blk;
+		dblist->sorted = 0;
+		return 0;
+	}
+	return EXT2_ET_DB_NOT_FOUND;
+}
+
+void ext2fs_dblist_sort(ext2_dblist dblist,
+			int (*sortfunc)(const void *,
+						    const void *))
+{
+	if (!sortfunc)
+		sortfunc = dir_block_cmp;
+	qsort(dblist->list, (size_t) dblist->count,
+	      sizeof(struct ext2_db_entry), sortfunc);
+	dblist->sorted = 1;
+}
+
+/*
+ * This function iterates over the directory block list
+ */
+errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
+				int (*func)(ext2_filsys fs,
+					    struct ext2_db_entry *db_info,
+					    void	*priv_data),
+				void *priv_data)
+{
+	ext2_ino_t	i;
+	int		ret;
+
+	EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
+
+	if (!dblist->sorted)
+		ext2fs_dblist_sort(dblist, 0);
+	for (i=0; i < dblist->count; i++) {
+		ret = (*func)(dblist->fs, &dblist->list[(int)i], priv_data);
+		if (ret & DBLIST_ABORT)
+			return 0;
+	}
+	return 0;
+}
+
+static int dir_block_cmp(const void *a, const void *b)
+{
+	const struct ext2_db_entry *db_a =
+		(const struct ext2_db_entry *) a;
+	const struct ext2_db_entry *db_b =
+		(const struct ext2_db_entry *) b;
+
+	if (db_a->blk != db_b->blk)
+		return (int) (db_a->blk - db_b->blk);
+
+	if (db_a->ino != db_b->ino)
+		return (int) (db_a->ino - db_b->ino);
+
+	return (int) (db_a->blockcnt - db_b->blockcnt);
+}
+
+int ext2fs_dblist_count(ext2_dblist dblist)
+{
+	return (int) dblist->count;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dblist_dir.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dblist_dir.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dblist_dir.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,75 @@
+/*
+ * dblist_dir.c --- iterate by directory entry
+ *
+ * Copyright 1997 by Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ *
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <time.h>
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
+		       void *priv_data);
+
+errcode_t ext2fs_dblist_dir_iterate(ext2_dblist dblist,
+				    int	flags,
+				    char	*block_buf,
+				    int (*func)(ext2_ino_t dir,
+						int	entry,
+						struct ext2_dir_entry *dirent,
+						int	offset,
+						int	blocksize,
+						char	*buf,
+						void	*priv_data),
+				    void *priv_data)
+{
+	errcode_t		retval;
+	struct dir_context	ctx;
+
+	EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
+
+	ctx.dir = 0;
+	ctx.flags = flags;
+	if (block_buf)
+		ctx.buf = block_buf;
+	else {
+		retval = ext2fs_get_mem(dblist->fs->blocksize, &ctx.buf);
+		if (retval)
+			return retval;
+	}
+	ctx.func = func;
+	ctx.priv_data = priv_data;
+	ctx.errcode = 0;
+
+	retval = ext2fs_dblist_iterate(dblist, db_dir_proc, &ctx);
+
+	if (!block_buf)
+		ext2fs_free_mem(&ctx.buf);
+	if (retval)
+		return retval;
+	return ctx.errcode;
+}
+
+static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
+		       void *priv_data)
+{
+	struct dir_context	*ctx;
+
+	ctx = (struct dir_context *) priv_data;
+	ctx->dir = db_info->ino;
+
+	return ext2fs_process_dir_block(fs, &db_info->blk,
+					db_info->blockcnt, 0, 0, priv_data);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dir_iterate.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dir_iterate.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dir_iterate.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,219 @@
+/*
+ * dir_iterate.c --- ext2fs directory iteration operations
+ *
+ * Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+/*
+ * This function checks to see whether or not a potential deleted
+ * directory entry looks valid.  What we do is check the deleted entry
+ * and each successive entry to make sure that they all look valid and
+ * that the last deleted entry ends at the beginning of the next
+ * undeleted entry.  Returns 1 if the deleted entry looks valid, zero
+ * if not valid.
+ */
+static int ext2fs_validate_entry(char *buf, int offset, int final_offset)
+{
+	struct ext2_dir_entry *dirent;
+
+	while (offset < final_offset) {
+		dirent = (struct ext2_dir_entry *)(buf + offset);
+		offset += dirent->rec_len;
+		if ((dirent->rec_len < 8) ||
+		    ((dirent->rec_len % 4) != 0) ||
+		    (((dirent->name_len & 0xFF)+8) > dirent->rec_len))
+			return 0;
+	}
+	return (offset == final_offset);
+}
+
+errcode_t ext2fs_dir_iterate2(ext2_filsys fs,
+			      ext2_ino_t dir,
+			      int flags,
+			      char *block_buf,
+			      int (*func)(ext2_ino_t	dir,
+					  int		entry,
+					  struct ext2_dir_entry *dirent,
+					  int	offset,
+					  int	blocksize,
+					  char	*buf,
+					  void	*priv_data),
+			      void *priv_data)
+{
+	struct		dir_context	ctx;
+	errcode_t	retval;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	retval = ext2fs_check_directory(fs, dir);
+	if (retval)
+		return retval;
+
+	ctx.dir = dir;
+	ctx.flags = flags;
+	if (block_buf)
+		ctx.buf = block_buf;
+	else {
+		retval = ext2fs_get_mem(fs->blocksize, &ctx.buf);
+		if (retval)
+			return retval;
+	}
+	ctx.func = func;
+	ctx.priv_data = priv_data;
+	ctx.errcode = 0;
+	retval = ext2fs_block_iterate2(fs, dir, 0, 0,
+				       ext2fs_process_dir_block, &ctx);
+	if (!block_buf)
+		ext2fs_free_mem(&ctx.buf);
+	if (retval)
+		return retval;
+	return ctx.errcode;
+}
+
+struct xlate {
+	int (*func)(struct ext2_dir_entry *dirent,
+		    int		offset,
+		    int		blocksize,
+		    char	*buf,
+		    void	*priv_data);
+	void *real_private;
+};
+
+static int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)),
+		      int entry EXT2FS_ATTR((unused)),
+		      struct ext2_dir_entry *dirent, int offset,
+		      int blocksize, char *buf, void *priv_data)
+{
+	struct xlate *xl = (struct xlate *) priv_data;
+
+	return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private);
+}
+
+extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
+			      ext2_ino_t dir,
+			      int flags,
+			      char *block_buf,
+			      int (*func)(struct ext2_dir_entry *dirent,
+					  int	offset,
+					  int	blocksize,
+					  char	*buf,
+					  void	*priv_data),
+			      void *priv_data)
+{
+	struct xlate xl;
+
+	xl.real_private = priv_data;
+	xl.func = func;
+
+	return ext2fs_dir_iterate2(fs, dir, flags, block_buf,
+				   xlate_func, &xl);
+}
+
+
+/*
+ * Helper function which is private to this module.  Used by
+ * ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate()
+ */
+int ext2fs_process_dir_block(ext2_filsys fs,
+			     blk_t	*blocknr,
+			     e2_blkcnt_t blockcnt,
+			     blk_t	ref_block EXT2FS_ATTR((unused)),
+			     int	ref_offset EXT2FS_ATTR((unused)),
+			     void	*priv_data)
+{
+	struct dir_context *ctx = (struct dir_context *) priv_data;
+	unsigned int	offset = 0;
+	unsigned int	next_real_entry = 0;
+	int		ret = 0;
+	int		changed = 0;
+	int		do_abort = 0;
+	int		entry, size;
+	struct ext2_dir_entry *dirent;
+
+	if (blockcnt < 0)
+		return 0;
+
+	entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE;
+
+	ctx->errcode = ext2fs_read_dir_block(fs, *blocknr, ctx->buf);
+	if (ctx->errcode)
+		return BLOCK_ABORT;
+
+	while (offset < fs->blocksize) {
+		dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
+		if (((offset + dirent->rec_len) > fs->blocksize) ||
+		    (dirent->rec_len < 8) ||
+		    ((dirent->rec_len % 4) != 0) ||
+		    (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
+			ctx->errcode = EXT2_ET_DIR_CORRUPTED;
+			return BLOCK_ABORT;
+		}
+		if (!dirent->inode &&
+		    !(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
+			goto next;
+
+		ret = (ctx->func)(ctx->dir,
+				  (next_real_entry > offset) ?
+				  DIRENT_DELETED_FILE : entry,
+				  dirent, offset,
+				  fs->blocksize, ctx->buf,
+				  ctx->priv_data);
+		if (entry < DIRENT_OTHER_FILE)
+			entry++;
+
+		if (ret & DIRENT_CHANGED)
+			changed++;
+		if (ret & DIRENT_ABORT) {
+			do_abort++;
+			break;
+		}
+next:
+		if (next_real_entry == offset)
+			next_real_entry += dirent->rec_len;
+
+		if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) {
+			size = ((dirent->name_len & 0xFF) + 11) & ~3;
+
+			if (dirent->rec_len != size)  {
+				unsigned int final_offset;
+
+				final_offset = offset + dirent->rec_len;
+				offset += size;
+				while (offset < final_offset &&
+				       !ext2fs_validate_entry(ctx->buf,
+							      offset,
+							      final_offset))
+					offset += 4;
+				continue;
+			}
+		}
+		offset += dirent->rec_len;
+	}
+
+	if (changed) {
+		ctx->errcode = ext2fs_write_dir_block(fs, *blocknr, ctx->buf);
+		if (ctx->errcode)
+			return BLOCK_ABORT;
+	}
+	if (do_abort)
+		return BLOCK_ABORT;
+	return 0;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dirblock.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dirblock.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dirblock.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,132 @@
+/*
+ * dirblock.c --- directory block routines.
+ *
+ * Copyright (C) 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <time.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
+				 void *buf, int flags EXT2FS_ATTR((unused)))
+{
+	errcode_t	retval;
+	char		*p, *end;
+	struct ext2_dir_entry *dirent;
+	unsigned int	name_len, rec_len;
+#if BB_BIG_ENDIAN
+	unsigned int do_swap;
+#endif
+
+	retval = io_channel_read_blk(fs->io, block, 1, buf);
+	if (retval)
+		return retval;
+#if BB_BIG_ENDIAN
+	do_swap = (fs->flags & (EXT2_FLAG_SWAP_BYTES|
+				EXT2_FLAG_SWAP_BYTES_READ)) != 0;
+#endif
+	p = (char *) buf;
+	end = (char *) buf + fs->blocksize;
+	while (p < end-8) {
+		dirent = (struct ext2_dir_entry *) p;
+#if BB_BIG_ENDIAN
+		if (do_swap) {
+			dirent->inode = ext2fs_swab32(dirent->inode);
+			dirent->rec_len = ext2fs_swab16(dirent->rec_len);
+			dirent->name_len = ext2fs_swab16(dirent->name_len);
+		}
+#endif
+		name_len = dirent->name_len;
+#ifdef WORDS_BIGENDIAN
+		if (flags & EXT2_DIRBLOCK_V2_STRUCT)
+			dirent->name_len = ext2fs_swab16(dirent->name_len);
+#endif
+		rec_len = dirent->rec_len;
+		if ((rec_len < 8) || (rec_len % 4)) {
+			rec_len = 8;
+			retval = EXT2_ET_DIR_CORRUPTED;
+		}
+		if (((name_len & 0xFF) + 8) > dirent->rec_len)
+			retval = EXT2_ET_DIR_CORRUPTED;
+		p += rec_len;
+	}
+	return retval;
+}
+
+errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
+				 void *buf)
+{
+	return ext2fs_read_dir_block2(fs, block, buf, 0);
+}
+
+
+errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
+				  void *inbuf, int flags EXT2FS_ATTR((unused)))
+{
+#if BB_BIG_ENDIAN
+	int		do_swap = 0;
+	errcode_t	retval;
+	char		*p, *end;
+	char		*buf = 0;
+	struct ext2_dir_entry *dirent;
+
+	if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+	    (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
+		do_swap = 1;
+
+#ifndef WORDS_BIGENDIAN
+	if (!do_swap)
+		return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
+#endif
+
+	retval = ext2fs_get_mem(fs->blocksize, &buf);
+	if (retval)
+		return retval;
+	memcpy(buf, inbuf, fs->blocksize);
+	p = buf;
+	end = buf + fs->blocksize;
+	while (p < end) {
+		dirent = (struct ext2_dir_entry *) p;
+		if ((dirent->rec_len < 8) ||
+		    (dirent->rec_len % 4)) {
+			ext2fs_free_mem(&buf);
+			return (EXT2_ET_DIR_CORRUPTED);
+		}
+		p += dirent->rec_len;
+		if (do_swap) {
+			dirent->inode = ext2fs_swab32(dirent->inode);
+			dirent->rec_len = ext2fs_swab16(dirent->rec_len);
+			dirent->name_len = ext2fs_swab16(dirent->name_len);
+		}
+#ifdef WORDS_BIGENDIAN
+		if (flags & EXT2_DIRBLOCK_V2_STRUCT)
+			dirent->name_len = ext2fs_swab16(dirent->name_len);
+#endif
+	}
+	retval = io_channel_write_blk(fs->io, block, 1, buf);
+	ext2fs_free_mem(&buf);
+	return retval;
+#else
+	return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
+#endif
+}
+
+
+errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
+				 void *inbuf)
+{
+	return ext2fs_write_dir_block2(fs, block, inbuf, 0);
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dirhash.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dirhash.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dirhash.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,233 @@
+/*
+ * dirhash.c -- Calculate the hash of a directory entry
+ *
+ * Copyright (c) 2001  Daniel Phillips
+ *
+ * Copyright (c) 2002 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * Keyed 32-bit hash function using TEA in a Davis-Meyer function
+ *   H0 = Key
+ *   Hi = E Mi(Hi-1) + Hi-1
+ *
+ * (see Applied Cryptography, 2nd edition, p448).
+ *
+ * Jeremy Fitzhardinge <jeremy at zip.com.au> 1998
+ *
+ * This code is made available under the terms of the GPL
+ */
+#define DELTA 0x9E3779B9
+
+static void TEA_transform(__u32 buf[4], __u32 const in[])
+{
+	__u32	sum = 0;
+	__u32	b0 = buf[0], b1 = buf[1];
+	__u32	a = in[0], b = in[1], c = in[2], d = in[3];
+	int	n = 16;
+
+	do {
+		sum += DELTA;
+		b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
+		b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
+	} while(--n);
+
+	buf[0] += b0;
+	buf[1] += b1;
+}
+
+/* F, G and H are basic MD4 functions: selection, majority, parity */
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/*
+ * The generic round function.  The application is so specific that
+ * we don't bother protecting all the arguments with parens, as is generally
+ * good macro practice, in favor of extra legibility.
+ * Rotation is separate from addition to prevent recomputation
+ */
+#define ROUND(f, a, b, c, d, x, s)	\
+	(a += f(b, c, d) + x, a = (a << s) | (a >> (32-s)))
+#define K1 0
+#define K2 013240474631UL
+#define K3 015666365641UL
+
+/*
+ * Basic cut-down MD4 transform.  Returns only 32 bits of result.
+ */
+static void halfMD4Transform (__u32 buf[4], __u32 const in[])
+{
+	__u32	a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+	/* Round 1 */
+	ROUND(F, a, b, c, d, in[0] + K1,  3);
+	ROUND(F, d, a, b, c, in[1] + K1,  7);
+	ROUND(F, c, d, a, b, in[2] + K1, 11);
+	ROUND(F, b, c, d, a, in[3] + K1, 19);
+	ROUND(F, a, b, c, d, in[4] + K1,  3);
+	ROUND(F, d, a, b, c, in[5] + K1,  7);
+	ROUND(F, c, d, a, b, in[6] + K1, 11);
+	ROUND(F, b, c, d, a, in[7] + K1, 19);
+
+	/* Round 2 */
+	ROUND(G, a, b, c, d, in[1] + K2,  3);
+	ROUND(G, d, a, b, c, in[3] + K2,  5);
+	ROUND(G, c, d, a, b, in[5] + K2,  9);
+	ROUND(G, b, c, d, a, in[7] + K2, 13);
+	ROUND(G, a, b, c, d, in[0] + K2,  3);
+	ROUND(G, d, a, b, c, in[2] + K2,  5);
+	ROUND(G, c, d, a, b, in[4] + K2,  9);
+	ROUND(G, b, c, d, a, in[6] + K2, 13);
+
+	/* Round 3 */
+	ROUND(H, a, b, c, d, in[3] + K3,  3);
+	ROUND(H, d, a, b, c, in[7] + K3,  9);
+	ROUND(H, c, d, a, b, in[2] + K3, 11);
+	ROUND(H, b, c, d, a, in[6] + K3, 15);
+	ROUND(H, a, b, c, d, in[1] + K3,  3);
+	ROUND(H, d, a, b, c, in[5] + K3,  9);
+	ROUND(H, c, d, a, b, in[0] + K3, 11);
+	ROUND(H, b, c, d, a, in[4] + K3, 15);
+
+	buf[0] += a;
+	buf[1] += b;
+	buf[2] += c;
+	buf[3] += d;
+}
+
+#undef ROUND
+#undef F
+#undef G
+#undef H
+#undef K1
+#undef K2
+#undef K3
+
+/* The old legacy hash */
+static ext2_dirhash_t dx_hack_hash (const char *name, int len)
+{
+	__u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
+	while (len--) {
+		__u32 hash = hash1 + (hash0 ^ (*name++ * 7152373));
+
+		if (hash & 0x80000000) hash -= 0x7fffffff;
+		hash1 = hash0;
+		hash0 = hash;
+	}
+	return (hash0 << 1);
+}
+
+static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
+{
+	__u32	pad, val;
+	int	i;
+
+	pad = (__u32)len | ((__u32)len << 8);
+	pad |= pad << 16;
+
+	val = pad;
+	if (len > num*4)
+		len = num * 4;
+	for (i=0; i < len; i++) {
+		if ((i % 4) == 0)
+			val = pad;
+		val = msg[i] + (val << 8);
+		if ((i % 4) == 3) {
+			*buf++ = val;
+			val = pad;
+			num--;
+		}
+	}
+	if (--num >= 0)
+		*buf++ = val;
+	while (--num >= 0)
+		*buf++ = pad;
+}
+
+/*
+ * Returns the hash of a filename.  If len is 0 and name is NULL, then
+ * this function can be used to test whether or not a hash version is
+ * supported.
+ *
+ * The seed is an 4 longword (32 bits) "secret" which can be used to
+ * uniquify a hash.  If the seed is all zero's, then some default seed
+ * may be used.
+ *
+ * A particular hash version specifies whether or not the seed is
+ * represented, and whether or not the returned hash is 32 bits or 64
+ * bits.  32 bit hashes will return 0 for the minor hash.
+ */
+errcode_t ext2fs_dirhash(int version, const char *name, int len,
+			 const __u32 *seed,
+			 ext2_dirhash_t *ret_hash,
+			 ext2_dirhash_t *ret_minor_hash)
+{
+	__u32	hash;
+	__u32	minor_hash = 0;
+	const char	*p;
+	int		i;
+	__u32		in[8], buf[4];
+
+	/* Initialize the default seed for the hash checksum functions */
+	buf[0] = 0x67452301;
+	buf[1] = 0xefcdab89;
+	buf[2] = 0x98badcfe;
+	buf[3] = 0x10325476;
+
+	/* Check to see if the seed is all zero's */
+	if (seed) {
+		for (i=0; i < 4; i++) {
+			if (seed[i])
+				break;
+		}
+		if (i < 4)
+			memcpy(buf, seed, sizeof(buf));
+	}
+
+	switch (version) {
+	case EXT2_HASH_LEGACY:
+		hash = dx_hack_hash(name, len);
+		break;
+	case EXT2_HASH_HALF_MD4:
+		p = name;
+		while (len > 0) {
+			str2hashbuf(p, len, in, 8);
+			halfMD4Transform(buf, in);
+			len -= 32;
+			p += 32;
+		}
+		minor_hash = buf[2];
+		hash = buf[1];
+		break;
+	case EXT2_HASH_TEA:
+		p = name;
+		while (len > 0) {
+			str2hashbuf(p, len, in, 4);
+			TEA_transform(buf, in);
+			len -= 16;
+			p += 16;
+		}
+		hash = buf[0];
+		minor_hash = buf[1];
+		break;
+	default:
+		*ret_hash = 0;
+		return EXT2_ET_DIRHASH_UNSUPP;
+	}
+	*ret_hash = hash & ~1;
+	if (ret_minor_hash)
+		*ret_minor_hash = minor_hash;
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dupfs.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dupfs.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/dupfs.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,96 @@
+/*
+ * dupfs.c --- duplicate a ext2 filesystem handle
+ *
+ * Copyright (C) 1997, 1998, 2001, 2003, 2005 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <time.h>
+#include <string.h>
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest)
+{
+	ext2_filsys	fs;
+	errcode_t	retval;
+
+	EXT2_CHECK_MAGIC(src, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
+	if (retval)
+		return retval;
+
+	*fs = *src;
+	fs->device_name = 0;
+	fs->super = 0;
+	fs->orig_super = 0;
+	fs->group_desc = 0;
+	fs->inode_map = 0;
+	fs->block_map = 0;
+	fs->badblocks = 0;
+	fs->dblist = 0;
+
+	io_channel_bumpcount(fs->io);
+	if (fs->icache)
+		fs->icache->refcount++;
+
+	retval = ext2fs_get_mem(strlen(src->device_name)+1, &fs->device_name);
+	if (retval)
+		goto errout;
+	strcpy(fs->device_name, src->device_name);
+
+	retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super);
+	if (retval)
+		goto errout;
+	memcpy(fs->super, src->super, SUPERBLOCK_SIZE);
+
+	retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super);
+	if (retval)
+		goto errout;
+	memcpy(fs->orig_super, src->orig_super, SUPERBLOCK_SIZE);
+
+	retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize,
+				&fs->group_desc);
+	if (retval)
+		goto errout;
+	memcpy(fs->group_desc, src->group_desc,
+	       (size_t) fs->desc_blocks * fs->blocksize);
+
+	if (src->inode_map) {
+		retval = ext2fs_copy_bitmap(src->inode_map, &fs->inode_map);
+		if (retval)
+			goto errout;
+	}
+	if (src->block_map) {
+		retval = ext2fs_copy_bitmap(src->block_map, &fs->block_map);
+		if (retval)
+			goto errout;
+	}
+	if (src->badblocks) {
+		retval = ext2fs_badblocks_copy(src->badblocks, &fs->badblocks);
+		if (retval)
+			goto errout;
+	}
+	if (src->dblist) {
+		retval = ext2fs_copy_dblist(src->dblist, &fs->dblist);
+		if (retval)
+			goto errout;
+	}
+	*dest = fs;
+	return 0;
+errout:
+	ext2fs_free(fs);
+	return retval;
+
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/e2image.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/e2image.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/e2image.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,51 @@
+/*
+ * e2image.h --- header file describing the ext2 image format
+ *
+ * Copyright (C) 2000 Theodore Ts'o.
+ *
+ * Note: this uses the POSIX IO interfaces, unlike most of the other
+ * functions in this library.  So sue me.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+
+struct ext2_image_hdr {
+	__u32	magic_number;	/* This must be EXT2_ET_MAGIC_E2IMAGE */
+	char	magic_descriptor[16]; /* "Ext2 Image 1.0", w/ null padding */
+	char	fs_hostname[64];/* Hostname of machine of image */
+	char	fs_netaddr[32];	/* Network address */
+	__u32	fs_netaddr_type;/* 0 = IPV4, 1 = IPV6, etc. */
+	__u32	fs_device;	/* Device number of image */
+	char	fs_device_name[64]; /* Device name */
+	char	fs_uuid[16];	/* UUID of filesystem */
+	__u32	fs_blocksize;	/* Block size of the filesystem */
+	__u32	fs_reserved[8];
+
+	__u32	image_device;	/* Device number of image file */
+	__u32	image_inode;	/* Inode number of image file */
+	__u32	image_time;	/* Time of image creation */
+	__u32	image_reserved[8];
+
+	__u32	offset_super;	/* Byte offset of the sb and descriptors */
+	__u32	offset_inode;	/* Byte offset of the inode table  */
+	__u32	offset_inodemap; /* Byte offset of the inode bitmaps */
+	__u32	offset_blockmap; /* Byte offset of the inode bitmaps */
+	__u32	offset_reserved[8];
+};
+
+
+
+
+
+
+
+
+
+
+
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/expanddir.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/expanddir.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/expanddir.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,126 @@
+/*
+ * expand.c --- expand an ext2fs directory
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999  Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct expand_dir_struct {
+	int		done;
+	int		newblocks;
+	errcode_t	err;
+};
+
+static int expand_dir_proc(ext2_filsys	fs,
+			   blk_t	*blocknr,
+			   e2_blkcnt_t	blockcnt,
+			   blk_t	ref_block EXT2FS_ATTR((unused)),
+			   int		ref_offset EXT2FS_ATTR((unused)),
+			   void		*priv_data)
+{
+	struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
+	blk_t	new_blk;
+	static blk_t	last_blk = 0;
+	char		*block;
+	errcode_t	retval;
+
+	if (*blocknr) {
+		last_blk = *blocknr;
+		return 0;
+	}
+	retval = ext2fs_new_block(fs, last_blk, 0, &new_blk);
+	if (retval) {
+		es->err = retval;
+		return BLOCK_ABORT;
+	}
+	if (blockcnt > 0) {
+		retval = ext2fs_new_dir_block(fs, 0, 0, &block);
+		if (retval) {
+			es->err = retval;
+			return BLOCK_ABORT;
+		}
+		es->done = 1;
+		retval = ext2fs_write_dir_block(fs, new_blk, block);
+	} else {
+		retval = ext2fs_get_mem(fs->blocksize, &block);
+		if (retval) {
+			es->err = retval;
+			return BLOCK_ABORT;
+		}
+		memset(block, 0, fs->blocksize);
+		retval = io_channel_write_blk(fs->io, new_blk, 1, block);
+	}
+	if (retval) {
+		es->err = retval;
+		return BLOCK_ABORT;
+	}
+	ext2fs_free_mem(&block);
+	*blocknr = new_blk;
+	ext2fs_block_alloc_stats(fs, new_blk, +1);
+	es->newblocks++;
+
+	if (es->done)
+		return (BLOCK_CHANGED | BLOCK_ABORT);
+	else
+		return BLOCK_CHANGED;
+}
+
+errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir)
+{
+	errcode_t	retval;
+	struct expand_dir_struct es;
+	struct ext2_inode	inode;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (!(fs->flags & EXT2_FLAG_RW))
+		return EXT2_ET_RO_FILSYS;
+
+	if (!fs->block_map)
+		return EXT2_ET_NO_BLOCK_BITMAP;
+
+	retval = ext2fs_check_directory(fs, dir);
+	if (retval)
+		return retval;
+
+	es.done = 0;
+	es.err = 0;
+	es.newblocks = 0;
+
+	retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
+				       0, expand_dir_proc, &es);
+
+	if (es.err)
+		return es.err;
+	if (!es.done)
+		return EXT2_ET_EXPAND_DIR_ERR;
+
+	/*
+	 * Update the size and block count fields in the inode.
+	 */
+	retval = ext2fs_read_inode(fs, dir, &inode);
+	if (retval)
+		return retval;
+
+	inode.i_size += fs->blocksize;
+	inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
+
+	retval = ext2fs_write_inode(fs, dir, &inode);
+	if (retval)
+		return retval;
+
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_err.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_err.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_err.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,115 @@
+/*
+ * ext2_err.h:
+ * This file is automatically generated; please do not edit it.
+ */
+
+#define EXT2_ET_BASE                             (2133571328L)
+#define EXT2_ET_MAGIC_EXT2FS_FILSYS              (2133571329L)
+#define EXT2_ET_MAGIC_BADBLOCKS_LIST             (2133571330L)
+#define EXT2_ET_MAGIC_BADBLOCKS_ITERATE          (2133571331L)
+#define EXT2_ET_MAGIC_INODE_SCAN                 (2133571332L)
+#define EXT2_ET_MAGIC_IO_CHANNEL                 (2133571333L)
+#define EXT2_ET_MAGIC_UNIX_IO_CHANNEL            (2133571334L)
+#define EXT2_ET_MAGIC_IO_MANAGER                 (2133571335L)
+#define EXT2_ET_MAGIC_BLOCK_BITMAP               (2133571336L)
+#define EXT2_ET_MAGIC_INODE_BITMAP               (2133571337L)
+#define EXT2_ET_MAGIC_GENERIC_BITMAP             (2133571338L)
+#define EXT2_ET_MAGIC_TEST_IO_CHANNEL            (2133571339L)
+#define EXT2_ET_MAGIC_DBLIST                     (2133571340L)
+#define EXT2_ET_MAGIC_ICOUNT                     (2133571341L)
+#define EXT2_ET_MAGIC_PQ_IO_CHANNEL              (2133571342L)
+#define EXT2_ET_MAGIC_EXT2_FILE                  (2133571343L)
+#define EXT2_ET_MAGIC_E2IMAGE                    (2133571344L)
+#define EXT2_ET_MAGIC_INODE_IO_CHANNEL           (2133571345L)
+#define EXT2_ET_MAGIC_RESERVED_9                 (2133571346L)
+#define EXT2_ET_BAD_MAGIC                        (2133571347L)
+#define EXT2_ET_REV_TOO_HIGH                     (2133571348L)
+#define EXT2_ET_RO_FILSYS                        (2133571349L)
+#define EXT2_ET_GDESC_READ                       (2133571350L)
+#define EXT2_ET_GDESC_WRITE                      (2133571351L)
+#define EXT2_ET_GDESC_BAD_BLOCK_MAP              (2133571352L)
+#define EXT2_ET_GDESC_BAD_INODE_MAP              (2133571353L)
+#define EXT2_ET_GDESC_BAD_INODE_TABLE            (2133571354L)
+#define EXT2_ET_INODE_BITMAP_WRITE               (2133571355L)
+#define EXT2_ET_INODE_BITMAP_READ                (2133571356L)
+#define EXT2_ET_BLOCK_BITMAP_WRITE               (2133571357L)
+#define EXT2_ET_BLOCK_BITMAP_READ                (2133571358L)
+#define EXT2_ET_INODE_TABLE_WRITE                (2133571359L)
+#define EXT2_ET_INODE_TABLE_READ                 (2133571360L)
+#define EXT2_ET_NEXT_INODE_READ                  (2133571361L)
+#define EXT2_ET_UNEXPECTED_BLOCK_SIZE            (2133571362L)
+#define EXT2_ET_DIR_CORRUPTED                    (2133571363L)
+#define EXT2_ET_SHORT_READ                       (2133571364L)
+#define EXT2_ET_SHORT_WRITE                      (2133571365L)
+#define EXT2_ET_DIR_NO_SPACE                     (2133571366L)
+#define EXT2_ET_NO_INODE_BITMAP                  (2133571367L)
+#define EXT2_ET_NO_BLOCK_BITMAP                  (2133571368L)
+#define EXT2_ET_BAD_INODE_NUM                    (2133571369L)
+#define EXT2_ET_BAD_BLOCK_NUM                    (2133571370L)
+#define EXT2_ET_EXPAND_DIR_ERR                   (2133571371L)
+#define EXT2_ET_TOOSMALL                         (2133571372L)
+#define EXT2_ET_BAD_BLOCK_MARK                   (2133571373L)
+#define EXT2_ET_BAD_BLOCK_UNMARK                 (2133571374L)
+#define EXT2_ET_BAD_BLOCK_TEST                   (2133571375L)
+#define EXT2_ET_BAD_INODE_MARK                   (2133571376L)
+#define EXT2_ET_BAD_INODE_UNMARK                 (2133571377L)
+#define EXT2_ET_BAD_INODE_TEST                   (2133571378L)
+#define EXT2_ET_FUDGE_BLOCK_BITMAP_END           (2133571379L)
+#define EXT2_ET_FUDGE_INODE_BITMAP_END           (2133571380L)
+#define EXT2_ET_BAD_IND_BLOCK                    (2133571381L)
+#define EXT2_ET_BAD_DIND_BLOCK                   (2133571382L)
+#define EXT2_ET_BAD_TIND_BLOCK                   (2133571383L)
+#define EXT2_ET_NEQ_BLOCK_BITMAP                 (2133571384L)
+#define EXT2_ET_NEQ_INODE_BITMAP                 (2133571385L)
+#define EXT2_ET_BAD_DEVICE_NAME                  (2133571386L)
+#define EXT2_ET_MISSING_INODE_TABLE              (2133571387L)
+#define EXT2_ET_CORRUPT_SUPERBLOCK               (2133571388L)
+#define EXT2_ET_BAD_GENERIC_MARK                 (2133571389L)
+#define EXT2_ET_BAD_GENERIC_UNMARK               (2133571390L)
+#define EXT2_ET_BAD_GENERIC_TEST                 (2133571391L)
+#define EXT2_ET_SYMLINK_LOOP                     (2133571392L)
+#define EXT2_ET_CALLBACK_NOTHANDLED              (2133571393L)
+#define EXT2_ET_BAD_BLOCK_IN_INODE_TABLE         (2133571394L)
+#define EXT2_ET_UNSUPP_FEATURE                   (2133571395L)
+#define EXT2_ET_RO_UNSUPP_FEATURE                (2133571396L)
+#define EXT2_ET_LLSEEK_FAILED                    (2133571397L)
+#define EXT2_ET_NO_MEMORY                        (2133571398L)
+#define EXT2_ET_INVALID_ARGUMENT                 (2133571399L)
+#define EXT2_ET_BLOCK_ALLOC_FAIL                 (2133571400L)
+#define EXT2_ET_INODE_ALLOC_FAIL                 (2133571401L)
+#define EXT2_ET_NO_DIRECTORY                     (2133571402L)
+#define EXT2_ET_TOO_MANY_REFS                    (2133571403L)
+#define EXT2_ET_FILE_NOT_FOUND                   (2133571404L)
+#define EXT2_ET_FILE_RO                          (2133571405L)
+#define EXT2_ET_DB_NOT_FOUND                     (2133571406L)
+#define EXT2_ET_DIR_EXISTS                       (2133571407L)
+#define EXT2_ET_UNIMPLEMENTED                    (2133571408L)
+#define EXT2_ET_CANCEL_REQUESTED                 (2133571409L)
+#define EXT2_ET_FILE_TOO_BIG                     (2133571410L)
+#define EXT2_ET_JOURNAL_NOT_BLOCK                (2133571411L)
+#define EXT2_ET_NO_JOURNAL_SB                    (2133571412L)
+#define EXT2_ET_JOURNAL_TOO_SMALL                (2133571413L)
+#define EXT2_ET_JOURNAL_UNSUPP_VERSION           (2133571414L)
+#define EXT2_ET_LOAD_EXT_JOURNAL                 (2133571415L)
+#define EXT2_ET_NO_JOURNAL                       (2133571416L)
+#define EXT2_ET_DIRHASH_UNSUPP                   (2133571417L)
+#define EXT2_ET_BAD_EA_BLOCK_NUM                 (2133571418L)
+#define EXT2_ET_TOO_MANY_INODES                  (2133571419L)
+#define EXT2_ET_NOT_IMAGE_FILE                   (2133571420L)
+#define EXT2_ET_RES_GDT_BLOCKS                   (2133571421L)
+#define EXT2_ET_RESIZE_INODE_CORRUPT             (2133571422L)
+#define EXT2_ET_SET_BMAP_NO_IND                  (2133571423L)
+
+#if 0
+extern const struct error_table et_ext2_error_table;
+extern void initialize_ext2_error_table(void);
+
+/* For compatibility with Heimdal */
+extern void initialize_ext2_error_table_r(struct et_list **list);
+
+#define ERROR_TABLE_BASE_ext2 (2133571328L)
+
+/* for compatibility with older versions... */
+#define init_ext2_err_tbl initialize_ext2_error_table
+#define ext2_err_base ERROR_TABLE_BASE_ext2
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_ext_attr.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_ext_attr.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_ext_attr.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,52 @@
+/*
+  File: linux/ext2_ext_attr.h
+
+  On-disk format of extended attributes for the ext2 filesystem.
+
+  (C) 2000 Andreas Gruenbacher, <a.gruenbacher at computer.org>
+*/
+
+/* Magic value in attribute blocks */
+#define EXT2_EXT_ATTR_MAGIC_v1		0xEA010000
+#define EXT2_EXT_ATTR_MAGIC		0xEA020000
+
+/* Maximum number of references to one attribute block */
+#define EXT2_EXT_ATTR_REFCOUNT_MAX	1024
+
+struct ext2_ext_attr_header {
+	__u32	h_magic;	/* magic number for identification */
+	__u32	h_refcount;	/* reference count */
+	__u32	h_blocks;	/* number of disk blocks used */
+	__u32	h_hash;		/* hash value of all attributes */
+	__u32	h_reserved[4];	/* zero right now */
+};
+
+struct ext2_ext_attr_entry {
+	__u8	e_name_len;	/* length of name */
+	__u8	e_name_index;	/* attribute name index */
+	__u16	e_value_offs;	/* offset in disk block of value */
+	__u32	e_value_block;	/* disk block attribute is stored on (n/i) */
+	__u32	e_value_size;	/* size of attribute value */
+	__u32	e_hash;		/* hash value of name and value */
+};
+
+#define EXT2_EXT_ATTR_PAD_BITS		2
+#define EXT2_EXT_ATTR_PAD		(1<<EXT2_EXT_ATTR_PAD_BITS)
+#define EXT2_EXT_ATTR_ROUND		(EXT2_EXT_ATTR_PAD-1)
+#define EXT2_EXT_ATTR_LEN(name_len) \
+	(((name_len) + EXT2_EXT_ATTR_ROUND + \
+	sizeof(struct ext2_ext_attr_entry)) & ~EXT2_EXT_ATTR_ROUND)
+#define EXT2_EXT_ATTR_NEXT(entry) \
+	( (struct ext2_ext_attr_entry *)( \
+	  (char *)(entry) + EXT2_EXT_ATTR_LEN((entry)->e_name_len)) )
+#define EXT2_EXT_ATTR_SIZE(size) \
+	(((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
+#define EXT2_EXT_IS_LAST_ENTRY(entry) (*((__u32 *)(entry)) == 0UL)
+#define EXT2_EXT_ATTR_NAME(entry) \
+	(((char *) (entry)) + sizeof(struct ext2_ext_attr_entry))
+#define EXT2_XATTR_LEN(name_len) \
+	(((name_len) + EXT2_EXT_ATTR_ROUND + \
+	sizeof(struct ext2_xattr_entry)) & ~EXT2_EXT_ATTR_ROUND)
+#define EXT2_XATTR_SIZE(size) \
+	(((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_fs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,569 @@
+/*
+ *  linux/include/linux/ext2_fs.h
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card at masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ *  from
+ *
+ *  linux/include/linux/minix_fs.h
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#ifndef _LINUX_EXT2_FS_H
+#define _LINUX_EXT2_FS_H
+
+#include "ext2_types.h"		/* Changed from linux/types.h */
+
+/*
+ * Special inode numbers
+ */
+#define EXT2_BAD_INO		 1	/* Bad blocks inode */
+#define EXT2_ROOT_INO		 2	/* Root inode */
+#define EXT2_ACL_IDX_INO	 3	/* ACL inode */
+#define EXT2_ACL_DATA_INO	 4	/* ACL inode */
+#define EXT2_BOOT_LOADER_INO	 5	/* Boot loader inode */
+#define EXT2_UNDEL_DIR_INO	 6	/* Undelete directory inode */
+#define EXT2_RESIZE_INO		 7	/* Reserved group descriptors inode */
+#define EXT2_JOURNAL_INO	 8	/* Journal inode */
+
+/* First non-reserved inode for old ext2 filesystems */
+#define EXT2_GOOD_OLD_FIRST_INO	11
+
+/*
+ * The second extended file system magic number
+ */
+#define EXT2_SUPER_MAGIC	0xEF53
+
+/* Assume that user mode programs are passing in an ext2fs superblock, not
+ * a kernel struct super_block.  This will allow us to call the feature-test
+ * macros from user land. */
+#define EXT2_SB(sb)	(sb)
+
+/*
+ * Maximal count of links to a file
+ */
+#define EXT2_LINK_MAX		32000
+
+/*
+ * Macro-instructions used to manage several block sizes
+ */
+#define EXT2_MIN_BLOCK_LOG_SIZE		10	/* 1024 */
+#define EXT2_MAX_BLOCK_LOG_SIZE		16	/* 65536 */
+#define EXT2_MIN_BLOCK_SIZE	(1 << EXT2_MIN_BLOCK_LOG_SIZE)
+#define EXT2_MAX_BLOCK_SIZE	(1 << EXT2_MAX_BLOCK_LOG_SIZE)
+#define EXT2_BLOCK_SIZE(s)	(EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
+#define EXT2_BLOCK_SIZE_BITS(s)	((s)->s_log_block_size + 10)
+#define EXT2_INODE_SIZE(s)	(((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
+				 EXT2_GOOD_OLD_INODE_SIZE : (s)->s_inode_size)
+#define EXT2_FIRST_INO(s)	(((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
+				 EXT2_GOOD_OLD_FIRST_INO : (s)->s_first_ino)
+#define EXT2_ADDR_PER_BLOCK(s)	(EXT2_BLOCK_SIZE(s) / sizeof(__u32))
+
+/*
+ * Macro-instructions used to manage fragments
+ */
+#define EXT2_MIN_FRAG_SIZE		EXT2_MIN_BLOCK_SIZE
+#define EXT2_MAX_FRAG_SIZE		EXT2_MAX_BLOCK_SIZE
+#define EXT2_MIN_FRAG_LOG_SIZE		EXT2_MIN_BLOCK_LOG_SIZE
+# define EXT2_FRAG_SIZE(s)		(EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
+# define EXT2_FRAGS_PER_BLOCK(s)	(EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
+
+/*
+ * ACL structures
+ */
+struct ext2_acl_header	/* Header of Access Control Lists */
+{
+	__u32	aclh_size;
+	__u32	aclh_file_count;
+	__u32	aclh_acle_count;
+	__u32	aclh_first_acle;
+};
+
+struct ext2_acl_entry	/* Access Control List Entry */
+{
+	__u32	acle_size;
+	__u16	acle_perms;	/* Access permissions */
+	__u16	acle_type;	/* Type of entry */
+	__u16	acle_tag;	/* User or group identity */
+	__u16	acle_pad1;
+	__u32	acle_next;	/* Pointer on next entry for the */
+					/* same inode or on next free entry */
+};
+
+/*
+ * Structure of a blocks group descriptor
+ */
+struct ext2_group_desc
+{
+	__u32	bg_block_bitmap;		/* Blocks bitmap block */
+	__u32	bg_inode_bitmap;		/* Inodes bitmap block */
+	__u32	bg_inode_table;		/* Inodes table block */
+	__u16	bg_free_blocks_count;	/* Free blocks count */
+	__u16	bg_free_inodes_count;	/* Free inodes count */
+	__u16	bg_used_dirs_count;	/* Directories count */
+	__u16	bg_pad;
+	__u32	bg_reserved[3];
+};
+
+/*
+ * Data structures used by the directory indexing feature
+ *
+ * Note: all of the multibyte integer fields are little endian.
+ */
+
+/*
+ * Note: dx_root_info is laid out so that if it should somehow get
+ * overlaid by a dirent the two low bits of the hash version will be
+ * zero.  Therefore, the hash version mod 4 should never be 0.
+ * Sincerely, the paranoia department.
+ */
+struct ext2_dx_root_info {
+	__u32 reserved_zero;
+	__u8 hash_version; /* 0 now, 1 at release */
+	__u8 info_length; /* 8 */
+	__u8 indirect_levels;
+	__u8 unused_flags;
+};
+
+#define EXT2_HASH_LEGACY	0
+#define EXT2_HASH_HALF_MD4	1
+#define EXT2_HASH_TEA		2
+
+#define EXT2_HASH_FLAG_INCOMPAT	0x1
+
+struct ext2_dx_entry {
+	__u32 hash;
+	__u32 block;
+};
+
+struct ext2_dx_countlimit {
+	__u16 limit;
+	__u16 count;
+};
+
+
+/*
+ * Macro-instructions used to manage group descriptors
+ */
+#define EXT2_BLOCKS_PER_GROUP(s)	(EXT2_SB(s)->s_blocks_per_group)
+#define EXT2_INODES_PER_GROUP(s)	(EXT2_SB(s)->s_inodes_per_group)
+#define EXT2_INODES_PER_BLOCK(s)	(EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
+/* limits imposed by 16-bit value gd_free_{blocks,inode}_count */
+#define EXT2_MAX_BLOCKS_PER_GROUP(s)	((1 << 16) - 8)
+#define EXT2_MAX_INODES_PER_GROUP(s)	((1 << 16) - EXT2_INODES_PER_BLOCK(s))
+#define EXT2_DESC_PER_BLOCK(s)		(EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
+
+/*
+ * Constants relative to the data blocks
+ */
+#define EXT2_NDIR_BLOCKS		12
+#define EXT2_IND_BLOCK			EXT2_NDIR_BLOCKS
+#define EXT2_DIND_BLOCK			(EXT2_IND_BLOCK + 1)
+#define EXT2_TIND_BLOCK			(EXT2_DIND_BLOCK + 1)
+#define EXT2_N_BLOCKS			(EXT2_TIND_BLOCK + 1)
+
+/*
+ * Inode flags
+ */
+#define EXT2_SECRM_FL			0x00000001 /* Secure deletion */
+#define EXT2_UNRM_FL			0x00000002 /* Undelete */
+#define EXT2_COMPR_FL			0x00000004 /* Compress file */
+#define EXT2_SYNC_FL			0x00000008 /* Synchronous updates */
+#define EXT2_IMMUTABLE_FL		0x00000010 /* Immutable file */
+#define EXT2_APPEND_FL			0x00000020 /* writes to file may only append */
+#define EXT2_NODUMP_FL			0x00000040 /* do not dump file */
+#define EXT2_NOATIME_FL			0x00000080 /* do not update atime */
+/* Reserved for compression usage... */
+#define EXT2_DIRTY_FL			0x00000100
+#define EXT2_COMPRBLK_FL		0x00000200 /* One or more compressed clusters */
+#define EXT2_NOCOMPR_FL			0x00000400 /* Access raw compressed data */
+#define EXT2_ECOMPR_FL			0x00000800 /* Compression error */
+/* End compression flags --- maybe not all used */
+#define EXT2_BTREE_FL			0x00001000 /* btree format dir */
+#define EXT2_INDEX_FL			0x00001000 /* hash-indexed directory */
+#define EXT2_IMAGIC_FL			0x00002000
+#define EXT3_JOURNAL_DATA_FL		0x00004000 /* file data should be journaled */
+#define EXT2_NOTAIL_FL			0x00008000 /* file tail should not be merged */
+#define EXT2_DIRSYNC_FL			0x00010000 /* Synchronous directory modifications */
+#define EXT2_TOPDIR_FL			0x00020000 /* Top of directory hierarchies*/
+#define EXT3_EXTENTS_FL			0x00080000 /* Inode uses extents */
+#define EXT2_RESERVED_FL		0x80000000 /* reserved for ext2 lib */
+
+#define EXT2_FL_USER_VISIBLE		0x0003DFFF /* User visible flags */
+#define EXT2_FL_USER_MODIFIABLE		0x000080FF /* User modifiable flags */
+
+/*
+ * ioctl commands
+ */
+#define EXT2_IOC_GETFLAGS		_IOR('f', 1, long)
+#define EXT2_IOC_SETFLAGS		_IOW('f', 2, long)
+#define EXT2_IOC_GETVERSION		_IOR('v', 1, long)
+#define EXT2_IOC_SETVERSION		_IOW('v', 2, long)
+
+/*
+ * Structure of an inode on the disk
+ */
+struct ext2_inode {
+	__u16	i_mode;		/* File mode */
+	__u16	i_uid;		/* Low 16 bits of Owner Uid */
+	__u32	i_size;		/* Size in bytes */
+	__u32	i_atime;	/* Access time */
+	__u32	i_ctime;	/* Creation time */
+	__u32	i_mtime;	/* Modification time */
+	__u32	i_dtime;	/* Deletion Time */
+	__u16	i_gid;		/* Low 16 bits of Group Id */
+	__u16	i_links_count;	/* Links count */
+	__u32	i_blocks;	/* Blocks count */
+	__u32	i_flags;	/* File flags */
+	union {
+		struct {
+			__u32  l_i_reserved1;
+		} linux1;
+		struct {
+			__u32  h_i_translator;
+		} hurd1;
+		struct {
+			__u32  m_i_reserved1;
+		} masix1;
+	} osd1;				/* OS dependent 1 */
+	__u32	i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
+	__u32	i_generation;	/* File version (for NFS) */
+	__u32	i_file_acl;	/* File ACL */
+	__u32	i_dir_acl;	/* Directory ACL */
+	__u32	i_faddr;	/* Fragment address */
+	union {
+		struct {
+			__u8	l_i_frag;	/* Fragment number */
+			__u8	l_i_fsize;	/* Fragment size */
+			__u16	i_pad1;
+			__u16	l_i_uid_high;	/* these 2 fields    */
+			__u16	l_i_gid_high;	/* were reserved2[0] */
+			__u32	l_i_reserved2;
+		} linux2;
+		struct {
+			__u8	h_i_frag;	/* Fragment number */
+			__u8	h_i_fsize;	/* Fragment size */
+			__u16	h_i_mode_high;
+			__u16	h_i_uid_high;
+			__u16	h_i_gid_high;
+			__u32	h_i_author;
+		} hurd2;
+		struct {
+			__u8	m_i_frag;	/* Fragment number */
+			__u8	m_i_fsize;	/* Fragment size */
+			__u16	m_pad1;
+			__u32	m_i_reserved2[2];
+		} masix2;
+	} osd2;				/* OS dependent 2 */
+};
+
+/*
+ * Permanent part of an large inode on the disk
+ */
+struct ext2_inode_large {
+	__u16	i_mode;		/* File mode */
+	__u16	i_uid;		/* Low 16 bits of Owner Uid */
+	__u32	i_size;		/* Size in bytes */
+	__u32	i_atime;	/* Access time */
+	__u32	i_ctime;	/* Creation time */
+	__u32	i_mtime;	/* Modification time */
+	__u32	i_dtime;	/* Deletion Time */
+	__u16	i_gid;		/* Low 16 bits of Group Id */
+	__u16	i_links_count;	/* Links count */
+	__u32	i_blocks;	/* Blocks count */
+	__u32	i_flags;	/* File flags */
+	union {
+		struct {
+			__u32  l_i_reserved1;
+		} linux1;
+		struct {
+			__u32  h_i_translator;
+		} hurd1;
+		struct {
+			__u32  m_i_reserved1;
+		} masix1;
+	} osd1;				/* OS dependent 1 */
+	__u32	i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
+	__u32	i_generation;	/* File version (for NFS) */
+	__u32	i_file_acl;	/* File ACL */
+	__u32	i_dir_acl;	/* Directory ACL */
+	__u32	i_faddr;	/* Fragment address */
+	union {
+		struct {
+			__u8	l_i_frag;	/* Fragment number */
+			__u8	l_i_fsize;	/* Fragment size */
+			__u16	i_pad1;
+			__u16	l_i_uid_high;	/* these 2 fields    */
+			__u16	l_i_gid_high;	/* were reserved2[0] */
+			__u32	l_i_reserved2;
+		} linux2;
+		struct {
+			__u8	h_i_frag;	/* Fragment number */
+			__u8	h_i_fsize;	/* Fragment size */
+			__u16	h_i_mode_high;
+			__u16	h_i_uid_high;
+			__u16	h_i_gid_high;
+			__u32	h_i_author;
+		} hurd2;
+		struct {
+			__u8	m_i_frag;	/* Fragment number */
+			__u8	m_i_fsize;	/* Fragment size */
+			__u16	m_pad1;
+			__u32	m_i_reserved2[2];
+		} masix2;
+	} osd2;				/* OS dependent 2 */
+	__u16	i_extra_isize;
+	__u16	i_pad1;
+};
+
+#define i_size_high	i_dir_acl
+
+/*
+ * File system states
+ */
+#define EXT2_VALID_FS			0x0001	/* Unmounted cleanly */
+#define EXT2_ERROR_FS			0x0002	/* Errors detected */
+
+/*
+ * Mount flags
+ */
+#define EXT2_MOUNT_CHECK		0x0001	/* Do mount-time checks */
+#define EXT2_MOUNT_GRPID		0x0004	/* Create files with directory's group */
+#define EXT2_MOUNT_DEBUG		0x0008	/* Some debugging messages */
+#define EXT2_MOUNT_ERRORS_CONT		0x0010	/* Continue on errors */
+#define EXT2_MOUNT_ERRORS_RO		0x0020	/* Remount fs ro on errors */
+#define EXT2_MOUNT_ERRORS_PANIC		0x0040	/* Panic on errors */
+#define EXT2_MOUNT_MINIX_DF		0x0080	/* Mimics the Minix statfs */
+#define EXT2_MOUNT_NO_UID32		0x0200  /* Disable 32-bit UIDs */
+
+#define clear_opt(o, opt)		o &= ~EXT2_MOUNT_##opt
+#define set_opt(o, opt)			o |= EXT2_MOUNT_##opt
+#define test_opt(sb, opt)		(EXT2_SB(sb)->s_mount_opt & \
+					 EXT2_MOUNT_##opt)
+/*
+ * Maximal mount counts between two filesystem checks
+ */
+#define EXT2_DFL_MAX_MNT_COUNT		20	/* Allow 20 mounts */
+#define EXT2_DFL_CHECKINTERVAL		0	/* Don't use interval check */
+
+/*
+ * Behaviour when detecting errors
+ */
+#define EXT2_ERRORS_CONTINUE		1	/* Continue execution */
+#define EXT2_ERRORS_RO			2	/* Remount fs read-only */
+#define EXT2_ERRORS_PANIC		3	/* Panic */
+#define EXT2_ERRORS_DEFAULT		EXT2_ERRORS_CONTINUE
+
+/*
+ * Structure of the super block
+ */
+struct ext2_super_block {
+	__u32	s_inodes_count;		/* Inodes count */
+	__u32	s_blocks_count;		/* Blocks count */
+	__u32	s_r_blocks_count;	/* Reserved blocks count */
+	__u32	s_free_blocks_count;	/* Free blocks count */
+	__u32	s_free_inodes_count;	/* Free inodes count */
+	__u32	s_first_data_block;	/* First Data Block */
+	__u32	s_log_block_size;	/* Block size */
+	__s32	s_log_frag_size;	/* Fragment size */
+	__u32	s_blocks_per_group;	/* # Blocks per group */
+	__u32	s_frags_per_group;	/* # Fragments per group */
+	__u32	s_inodes_per_group;	/* # Inodes per group */
+	__u32	s_mtime;		/* Mount time */
+	__u32	s_wtime;		/* Write time */
+	__u16	s_mnt_count;		/* Mount count */
+	__s16	s_max_mnt_count;	/* Maximal mount count */
+	__u16	s_magic;		/* Magic signature */
+	__u16	s_state;		/* File system state */
+	__u16	s_errors;		/* Behaviour when detecting errors */
+	__u16	s_minor_rev_level;	/* minor revision level */
+	__u32	s_lastcheck;		/* time of last check */
+	__u32	s_checkinterval;	/* max. time between checks */
+	__u32	s_creator_os;		/* OS */
+	__u32	s_rev_level;		/* Revision level */
+	__u16	s_def_resuid;		/* Default uid for reserved blocks */
+	__u16	s_def_resgid;		/* Default gid for reserved blocks */
+	/*
+	 * These fields are for EXT2_DYNAMIC_REV superblocks only.
+	 *
+	 * Note: the difference between the compatible feature set and
+	 * the incompatible feature set is that if there is a bit set
+	 * in the incompatible feature set that the kernel doesn't
+	 * know about, it should refuse to mount the filesystem.
+	 *
+	 * e2fsck's requirements are more strict; if it doesn't know
+	 * about a feature in either the compatible or incompatible
+	 * feature set, it must abort and not try to meddle with
+	 * things it doesn't understand...
+	 */
+	__u32	s_first_ino;		/* First non-reserved inode */
+	__u16   s_inode_size;		/* size of inode structure */
+	__u16	s_block_group_nr;	/* block group # of this superblock */
+	__u32	s_feature_compat;	/* compatible feature set */
+	__u32	s_feature_incompat;	/* incompatible feature set */
+	__u32	s_feature_ro_compat;	/* readonly-compatible feature set */
+	__u8	s_uuid[16];		/* 128-bit uuid for volume */
+	char	s_volume_name[16];	/* volume name */
+	char	s_last_mounted[64];	/* directory where last mounted */
+	__u32	s_algorithm_usage_bitmap; /* For compression */
+	/*
+	 * Performance hints.  Directory preallocation should only
+	 * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
+	 */
+	__u8	s_prealloc_blocks;	/* Nr of blocks to try to preallocate*/
+	__u8	s_prealloc_dir_blocks;	/* Nr to preallocate for dirs */
+	__u16	s_reserved_gdt_blocks;	/* Per group table for online growth */
+	/*
+	 * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
+	 */
+	__u8	s_journal_uuid[16];	/* uuid of journal superblock */
+	__u32	s_journal_inum;		/* inode number of journal file */
+	__u32	s_journal_dev;		/* device number of journal file */
+	__u32	s_last_orphan;		/* start of list of inodes to delete */
+	__u32	s_hash_seed[4];		/* HTREE hash seed */
+	__u8	s_def_hash_version;	/* Default hash version to use */
+	__u8	s_jnl_backup_type;	/* Default type of journal backup */
+	__u16	s_reserved_word_pad;
+	__u32	s_default_mount_opts;
+	__u32	s_first_meta_bg;	/* First metablock group */
+	__u32	s_mkfs_time;		/* When the filesystem was created */
+	__u32	s_jnl_blocks[17];	/* Backup of the journal inode */
+	__u32	s_reserved[172];	/* Padding to the end of the block */
+};
+
+/*
+ * Codes for operating systems
+ */
+#define EXT2_OS_LINUX		0
+#define EXT2_OS_HURD		1
+#define EXT2_OS_MASIX		2
+#define EXT2_OS_FREEBSD		3
+#define EXT2_OS_LITES		4
+
+/*
+ * Revision levels
+ */
+#define EXT2_GOOD_OLD_REV	0	/* The good old (original) format */
+#define EXT2_DYNAMIC_REV	1	/* V2 format w/ dynamic inode sizes */
+
+#define EXT2_CURRENT_REV	EXT2_GOOD_OLD_REV
+#define EXT2_MAX_SUPP_REV	EXT2_DYNAMIC_REV
+
+#define EXT2_GOOD_OLD_INODE_SIZE 128
+
+/*
+ * Journal inode backup types
+ */
+#define EXT3_JNL_BACKUP_BLOCKS	1
+
+/*
+ * Feature set definitions
+ */
+
+#define EXT2_HAS_COMPAT_FEATURE(sb,mask)			\
+	( EXT2_SB(sb)->s_feature_compat & (mask) )
+#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask)			\
+	( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
+#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask)			\
+	( EXT2_SB(sb)->s_feature_incompat & (mask) )
+
+#define EXT2_FEATURE_COMPAT_DIR_PREALLOC	0x0001
+#define EXT2_FEATURE_COMPAT_IMAGIC_INODES	0x0002
+#define EXT3_FEATURE_COMPAT_HAS_JOURNAL		0x0004
+#define EXT2_FEATURE_COMPAT_EXT_ATTR		0x0008
+#define EXT2_FEATURE_COMPAT_RESIZE_INODE	0x0010
+#define EXT2_FEATURE_COMPAT_DIR_INDEX		0x0020
+
+#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER	0x0001
+#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE	0x0002
+/* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR	0x0004 not used */
+
+#define EXT2_FEATURE_INCOMPAT_COMPRESSION	0x0001
+#define EXT2_FEATURE_INCOMPAT_FILETYPE		0x0002
+#define EXT3_FEATURE_INCOMPAT_RECOVER		0x0004 /* Needs recovery */
+#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV	0x0008 /* Journal device */
+#define EXT2_FEATURE_INCOMPAT_META_BG		0x0010
+#define EXT3_FEATURE_INCOMPAT_EXTENTS		0x0040
+
+
+#define EXT2_FEATURE_COMPAT_SUPP	0
+#define EXT2_FEATURE_INCOMPAT_SUPP	(EXT2_FEATURE_INCOMPAT_FILETYPE)
+#define EXT2_FEATURE_RO_COMPAT_SUPP	(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+					 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
+					 EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
+
+/*
+ * Default values for user and/or group using reserved blocks
+ */
+#define EXT2_DEF_RESUID		0
+#define EXT2_DEF_RESGID		0
+
+/*
+ * Default mount options
+ */
+#define EXT2_DEFM_DEBUG		0x0001
+#define EXT2_DEFM_BSDGROUPS	0x0002
+#define EXT2_DEFM_XATTR_USER	0x0004
+#define EXT2_DEFM_ACL		0x0008
+#define EXT2_DEFM_UID16		0x0010
+#define EXT3_DEFM_JMODE		0x0060
+#define EXT3_DEFM_JMODE_DATA	0x0020
+#define EXT3_DEFM_JMODE_ORDERED	0x0040
+#define EXT3_DEFM_JMODE_WBACK	0x0060
+
+/*
+ * Structure of a directory entry
+ */
+#define EXT2_NAME_LEN 255
+
+struct ext2_dir_entry {
+	__u32	inode;			/* Inode number */
+	__u16	rec_len;		/* Directory entry length */
+	__u16	name_len;		/* Name length */
+	char	name[EXT2_NAME_LEN];	/* File name */
+};
+
+/*
+ * The new version of the directory entry.  Since EXT2 structures are
+ * stored in intel byte order, and the name_len field could never be
+ * bigger than 255 chars, it's safe to reclaim the extra byte for the
+ * file_type field.
+ */
+struct ext2_dir_entry_2 {
+	__u32	inode;			/* Inode number */
+	__u16	rec_len;		/* Directory entry length */
+	__u8	name_len;		/* Name length */
+	__u8	file_type;
+	char	name[EXT2_NAME_LEN];	/* File name */
+};
+
+/*
+ * Ext2 directory file types.  Only the low 3 bits are used.  The
+ * other bits are reserved for now.
+ */
+#define EXT2_FT_UNKNOWN		0
+#define EXT2_FT_REG_FILE	1
+#define EXT2_FT_DIR		2
+#define EXT2_FT_CHRDEV		3
+#define EXT2_FT_BLKDEV		4
+#define EXT2_FT_FIFO		5
+#define EXT2_FT_SOCK		6
+#define EXT2_FT_SYMLINK		7
+
+#define EXT2_FT_MAX		8
+
+/*
+ * EXT2_DIR_PAD defines the directory entries boundaries
+ *
+ * NOTE: It must be a multiple of 4
+ */
+#define EXT2_DIR_PAD			4
+#define EXT2_DIR_ROUND			(EXT2_DIR_PAD - 1)
+#define EXT2_DIR_REC_LEN(name_len)	(((name_len) + 8 + EXT2_DIR_ROUND) & \
+					 ~EXT2_DIR_ROUND)
+
+#endif	/* _LINUX_EXT2_FS_H */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_io.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_io.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_io.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,113 @@
+/*
+ * io.h --- the I/O manager abstraction
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#ifndef _EXT2FS_EXT2_IO_H
+#define _EXT2FS_EXT2_IO_H
+
+/*
+ * ext2_loff_t is defined here since unix_io.c needs it.
+ */
+#if defined(__GNUC__) || defined(HAS_LONG_LONG)
+typedef long long	ext2_loff_t;
+#else
+typedef long		ext2_loff_t;
+#endif
+
+/* llseek.c */
+/* ext2_loff_t ext2fs_llseek (int, ext2_loff_t, int); */
+#ifdef CONFIG_LFS
+# define ext2fs_llseek lseek64
+#else
+# define ext2fs_llseek lseek
+#endif
+
+typedef struct struct_io_manager *io_manager;
+typedef struct struct_io_channel *io_channel;
+
+#define CHANNEL_FLAGS_WRITETHROUGH	0x01
+
+struct struct_io_channel {
+	errcode_t	magic;
+	io_manager	manager;
+	char		*name;
+	int		block_size;
+	errcode_t	(*read_error)(io_channel channel,
+				      unsigned long block,
+				      int count,
+				      void *data,
+				      size_t size,
+				      int actual_bytes_read,
+				      errcode_t error);
+	errcode_t       (*write_error)(io_channel channel,
+				       unsigned long block,
+				       int count,
+				       const void *data,
+				       size_t size,
+				       int actual_bytes_written,
+				       errcode_t error);
+	int		refcount;
+	int		flags;
+	int		reserved[14];
+	void		*private_data;
+	void		*app_data;
+};
+
+struct struct_io_manager {
+	errcode_t magic;
+	const char *name;
+	errcode_t (*open)(const char *name, int flags, io_channel *channel);
+	errcode_t (*close)(io_channel channel);
+	errcode_t (*set_blksize)(io_channel channel, int blksize);
+	errcode_t (*read_blk)(io_channel channel, unsigned long block,
+			      int count, void *data);
+	errcode_t (*write_blk)(io_channel channel, unsigned long block,
+			       int count, const void *data);
+	errcode_t (*flush)(io_channel channel);
+	errcode_t (*write_byte)(io_channel channel, unsigned long offset,
+				int count, const void *data);
+	errcode_t (*set_option)(io_channel channel, const char *option,
+				const char *arg);
+	int             reserved[14];
+};
+
+#define IO_FLAG_RW	1
+
+/*
+ * Convenience functions....
+ */
+#define io_channel_close(c)		((c)->manager->close((c)))
+#define io_channel_set_blksize(c,s)	((c)->manager->set_blksize((c),s))
+#define io_channel_read_blk(c,b,n,d)	((c)->manager->read_blk((c),b,n,d))
+#define io_channel_write_blk(c,b,n,d)	((c)->manager->write_blk((c),b,n,d))
+#define io_channel_flush(c)		((c)->manager->flush((c)))
+#define io_channel_bumpcount(c)		((c)->refcount++)
+
+/* io_manager.c */
+extern errcode_t io_channel_set_options(io_channel channel,
+					const char *options);
+extern errcode_t io_channel_write_byte(io_channel channel,
+				       unsigned long offset,
+				       int count, const void *data);
+
+/* unix_io.c */
+extern io_manager unix_io_manager;
+
+/* test_io.c */
+extern io_manager test_io_manager, test_io_backing_manager;
+extern void (*test_io_cb_read_blk)
+	(unsigned long block, int count, errcode_t err);
+extern void (*test_io_cb_write_blk)
+	(unsigned long block, int count, errcode_t err);
+extern void (*test_io_cb_set_blksize)
+	(int blksize, errcode_t err);
+
+#endif /* _EXT2FS_EXT2_IO_H */
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_types.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_types.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2_types.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#include <linux/types.h>

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,922 @@
+/*
+ * ext2fs.h --- ext2fs
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#ifndef _EXT2FS_EXT2FS_H
+#define _EXT2FS_EXT2FS_H
+
+
+#define EXT2FS_ATTR(x)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Where the master copy of the superblock is located, and how big
+ * superblocks are supposed to be.  We define SUPERBLOCK_SIZE because
+ * the size of the superblock structure is not necessarily trustworthy
+ * (some versions have the padding set up so that the superblock is
+ * 1032 bytes long).
+ */
+#define SUPERBLOCK_OFFSET	1024
+#define SUPERBLOCK_SIZE		1024
+
+/*
+ * The last ext2fs revision level that this version of the library is
+ * able to support.
+ */
+#define EXT2_LIB_CURRENT_REV	EXT2_DYNAMIC_REV
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "ext2_types.h"
+#include "ext2_fs.h"
+
+typedef __u32		ext2_ino_t;
+typedef __u32		blk_t;
+typedef __u32		dgrp_t;
+typedef __u32		ext2_off_t;
+typedef __s64		e2_blkcnt_t;
+typedef __u32		ext2_dirhash_t;
+
+#include "ext2_io.h"
+#include "ext2_err.h"
+
+typedef struct struct_ext2_filsys *ext2_filsys;
+
+struct ext2fs_struct_generic_bitmap {
+	errcode_t	magic;
+	ext2_filsys	fs;
+	__u32		start, end;
+	__u32		real_end;
+	char	*	description;
+	char	*	bitmap;
+	errcode_t	base_error_code;
+	__u32		reserved[7];
+};
+
+#define EXT2FS_MARK_ERROR	0
+#define EXT2FS_UNMARK_ERROR	1
+#define EXT2FS_TEST_ERROR	2
+
+typedef struct ext2fs_struct_generic_bitmap *ext2fs_generic_bitmap;
+typedef struct ext2fs_struct_generic_bitmap *ext2fs_inode_bitmap;
+typedef struct ext2fs_struct_generic_bitmap *ext2fs_block_bitmap;
+
+#define EXT2_FIRST_INODE(s)	EXT2_FIRST_INO(s)
+
+/*
+ * badblocks list definitions
+ */
+
+typedef struct ext2_struct_u32_list *ext2_badblocks_list;
+typedef struct ext2_struct_u32_iterate *ext2_badblocks_iterate;
+
+typedef struct ext2_struct_u32_list *ext2_u32_list;
+typedef struct ext2_struct_u32_iterate *ext2_u32_iterate;
+
+/* old */
+typedef struct ext2_struct_u32_list *badblocks_list;
+typedef struct ext2_struct_u32_iterate *badblocks_iterate;
+
+#define BADBLOCKS_FLAG_DIRTY	1
+
+/*
+ * ext2_dblist structure and abstractions (see dblist.c)
+ */
+struct ext2_db_entry {
+	ext2_ino_t	ino;
+	blk_t	blk;
+	int	blockcnt;
+};
+
+typedef struct ext2_struct_dblist *ext2_dblist;
+
+#define DBLIST_ABORT	1
+
+/*
+ * ext2_fileio definitions
+ */
+
+#define EXT2_FILE_WRITE		0x0001
+#define EXT2_FILE_CREATE	0x0002
+
+#define EXT2_FILE_MASK		0x00FF
+
+#define EXT2_FILE_BUF_DIRTY	0x4000
+#define EXT2_FILE_BUF_VALID	0x2000
+
+typedef struct ext2_file *ext2_file_t;
+
+#define EXT2_SEEK_SET	0
+#define EXT2_SEEK_CUR	1
+#define EXT2_SEEK_END	2
+
+/*
+ * Flags for the ext2_filsys structure and for ext2fs_open()
+ */
+#define EXT2_FLAG_RW			0x01
+#define EXT2_FLAG_CHANGED		0x02
+#define EXT2_FLAG_DIRTY			0x04
+#define EXT2_FLAG_VALID			0x08
+#define EXT2_FLAG_IB_DIRTY		0x10
+#define EXT2_FLAG_BB_DIRTY		0x20
+#define EXT2_FLAG_SWAP_BYTES		0x40
+#define EXT2_FLAG_SWAP_BYTES_READ	0x80
+#define EXT2_FLAG_SWAP_BYTES_WRITE	0x100
+#define EXT2_FLAG_MASTER_SB_ONLY	0x200
+#define EXT2_FLAG_FORCE			0x400
+#define EXT2_FLAG_SUPER_ONLY		0x800
+#define EXT2_FLAG_JOURNAL_DEV_OK	0x1000
+#define EXT2_FLAG_IMAGE_FILE		0x2000
+
+/*
+ * Special flag in the ext2 inode i_flag field that means that this is
+ * a new inode.  (So that ext2_write_inode() can clear extra fields.)
+ */
+#define EXT2_NEW_INODE_FL	0x80000000
+
+/*
+ * Flags for mkjournal
+ *
+ * EXT2_MKJOURNAL_V1_SUPER	Make a (deprecated) V1 journal superblock
+ */
+#define EXT2_MKJOURNAL_V1_SUPER	0x0000001
+
+struct struct_ext2_filsys {
+	errcode_t			magic;
+	io_channel			io;
+	int				flags;
+	char *				device_name;
+	struct ext2_super_block	*	super;
+	unsigned int			blocksize;
+	int				fragsize;
+	dgrp_t				group_desc_count;
+	unsigned long			desc_blocks;
+	struct ext2_group_desc *	group_desc;
+	int				inode_blocks_per_group;
+	ext2fs_inode_bitmap		inode_map;
+	ext2fs_block_bitmap		block_map;
+	errcode_t (*get_blocks)(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
+	errcode_t (*check_directory)(ext2_filsys fs, ext2_ino_t ino);
+	errcode_t (*write_bitmaps)(ext2_filsys fs);
+	errcode_t (*read_inode)(ext2_filsys fs, ext2_ino_t ino,
+				struct ext2_inode *inode);
+	errcode_t (*write_inode)(ext2_filsys fs, ext2_ino_t ino,
+				struct ext2_inode *inode);
+	ext2_badblocks_list		badblocks;
+	ext2_dblist			dblist;
+	__u32				stride;	/* for mke2fs */
+	struct ext2_super_block *	orig_super;
+	struct ext2_image_hdr *		image_header;
+	__u32				umask;
+	/*
+	 * Reserved for future expansion
+	 */
+	__u32				reserved[8];
+
+	/*
+	 * Reserved for the use of the calling application.
+	 */
+	void *				priv_data;
+
+	/*
+	 * Inode cache
+	 */
+	struct ext2_inode_cache		*icache;
+	io_channel			image_io;
+};
+
+#include "bitops.h"
+
+/*
+ * Return flags for the block iterator functions
+ */
+#define BLOCK_CHANGED	1
+#define BLOCK_ABORT	2
+#define BLOCK_ERROR	4
+
+/*
+ * Block interate flags
+ *
+ * BLOCK_FLAG_APPEND, or BLOCK_FLAG_HOLE, indicates that the interator
+ * function should be called on blocks where the block number is zero.
+ * This is used by ext2fs_expand_dir() to be able to add a new block
+ * to an inode.  It can also be used for programs that want to be able
+ * to deal with files that contain "holes".
+ *
+ * BLOCK_FLAG_TRAVERSE indicates that the iterator function for the
+ * indirect, doubly indirect, etc. blocks should be called after all
+ * of the blocks containined in the indirect blocks are processed.
+ * This is useful if you are going to be deallocating blocks from an
+ * inode.
+ *
+ * BLOCK_FLAG_DATA_ONLY indicates that the iterator function should be
+ * called for data blocks only.
+ *
+ * BLOCK_FLAG_NO_LARGE is for internal use only.  It informs
+ * ext2fs_block_iterate2 that large files won't be accepted.
+ */
+#define BLOCK_FLAG_APPEND	1
+#define BLOCK_FLAG_HOLE		1
+#define BLOCK_FLAG_DEPTH_TRAVERSE	2
+#define BLOCK_FLAG_DATA_ONLY	4
+
+#define BLOCK_FLAG_NO_LARGE	0x1000
+
+/*
+ * Magic "block count" return values for the block iterator function.
+ */
+#define BLOCK_COUNT_IND		(-1)
+#define BLOCK_COUNT_DIND	(-2)
+#define BLOCK_COUNT_TIND	(-3)
+#define BLOCK_COUNT_TRANSLATOR	(-4)
+
+#if 0
+/*
+ * Flags for ext2fs_move_blocks
+ */
+#define EXT2_BMOVE_GET_DBLIST	0x0001
+#define EXT2_BMOVE_DEBUG	0x0002
+#endif
+
+/*
+ * Flags for directory block reading and writing functions
+ */
+#define EXT2_DIRBLOCK_V2_STRUCT	0x0001
+
+/*
+ * Return flags for the directory iterator functions
+ */
+#define DIRENT_CHANGED	1
+#define DIRENT_ABORT	2
+#define DIRENT_ERROR	3
+
+/*
+ * Directory iterator flags
+ */
+
+#define DIRENT_FLAG_INCLUDE_EMPTY	1
+#define DIRENT_FLAG_INCLUDE_REMOVED	2
+
+#define DIRENT_DOT_FILE		1
+#define DIRENT_DOT_DOT_FILE	2
+#define DIRENT_OTHER_FILE	3
+#define DIRENT_DELETED_FILE	4
+
+/*
+ * Inode scan definitions
+ */
+typedef struct ext2_struct_inode_scan *ext2_inode_scan;
+
+/*
+ * ext2fs_scan flags
+ */
+#define EXT2_SF_CHK_BADBLOCKS	0x0001
+#define EXT2_SF_BAD_INODE_BLK	0x0002
+#define EXT2_SF_BAD_EXTRA_BYTES	0x0004
+#define EXT2_SF_SKIP_MISSING_ITABLE	0x0008
+
+/*
+ * ext2fs_check_if_mounted flags
+ */
+#define EXT2_MF_MOUNTED		1
+#define EXT2_MF_ISROOT		2
+#define EXT2_MF_READONLY	4
+#define EXT2_MF_SWAP		8
+#define EXT2_MF_BUSY		16
+
+/*
+ * Ext2/linux mode flags.  We define them here so that we don't need
+ * to depend on the OS's sys/stat.h, since we may be compiling on a
+ * non-Linux system.
+ */
+#define LINUX_S_IFMT  00170000
+#define LINUX_S_IFSOCK 0140000
+#define LINUX_S_IFLNK	 0120000
+#define LINUX_S_IFREG  0100000
+#define LINUX_S_IFBLK  0060000
+#define LINUX_S_IFDIR  0040000
+#define LINUX_S_IFCHR  0020000
+#define LINUX_S_IFIFO  0010000
+#define LINUX_S_ISUID  0004000
+#define LINUX_S_ISGID  0002000
+#define LINUX_S_ISVTX  0001000
+
+#define LINUX_S_IRWXU 00700
+#define LINUX_S_IRUSR 00400
+#define LINUX_S_IWUSR 00200
+#define LINUX_S_IXUSR 00100
+
+#define LINUX_S_IRWXG 00070
+#define LINUX_S_IRGRP 00040
+#define LINUX_S_IWGRP 00020
+#define LINUX_S_IXGRP 00010
+
+#define LINUX_S_IRWXO 00007
+#define LINUX_S_IROTH 00004
+#define LINUX_S_IWOTH 00002
+#define LINUX_S_IXOTH 00001
+
+#define LINUX_S_ISLNK(m)	(((m) & LINUX_S_IFMT) == LINUX_S_IFLNK)
+#define LINUX_S_ISREG(m)	(((m) & LINUX_S_IFMT) == LINUX_S_IFREG)
+#define LINUX_S_ISDIR(m)	(((m) & LINUX_S_IFMT) == LINUX_S_IFDIR)
+#define LINUX_S_ISCHR(m)	(((m) & LINUX_S_IFMT) == LINUX_S_IFCHR)
+#define LINUX_S_ISBLK(m)	(((m) & LINUX_S_IFMT) == LINUX_S_IFBLK)
+#define LINUX_S_ISFIFO(m)	(((m) & LINUX_S_IFMT) == LINUX_S_IFIFO)
+#define LINUX_S_ISSOCK(m)	(((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK)
+
+/*
+ * ext2 size of an inode
+ */
+#define EXT2_I_SIZE(i)	((i)->i_size | ((__u64) (i)->i_size_high << 32))
+
+/*
+ * ext2_icount_t abstraction
+ */
+#define EXT2_ICOUNT_OPT_INCREMENT	0x01
+
+typedef struct ext2_icount *ext2_icount_t;
+
+/*
+ * Flags for ext2fs_bmap
+ */
+#define BMAP_ALLOC	0x0001
+#define BMAP_SET	0x0002
+
+/*
+ * Flags for imager.c functions
+ */
+#define IMAGER_FLAG_INODEMAP	1
+#define IMAGER_FLAG_SPARSEWRITE	2
+
+/*
+ * For checking structure magic numbers...
+ */
+
+#define EXT2_CHECK_MAGIC(struct, code) \
+	  if ((struct)->magic != (code)) return (code)
+
+
+/*
+ * For ext2 compression support
+ */
+#define EXT2FS_COMPRESSED_BLKADDR ((blk_t) 0xffffffff)
+#define HOLE_BLKADDR(_b) ((_b) == 0 || (_b) == EXT2FS_COMPRESSED_BLKADDR)
+
+/*
+ * Features supported by this version of the library
+ */
+#define EXT2_LIB_FEATURE_COMPAT_SUPP	(EXT2_FEATURE_COMPAT_DIR_PREALLOC|\
+					 EXT2_FEATURE_COMPAT_IMAGIC_INODES|\
+					 EXT3_FEATURE_COMPAT_HAS_JOURNAL|\
+					 EXT2_FEATURE_COMPAT_RESIZE_INODE|\
+					 EXT2_FEATURE_COMPAT_DIR_INDEX|\
+					 EXT2_FEATURE_COMPAT_EXT_ATTR)
+
+/* This #ifdef is temporary until compression is fully supported */
+#ifdef ENABLE_COMPRESSION
+#ifndef I_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL
+/* If the below warning bugs you, then have
+   `CPPFLAGS=-DI_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL' in your
+   environment at configure time. */
+ #warning "Compression support is experimental"
+#endif
+#define EXT2_LIB_FEATURE_INCOMPAT_SUPP	(EXT2_FEATURE_INCOMPAT_FILETYPE|\
+					 EXT2_FEATURE_INCOMPAT_COMPRESSION|\
+					 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
+					 EXT2_FEATURE_INCOMPAT_META_BG|\
+					 EXT3_FEATURE_INCOMPAT_RECOVER)
+#else
+#define EXT2_LIB_FEATURE_INCOMPAT_SUPP	(EXT2_FEATURE_INCOMPAT_FILETYPE|\
+					 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
+					 EXT2_FEATURE_INCOMPAT_META_BG|\
+					 EXT3_FEATURE_INCOMPAT_RECOVER)
+#endif
+#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP	(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
+					 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
+/*
+ * function prototypes
+ */
+
+/* alloc.c */
+extern errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode,
+				  ext2fs_inode_bitmap map, ext2_ino_t *ret);
+extern errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
+				  ext2fs_block_bitmap map, blk_t *ret);
+extern errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start,
+					blk_t finish, int num,
+					ext2fs_block_bitmap map,
+					blk_t *ret);
+extern errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
+				    char *block_buf, blk_t *ret);
+
+/* alloc_sb.c */
+extern int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
+					dgrp_t group,
+					ext2fs_block_bitmap bmap);
+
+/* alloc_stats.c */
+void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse);
+void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
+			       int inuse, int isdir);
+void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse);
+
+/* alloc_tables.c */
+extern errcode_t ext2fs_allocate_tables(ext2_filsys fs);
+extern errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
+					     ext2fs_block_bitmap bmap);
+
+/* badblocks.c */
+extern errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size);
+extern errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk);
+extern int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk);
+extern int ext2fs_u32_list_test(ext2_u32_list bb, blk_t blk);
+extern errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
+					       ext2_u32_iterate *ret);
+extern int ext2fs_u32_list_iterate(ext2_u32_iterate iter, blk_t *blk);
+extern void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter);
+extern errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest);
+extern int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2);
+
+extern errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret,
+					    int size);
+extern errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb,
+					   blk_t blk);
+extern int ext2fs_badblocks_list_test(ext2_badblocks_list bb,
+				    blk_t blk);
+extern int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk);
+extern void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk);
+extern errcode_t
+	ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
+					    ext2_badblocks_iterate *ret);
+extern int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter,
+					 blk_t *blk);
+extern void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter);
+extern errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
+				       ext2_badblocks_list *dest);
+extern int ext2fs_badblocks_equal(ext2_badblocks_list bb1,
+				  ext2_badblocks_list bb2);
+extern int ext2fs_u32_list_count(ext2_u32_list bb);
+
+/* bb_compat */
+extern errcode_t badblocks_list_create(badblocks_list *ret, int size);
+extern errcode_t badblocks_list_add(badblocks_list bb, blk_t blk);
+extern int badblocks_list_test(badblocks_list bb, blk_t blk);
+extern errcode_t badblocks_list_iterate_begin(badblocks_list bb,
+					      badblocks_iterate *ret);
+extern int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk);
+extern void badblocks_list_iterate_end(badblocks_iterate iter);
+extern void badblocks_list_free(badblocks_list bb);
+
+/* bb_inode.c */
+extern errcode_t ext2fs_update_bb_inode(ext2_filsys fs,
+					ext2_badblocks_list bb_list);
+
+/* bitmaps.c */
+extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs);
+extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs);
+extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs);
+extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs);
+extern errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
+						__u32 end,
+						__u32 real_end,
+						const char *descr,
+						ext2fs_generic_bitmap *ret);
+extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
+					      const char *descr,
+					      ext2fs_block_bitmap *ret);
+extern errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
+					      const char *descr,
+					      ext2fs_inode_bitmap *ret);
+extern errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
+					       ext2_ino_t end, ext2_ino_t *oend);
+extern errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
+					       blk_t end, blk_t *oend);
+extern void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap);
+extern void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap);
+extern errcode_t ext2fs_read_bitmaps(ext2_filsys fs);
+extern errcode_t ext2fs_write_bitmaps(ext2_filsys fs);
+
+/* block.c */
+extern errcode_t ext2fs_block_iterate(ext2_filsys fs,
+				      ext2_ino_t	ino,
+				      int	flags,
+				      char *block_buf,
+				      int (*func)(ext2_filsys fs,
+						  blk_t	*blocknr,
+						  int	blockcnt,
+						  void	*priv_data),
+				      void *priv_data);
+errcode_t ext2fs_block_iterate2(ext2_filsys fs,
+				ext2_ino_t	ino,
+				int	flags,
+				char *block_buf,
+				int (*func)(ext2_filsys fs,
+					    blk_t	*blocknr,
+					    e2_blkcnt_t	blockcnt,
+					    blk_t	ref_blk,
+					    int		ref_offset,
+					    void	*priv_data),
+				void *priv_data);
+
+/* bmap.c */
+extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
+			     struct ext2_inode *inode,
+			     char *block_buf, int bmap_flags,
+			     blk_t block, blk_t *phys_blk);
+
+
+#if 0
+/* bmove.c */
+extern errcode_t ext2fs_move_blocks(ext2_filsys fs,
+				    ext2fs_block_bitmap reserve,
+				    ext2fs_block_bitmap alloc_map,
+				    int flags);
+#endif
+
+/* check_desc.c */
+extern errcode_t ext2fs_check_desc(ext2_filsys fs);
+
+/* closefs.c */
+extern errcode_t ext2fs_close(ext2_filsys fs);
+extern errcode_t ext2fs_flush(ext2_filsys fs);
+extern int ext2fs_bg_has_super(ext2_filsys fs, int group_block);
+extern int ext2fs_super_and_bgd_loc(ext2_filsys fs,
+				    dgrp_t group,
+				    blk_t *ret_super_blk,
+				    blk_t *ret_old_desc_blk,
+				    blk_t *ret_new_desc_blk,
+				    int *ret_meta_bg);
+extern void ext2fs_update_dynamic_rev(ext2_filsys fs);
+
+/* cmp_bitmaps.c */
+extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
+					     ext2fs_block_bitmap bm2);
+extern errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
+					     ext2fs_inode_bitmap bm2);
+
+/* dblist.c */
+
+extern errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs);
+extern errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist);
+extern errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino,
+				      blk_t blk, int blockcnt);
+extern void ext2fs_dblist_sort(ext2_dblist dblist,
+			       int (*sortfunc)(const void *,
+							   const void *));
+extern errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
+	int (*func)(ext2_filsys fs, struct ext2_db_entry *db_info,
+		    void	*priv_data),
+       void *priv_data);
+extern errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino,
+				      blk_t blk, int blockcnt);
+extern errcode_t ext2fs_copy_dblist(ext2_dblist src,
+				    ext2_dblist *dest);
+extern int ext2fs_dblist_count(ext2_dblist dblist);
+
+/* dblist_dir.c */
+extern errcode_t
+	ext2fs_dblist_dir_iterate(ext2_dblist dblist,
+				  int	flags,
+				  char	*block_buf,
+				  int (*func)(ext2_ino_t	dir,
+					      int		entry,
+					      struct ext2_dir_entry *dirent,
+					      int	offset,
+					      int	blocksize,
+					      char	*buf,
+					      void	*priv_data),
+				  void *priv_data);
+
+/* dirblock.c */
+extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
+				       void *buf);
+extern errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
+					void *buf, int flags);
+extern errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
+					void *buf);
+extern errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
+					 void *buf, int flags);
+
+/* dirhash.c */
+extern errcode_t ext2fs_dirhash(int version, const char *name, int len,
+				const __u32 *seed,
+				ext2_dirhash_t *ret_hash,
+				ext2_dirhash_t *ret_minor_hash);
+
+
+/* dir_iterate.c */
+extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
+			      ext2_ino_t dir,
+			      int flags,
+			      char *block_buf,
+			      int (*func)(struct ext2_dir_entry *dirent,
+					  int	offset,
+					  int	blocksize,
+					  char	*buf,
+					  void	*priv_data),
+			      void *priv_data);
+extern errcode_t ext2fs_dir_iterate2(ext2_filsys fs,
+			      ext2_ino_t dir,
+			      int flags,
+			      char *block_buf,
+			      int (*func)(ext2_ino_t	dir,
+					  int	entry,
+					  struct ext2_dir_entry *dirent,
+					  int	offset,
+					  int	blocksize,
+					  char	*buf,
+					  void	*priv_data),
+			      void *priv_data);
+
+/* dupfs.c */
+extern errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest);
+
+/* expanddir.c */
+extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir);
+
+/* ext_attr.c */
+extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf);
+extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block,
+				       void *buf);
+extern errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
+					   char *block_buf,
+					   int adjust, __u32 *newcount);
+
+/* fileio.c */
+extern errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
+				   struct ext2_inode *inode,
+				   int flags, ext2_file_t *ret);
+extern errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
+				  int flags, ext2_file_t *ret);
+extern ext2_filsys ext2fs_file_get_fs(ext2_file_t file);
+extern errcode_t ext2fs_file_close(ext2_file_t file);
+extern errcode_t ext2fs_file_flush(ext2_file_t file);
+extern errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
+				  unsigned int wanted, unsigned int *got);
+extern errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
+				   unsigned int nbytes, unsigned int *written);
+extern errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
+				   int whence, __u64 *ret_pos);
+extern errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
+				   int whence, ext2_off_t *ret_pos);
+errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size);
+extern ext2_off_t ext2fs_file_get_size(ext2_file_t file);
+extern errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size);
+
+/* finddev.c */
+extern char *ext2fs_find_block_device(dev_t device);
+
+/* flushb.c */
+extern errcode_t ext2fs_sync_device(int fd, int flushb);
+
+/* freefs.c */
+extern void ext2fs_free(ext2_filsys fs);
+extern void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap);
+extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap);
+extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap);
+extern void ext2fs_free_dblist(ext2_dblist dblist);
+extern void ext2fs_badblocks_list_free(ext2_badblocks_list bb);
+extern void ext2fs_u32_list_free(ext2_u32_list bb);
+
+/* getsize.c */
+extern errcode_t ext2fs_get_device_size(const char *file, int blocksize,
+					blk_t *retblocks);
+
+/* getsectsize.c */
+errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize);
+
+/* imager.c */
+extern errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags);
+extern errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, int flags);
+extern errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, int flags);
+extern errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, int flags);
+extern errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags);
+extern errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags);
+
+/* ind_block.c */
+errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf);
+errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf);
+
+/* initialize.c */
+extern errcode_t ext2fs_initialize(const char *name, int flags,
+				   struct ext2_super_block *param,
+				   io_manager manager, ext2_filsys *ret_fs);
+
+/* icount.c */
+extern void ext2fs_free_icount(ext2_icount_t icount);
+extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags,
+				       unsigned int size,
+				       ext2_icount_t hint, ext2_icount_t *ret);
+extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags,
+				      unsigned int size,
+				      ext2_icount_t *ret);
+extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino,
+				     __u16 *ret);
+extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
+					 __u16 *ret);
+extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
+					 __u16 *ret);
+extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
+				     __u16 count);
+extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount);
+errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *);
+
+/* inode.c */
+extern errcode_t ext2fs_flush_icache(ext2_filsys fs);
+extern errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan,
+					    ext2_ino_t *ino,
+					    struct ext2_inode *inode,
+					    int bufsize);
+extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
+				  ext2_inode_scan *ret_scan);
+extern void ext2fs_close_inode_scan(ext2_inode_scan scan);
+extern errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
+			       struct ext2_inode *inode);
+extern errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
+						   int	group);
+extern void ext2fs_set_inode_callback
+	(ext2_inode_scan scan,
+	 errcode_t (*done_group)(ext2_filsys fs,
+				 dgrp_t group,
+				 void * priv_data),
+	 void *done_group_data);
+extern int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
+				   int clear_flags);
+extern errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
+					struct ext2_inode * inode,
+					int bufsize);
+extern errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino,
+			    struct ext2_inode * inode);
+extern errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
+					 struct ext2_inode * inode,
+					 int bufsize);
+extern errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
+			    struct ext2_inode * inode);
+extern errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
+			    struct ext2_inode * inode);
+extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
+extern errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino);
+
+/* inode_io.c */
+extern io_manager inode_io_manager;
+extern errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
+					char **name);
+extern errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
+					 struct ext2_inode *inode,
+					 char **name);
+
+/* ismounted.c */
+extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags);
+extern errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
+					  char *mtpt, int mtlen);
+
+/* namei.c */
+extern errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name,
+			 int namelen, char *buf, ext2_ino_t *inode);
+extern errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
+			const char *name, ext2_ino_t *inode);
+errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
+			      const char *name, ext2_ino_t *inode);
+extern errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
+			ext2_ino_t inode, ext2_ino_t *res_inode);
+
+/* native.c */
+int ext2fs_native_flag(void);
+
+/* newdir.c */
+extern errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
+				ext2_ino_t parent_ino, char **block);
+
+/* mkdir.c */
+extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
+			      const char *name);
+
+/* mkjournal.c */
+extern errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
+						  __u32 size, int flags,
+						  char  **ret_jsb);
+extern errcode_t ext2fs_add_journal_device(ext2_filsys fs,
+					   ext2_filsys journal_dev);
+extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size,
+					  int flags);
+
+/* openfs.c */
+extern errcode_t ext2fs_open(const char *name, int flags, int superblock,
+			     unsigned int block_size, io_manager manager,
+			     ext2_filsys *ret_fs);
+extern errcode_t ext2fs_open2(const char *name, const char *io_options,
+			      int flags, int superblock,
+			      unsigned int block_size, io_manager manager,
+			      ext2_filsys *ret_fs);
+extern blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block,
+					 dgrp_t i);
+errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io);
+errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io);
+errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io);
+
+/* get_pathname.c */
+extern errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino,
+			       char **name);
+
+/* link.c */
+errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
+		      ext2_ino_t ino, int flags);
+errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, const char *name,
+			ext2_ino_t ino, int flags);
+
+/* read_bb.c */
+extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs,
+				      ext2_badblocks_list *bb_list);
+
+/* read_bb_file.c */
+extern errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f,
+				      ext2_badblocks_list *bb_list,
+				      void *priv_data,
+				      void (*invalid)(ext2_filsys fs,
+						      blk_t blk,
+						      char *badstr,
+						      void *priv_data));
+extern errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
+				     ext2_badblocks_list *bb_list,
+				     void (*invalid)(ext2_filsys fs,
+						     blk_t blk));
+
+/* res_gdt.c */
+extern errcode_t ext2fs_create_resize_inode(ext2_filsys fs);
+
+/* rs_bitmap.c */
+extern errcode_t ext2fs_resize_generic_bitmap(__u32 new_end,
+					      __u32 new_real_end,
+					      ext2fs_generic_bitmap bmap);
+extern errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
+					    ext2fs_inode_bitmap bmap);
+extern errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
+					    ext2fs_block_bitmap bmap);
+extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
+				    ext2fs_generic_bitmap *dest);
+
+/* swapfs.c */
+extern void ext2fs_swap_ext_attr(char *to, char *from, int bufsize,
+				 int has_header);
+extern void ext2fs_swap_super(struct ext2_super_block * super);
+extern void ext2fs_swap_group_desc(struct ext2_group_desc *gdp);
+extern void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
+				   struct ext2_inode_large *f, int hostorder,
+				   int bufsize);
+extern void ext2fs_swap_inode(ext2_filsys fs,struct ext2_inode *t,
+			      struct ext2_inode *f, int hostorder);
+
+/* valid_blk.c */
+extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode);
+
+/* version.c */
+extern int ext2fs_parse_version_string(const char *ver_string);
+extern int ext2fs_get_library_version(const char **ver_string,
+				      const char **date_string);
+
+/* write_bb_file.c */
+extern errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
+				      unsigned int flags,
+				      FILE *f);
+
+
+/* inline functions */
+extern errcode_t ext2fs_get_mem(unsigned long size, void *ptr);
+extern errcode_t ext2fs_free_mem(void *ptr);
+extern errcode_t ext2fs_resize_mem(unsigned long old_size,
+				   unsigned long size, void *ptr);
+extern void ext2fs_mark_super_dirty(ext2_filsys fs);
+extern void ext2fs_mark_changed(ext2_filsys fs);
+extern int ext2fs_test_changed(ext2_filsys fs);
+extern void ext2fs_mark_valid(ext2_filsys fs);
+extern void ext2fs_unmark_valid(ext2_filsys fs);
+extern int ext2fs_test_valid(ext2_filsys fs);
+extern void ext2fs_mark_ib_dirty(ext2_filsys fs);
+extern void ext2fs_mark_bb_dirty(ext2_filsys fs);
+extern int ext2fs_test_ib_dirty(ext2_filsys fs);
+extern int ext2fs_test_bb_dirty(ext2_filsys fs);
+extern int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk);
+extern int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino);
+extern blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
+				      struct ext2_inode *inode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _EXT2FS_EXT2FS_H */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2fsP.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2fsP.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2fsP.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,88 @@
+/*
+ * ext2fsP.h --- private header file for ext2 library
+ *
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include "ext2fs.h"
+
+/*
+ * Badblocks list
+ */
+struct ext2_struct_u32_list {
+	int	magic;
+	int	num;
+	int	size;
+	__u32	*list;
+	int	badblocks_flags;
+};
+
+struct ext2_struct_u32_iterate {
+	int			magic;
+	ext2_u32_list		bb;
+	int			ptr;
+};
+
+
+/*
+ * Directory block iterator definition
+ */
+struct ext2_struct_dblist {
+	int			magic;
+	ext2_filsys		fs;
+	ext2_ino_t		size;
+	ext2_ino_t		count;
+	int			sorted;
+	struct ext2_db_entry *	list;
+};
+
+/*
+ * For directory iterators
+ */
+struct dir_context {
+	ext2_ino_t		dir;
+	int		flags;
+	char		*buf;
+	int (*func)(ext2_ino_t	dir,
+		    int	entry,
+		    struct ext2_dir_entry *dirent,
+		    int	offset,
+		    int	blocksize,
+		    char	*buf,
+		    void	*priv_data);
+	void		*priv_data;
+	errcode_t	errcode;
+};
+
+/*
+ * Inode cache structure
+ */
+struct ext2_inode_cache {
+	void *				buffer;
+	blk_t				buffer_blk;
+	int				cache_last;
+	int				cache_size;
+	int				refcount;
+	struct ext2_inode_cache_ent	*cache;
+};
+
+struct ext2_inode_cache_ent {
+	ext2_ino_t		ino;
+	struct ext2_inode	inode;
+};
+
+/* Function prototypes */
+
+extern int ext2fs_process_dir_block(ext2_filsys		fs,
+				    blk_t		*blocknr,
+				    e2_blkcnt_t		blockcnt,
+				    blk_t		ref_block,
+				    int			ref_offset,
+				    void		*priv_data);
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs_inline.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs_inline.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext2fs_inline.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,366 @@
+/*
+ * ext2fs.h --- ext2fs
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include "ext2fs.h"
+#include "bitops.h"
+#include <string.h>
+
+/*
+ *  Allocate memory
+ */
+errcode_t ext2fs_get_mem(unsigned long size, void *ptr)
+{
+	void **pp = (void **)ptr;
+
+	*pp = malloc(size);
+	if (!*pp)
+		return EXT2_ET_NO_MEMORY;
+	return 0;
+}
+
+/*
+ * Free memory
+ */
+errcode_t ext2fs_free_mem(void *ptr)
+{
+	void **pp = (void **)ptr;
+
+	free(*pp);
+	*pp = 0;
+	return 0;
+}
+
+/*
+ *  Resize memory
+ */
+errcode_t ext2fs_resize_mem(unsigned long EXT2FS_ATTR((unused)) old_size,
+				     unsigned long size, void *ptr)
+{
+	void *p;
+
+	/* Use "memcpy" for pointer assignments here to avoid problems
+	 * with C99 strict type aliasing rules. */
+	memcpy(&p, ptr, sizeof (p));
+	p = realloc(p, size);
+	if (!p)
+		return EXT2_ET_NO_MEMORY;
+	memcpy(ptr, &p, sizeof (p));
+	return 0;
+}
+
+/*
+ * Mark a filesystem superblock as dirty
+ */
+void ext2fs_mark_super_dirty(ext2_filsys fs)
+{
+	fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_CHANGED;
+}
+
+/*
+ * Mark a filesystem as changed
+ */
+void ext2fs_mark_changed(ext2_filsys fs)
+{
+	fs->flags |= EXT2_FLAG_CHANGED;
+}
+
+/*
+ * Check to see if a filesystem has changed
+ */
+int ext2fs_test_changed(ext2_filsys fs)
+{
+	return (fs->flags & EXT2_FLAG_CHANGED);
+}
+
+/*
+ * Mark a filesystem as valid
+ */
+void ext2fs_mark_valid(ext2_filsys fs)
+{
+	fs->flags |= EXT2_FLAG_VALID;
+}
+
+/*
+ * Mark a filesystem as NOT valid
+ */
+void ext2fs_unmark_valid(ext2_filsys fs)
+{
+	fs->flags &= ~EXT2_FLAG_VALID;
+}
+
+/*
+ * Check to see if a filesystem is valid
+ */
+int ext2fs_test_valid(ext2_filsys fs)
+{
+	return (fs->flags & EXT2_FLAG_VALID);
+}
+
+/*
+ * Mark the inode bitmap as dirty
+ */
+void ext2fs_mark_ib_dirty(ext2_filsys fs)
+{
+	fs->flags |= EXT2_FLAG_IB_DIRTY | EXT2_FLAG_CHANGED;
+}
+
+/*
+ * Mark the block bitmap as dirty
+ */
+void ext2fs_mark_bb_dirty(ext2_filsys fs)
+{
+	fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_CHANGED;
+}
+
+/*
+ * Check to see if a filesystem's inode bitmap is dirty
+ */
+int ext2fs_test_ib_dirty(ext2_filsys fs)
+{
+	return (fs->flags & EXT2_FLAG_IB_DIRTY);
+}
+
+/*
+ * Check to see if a filesystem's block bitmap is dirty
+ */
+int ext2fs_test_bb_dirty(ext2_filsys fs)
+{
+	return (fs->flags & EXT2_FLAG_BB_DIRTY);
+}
+
+/*
+ * Return the group # of a block
+ */
+int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk)
+{
+	return (blk - fs->super->s_first_data_block) /
+		fs->super->s_blocks_per_group;
+}
+
+/*
+ * Return the group # of an inode number
+ */
+int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino)
+{
+	return (ino - 1) / fs->super->s_inodes_per_group;
+}
+
+blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
+					struct ext2_inode *inode)
+{
+       return inode->i_blocks -
+	      (inode->i_file_acl ? fs->blocksize >> 9 : 0);
+}
+
+
+
+
+
+
+
+
+
+__u16 ext2fs_swab16(__u16 val)
+{
+	return (val >> 8) | (val << 8);
+}
+
+__u32 ext2fs_swab32(__u32 val)
+{
+	return ((val>>24) | ((val>>8)&0xFF00) |
+		((val<<8)&0xFF0000) | (val<<24));
+}
+
+int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
+					blk_t bitno);
+
+int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
+					blk_t bitno)
+{
+	if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
+		ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno);
+		return 0;
+	}
+	return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
+}
+
+int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
+				       blk_t block)
+{
+	return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap)
+				       bitmap,
+					  block);
+}
+
+int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
+					 blk_t block)
+{
+	return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+					    block);
+}
+
+int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
+				       blk_t block)
+{
+	return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+					  block);
+}
+
+int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+				       ext2_ino_t inode)
+{
+	return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+					  inode);
+}
+
+int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+					 ext2_ino_t inode)
+{
+	return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+				     inode);
+}
+
+int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
+				       ext2_ino_t inode)
+{
+	return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+					  inode);
+}
+
+void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
+					    blk_t block)
+{
+	ext2fs_set_bit(block - bitmap->start, bitmap->bitmap);
+}
+
+void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
+					      blk_t block)
+{
+	ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap);
+}
+
+int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
+					    blk_t block)
+{
+	return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap);
+}
+
+void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+					    ext2_ino_t inode)
+{
+	ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap);
+}
+
+void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+					      ext2_ino_t inode)
+{
+	ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap);
+}
+
+int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
+					   ext2_ino_t inode)
+{
+	return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap);
+}
+
+blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
+{
+	return bitmap->start;
+}
+
+ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
+{
+	return bitmap->start;
+}
+
+blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
+{
+	return bitmap->end;
+}
+
+ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
+{
+	return bitmap->end;
+}
+
+int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
+					    blk_t block, int num)
+{
+	int	i;
+
+	if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
+				   block, bitmap->description);
+		return 0;
+	}
+	for (i=0; i < num; i++) {
+		if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
+			return 0;
+	}
+	return 1;
+}
+
+int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
+						 blk_t block, int num)
+{
+	int	i;
+
+	for (i=0; i < num; i++) {
+		if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
+			return 0;
+	}
+	return 1;
+}
+
+void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+					     blk_t block, int num)
+{
+	int	i;
+
+	if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
+				   bitmap->description);
+		return;
+	}
+	for (i=0; i < num; i++)
+		ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
+}
+
+void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+						  blk_t block, int num)
+{
+	int	i;
+
+	for (i=0; i < num; i++)
+		ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
+}
+
+void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+					       blk_t block, int num)
+{
+	int	i;
+
+	if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
+				   bitmap->description);
+		return;
+	}
+	for (i=0; i < num; i++)
+		ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
+}
+
+void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+						    blk_t block, int num)
+{
+	int	i;
+	for (i=0; i < num; i++)
+		ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext_attr.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext_attr.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ext_attr.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,100 @@
+/*
+ * ext_attr.c --- extended attribute blocks
+ *
+ * Copyright (C) 2001 Andreas Gruenbacher, <a.gruenbacher at computer.org>
+ *
+ * Copyright (C) 2002 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+
+#include "ext2_fs.h"
+#include "ext2_ext_attr.h"
+#include "ext2fs.h"
+
+errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf)
+{
+	errcode_t	retval;
+
+	retval = io_channel_read_blk(fs->io, block, 1, buf);
+	if (retval)
+		return retval;
+#if BB_BIG_ENDIAN
+	if ((fs->flags & (EXT2_FLAG_SWAP_BYTES|
+			  EXT2_FLAG_SWAP_BYTES_READ)) != 0)
+		ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1);
+#endif
+	return 0;
+}
+
+errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf)
+{
+	errcode_t	retval;
+	char		*write_buf;
+	char		*buf = NULL;
+
+	if (BB_BIG_ENDIAN && ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+	    (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))) {
+		retval = ext2fs_get_mem(fs->blocksize, &buf);
+		if (retval)
+			return retval;
+		write_buf = buf;
+		ext2fs_swap_ext_attr(buf, inbuf, fs->blocksize, 1);
+	} else
+		write_buf = (char *) inbuf;
+	retval = io_channel_write_blk(fs->io, block, 1, write_buf);
+	if (buf)
+		ext2fs_free_mem(&buf);
+	if (!retval)
+		ext2fs_mark_changed(fs);
+	return retval;
+}
+
+/*
+ * This function adjusts the reference count of the EA block.
+ */
+errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
+				    char *block_buf, int adjust,
+				    __u32 *newcount)
+{
+	errcode_t	retval;
+	struct ext2_ext_attr_header *header;
+	char	*buf = 0;
+
+	if ((blk >= fs->super->s_blocks_count) ||
+	    (blk < fs->super->s_first_data_block))
+		return EXT2_ET_BAD_EA_BLOCK_NUM;
+
+	if (!block_buf) {
+		retval = ext2fs_get_mem(fs->blocksize, &buf);
+		if (retval)
+			return retval;
+		block_buf = buf;
+	}
+
+	retval = ext2fs_read_ext_attr(fs, blk, block_buf);
+	if (retval)
+		goto errout;
+
+	header = (struct ext2_ext_attr_header *) block_buf;
+	header->h_refcount += adjust;
+	if (newcount)
+		*newcount = header->h_refcount;
+
+	retval = ext2fs_write_ext_attr(fs, blk, block_buf);
+	if (retval)
+		goto errout;
+
+errout:
+	if (buf)
+		ext2fs_free_mem(&buf);
+	return retval;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/fileio.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/fileio.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/fileio.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,376 @@
+/*
+ * fileio.c --- Simple file I/O routines
+ *
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct ext2_file {
+	errcode_t		magic;
+	ext2_filsys		fs;
+	ext2_ino_t		ino;
+	struct ext2_inode	inode;
+	int			flags;
+	__u64			pos;
+	blk_t			blockno;
+	blk_t			physblock;
+	char			*buf;
+};
+
+#define BMAP_BUFFER (file->buf + fs->blocksize)
+
+errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
+			    struct ext2_inode *inode,
+			    int flags, ext2_file_t *ret)
+{
+	ext2_file_t	file;
+	errcode_t	retval;
+
+	/*
+	 * Don't let caller create or open a file for writing if the
+	 * filesystem is read-only.
+	 */
+	if ((flags & (EXT2_FILE_WRITE | EXT2_FILE_CREATE)) &&
+	    !(fs->flags & EXT2_FLAG_RW))
+		return EXT2_ET_RO_FILSYS;
+
+	retval = ext2fs_get_mem(sizeof(struct ext2_file), &file);
+	if (retval)
+		return retval;
+
+	memset(file, 0, sizeof(struct ext2_file));
+	file->magic = EXT2_ET_MAGIC_EXT2_FILE;
+	file->fs = fs;
+	file->ino = ino;
+	file->flags = flags & EXT2_FILE_MASK;
+
+	if (inode) {
+		memcpy(&file->inode, inode, sizeof(struct ext2_inode));
+	} else {
+		retval = ext2fs_read_inode(fs, ino, &file->inode);
+		if (retval)
+			goto fail;
+	}
+
+	retval = ext2fs_get_mem(fs->blocksize * 3, &file->buf);
+	if (retval)
+		goto fail;
+
+	*ret = file;
+	return 0;
+
+fail:
+	ext2fs_free_mem(&file->buf);
+	ext2fs_free_mem(&file);
+	return retval;
+}
+
+errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
+			   int flags, ext2_file_t *ret)
+{
+	return ext2fs_file_open2(fs, ino, NULL, flags, ret);
+}
+
+/*
+ * This function returns the filesystem handle of a file from the structure
+ */
+ext2_filsys ext2fs_file_get_fs(ext2_file_t file)
+{
+	if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
+		return 0;
+	return file->fs;
+}
+
+/*
+ * This function flushes the dirty block buffer out to disk if
+ * necessary.
+ */
+errcode_t ext2fs_file_flush(ext2_file_t file)
+{
+	errcode_t	retval;
+	ext2_filsys fs;
+
+	EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
+	fs = file->fs;
+
+	if (!(file->flags & EXT2_FILE_BUF_VALID) ||
+	    !(file->flags & EXT2_FILE_BUF_DIRTY))
+		return 0;
+
+	/*
+	 * OK, the physical block hasn't been allocated yet.
+	 * Allocate it.
+	 */
+	if (!file->physblock) {
+		retval = ext2fs_bmap(fs, file->ino, &file->inode,
+				     BMAP_BUFFER, file->ino ? BMAP_ALLOC : 0,
+				     file->blockno, &file->physblock);
+		if (retval)
+			return retval;
+	}
+
+	retval = io_channel_write_blk(fs->io, file->physblock,
+				      1, file->buf);
+	if (retval)
+		return retval;
+
+	file->flags &= ~EXT2_FILE_BUF_DIRTY;
+
+	return retval;
+}
+
+/*
+ * This function synchronizes the file's block buffer and the current
+ * file position, possibly invalidating block buffer if necessary
+ */
+static errcode_t sync_buffer_position(ext2_file_t file)
+{
+	blk_t	b;
+	errcode_t	retval;
+
+	b = file->pos / file->fs->blocksize;
+	if (b != file->blockno) {
+		retval = ext2fs_file_flush(file);
+		if (retval)
+			return retval;
+		file->flags &= ~EXT2_FILE_BUF_VALID;
+	}
+	file->blockno = b;
+	return 0;
+}
+
+/*
+ * This function loads the file's block buffer with valid data from
+ * the disk as necessary.
+ *
+ * If dontfill is true, then skip initializing the buffer since we're
+ * going to be replacing its entire contents anyway.  If set, then the
+ * function basically only sets file->physblock and EXT2_FILE_BUF_VALID
+ */
+#define DONTFILL 1
+static errcode_t load_buffer(ext2_file_t file, int dontfill)
+{
+	ext2_filsys	fs = file->fs;
+	errcode_t	retval;
+
+	if (!(file->flags & EXT2_FILE_BUF_VALID)) {
+		retval = ext2fs_bmap(fs, file->ino, &file->inode,
+				     BMAP_BUFFER, 0, file->blockno,
+				     &file->physblock);
+		if (retval)
+			return retval;
+		if (!dontfill) {
+			if (file->physblock) {
+				retval = io_channel_read_blk(fs->io,
+							     file->physblock,
+							     1, file->buf);
+				if (retval)
+					return retval;
+			} else
+				memset(file->buf, 0, fs->blocksize);
+		}
+		file->flags |= EXT2_FILE_BUF_VALID;
+	}
+	return 0;
+}
+
+
+errcode_t ext2fs_file_close(ext2_file_t file)
+{
+	errcode_t	retval;
+
+	EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
+
+	retval = ext2fs_file_flush(file);
+
+	ext2fs_free_mem(&file->buf);
+	ext2fs_free_mem(&file);
+
+	return retval;
+}
+
+
+errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
+			   unsigned int wanted, unsigned int *got)
+{
+	ext2_filsys	fs;
+	errcode_t	retval = 0;
+	unsigned int	start, c, count = 0;
+	__u64		left;
+	char		*ptr = (char *) buf;
+
+	EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
+	fs = file->fs;
+
+	while ((file->pos < EXT2_I_SIZE(&file->inode)) && (wanted > 0)) {
+		retval = sync_buffer_position(file);
+		if (retval)
+			goto fail;
+		retval = load_buffer(file, 0);
+		if (retval)
+			goto fail;
+
+		start = file->pos % fs->blocksize;
+		c = fs->blocksize - start;
+		if (c > wanted)
+			c = wanted;
+		left = EXT2_I_SIZE(&file->inode) - file->pos ;
+		if (c > left)
+			c = left;
+
+		memcpy(ptr, file->buf+start, c);
+		file->pos += c;
+		ptr += c;
+		count += c;
+		wanted -= c;
+	}
+
+fail:
+	if (got)
+		*got = count;
+	return retval;
+}
+
+
+errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
+			    unsigned int nbytes, unsigned int *written)
+{
+	ext2_filsys	fs;
+	errcode_t	retval = 0;
+	unsigned int	start, c, count = 0;
+	const char	*ptr = (const char *) buf;
+
+	EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
+	fs = file->fs;
+
+	if (!(file->flags & EXT2_FILE_WRITE))
+		return EXT2_ET_FILE_RO;
+
+	while (nbytes > 0) {
+		retval = sync_buffer_position(file);
+		if (retval)
+			goto fail;
+
+		start = file->pos % fs->blocksize;
+		c = fs->blocksize - start;
+		if (c > nbytes)
+			c = nbytes;
+
+		/*
+		 * We only need to do a read-modify-update cycle if
+		 * we're doing a partial write.
+		 */
+		retval = load_buffer(file, (c == fs->blocksize));
+		if (retval)
+			goto fail;
+
+		file->flags |= EXT2_FILE_BUF_DIRTY;
+		memcpy(file->buf+start, ptr, c);
+		file->pos += c;
+		ptr += c;
+		count += c;
+		nbytes -= c;
+	}
+
+fail:
+	if (written)
+		*written = count;
+	return retval;
+}
+
+errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
+			    int whence, __u64 *ret_pos)
+{
+	EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
+
+	if (whence == EXT2_SEEK_SET)
+		file->pos = offset;
+	else if (whence == EXT2_SEEK_CUR)
+		file->pos += offset;
+	else if (whence == EXT2_SEEK_END)
+		file->pos = EXT2_I_SIZE(&file->inode) + offset;
+	else
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	if (ret_pos)
+		*ret_pos = file->pos;
+
+	return 0;
+}
+
+errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
+			    int whence, ext2_off_t *ret_pos)
+{
+	__u64		loffset, ret_loffset;
+	errcode_t	retval;
+
+	loffset = offset;
+	retval = ext2fs_file_llseek(file, loffset, whence, &ret_loffset);
+	if (ret_pos)
+		*ret_pos = (ext2_off_t) ret_loffset;
+	return retval;
+}
+
+
+/*
+ * This function returns the size of the file, according to the inode
+ */
+errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size)
+{
+	if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
+		return EXT2_ET_MAGIC_EXT2_FILE;
+	*ret_size = EXT2_I_SIZE(&file->inode);
+	return 0;
+}
+
+/*
+ * This function returns the size of the file, according to the inode
+ */
+ext2_off_t ext2fs_file_get_size(ext2_file_t file)
+{
+	__u64	size;
+
+	if (ext2fs_file_get_lsize(file, &size))
+		return 0;
+	if ((size >> 32) != 0)
+		return 0;
+	return size;
+}
+
+/*
+ * This function sets the size of the file, truncating it if necessary
+ *
+ * XXX still need to call truncate
+ */
+errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size)
+{
+	errcode_t	retval;
+	EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
+
+	file->inode.i_size = size;
+	file->inode.i_size_high = 0;
+	if (file->ino) {
+		retval = ext2fs_write_inode(file->fs, file->ino, &file->inode);
+		if (retval)
+			return retval;
+	}
+
+	/*
+	 * XXX truncate inode if necessary
+	 */
+
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/finddev.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/finddev.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/finddev.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,198 @@
+/*
+ * finddev.c -- this routine attempts to find a particular device in
+ *	/dev
+ *
+ * Copyright (C) 2000 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#include <dirent.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_SYS_MKDEV_H
+#include <sys/mkdev.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct dir_list {
+	char	*name;
+	struct dir_list *next;
+};
+
+/*
+ * This function adds an entry to the directory list
+ */
+static void add_to_dirlist(const char *name, struct dir_list **list)
+{
+	struct dir_list *dp;
+
+	dp = xmalloc(sizeof(struct dir_list));
+	dp->name = xmalloc(strlen(name)+1);
+	strcpy(dp->name, name);
+	dp->next = *list;
+	*list = dp;
+}
+
+/*
+ * This function frees a directory list
+ */
+static void free_dirlist(struct dir_list **list)
+{
+	struct dir_list *dp, *next;
+
+	for (dp = *list; dp; dp = next) {
+		next = dp->next;
+		free(dp->name);
+		free(dp);
+	}
+	*list = 0;
+}
+
+static int scan_dir(char *dir_name, dev_t device, struct dir_list **list,
+		    char **ret_path)
+{
+	DIR	*dir;
+	struct dirent *dp;
+	char	path[1024], *cp;
+	int	dirlen;
+	struct stat st;
+
+	dirlen = strlen(dir_name);
+	if ((dir = opendir(dir_name)) == NULL)
+		return errno;
+	dp = readdir(dir);
+	while (dp) {
+		if (dirlen + strlen(dp->d_name) + 2 >= sizeof(path))
+			goto skip_to_next;
+		if (dp->d_name[0] == '.' &&
+		    ((dp->d_name[1] == 0) ||
+		     ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
+			goto skip_to_next;
+		sprintf(path, "%s/%s", dir_name, dp->d_name);
+		if (stat(path, &st) < 0)
+			goto skip_to_next;
+		if (S_ISDIR(st.st_mode))
+			add_to_dirlist(path, list);
+		if (S_ISBLK(st.st_mode) && st.st_rdev == device) {
+			cp = xmalloc(strlen(path)+1);
+			strcpy(cp, path);
+			*ret_path = cp;
+			goto success;
+		}
+	skip_to_next:
+		dp = readdir(dir);
+	}
+success:
+	closedir(dir);
+	return 0;
+}
+
+/*
+ * This function finds the pathname to a block device with a given
+ * device number.  It returns a pointer to allocated memory to the
+ * pathname on success, and NULL on failure.
+ */
+char *ext2fs_find_block_device(dev_t device)
+{
+	struct dir_list *list = 0, *new_list = 0;
+	struct dir_list *current;
+	char	*ret_path = 0;
+
+	/*
+	 * Add the starting directories to search...
+	 */
+	add_to_dirlist("/devices", &list);
+	add_to_dirlist("/devfs", &list);
+	add_to_dirlist("/dev", &list);
+
+	while (list) {
+		current = list;
+		list = list->next;
+#ifdef DEBUG
+		printf("Scanning directory %s\n", current->name);
+#endif
+		scan_dir(current->name, device, &new_list, &ret_path);
+		free(current->name);
+		free(current);
+		if (ret_path)
+			break;
+		/*
+		 * If we're done checking at this level, descend to
+		 * the next level of subdirectories. (breadth-first)
+		 */
+		if (list == 0) {
+			list = new_list;
+			new_list = 0;
+		}
+	}
+	free_dirlist(&list);
+	free_dirlist(&new_list);
+	return ret_path;
+}
+
+
+#ifdef DEBUG
+int main(int argc, char** argv)
+{
+	char	*devname, *tmp;
+	int	major, minor;
+	dev_t	device;
+	const char *errmsg = "Couldn't parse %s: %s\n";
+
+	if ((argc != 2) && (argc != 3)) {
+		fprintf(stderr, "Usage: %s device_number\n", argv[0]);
+		fprintf(stderr, "\t: %s major minor\n", argv[0]);
+		exit(1);
+	}
+	if (argc == 2) {
+		device = strtoul(argv[1], &tmp, 0);
+		if (*tmp) {
+			fprintf(stderr, errmsg, "device number", argv[1]);
+			exit(1);
+		}
+	} else {
+		major = strtoul(argv[1], &tmp, 0);
+		if (*tmp) {
+			fprintf(stderr, errmsg, "major number", argv[1]);
+			exit(1);
+		}
+		minor = strtoul(argv[2], &tmp, 0);
+		if (*tmp) {
+			fprintf(stderr, errmsg, "minor number", argv[2]);
+			exit(1);
+		}
+		device = makedev(major, minor);
+		printf("Looking for device 0x%04x (%d:%d)\n", device,
+		       major, minor);
+	}
+	devname = ext2fs_find_block_device(device);
+	if (devname) {
+		printf("Found device!  %s\n", devname);
+		free(devname);
+	} else {
+		printf("Couldn't find device.\n");
+	}
+	return 0;
+}
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/flushb.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/flushb.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/flushb.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,82 @@
+/*
+ * flushb.c --- Hides system-dependent information for both syncing a
+ *	device to disk and to flush any buffers from disk cache.
+ *
+ * Copyright (C) 2000 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#if HAVE_SYS_MOUNT_H
+#include <sys/param.h>
+#include <sys/mount.h>		/* This may define BLKFLSBUF */
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * For Linux, define BLKFLSBUF and FDFLUSH if necessary, since
+ * not all portable header file does so for us.  This really should be
+ * fixed in the glibc header files.  (Recent glibcs appear to define
+ * BLKFLSBUF in sys/mount.h, but FDFLUSH still doesn't seem to be
+ * defined anywhere portable.)  Until then....
+ */
+#ifdef __linux__
+#ifndef BLKFLSBUF
+#define BLKFLSBUF	_IO(0x12,97)	/* flush buffer cache */
+#endif
+#ifndef FDFLUSH
+#define FDFLUSH		_IO(2,0x4b)	/* flush floppy disk */
+#endif
+#endif
+
+/*
+ * This function will sync a device/file, and optionally attempt to
+ * flush the buffer cache.  The latter is basically only useful for
+ * system benchmarks and for torturing systems in burn-in tests.  :)
+ */
+errcode_t ext2fs_sync_device(int fd, int flushb)
+{
+	/*
+	 * We always sync the device in case we're running on old
+	 * kernels for which we can lose data if we don't.  (There
+	 * still is a race condition for those kernels, but this
+	 * reduces it greatly.)
+	 */
+	if (fsync (fd) == -1)
+		return errno;
+
+	if (flushb) {
+
+#ifdef BLKFLSBUF
+		if (ioctl (fd, BLKFLSBUF, 0) == 0)
+			return 0;
+#else
+#ifdef __GNUC__
+# warning BLKFLSBUF not defined
+#endif /* __GNUC__ */
+#endif
+#ifdef FDFLUSH
+		ioctl (fd, FDFLUSH, 0);   /* In case this is a floppy */
+#else
+#ifdef __GNUC__
+# warning FDFLUSH not defined
+#endif /* __GNUC__ */
+#endif
+	}
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/freefs.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/freefs.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/freefs.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,127 @@
+/*
+ * freefs.c --- free an ext2 filesystem
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache);
+
+void ext2fs_free(ext2_filsys fs)
+{
+	if (!fs || (fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS))
+		return;
+	if (fs->image_io != fs->io) {
+		if (fs->image_io)
+			io_channel_close(fs->image_io);
+	}
+	if (fs->io) {
+		io_channel_close(fs->io);
+	}
+	ext2fs_free_mem(&fs->device_name);
+	ext2fs_free_mem(&fs->super);
+	ext2fs_free_mem(&fs->orig_super);
+	ext2fs_free_mem(&fs->group_desc);
+	ext2fs_free_block_bitmap(fs->block_map);
+	ext2fs_free_inode_bitmap(fs->inode_map);
+
+	ext2fs_badblocks_list_free(fs->badblocks);
+	fs->badblocks = 0;
+
+	ext2fs_free_dblist(fs->dblist);
+
+	if (fs->icache)
+		ext2fs_free_inode_cache(fs->icache);
+
+	fs->magic = 0;
+
+	ext2fs_free_mem(&fs);
+}
+
+void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap)
+{
+	if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_GENERIC_BITMAP))
+		return;
+
+	bitmap->magic = 0;
+	ext2fs_free_mem(&bitmap->description);
+	ext2fs_free_mem(&bitmap->bitmap);
+	ext2fs_free_mem(&bitmap);
+}
+
+void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap)
+{
+	if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP))
+		return;
+
+	bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
+	ext2fs_free_generic_bitmap(bitmap);
+}
+
+void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap)
+{
+	if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP))
+		return;
+
+	bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
+	ext2fs_free_generic_bitmap(bitmap);
+}
+
+/*
+ * Free the inode cache structure
+ */
+static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache)
+{
+	if (--icache->refcount)
+		return;
+	ext2fs_free_mem(&icache->buffer);
+	ext2fs_free_mem(&icache->cache);
+	icache->buffer_blk = 0;
+	ext2fs_free_mem(&icache);
+}
+
+/*
+ * This procedure frees a badblocks list.
+ */
+void ext2fs_u32_list_free(ext2_u32_list bb)
+{
+	if (!bb || bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
+		return;
+
+	ext2fs_free_mem(&bb->list);
+	ext2fs_free_mem(&bb);
+}
+
+void ext2fs_badblocks_list_free(ext2_badblocks_list bb)
+{
+	ext2fs_u32_list_free((ext2_u32_list) bb);
+}
+
+
+/*
+ * Free a directory block list
+ */
+void ext2fs_free_dblist(ext2_dblist dblist)
+{
+	if (!dblist || (dblist->magic != EXT2_ET_MAGIC_DBLIST))
+		return;
+
+	ext2fs_free_mem(&dblist->list);
+	if (dblist->fs && dblist->fs->dblist == dblist)
+		dblist->fs->dblist = 0;
+	dblist->magic = 0;
+	ext2fs_free_mem(&dblist);
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/gen_bitmap.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/gen_bitmap.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/gen_bitmap.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,48 @@
+/*
+ * gen_bitmap.c --- Generic bitmap routines that used to be inlined.
+ *
+ * Copyright (C) 2001 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
+					 __u32 bitno)
+{
+	if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
+		ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno);
+		return 0;
+	}
+	return ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap);
+}
+
+int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
+					   blk_t bitno)
+{
+	if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
+		ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
+		return 0;
+	}
+	return ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/get_pathname.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/get_pathname.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/get_pathname.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,156 @@
+/*
+ * get_pathname.c --- do directry/inode -> name translation
+ *
+ * Copyright (C) 1993, 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ *
+ *	ext2fs_get_pathname(fs, dir, ino, name)
+ *
+ *	This function translates takes two inode numbers into a
+ *	string, placing the result in <name>.  <dir> is the containing
+ *	directory inode, and <ino> is the inode number itself.  If
+ *	<ino> is zero, then ext2fs_get_pathname will return pathname
+ *	of the the directory <dir>.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct get_pathname_struct {
+	ext2_ino_t	search_ino;
+	ext2_ino_t	parent;
+	char		*name;
+	errcode_t	errcode;
+};
+
+#ifdef __TURBOC__
+# pragma argsused
+#endif
+static int get_pathname_proc(struct ext2_dir_entry *dirent,
+			     int	offset EXT2FS_ATTR((unused)),
+			     int	blocksize EXT2FS_ATTR((unused)),
+			     char	*buf EXT2FS_ATTR((unused)),
+			     void	*priv_data)
+{
+	struct get_pathname_struct	*gp;
+	errcode_t			retval;
+
+	gp = (struct get_pathname_struct *) priv_data;
+
+	if (((dirent->name_len & 0xFF) == 2) &&
+	    !strncmp(dirent->name, "..", 2))
+		gp->parent = dirent->inode;
+	if (dirent->inode == gp->search_ino) {
+		retval = ext2fs_get_mem((dirent->name_len & 0xFF) + 1,
+					&gp->name);
+		if (retval) {
+			gp->errcode = retval;
+			return DIRENT_ABORT;
+		}
+		strncpy(gp->name, dirent->name, (dirent->name_len & 0xFF));
+		gp->name[dirent->name_len & 0xFF] = '\0';
+		return DIRENT_ABORT;
+	}
+	return 0;
+}
+
+static errcode_t ext2fs_get_pathname_int(ext2_filsys fs, ext2_ino_t dir,
+					 ext2_ino_t ino, int maxdepth,
+					 char *buf, char **name)
+{
+	struct get_pathname_struct gp;
+	char	*parent_name, *ret;
+	errcode_t	retval;
+
+	if (dir == ino) {
+		retval = ext2fs_get_mem(2, name);
+		if (retval)
+			return retval;
+		strcpy(*name, (dir == EXT2_ROOT_INO) ? "/" : ".");
+		return 0;
+	}
+
+	if (!dir || (maxdepth < 0)) {
+		retval = ext2fs_get_mem(4, name);
+		if (retval)
+			return retval;
+		strcpy(*name, "...");
+		return 0;
+	}
+
+	gp.search_ino = ino;
+	gp.parent = 0;
+	gp.name = 0;
+	gp.errcode = 0;
+
+	retval = ext2fs_dir_iterate(fs, dir, 0, buf, get_pathname_proc, &gp);
+	if (retval)
+		goto cleanup;
+	if (gp.errcode) {
+		retval = gp.errcode;
+		goto cleanup;
+	}
+
+	retval = ext2fs_get_pathname_int(fs, gp.parent, dir, maxdepth-1,
+					 buf, &parent_name);
+	if (retval)
+		goto cleanup;
+	if (!ino) {
+		*name = parent_name;
+		return 0;
+	}
+
+	if (gp.name)
+		retval = ext2fs_get_mem(strlen(parent_name)+strlen(gp.name)+2,
+					&ret);
+	else
+		retval = ext2fs_get_mem(strlen(parent_name)+5, &ret);
+	if (retval)
+		goto cleanup;
+
+	ret[0] = 0;
+	if (parent_name[1])
+		strcat(ret, parent_name);
+	strcat(ret, "/");
+	if (gp.name)
+		strcat(ret, gp.name);
+	else
+		strcat(ret, "???");
+	*name = ret;
+	ext2fs_free_mem(&parent_name);
+	retval = 0;
+
+cleanup:
+	ext2fs_free_mem(&gp.name);
+	return retval;
+}
+
+errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino,
+			      char **name)
+{
+	char	*buf;
+	errcode_t	retval;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	retval = ext2fs_get_mem(fs->blocksize, &buf);
+	if (retval)
+		return retval;
+	if (dir == ino)
+		ino = 0;
+	retval = ext2fs_get_pathname_int(fs, dir, ino, 32, buf, name);
+	ext2fs_free_mem(&buf);
+	return retval;
+
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/getsectsize.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/getsectsize.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/getsectsize.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,57 @@
+/*
+ * getsectsize.c --- get the sector size of a device.
+ *
+ * Copyright (C) 1995, 1995 Theodore Ts'o.
+ * Copyright (C) 2003 VMware, Inc.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <fcntl.h>
+#ifdef HAVE_LINUX_FD_H
+#include <sys/ioctl.h>
+#include <linux/fd.h>
+#endif
+
+#if defined(__linux__) && defined(_IO) && !defined(BLKSSZGET)
+#define BLKSSZGET  _IO(0x12,104)/* get block device sector size */
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * Returns the number of blocks in a partition
+ */
+errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize)
+{
+	int	fd;
+
+#ifdef CONFIG_LFS
+	fd = open64(file, O_RDONLY);
+#else
+	fd = open(file, O_RDONLY);
+#endif
+	if (fd < 0)
+		return errno;
+
+#ifdef BLKSSZGET
+	if (ioctl(fd, BLKSSZGET, sectsize) >= 0) {
+		close(fd);
+		return 0;
+	}
+#endif
+	*sectsize = 0;
+	close(fd);
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/getsize.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/getsize.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/getsize.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,290 @@
+/*
+ * getsize.c --- get the size of a partition.
+ *
+ * Copyright (C) 1995, 1995 Theodore Ts'o.
+ * Copyright (C) 2003 VMware, Inc.
+ *
+ * Windows version of ext2fs_get_device_size by Chris Li, VMware.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <fcntl.h>
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_LINUX_FD_H
+#include <linux/fd.h>
+#endif
+#ifdef HAVE_SYS_DISKLABEL_H
+#include <sys/disklabel.h>
+#endif
+#ifdef HAVE_SYS_DISK_H
+#ifdef HAVE_SYS_QUEUE_H
+#include <sys/queue.h> /* for LIST_HEAD */
+#endif
+#include <sys/disk.h>
+#endif
+#ifdef __linux__
+#include <sys/utsname.h>
+#endif
+
+#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
+#define BLKGETSIZE _IO(0x12,96)	/* return device size */
+#endif
+
+#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
+#define BLKGETSIZE64 _IOR(0x12,114,size_t)	/* return device size in bytes (u64 *arg) */
+#endif
+
+#ifdef APPLE_DARWIN
+#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
+#endif /* APPLE_DARWIN */
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#if defined(__CYGWIN__) || defined (WIN32)
+#include <windows.h>
+#include <winioctl.h>
+
+#if (_WIN32_WINNT >= 0x0500)
+#define HAVE_GET_FILE_SIZE_EX 1
+#endif
+
+errcode_t ext2fs_get_device_size(const char *file, int blocksize,
+				 blk_t *retblocks)
+{
+	HANDLE dev;
+	PARTITION_INFORMATION pi;
+	DISK_GEOMETRY gi;
+	DWORD retbytes;
+#ifdef HAVE_GET_FILE_SIZE_EX
+	LARGE_INTEGER filesize;
+#else
+	DWORD filesize;
+#endif /* HAVE_GET_FILE_SIZE_EX */
+
+	dev = CreateFile(file, GENERIC_READ,
+			 FILE_SHARE_READ | FILE_SHARE_WRITE ,
+			 NULL,  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,  NULL);
+
+	if (dev == INVALID_HANDLE_VALUE)
+		return EBADF;
+	if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO,
+			    &pi, sizeof(PARTITION_INFORMATION),
+			    &pi, sizeof(PARTITION_INFORMATION),
+			    &retbytes, NULL)) {
+
+		*retblocks = pi.PartitionLength.QuadPart / blocksize;
+
+	} else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY,
+				&gi, sizeof(DISK_GEOMETRY),
+				&gi, sizeof(DISK_GEOMETRY),
+				&retbytes, NULL)) {
+
+		*retblocks = gi.BytesPerSector *
+			     gi.SectorsPerTrack *
+			     gi.TracksPerCylinder *
+			     gi.Cylinders.QuadPart / blocksize;
+
+#ifdef HAVE_GET_FILE_SIZE_EX
+	} else if (GetFileSizeEx(dev, &filesize)) {
+		*retblocks = filesize.QuadPart / blocksize;
+	}
+#else
+	} else {
+		filesize = GetFileSize(dev, NULL);
+		if (INVALID_FILE_SIZE != filesize) {
+			*retblocks = filesize / blocksize;
+		}
+	}
+#endif /* HAVE_GET_FILE_SIZE_EX */
+
+	CloseHandle(dev);
+	return 0;
+}
+
+#else
+
+static int valid_offset (int fd, ext2_loff_t offset)
+{
+	char ch;
+
+	if (ext2fs_llseek (fd, offset, 0) < 0)
+		return 0;
+	if (read (fd, &ch, 1) < 1)
+		return 0;
+	return 1;
+}
+
+/*
+ * Returns the number of blocks in a partition
+ */
+errcode_t ext2fs_get_device_size(const char *file, int blocksize,
+				 blk_t *retblocks)
+{
+	int	fd;
+	int valid_blkgetsize64 = 1;
+#ifdef __linux__
+	struct		utsname ut;
+#endif
+	unsigned long long size64;
+	unsigned long	size;
+	ext2_loff_t high, low;
+#ifdef FDGETPRM
+	struct floppy_struct this_floppy;
+#endif
+#ifdef HAVE_SYS_DISKLABEL_H
+	int part;
+	struct disklabel lab;
+	struct partition *pp;
+	char ch;
+#endif /* HAVE_SYS_DISKLABEL_H */
+
+#ifdef CONFIG_LFS
+	fd = open64(file, O_RDONLY);
+#else
+	fd = open(file, O_RDONLY);
+#endif
+	if (fd < 0)
+		return errno;
+
+#ifdef DKIOCGETBLOCKCOUNT	/* For Apple Darwin */
+	if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
+		if ((sizeof(*retblocks) < sizeof(unsigned long long))
+		    && ((size64 / (blocksize / 512)) > 0xFFFFFFFF))
+			return EFBIG;
+		close(fd);
+		*retblocks = size64 / (blocksize / 512);
+		return 0;
+	}
+#endif
+
+#ifdef BLKGETSIZE64
+#ifdef __linux__
+	if ((uname(&ut) == 0) &&
+	    ((ut.release[0] == '2') && (ut.release[1] == '.') &&
+	     (ut.release[2] < '6') && (ut.release[3] == '.')))
+		valid_blkgetsize64 = 0;
+#endif
+	if (valid_blkgetsize64 &&
+	    ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
+		if ((sizeof(*retblocks) < sizeof(unsigned long long))
+		    && ((size64 / blocksize) > 0xFFFFFFFF))
+			return EFBIG;
+		close(fd);
+		*retblocks = size64 / blocksize;
+		return 0;
+	}
+#endif
+
+#ifdef BLKGETSIZE
+	if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
+		close(fd);
+		*retblocks = size / (blocksize / 512);
+		return 0;
+	}
+#endif
+
+#ifdef FDGETPRM
+	if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
+		close(fd);
+		*retblocks = this_floppy.size / (blocksize / 512);
+		return 0;
+	}
+#endif
+
+#ifdef HAVE_SYS_DISKLABEL_H
+#if defined(DIOCGMEDIASIZE)
+	{
+	    off_t ms;
+	    u_int bs;
+	    if (ioctl(fd, DIOCGMEDIASIZE, &ms) >= 0) {
+		*retblocks = ms / blocksize;
+		return 0;
+	    }
+	}
+#elif defined(DIOCGDINFO)
+	/* old disklabel interface */
+	part = strlen(file) - 1;
+	if (part >= 0) {
+		ch = file[part];
+		if (isdigit(ch))
+			part = 0;
+		else if (ch >= 'a' && ch <= 'h')
+			part = ch - 'a';
+		else
+			part = -1;
+	}
+	if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
+		pp = &lab.d_partitions[part];
+		if (pp->p_size) {
+			close(fd);
+			*retblocks = pp->p_size / (blocksize / 512);
+			return 0;
+		}
+	}
+#endif /* defined(DIOCG*) */
+#endif /* HAVE_SYS_DISKLABEL_H */
+
+	/*
+	 * OK, we couldn't figure it out by using a specialized ioctl,
+	 * which is generally the best way.  So do binary search to
+	 * find the size of the partition.
+	 */
+	low = 0;
+	for (high = 1024; valid_offset (fd, high); high *= 2)
+		low = high;
+	while (low < high - 1)
+	{
+		const ext2_loff_t mid = (low + high) / 2;
+
+		if (valid_offset (fd, mid))
+			low = mid;
+		else
+			high = mid;
+	}
+	valid_offset (fd, 0);
+	close(fd);
+	size64 = low + 1;
+	if ((sizeof(*retblocks) < sizeof(unsigned long long))
+	    && ((size64 / blocksize) > 0xFFFFFFFF))
+		return EFBIG;
+	*retblocks = size64 / blocksize;
+	return 0;
+}
+
+#endif /* WIN32 */
+
+#ifdef DEBUG
+int main(int argc, char **argv)
+{
+	blk_t	blocks;
+	int	retval;
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s device\n", argv[0]);
+		exit(1);
+	}
+
+	retval = ext2fs_get_device_size(argv[1], 1024, &blocks);
+	if (retval) {
+		com_err(argv[0], retval,
+			"while calling ext2fs_get_device_size");
+		exit(1);
+	}
+	printf("Device %s has %d 1k blocks.\n", argv[1], blocks);
+	exit(0);
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/icount.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/icount.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/icount.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,480 @@
+/*
+ * icount.c --- an efficient inode count abstraction
+ *
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * The data storage strategy used by icount relies on the observation
+ * that most inode counts are either zero (for non-allocated inodes),
+ * one (for most files), and only a few that are two or more
+ * (directories and files that are linked to more than one directory).
+ *
+ * Also, e2fsck tends to load the icount data sequentially.
+ *
+ * So, we use an inode bitmap to indicate which inodes have a count of
+ * one, and then use a sorted list to store the counts for inodes
+ * which are greater than one.
+ *
+ * We also use an optional bitmap to indicate which inodes are already
+ * in the sorted list, to speed up the use of this abstraction by
+ * e2fsck's pass 2.  Pass 2 increments inode counts as it finds them,
+ * so this extra bitmap avoids searching the sorted list to see if a
+ * particular inode is on the sorted list already.
+ */
+
+struct ext2_icount_el {
+	ext2_ino_t	ino;
+	__u16	count;
+};
+
+struct ext2_icount {
+	errcode_t		magic;
+	ext2fs_inode_bitmap	single;
+	ext2fs_inode_bitmap	multiple;
+	ext2_ino_t		count;
+	ext2_ino_t		size;
+	ext2_ino_t		num_inodes;
+	ext2_ino_t		cursor;
+	struct ext2_icount_el	*list;
+};
+
+void ext2fs_free_icount(ext2_icount_t icount)
+{
+	if (!icount)
+		return;
+
+	icount->magic = 0;
+	ext2fs_free_mem(&icount->list);
+	ext2fs_free_inode_bitmap(icount->single);
+	ext2fs_free_inode_bitmap(icount->multiple);
+	ext2fs_free_mem(&icount);
+}
+
+errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, unsigned int size,
+				ext2_icount_t hint, ext2_icount_t *ret)
+{
+	ext2_icount_t	icount;
+	errcode_t	retval;
+	size_t		bytes;
+	ext2_ino_t	i;
+
+	if (hint) {
+		EXT2_CHECK_MAGIC(hint, EXT2_ET_MAGIC_ICOUNT);
+		if (hint->size > size)
+			size = (size_t) hint->size;
+	}
+
+	retval = ext2fs_get_mem(sizeof(struct ext2_icount), &icount);
+	if (retval)
+		return retval;
+	memset(icount, 0, sizeof(struct ext2_icount));
+
+	retval = ext2fs_allocate_inode_bitmap(fs, 0,
+					      &icount->single);
+	if (retval)
+		goto errout;
+
+	if (flags & EXT2_ICOUNT_OPT_INCREMENT) {
+		retval = ext2fs_allocate_inode_bitmap(fs, 0,
+						      &icount->multiple);
+		if (retval)
+			goto errout;
+	} else
+		icount->multiple = 0;
+
+	if (size) {
+		icount->size = size;
+	} else {
+		/*
+		 * Figure out how many special case inode counts we will
+		 * have.  We know we will need one for each directory;
+		 * we also need to reserve some extra room for file links
+		 */
+		retval = ext2fs_get_num_dirs(fs, &icount->size);
+		if (retval)
+			goto errout;
+		icount->size += fs->super->s_inodes_count / 50;
+	}
+
+	bytes = (size_t) (icount->size * sizeof(struct ext2_icount_el));
+#if 0
+	printf("Icount allocated %d entries, %d bytes.\n",
+	       icount->size, bytes);
+#endif
+	retval = ext2fs_get_mem(bytes, &icount->list);
+	if (retval)
+		goto errout;
+	memset(icount->list, 0, bytes);
+
+	icount->magic = EXT2_ET_MAGIC_ICOUNT;
+	icount->count = 0;
+	icount->cursor = 0;
+	icount->num_inodes = fs->super->s_inodes_count;
+
+	/*
+	 * Populate the sorted list with those entries which were
+	 * found in the hint icount (since those are ones which will
+	 * likely need to be in the sorted list this time around).
+	 */
+	if (hint) {
+		for (i=0; i < hint->count; i++)
+			icount->list[i].ino = hint->list[i].ino;
+		icount->count = hint->count;
+	}
+
+	*ret = icount;
+	return 0;
+
+errout:
+	ext2fs_free_icount(icount);
+	return(retval);
+}
+
+errcode_t ext2fs_create_icount(ext2_filsys fs, int flags,
+			       unsigned int size,
+			       ext2_icount_t *ret)
+{
+	return ext2fs_create_icount2(fs, flags, size, 0, ret);
+}
+
+/*
+ * insert_icount_el() --- Insert a new entry into the sorted list at a
+ *	specified position.
+ */
+static struct ext2_icount_el *insert_icount_el(ext2_icount_t icount,
+					    ext2_ino_t ino, int pos)
+{
+	struct ext2_icount_el	*el;
+	errcode_t		retval;
+	ext2_ino_t			new_size = 0;
+	int			num;
+
+	if (icount->count >= icount->size) {
+		if (icount->count) {
+			new_size = icount->list[(unsigned)icount->count-1].ino;
+			new_size = (ext2_ino_t) (icount->count *
+				((float) icount->num_inodes / new_size));
+		}
+		if (new_size < (icount->size + 100))
+			new_size = icount->size + 100;
+#if 0
+		printf("Reallocating icount %d entries...\n", new_size);
+#endif
+		retval = ext2fs_resize_mem((size_t) icount->size *
+					   sizeof(struct ext2_icount_el),
+					   (size_t) new_size *
+					   sizeof(struct ext2_icount_el),
+					   &icount->list);
+		if (retval)
+			return 0;
+		icount->size = new_size;
+	}
+	num = (int) icount->count - pos;
+	if (num < 0)
+		return 0;	/* should never happen */
+	if (num) {
+		memmove(&icount->list[pos+1], &icount->list[pos],
+			sizeof(struct ext2_icount_el) * num);
+	}
+	icount->count++;
+	el = &icount->list[pos];
+	el->count = 0;
+	el->ino = ino;
+	return el;
+}
+
+/*
+ * get_icount_el() --- given an inode number, try to find icount
+ *	information in the sorted list.  If the create flag is set,
+ *	and we can't find an entry, create one in the sorted list.
+ */
+static struct ext2_icount_el *get_icount_el(ext2_icount_t icount,
+					    ext2_ino_t ino, int create)
+{
+	float	range;
+	int	low, high, mid;
+	ext2_ino_t	lowval, highval;
+
+	if (!icount || !icount->list)
+		return 0;
+
+	if (create && ((icount->count == 0) ||
+		       (ino > icount->list[(unsigned)icount->count-1].ino))) {
+		return insert_icount_el(icount, ino, (unsigned) icount->count);
+	}
+	if (icount->count == 0)
+		return 0;
+
+	if (icount->cursor >= icount->count)
+		icount->cursor = 0;
+	if (ino == icount->list[icount->cursor].ino)
+		return &icount->list[icount->cursor++];
+#if 0
+	printf("Non-cursor get_icount_el: %u\n", ino);
+#endif
+	low = 0;
+	high = (int) icount->count-1;
+	while (low <= high) {
+#if 0
+		mid = (low+high)/2;
+#else
+		if (low == high)
+			mid = low;
+		else {
+			/* Interpolate for efficiency */
+			lowval = icount->list[low].ino;
+			highval = icount->list[high].ino;
+
+			if (ino < lowval)
+				range = 0;
+			else if (ino > highval)
+				range = 1;
+			else
+				range = ((float) (ino - lowval)) /
+					(highval - lowval);
+			mid = low + ((int) (range * (high-low)));
+		}
+#endif
+		if (ino == icount->list[mid].ino) {
+			icount->cursor = mid+1;
+			return &icount->list[mid];
+		}
+		if (ino < icount->list[mid].ino)
+			high = mid-1;
+		else
+			low = mid+1;
+	}
+	/*
+	 * If we need to create a new entry, it should be right at
+	 * low (where high will be left at low-1).
+	 */
+	if (create)
+		return insert_icount_el(icount, ino, low);
+	return 0;
+}
+
+errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out)
+{
+	errcode_t	ret = 0;
+	unsigned int	i;
+	const char *bad = "bad icount";
+
+	EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+
+	if (icount->count > icount->size) {
+		fprintf(out, "%s: count > size\n", bad);
+		return EXT2_ET_INVALID_ARGUMENT;
+	}
+	for (i=1; i < icount->count; i++) {
+		if (icount->list[i-1].ino >= icount->list[i].ino) {
+			fprintf(out, "%s: list[%d].ino=%u, list[%d].ino=%u\n",
+				bad, i-1, icount->list[i-1].ino,
+				i, icount->list[i].ino);
+			ret = EXT2_ET_INVALID_ARGUMENT;
+		}
+	}
+	return ret;
+}
+
+errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret)
+{
+	struct ext2_icount_el	*el;
+
+	EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+
+	if (!ino || (ino > icount->num_inodes))
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	if (ext2fs_test_inode_bitmap(icount->single, ino)) {
+		*ret = 1;
+		return 0;
+	}
+	if (icount->multiple &&
+	    !ext2fs_test_inode_bitmap(icount->multiple, ino)) {
+		*ret = 0;
+		return 0;
+	}
+	el = get_icount_el(icount, ino, 0);
+	if (!el) {
+		*ret = 0;
+		return 0;
+	}
+	*ret = el->count;
+	return 0;
+}
+
+errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
+				  __u16 *ret)
+{
+	struct ext2_icount_el	*el;
+
+	EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+
+	if (!ino || (ino > icount->num_inodes))
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	if (ext2fs_test_inode_bitmap(icount->single, ino)) {
+		/*
+		 * If the existing count is 1, then we know there is
+		 * no entry in the list.
+		 */
+		el = get_icount_el(icount, ino, 1);
+		if (!el)
+			return EXT2_ET_NO_MEMORY;
+		ext2fs_unmark_inode_bitmap(icount->single, ino);
+		el->count = 2;
+	} else if (icount->multiple) {
+		/*
+		 * The count is either zero or greater than 1; if the
+		 * inode is set in icount->multiple, then there should
+		 * be an entry in the list, so find it using
+		 * get_icount_el().
+		 */
+		if (ext2fs_test_inode_bitmap(icount->multiple, ino)) {
+			el = get_icount_el(icount, ino, 1);
+			if (!el)
+				return EXT2_ET_NO_MEMORY;
+			el->count++;
+		} else {
+			/*
+			 * The count was zero; mark the single bitmap
+			 * and return.
+			 */
+		zero_count:
+			ext2fs_mark_inode_bitmap(icount->single, ino);
+			if (ret)
+				*ret = 1;
+			return 0;
+		}
+	} else {
+		/*
+		 * The count is either zero or greater than 1; try to
+		 * find an entry in the list to determine which.
+		 */
+		el = get_icount_el(icount, ino, 0);
+		if (!el) {
+			/* No entry means the count was zero */
+			goto zero_count;
+		}
+		el = get_icount_el(icount, ino, 1);
+		if (!el)
+			return EXT2_ET_NO_MEMORY;
+		el->count++;
+	}
+	if (icount->multiple)
+		ext2fs_mark_inode_bitmap(icount->multiple, ino);
+	if (ret)
+		*ret = el->count;
+	return 0;
+}
+
+errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
+				  __u16 *ret)
+{
+	struct ext2_icount_el	*el;
+
+	if (!ino || (ino > icount->num_inodes))
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+
+	if (ext2fs_test_inode_bitmap(icount->single, ino)) {
+		ext2fs_unmark_inode_bitmap(icount->single, ino);
+		if (icount->multiple)
+			ext2fs_unmark_inode_bitmap(icount->multiple, ino);
+		else {
+			el = get_icount_el(icount, ino, 0);
+			if (el)
+				el->count = 0;
+		}
+		if (ret)
+			*ret = 0;
+		return 0;
+	}
+
+	if (icount->multiple &&
+	    !ext2fs_test_inode_bitmap(icount->multiple, ino))
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	el = get_icount_el(icount, ino, 0);
+	if (!el || el->count == 0)
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	el->count--;
+	if (el->count == 1)
+		ext2fs_mark_inode_bitmap(icount->single, ino);
+	if ((el->count == 0) && icount->multiple)
+		ext2fs_unmark_inode_bitmap(icount->multiple, ino);
+
+	if (ret)
+		*ret = el->count;
+	return 0;
+}
+
+errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
+			      __u16 count)
+{
+	struct ext2_icount_el	*el;
+
+	if (!ino || (ino > icount->num_inodes))
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+
+	if (count == 1) {
+		ext2fs_mark_inode_bitmap(icount->single, ino);
+		if (icount->multiple)
+			ext2fs_unmark_inode_bitmap(icount->multiple, ino);
+		return 0;
+	}
+	if (count == 0) {
+		ext2fs_unmark_inode_bitmap(icount->single, ino);
+		if (icount->multiple) {
+			/*
+			 * If the icount->multiple bitmap is enabled,
+			 * we can just clear both bitmaps and we're done
+			 */
+			ext2fs_unmark_inode_bitmap(icount->multiple, ino);
+		} else {
+			el = get_icount_el(icount, ino, 0);
+			if (el)
+				el->count = 0;
+		}
+		return 0;
+	}
+
+	/*
+	 * Get the icount element
+	 */
+	el = get_icount_el(icount, ino, 1);
+	if (!el)
+		return EXT2_ET_NO_MEMORY;
+	el->count = count;
+	ext2fs_unmark_inode_bitmap(icount->single, ino);
+	if (icount->multiple)
+		ext2fs_mark_inode_bitmap(icount->multiple, ino);
+	return 0;
+}
+
+ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount)
+{
+	if (!icount || icount->magic != EXT2_ET_MAGIC_ICOUNT)
+		return 0;
+
+	return icount->size;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/imager.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/imager.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/imager.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,376 @@
+/*
+ * image.c --- writes out the critical parts of the filesystem as a
+ *	flat file.
+ *
+ * Copyright (C) 2000 Theodore Ts'o.
+ *
+ * Note: this uses the POSIX IO interfaces, unlike most of the other
+ * functions in this library.  So sue me.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#ifndef HAVE_TYPE_SSIZE_T
+typedef int ssize_t;
+#endif
+
+/*
+ * This function returns 1 if the specified block is all zeros
+ */
+static int check_zero_block(char *buf, int blocksize)
+{
+	char	*cp = buf;
+	int	left = blocksize;
+
+	while (left > 0) {
+		if (*cp++)
+			return 0;
+		left--;
+	}
+	return 1;
+}
+
+/*
+ * Write the inode table out as a single block.
+ */
+#define BUF_BLOCKS	32
+
+errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags)
+{
+	unsigned int	group, left, c, d;
+	char		*buf, *cp;
+	blk_t		blk;
+	ssize_t		actual;
+	errcode_t	retval;
+
+	buf = xmalloc(fs->blocksize * BUF_BLOCKS);
+
+	for (group = 0; group < fs->group_desc_count; group++) {
+		blk = fs->group_desc[(unsigned)group].bg_inode_table;
+		if (!blk)
+			return EXT2_ET_MISSING_INODE_TABLE;
+		left = fs->inode_blocks_per_group;
+		while (left) {
+			c = BUF_BLOCKS;
+			if (c > left)
+				c = left;
+			retval = io_channel_read_blk(fs->io, blk, c, buf);
+			if (retval)
+				goto errout;
+			cp = buf;
+			while (c) {
+				if (!(flags & IMAGER_FLAG_SPARSEWRITE)) {
+					d = c;
+					goto skip_sparse;
+				}
+				/* Skip zero blocks */
+				if (check_zero_block(cp, fs->blocksize)) {
+					c--;
+					blk++;
+					left--;
+					cp += fs->blocksize;
+					lseek(fd, fs->blocksize, SEEK_CUR);
+					continue;
+				}
+				/* Find non-zero blocks */
+				for (d=1; d < c; d++) {
+					if (check_zero_block(cp + d*fs->blocksize, fs->blocksize))
+						break;
+				}
+			skip_sparse:
+				actual = write(fd, cp, fs->blocksize * d);
+				if (actual == -1) {
+					retval = errno;
+					goto errout;
+				}
+				if (actual != (ssize_t) (fs->blocksize * d)) {
+					retval = EXT2_ET_SHORT_WRITE;
+					goto errout;
+				}
+				blk += d;
+				left -= d;
+				cp += fs->blocksize * d;
+				c -= d;
+			}
+		}
+	}
+	retval = 0;
+
+errout:
+	free(buf);
+	return retval;
+}
+
+/*
+ * Read in the inode table and stuff it into place
+ */
+errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd,
+				  int flags EXT2FS_ATTR((unused)))
+{
+	unsigned int	group, c, left;
+	char		*buf;
+	blk_t		blk;
+	ssize_t		actual;
+	errcode_t	retval;
+
+	buf = xmalloc(fs->blocksize * BUF_BLOCKS);
+
+	for (group = 0; group < fs->group_desc_count; group++) {
+		blk = fs->group_desc[(unsigned)group].bg_inode_table;
+		if (!blk) {
+			retval = EXT2_ET_MISSING_INODE_TABLE;
+			goto errout;
+		}
+		left = fs->inode_blocks_per_group;
+		while (left) {
+			c = BUF_BLOCKS;
+			if (c > left)
+				c = left;
+			actual = read(fd, buf, fs->blocksize * c);
+			if (actual == -1) {
+				retval = errno;
+				goto errout;
+			}
+			if (actual != (ssize_t) (fs->blocksize * c)) {
+				retval = EXT2_ET_SHORT_READ;
+				goto errout;
+			}
+			retval = io_channel_write_blk(fs->io, blk, c, buf);
+			if (retval)
+				goto errout;
+
+			blk += c;
+			left -= c;
+		}
+	}
+	retval = ext2fs_flush_icache(fs);
+
+errout:
+	free(buf);
+	return retval;
+}
+
+/*
+ * Write out superblock and group descriptors
+ */
+errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
+				   int flags EXT2FS_ATTR((unused)))
+{
+	char		*buf, *cp;
+	ssize_t		actual;
+	errcode_t	retval;
+
+	buf = xmalloc(fs->blocksize);
+
+	/*
+	 * Write out the superblock
+	 */
+	memset(buf, 0, fs->blocksize);
+	memcpy(buf, fs->super, SUPERBLOCK_SIZE);
+	actual = write(fd, buf, fs->blocksize);
+	if (actual == -1) {
+		retval = errno;
+		goto errout;
+	}
+	if (actual != (ssize_t) fs->blocksize) {
+		retval = EXT2_ET_SHORT_WRITE;
+		goto errout;
+	}
+
+	/*
+	 * Now write out the block group descriptors
+	 */
+	cp = (char *) fs->group_desc;
+	actual = write(fd, cp, fs->blocksize * fs->desc_blocks);
+	if (actual == -1) {
+		retval = errno;
+		goto errout;
+	}
+	if (actual != (ssize_t) (fs->blocksize * fs->desc_blocks)) {
+		retval = EXT2_ET_SHORT_WRITE;
+		goto errout;
+	}
+
+	retval = 0;
+
+errout:
+	free(buf);
+	return retval;
+}
+
+/*
+ * Read the superblock and group descriptors and overwrite them.
+ */
+errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd,
+				  int flags EXT2FS_ATTR((unused)))
+{
+	char		*buf;
+	ssize_t		actual, size;
+	errcode_t	retval;
+
+	size = fs->blocksize * (fs->group_desc_count + 1);
+	buf = xmalloc(size);
+
+	/*
+	 * Read it all in.
+	 */
+	actual = read(fd, buf, size);
+	if (actual == -1) {
+		retval = errno;
+		goto errout;
+	}
+	if (actual != size) {
+		retval = EXT2_ET_SHORT_READ;
+		goto errout;
+	}
+
+	/*
+	 * Now copy in the superblock and group descriptors
+	 */
+	memcpy(fs->super, buf, SUPERBLOCK_SIZE);
+
+	memcpy(fs->group_desc, buf + fs->blocksize,
+	       fs->blocksize * fs->group_desc_count);
+
+	retval = 0;
+
+errout:
+	free(buf);
+	return retval;
+}
+
+/*
+ * Write the block/inode bitmaps.
+ */
+errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
+{
+	char		*ptr;
+	int		c, size;
+	char		zero_buf[1024];
+	ssize_t		actual;
+	errcode_t	retval;
+
+	if (flags & IMAGER_FLAG_INODEMAP) {
+		if (!fs->inode_map) {
+			retval = ext2fs_read_inode_bitmap(fs);
+			if (retval)
+				return retval;
+		}
+		ptr = fs->inode_map->bitmap;
+		size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
+	} else {
+		if (!fs->block_map) {
+			retval = ext2fs_read_block_bitmap(fs);
+			if (retval)
+				return retval;
+		}
+		ptr = fs->block_map->bitmap;
+		size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
+	}
+	size = size * fs->group_desc_count;
+
+	actual = write(fd, ptr, size);
+	if (actual == -1) {
+		retval = errno;
+		goto errout;
+	}
+	if (actual != size) {
+		retval = EXT2_ET_SHORT_WRITE;
+		goto errout;
+	}
+	size = size % fs->blocksize;
+	memset(zero_buf, 0, sizeof(zero_buf));
+	if (size) {
+		size = fs->blocksize - size;
+		while (size) {
+			c = size;
+			if (c > (int) sizeof(zero_buf))
+				c = sizeof(zero_buf);
+			actual = write(fd, zero_buf, c);
+			if (actual == -1) {
+				retval = errno;
+				goto errout;
+			}
+			if (actual != c) {
+				retval = EXT2_ET_SHORT_WRITE;
+				goto errout;
+			}
+			size -= c;
+		}
+	}
+	retval = 0;
+errout:
+	return (retval);
+}
+
+
+/*
+ * Read the block/inode bitmaps.
+ */
+errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
+{
+	char		*ptr, *buf = 0;
+	int		size;
+	ssize_t		actual;
+	errcode_t	retval;
+
+	if (flags & IMAGER_FLAG_INODEMAP) {
+		if (!fs->inode_map) {
+			retval = ext2fs_read_inode_bitmap(fs);
+			if (retval)
+				return retval;
+		}
+		ptr = fs->inode_map->bitmap;
+		size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
+	} else {
+		if (!fs->block_map) {
+			retval = ext2fs_read_block_bitmap(fs);
+			if (retval)
+				return retval;
+		}
+		ptr = fs->block_map->bitmap;
+		size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
+	}
+	size = size * fs->group_desc_count;
+
+	buf = xmalloc(size);
+
+	actual = read(fd, buf, size);
+	if (actual == -1) {
+		retval = errno;
+		goto errout;
+	}
+	if (actual != size) {
+		retval = EXT2_ET_SHORT_WRITE;
+		goto errout;
+	}
+	memcpy(ptr, buf, size);
+
+	retval = 0;
+errout:
+	free(buf);
+	return (retval);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ind_block.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ind_block.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ind_block.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,70 @@
+/*
+ * ind_block.c --- indirect block I/O routines
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ *	2001, 2002, 2003, 2004, 2005 by  Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf)
+{
+	errcode_t	retval;
+#if BB_BIG_ENDIAN
+	blk_t		*block_nr;
+	int		i;
+	int		limit = fs->blocksize >> 2;
+#endif
+
+	if ((fs->flags & EXT2_FLAG_IMAGE_FILE) &&
+	    (fs->io != fs->image_io))
+		memset(buf, 0, fs->blocksize);
+	else {
+		retval = io_channel_read_blk(fs->io, blk, 1, buf);
+		if (retval)
+			return retval;
+	}
+#if BB_BIG_ENDIAN
+	if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_READ)) {
+		block_nr = (blk_t *) buf;
+		for (i = 0; i < limit; i++, block_nr++)
+			*block_nr = ext2fs_swab32(*block_nr);
+	}
+#endif
+	return 0;
+}
+
+errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf)
+{
+#if BB_BIG_ENDIAN
+	blk_t		*block_nr;
+	int		i;
+	int		limit = fs->blocksize >> 2;
+#endif
+
+	if (fs->flags & EXT2_FLAG_IMAGE_FILE)
+		return 0;
+
+#if BB_BIG_ENDIAN
+	if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_WRITE)) {
+		block_nr = (blk_t *) buf;
+		for (i = 0; i < limit; i++, block_nr++)
+			*block_nr = ext2fs_swab32(*block_nr);
+	}
+#endif
+	return io_channel_write_blk(fs->io, blk, 1, buf);
+}
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/initialize.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/initialize.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/initialize.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,387 @@
+/*
+ * initialize.c --- initialize a filesystem handle given superblock
+ *	parameters.  Used by mke2fs when initializing a filesystem.
+ *
+ * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#if defined(__linux__)    &&	defined(EXT2_OS_LINUX)
+#define CREATOR_OS EXT2_OS_LINUX
+#else
+#if defined(__GNU__)     &&	defined(EXT2_OS_HURD)
+#define CREATOR_OS EXT2_OS_HURD
+#else
+#if defined(__FreeBSD__) &&	defined(EXT2_OS_FREEBSD)
+#define CREATOR_OS EXT2_OS_FREEBSD
+#else
+#if defined(LITES)	   &&	defined(EXT2_OS_LITES)
+#define CREATOR_OS EXT2_OS_LITES
+#else
+#define CREATOR_OS EXT2_OS_LINUX /* by default */
+#endif /* defined(LITES) && defined(EXT2_OS_LITES) */
+#endif /* defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) */
+#endif /* defined(__GNU__)     && defined(EXT2_OS_HURD) */
+#endif /* defined(__linux__)   && defined(EXT2_OS_LINUX) */
+
+/*
+ * Note we override the kernel include file's idea of what the default
+ * check interval (never) should be.  It's a good idea to check at
+ * least *occasionally*, specially since servers will never rarely get
+ * to reboot, since Linux is so robust these days.  :-)
+ *
+ * 180 days (six months) seems like a good value.
+ */
+#ifdef EXT2_DFL_CHECKINTERVAL
+#undef EXT2_DFL_CHECKINTERVAL
+#endif
+#define EXT2_DFL_CHECKINTERVAL (86400L * 180L)
+
+/*
+ * Calculate the number of GDT blocks to reserve for online filesystem growth.
+ * The absolute maximum number of GDT blocks we can reserve is determined by
+ * the number of block pointers that can fit into a single block.
+ */
+static int calc_reserved_gdt_blocks(ext2_filsys fs)
+{
+	struct ext2_super_block *sb = fs->super;
+	unsigned long bpg = sb->s_blocks_per_group;
+	unsigned int gdpb = fs->blocksize / sizeof(struct ext2_group_desc);
+	unsigned long max_blocks = 0xffffffff;
+	unsigned long rsv_groups;
+	int rsv_gdb;
+
+	/* We set it at 1024x the current filesystem size, or
+	 * the upper block count limit (2^32), whichever is lower.
+	 */
+	if (sb->s_blocks_count < max_blocks / 1024)
+		max_blocks = sb->s_blocks_count * 1024;
+	rsv_groups = (max_blocks - sb->s_first_data_block + bpg - 1) / bpg;
+	rsv_gdb = (rsv_groups + gdpb - 1) / gdpb - fs->desc_blocks;
+	if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb))
+		rsv_gdb = EXT2_ADDR_PER_BLOCK(sb);
+#ifdef RES_GDT_DEBUG
+	printf("max_blocks %lu, rsv_groups = %lu, rsv_gdb = %lu\n",
+	       max_blocks, rsv_groups, rsv_gdb);
+#endif
+
+	return rsv_gdb;
+}
+
+errcode_t ext2fs_initialize(const char *name, int flags,
+			    struct ext2_super_block *param,
+			    io_manager manager, ext2_filsys *ret_fs)
+{
+	ext2_filsys	fs;
+	errcode_t	retval;
+	struct ext2_super_block *super;
+	int		frags_per_block;
+	unsigned int	rem;
+	unsigned int	overhead = 0;
+	blk_t		group_block;
+	unsigned int	ipg;
+	dgrp_t		i;
+	blk_t		numblocks;
+	int		rsv_gdt;
+	char		*buf;
+
+	if (!param || !param->s_blocks_count)
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
+	if (retval)
+		return retval;
+
+	memset(fs, 0, sizeof(struct struct_ext2_filsys));
+	fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
+	fs->flags = flags | EXT2_FLAG_RW;
+	fs->umask = 022;
+#ifdef WORDS_BIGENDIAN
+	fs->flags |= EXT2_FLAG_SWAP_BYTES;
+#endif
+	retval = manager->open(name, IO_FLAG_RW, &fs->io);
+	if (retval)
+		goto cleanup;
+	fs->image_io = fs->io;
+	fs->io->app_data = fs;
+	retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name);
+	if (retval)
+		goto cleanup;
+
+	strcpy(fs->device_name, name);
+	retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super);
+	if (retval)
+		goto cleanup;
+	fs->super = super;
+
+	memset(super, 0, SUPERBLOCK_SIZE);
+
+#define set_field(field, default) (super->field = param->field ? \
+				   param->field : (default))
+
+	super->s_magic = EXT2_SUPER_MAGIC;
+	super->s_state = EXT2_VALID_FS;
+
+	set_field(s_log_block_size, 0);	/* default blocksize: 1024 bytes */
+	set_field(s_log_frag_size, 0); /* default fragsize: 1024 bytes */
+	set_field(s_first_data_block, super->s_log_block_size ? 0 : 1);
+	set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT);
+	set_field(s_errors, EXT2_ERRORS_DEFAULT);
+	set_field(s_feature_compat, 0);
+	set_field(s_feature_incompat, 0);
+	set_field(s_feature_ro_compat, 0);
+	set_field(s_first_meta_bg, 0);
+	if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
+		retval = EXT2_ET_UNSUPP_FEATURE;
+		goto cleanup;
+	}
+	if (super->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
+		retval = EXT2_ET_RO_UNSUPP_FEATURE;
+		goto cleanup;
+	}
+
+	set_field(s_rev_level, EXT2_GOOD_OLD_REV);
+	if (super->s_rev_level >= EXT2_DYNAMIC_REV) {
+		set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO);
+		set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE);
+	}
+
+	set_field(s_checkinterval, EXT2_DFL_CHECKINTERVAL);
+	super->s_mkfs_time = super->s_lastcheck = time(NULL);
+
+	super->s_creator_os = CREATOR_OS;
+
+	fs->blocksize = EXT2_BLOCK_SIZE(super);
+	fs->fragsize = EXT2_FRAG_SIZE(super);
+	frags_per_block = fs->blocksize / fs->fragsize;
+
+	/* default: (fs->blocksize*8) blocks/group, up to 2^16 (GDT limit) */
+	set_field(s_blocks_per_group, fs->blocksize * 8);
+	if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super))
+		super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super);
+	super->s_frags_per_group = super->s_blocks_per_group * frags_per_block;
+
+	super->s_blocks_count = param->s_blocks_count;
+	super->s_r_blocks_count = param->s_r_blocks_count;
+	if (super->s_r_blocks_count >= param->s_blocks_count) {
+		retval = EXT2_ET_INVALID_ARGUMENT;
+		goto cleanup;
+	}
+
+	/*
+	 * If we're creating an external journal device, we don't need
+	 * to bother with the rest.
+	 */
+	if (super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+		fs->group_desc_count = 0;
+		ext2fs_mark_super_dirty(fs);
+		*ret_fs = fs;
+		return 0;
+	}
+
+retry:
+	fs->group_desc_count = (super->s_blocks_count -
+				super->s_first_data_block +
+				EXT2_BLOCKS_PER_GROUP(super) - 1)
+		/ EXT2_BLOCKS_PER_GROUP(super);
+	if (fs->group_desc_count == 0) {
+		retval = EXT2_ET_TOOSMALL;
+		goto cleanup;
+	}
+	fs->desc_blocks = (fs->group_desc_count +
+			   EXT2_DESC_PER_BLOCK(super) - 1)
+		/ EXT2_DESC_PER_BLOCK(super);
+
+	i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize;
+	set_field(s_inodes_count, super->s_blocks_count / i);
+
+	/*
+	 * Make sure we have at least EXT2_FIRST_INO + 1 inodes, so
+	 * that we have enough inodes for the filesystem(!)
+	 */
+	if (super->s_inodes_count < EXT2_FIRST_INODE(super)+1)
+		super->s_inodes_count = EXT2_FIRST_INODE(super)+1;
+
+	/*
+	 * There should be at least as many inodes as the user
+	 * requested.  Figure out how many inodes per group that
+	 * should be.  But make sure that we don't allocate more than
+	 * one bitmap's worth of inodes each group.
+	 */
+	ipg = (super->s_inodes_count + fs->group_desc_count - 1) /
+		fs->group_desc_count;
+	if (ipg > fs->blocksize * 8) {
+		if (super->s_blocks_per_group >= 256) {
+			/* Try again with slightly different parameters */
+			super->s_blocks_per_group -= 8;
+			super->s_blocks_count = param->s_blocks_count;
+			super->s_frags_per_group = super->s_blocks_per_group *
+				frags_per_block;
+			goto retry;
+		} else
+			return EXT2_ET_TOO_MANY_INODES;
+	}
+
+	if (ipg > (unsigned) EXT2_MAX_INODES_PER_GROUP(super))
+		ipg = EXT2_MAX_INODES_PER_GROUP(super);
+
+	super->s_inodes_per_group = ipg;
+	if (super->s_inodes_count > ipg * fs->group_desc_count)
+		super->s_inodes_count = ipg * fs->group_desc_count;
+
+	/*
+	 * Make sure the number of inodes per group completely fills
+	 * the inode table blocks in the descriptor.  If not, add some
+	 * additional inodes/group.  Waste not, want not...
+	 */
+	fs->inode_blocks_per_group = (((super->s_inodes_per_group *
+					EXT2_INODE_SIZE(super)) +
+				       EXT2_BLOCK_SIZE(super) - 1) /
+				      EXT2_BLOCK_SIZE(super));
+	super->s_inodes_per_group = ((fs->inode_blocks_per_group *
+				      EXT2_BLOCK_SIZE(super)) /
+				     EXT2_INODE_SIZE(super));
+	/*
+	 * Finally, make sure the number of inodes per group is a
+	 * multiple of 8.  This is needed to simplify the bitmap
+	 * splicing code.
+	 */
+	super->s_inodes_per_group &= ~7;
+	fs->inode_blocks_per_group = (((super->s_inodes_per_group *
+					EXT2_INODE_SIZE(super)) +
+				       EXT2_BLOCK_SIZE(super) - 1) /
+				      EXT2_BLOCK_SIZE(super));
+
+	/*
+	 * adjust inode count to reflect the adjusted inodes_per_group
+	 */
+	super->s_inodes_count = super->s_inodes_per_group *
+		fs->group_desc_count;
+	super->s_free_inodes_count = super->s_inodes_count;
+
+	/*
+	 * check the number of reserved group descriptor table blocks
+	 */
+	if (super->s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE)
+		rsv_gdt = calc_reserved_gdt_blocks(fs);
+	else
+		rsv_gdt = 0;
+	set_field(s_reserved_gdt_blocks, rsv_gdt);
+	if (super->s_reserved_gdt_blocks > EXT2_ADDR_PER_BLOCK(super)) {
+		retval = EXT2_ET_RES_GDT_BLOCKS;
+		goto cleanup;
+	}
+
+	/*
+	 * Overhead is the number of bookkeeping blocks per group.  It
+	 * includes the superblock backup, the group descriptor
+	 * backups, the inode bitmap, the block bitmap, and the inode
+	 * table.
+	 */
+
+	overhead = (int) (2 + fs->inode_blocks_per_group);
+
+	if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1))
+		overhead += 1 + fs->desc_blocks + super->s_reserved_gdt_blocks;
+
+	/* This can only happen if the user requested too many inodes */
+	if (overhead > super->s_blocks_per_group)
+		return EXT2_ET_TOO_MANY_INODES;
+
+	/*
+	 * See if the last group is big enough to support the
+	 * necessary data structures.  If not, we need to get rid of
+	 * it.
+	 */
+	rem = ((super->s_blocks_count - super->s_first_data_block) %
+	       super->s_blocks_per_group);
+	if ((fs->group_desc_count == 1) && rem && (rem < overhead))
+		return EXT2_ET_TOOSMALL;
+	if (rem && (rem < overhead+50)) {
+		super->s_blocks_count -= rem;
+		goto retry;
+	}
+
+	/*
+	 * At this point we know how big the filesystem will be.  So
+	 * we can do any and all allocations that depend on the block
+	 * count.
+	 */
+
+	retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
+	if (retval)
+		goto cleanup;
+
+	sprintf(buf, "block bitmap for %s", fs->device_name);
+	retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
+	if (retval)
+		goto cleanup;
+
+	sprintf(buf, "inode bitmap for %s", fs->device_name);
+	retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
+	if (retval)
+		goto cleanup;
+
+	ext2fs_free_mem(&buf);
+
+	retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize,
+				&fs->group_desc);
+	if (retval)
+		goto cleanup;
+
+	memset(fs->group_desc, 0, (size_t) fs->desc_blocks * fs->blocksize);
+
+	/*
+	 * Reserve the superblock and group descriptors for each
+	 * group, and fill in the correct group statistics for group.
+	 * Note that although the block bitmap, inode bitmap, and
+	 * inode table have not been allocated (and in fact won't be
+	 * by this routine), they are accounted for nevertheless.
+	 */
+	group_block = super->s_first_data_block;
+	super->s_free_blocks_count = 0;
+	for (i = 0; i < fs->group_desc_count; i++) {
+		numblocks = ext2fs_reserve_super_and_bgd(fs, i, fs->block_map);
+
+		super->s_free_blocks_count += numblocks;
+		fs->group_desc[i].bg_free_blocks_count = numblocks;
+		fs->group_desc[i].bg_free_inodes_count =
+			fs->super->s_inodes_per_group;
+		fs->group_desc[i].bg_used_dirs_count = 0;
+
+		group_block += super->s_blocks_per_group;
+	}
+
+	ext2fs_mark_super_dirty(fs);
+	ext2fs_mark_bb_dirty(fs);
+	ext2fs_mark_ib_dirty(fs);
+
+	io_channel_set_blksize(fs->io, fs->blocksize);
+
+	*ret_fs = fs;
+	return 0;
+cleanup:
+	ext2fs_free(fs);
+	return retval;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/inline.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/inline.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/inline.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,32 @@
+/*
+ * inline.c --- Includes the inlined functions defined in the header
+ *	files as standalone functions, in case the application program
+ *	is compiled with inlining turned off.
+ *
+ * Copyright (C) 1993, 1994 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#define INCLUDE_INLINE_FUNCS
+#include "ext2fs.h"
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/inode.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/inode.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/inode.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,788 @@
+/*
+ * inode.c --- utility routines to read and write inodes
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+#include "e2image.h"
+
+struct ext2_struct_inode_scan {
+	errcode_t		magic;
+	ext2_filsys		fs;
+	ext2_ino_t		current_inode;
+	blk_t			current_block;
+	dgrp_t			current_group;
+	ext2_ino_t		inodes_left;
+	blk_t			blocks_left;
+	dgrp_t			groups_left;
+	blk_t			inode_buffer_blocks;
+	char *			inode_buffer;
+	int			inode_size;
+	char *			ptr;
+	int			bytes_left;
+	char			*temp_buffer;
+	errcode_t		(*done_group)(ext2_filsys fs,
+					      dgrp_t group,
+					      void * priv_data);
+	void *			done_group_data;
+	int			bad_block_ptr;
+	int			scan_flags;
+	int			reserved[6];
+};
+
+/*
+ * This routine flushes the icache, if it exists.
+ */
+errcode_t ext2fs_flush_icache(ext2_filsys fs)
+{
+	int	i;
+
+	if (!fs->icache)
+		return 0;
+
+	for (i=0; i < fs->icache->cache_size; i++)
+		fs->icache->cache[i].ino = 0;
+
+	fs->icache->buffer_blk = 0;
+	return 0;
+}
+
+static errcode_t create_icache(ext2_filsys fs)
+{
+	errcode_t	retval;
+
+	if (fs->icache)
+		return 0;
+	retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), &fs->icache);
+	if (retval)
+		return retval;
+
+	memset(fs->icache, 0, sizeof(struct ext2_inode_cache));
+	retval = ext2fs_get_mem(fs->blocksize, &fs->icache->buffer);
+	if (retval) {
+		ext2fs_free_mem(&fs->icache);
+		return retval;
+	}
+	fs->icache->buffer_blk = 0;
+	fs->icache->cache_last = -1;
+	fs->icache->cache_size = 4;
+	fs->icache->refcount = 1;
+	retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache_ent)
+				* fs->icache->cache_size,
+				&fs->icache->cache);
+	if (retval) {
+		ext2fs_free_mem(&fs->icache->buffer);
+		ext2fs_free_mem(&fs->icache);
+		return retval;
+	}
+	ext2fs_flush_icache(fs);
+	return 0;
+}
+
+errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
+				 ext2_inode_scan *ret_scan)
+{
+	ext2_inode_scan	scan;
+	errcode_t	retval;
+	errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks);
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	/*
+	 * If fs->badblocks isn't set, then set it --- since the inode
+	 * scanning functions require it.
+	 */
+	if (fs->badblocks == 0) {
+		/*
+		 * Temporarly save fs->get_blocks and set it to zero,
+		 * for compatibility with old e2fsck's.
+		 */
+		save_get_blocks = fs->get_blocks;
+		fs->get_blocks = 0;
+		retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
+		if (retval) {
+			ext2fs_badblocks_list_free(fs->badblocks);
+			fs->badblocks = 0;
+		}
+		fs->get_blocks = save_get_blocks;
+	}
+
+	retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan);
+	if (retval)
+		return retval;
+	memset(scan, 0, sizeof(struct ext2_struct_inode_scan));
+
+	scan->magic = EXT2_ET_MAGIC_INODE_SCAN;
+	scan->fs = fs;
+	scan->inode_size = EXT2_INODE_SIZE(fs->super);
+	scan->bytes_left = 0;
+	scan->current_group = 0;
+	scan->groups_left = fs->group_desc_count - 1;
+	scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8;
+	scan->current_block = scan->fs->
+		group_desc[scan->current_group].bg_inode_table;
+	scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
+	scan->blocks_left = scan->fs->inode_blocks_per_group;
+	retval = ext2fs_get_mem((size_t) (scan->inode_buffer_blocks *
+					  fs->blocksize),
+				&scan->inode_buffer);
+	scan->done_group = 0;
+	scan->done_group_data = 0;
+	scan->bad_block_ptr = 0;
+	if (retval) {
+		ext2fs_free_mem(&scan);
+		return retval;
+	}
+	retval = ext2fs_get_mem(scan->inode_size, &scan->temp_buffer);
+	if (retval) {
+		ext2fs_free_mem(&scan->inode_buffer);
+		ext2fs_free_mem(&scan);
+		return retval;
+	}
+	if (scan->fs->badblocks && scan->fs->badblocks->num)
+		scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS;
+	*ret_scan = scan;
+	return 0;
+}
+
+void ext2fs_close_inode_scan(ext2_inode_scan scan)
+{
+	if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
+		return;
+
+	ext2fs_free_mem(&scan->inode_buffer);
+	scan->inode_buffer = NULL;
+	ext2fs_free_mem(&scan->temp_buffer);
+	scan->temp_buffer = NULL;
+	ext2fs_free_mem(&scan);
+	return;
+}
+
+void ext2fs_set_inode_callback(ext2_inode_scan scan,
+			       errcode_t (*done_group)(ext2_filsys fs,
+						       dgrp_t group,
+						       void * priv_data),
+			       void *done_group_data)
+{
+	if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
+		return;
+
+	scan->done_group = done_group;
+	scan->done_group_data = done_group_data;
+}
+
+int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
+			    int clear_flags)
+{
+	int	old_flags;
+
+	if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
+		return 0;
+
+	old_flags = scan->scan_flags;
+	scan->scan_flags &= ~clear_flags;
+	scan->scan_flags |= set_flags;
+	return old_flags;
+}
+
+/*
+ * This function is called by ext2fs_get_next_inode when it needs to
+ * get ready to read in a new blockgroup.
+ */
+static errcode_t get_next_blockgroup(ext2_inode_scan scan)
+{
+	scan->current_group++;
+	scan->groups_left--;
+
+	scan->current_block = scan->fs->
+		group_desc[scan->current_group].bg_inode_table;
+
+	scan->current_inode = scan->current_group *
+		EXT2_INODES_PER_GROUP(scan->fs->super);
+
+	scan->bytes_left = 0;
+	scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
+	scan->blocks_left = scan->fs->inode_blocks_per_group;
+	return 0;
+}
+
+errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
+					    int	group)
+{
+	scan->current_group = group - 1;
+	scan->groups_left = scan->fs->group_desc_count - group;
+	return get_next_blockgroup(scan);
+}
+
+/*
+ * This function is called by get_next_blocks() to check for bad
+ * blocks in the inode table.
+ *
+ * This function assumes that badblocks_list->list is sorted in
+ * increasing order.
+ */
+static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan,
+					    blk_t *num_blocks)
+{
+	blk_t	blk = scan->current_block;
+	badblocks_list	bb = scan->fs->badblocks;
+
+	/*
+	 * If the inode table is missing, then obviously there are no
+	 * bad blocks.  :-)
+	 */
+	if (blk == 0)
+		return 0;
+
+	/*
+	 * If the current block is greater than the bad block listed
+	 * in the bad block list, then advance the pointer until this
+	 * is no longer the case.  If we run out of bad blocks, then
+	 * we don't need to do any more checking!
+	 */
+	while (blk > bb->list[scan->bad_block_ptr]) {
+		if (++scan->bad_block_ptr >= bb->num) {
+			scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
+			return 0;
+		}
+	}
+
+	/*
+	 * If the current block is equal to the bad block listed in
+	 * the bad block list, then handle that one block specially.
+	 * (We could try to handle runs of bad blocks, but that
+	 * only increases CPU efficiency by a small amount, at the
+	 * expense of a huge expense of code complexity, and for an
+	 * uncommon case at that.)
+	 */
+	if (blk == bb->list[scan->bad_block_ptr]) {
+		scan->scan_flags |= EXT2_SF_BAD_INODE_BLK;
+		*num_blocks = 1;
+		if (++scan->bad_block_ptr >= bb->num)
+			scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
+		return 0;
+	}
+
+	/*
+	 * If there is a bad block in the range that we're about to
+	 * read in, adjust the number of blocks to read so that we we
+	 * don't read in the bad block.  (Then the next block to read
+	 * will be the bad block, which is handled in the above case.)
+	 */
+	if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr])
+		*num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk);
+
+	return 0;
+}
+
+/*
+ * This function is called by ext2fs_get_next_inode when it needs to
+ * read in more blocks from the current blockgroup's inode table.
+ */
+static errcode_t get_next_blocks(ext2_inode_scan scan)
+{
+	blk_t		num_blocks;
+	errcode_t	retval;
+
+	/*
+	 * Figure out how many blocks to read; we read at most
+	 * inode_buffer_blocks, and perhaps less if there aren't that
+	 * many blocks left to read.
+	 */
+	num_blocks = scan->inode_buffer_blocks;
+	if (num_blocks > scan->blocks_left)
+		num_blocks = scan->blocks_left;
+
+	/*
+	 * If the past block "read" was a bad block, then mark the
+	 * left-over extra bytes as also being bad.
+	 */
+	if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) {
+		if (scan->bytes_left)
+			scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES;
+		scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK;
+	}
+
+	/*
+	 * Do inode bad block processing, if necessary.
+	 */
+	if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) {
+		retval = check_for_inode_bad_blocks(scan, &num_blocks);
+		if (retval)
+			return retval;
+	}
+
+	if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) ||
+	    (scan->current_block == 0)) {
+		memset(scan->inode_buffer, 0,
+		       (size_t) num_blocks * scan->fs->blocksize);
+	} else {
+		retval = io_channel_read_blk(scan->fs->io,
+					     scan->current_block,
+					     (int) num_blocks,
+					     scan->inode_buffer);
+		if (retval)
+			return EXT2_ET_NEXT_INODE_READ;
+	}
+	scan->ptr = scan->inode_buffer;
+	scan->bytes_left = num_blocks * scan->fs->blocksize;
+
+	scan->blocks_left -= num_blocks;
+	if (scan->current_block)
+		scan->current_block += num_blocks;
+	return 0;
+}
+
+#if 0
+/*
+ * Returns 1 if the entire inode_buffer has a non-zero size and
+ * contains all zeros.  (Not just deleted inodes, since that means
+ * that part of the inode table was used at one point; we want all
+ * zeros, which means that the inode table is pristine.)
+ */
+static inline int is_empty_scan(ext2_inode_scan scan)
+{
+	int	i;
+
+	if (scan->bytes_left == 0)
+		return 0;
+
+	for (i=0; i < scan->bytes_left; i++)
+		if (scan->ptr[i])
+			return 0;
+	return 1;
+}
+#endif
+
+errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino,
+				     struct ext2_inode *inode, int bufsize)
+{
+	errcode_t	retval;
+	int		extra_bytes = 0;
+
+	EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN);
+
+	/*
+	 * Do we need to start reading a new block group?
+	 */
+	if (scan->inodes_left <= 0) {
+	force_new_group:
+		if (scan->done_group) {
+			retval = (scan->done_group)
+				(scan->fs, scan->current_group,
+				 scan->done_group_data);
+			if (retval)
+				return retval;
+		}
+		if (scan->groups_left <= 0) {
+			*ino = 0;
+			return 0;
+		}
+		retval = get_next_blockgroup(scan);
+		if (retval)
+			return retval;
+	}
+	/*
+	 * This is done outside the above if statement so that the
+	 * check can be done for block group #0.
+	 */
+	if (scan->current_block == 0) {
+		if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) {
+			goto force_new_group;
+		} else
+			return EXT2_ET_MISSING_INODE_TABLE;
+	}
+
+
+	/*
+	 * Have we run out of space in the inode buffer?  If so, we
+	 * need to read in more blocks.
+	 */
+	if (scan->bytes_left < scan->inode_size) {
+		memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left);
+		extra_bytes = scan->bytes_left;
+
+		retval = get_next_blocks(scan);
+		if (retval)
+			return retval;
+#if 0
+		/*
+		 * XXX test  Need check for used inode somehow.
+		 * (Note: this is hard.)
+		 */
+		if (is_empty_scan(scan))
+			goto force_new_group;
+#endif
+	}
+
+	retval = 0;
+	if (extra_bytes) {
+		memcpy(scan->temp_buffer+extra_bytes, scan->ptr,
+		       scan->inode_size - extra_bytes);
+		scan->ptr += scan->inode_size - extra_bytes;
+		scan->bytes_left -= scan->inode_size - extra_bytes;
+
+#if BB_BIG_ENDIAN
+		if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+		    (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
+			ext2fs_swap_inode_full(scan->fs,
+				(struct ext2_inode_large *) inode,
+				(struct ext2_inode_large *) scan->temp_buffer,
+				0, bufsize);
+		else
+#endif
+			*inode = *((struct ext2_inode *) scan->temp_buffer);
+		if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES)
+			retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
+		scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES;
+	} else {
+#if BB_BIG_ENDIAN
+		if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+		    (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
+			ext2fs_swap_inode_full(scan->fs,
+				(struct ext2_inode_large *) inode,
+				(struct ext2_inode_large *) scan->ptr,
+				0, bufsize);
+		else
+#endif
+			memcpy(inode, scan->ptr, bufsize);
+		scan->ptr += scan->inode_size;
+		scan->bytes_left -= scan->inode_size;
+		if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK)
+			retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
+	}
+
+	scan->inodes_left--;
+	scan->current_inode++;
+	*ino = scan->current_inode;
+	return retval;
+}
+
+errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
+				struct ext2_inode *inode)
+{
+	return ext2fs_get_next_inode_full(scan, ino, inode,
+						sizeof(struct ext2_inode));
+}
+
+/*
+ * Functions to read and write a single inode.
+ */
+errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
+				 struct ext2_inode * inode, int bufsize)
+{
+	unsigned long	group, block, block_nr, offset;
+	char		*ptr;
+	errcode_t	retval;
+	int		clen, i, inodes_per_block, length;
+	io_channel	io;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	/* Check to see if user has an override function */
+	if (fs->read_inode) {
+		retval = (fs->read_inode)(fs, ino, inode);
+		if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
+			return retval;
+	}
+	/* Create inode cache if not present */
+	if (!fs->icache) {
+		retval = create_icache(fs);
+		if (retval)
+			return retval;
+	}
+	/* Check to see if it's in the inode cache */
+	if (bufsize == sizeof(struct ext2_inode)) {
+		/* only old good inode can be retrieve from the cache */
+		for (i=0; i < fs->icache->cache_size; i++) {
+			if (fs->icache->cache[i].ino == ino) {
+				*inode = fs->icache->cache[i].inode;
+				return 0;
+			}
+		}
+	}
+	if ((ino == 0) || (ino > fs->super->s_inodes_count))
+		return EXT2_ET_BAD_INODE_NUM;
+	if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
+		inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super);
+		block_nr = fs->image_header->offset_inode / fs->blocksize;
+		block_nr += (ino - 1) / inodes_per_block;
+		offset = ((ino - 1) % inodes_per_block) *
+			EXT2_INODE_SIZE(fs->super);
+		io = fs->image_io;
+	} else {
+		group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
+		offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
+			EXT2_INODE_SIZE(fs->super);
+		block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
+		if (!fs->group_desc[(unsigned)group].bg_inode_table)
+			return EXT2_ET_MISSING_INODE_TABLE;
+		block_nr = fs->group_desc[(unsigned)group].bg_inode_table +
+			block;
+		io = fs->io;
+	}
+	offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
+
+	length = EXT2_INODE_SIZE(fs->super);
+	if (bufsize < length)
+		length = bufsize;
+
+	ptr = (char *) inode;
+	while (length) {
+		clen = length;
+		if ((offset + length) > fs->blocksize)
+			clen = fs->blocksize - offset;
+
+		if (block_nr != fs->icache->buffer_blk) {
+			retval = io_channel_read_blk(io, block_nr, 1,
+						     fs->icache->buffer);
+			if (retval)
+				return retval;
+			fs->icache->buffer_blk = block_nr;
+		}
+
+		memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset,
+		       clen);
+
+		offset = 0;
+		length -= clen;
+		ptr += clen;
+		block_nr++;
+	}
+
+#if BB_BIG_ENDIAN
+	if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+	    (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
+		ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) inode,
+				       (struct ext2_inode_large *) inode,
+				       0, length);
+#endif
+
+	/* Update the inode cache */
+	fs->icache->cache_last = (fs->icache->cache_last + 1) %
+		fs->icache->cache_size;
+	fs->icache->cache[fs->icache->cache_last].ino = ino;
+	fs->icache->cache[fs->icache->cache_last].inode = *inode;
+
+	return 0;
+}
+
+errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino,
+			    struct ext2_inode * inode)
+{
+	return ext2fs_read_inode_full(fs, ino, inode,
+					sizeof(struct ext2_inode));
+}
+
+errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
+				  struct ext2_inode * inode, int bufsize)
+{
+	unsigned long group, block, block_nr, offset;
+	errcode_t retval = 0;
+	struct ext2_inode_large temp_inode, *w_inode;
+	char *ptr;
+	int clen, i, length;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	/* Check to see if user provided an override function */
+	if (fs->write_inode) {
+		retval = (fs->write_inode)(fs, ino, inode);
+		if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
+			return retval;
+	}
+
+	/* Check to see if the inode cache needs to be updated */
+	if (fs->icache) {
+		for (i=0; i < fs->icache->cache_size; i++) {
+			if (fs->icache->cache[i].ino == ino) {
+				fs->icache->cache[i].inode = *inode;
+				break;
+			}
+		}
+	} else {
+		retval = create_icache(fs);
+		if (retval)
+			return retval;
+	}
+
+	if (!(fs->flags & EXT2_FLAG_RW))
+		return EXT2_ET_RO_FILSYS;
+
+	if ((ino == 0) || (ino > fs->super->s_inodes_count))
+		return EXT2_ET_BAD_INODE_NUM;
+
+	length = bufsize;
+	if (length < EXT2_INODE_SIZE(fs->super))
+		length = EXT2_INODE_SIZE(fs->super);
+
+	if (length > (int) sizeof(struct ext2_inode_large)) {
+		w_inode = xmalloc(length);
+	} else
+		w_inode = &temp_inode;
+	memset(w_inode, 0, length);
+
+#if BB_BIG_ENDIAN
+	if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+	    (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
+		ext2fs_swap_inode_full(fs, w_inode,
+				       (struct ext2_inode_large *) inode,
+				       1, bufsize);
+	else
+#endif
+		memcpy(w_inode, inode, bufsize);
+
+	group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
+	offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
+		EXT2_INODE_SIZE(fs->super);
+	block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
+	if (!fs->group_desc[(unsigned) group].bg_inode_table)
+		return EXT2_ET_MISSING_INODE_TABLE;
+	block_nr = fs->group_desc[(unsigned) group].bg_inode_table + block;
+
+	offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
+
+	length = EXT2_INODE_SIZE(fs->super);
+	if (length > bufsize)
+		length = bufsize;
+
+	ptr = (char *) w_inode;
+
+	while (length) {
+		clen = length;
+		if ((offset + length) > fs->blocksize)
+			clen = fs->blocksize - offset;
+
+		if (fs->icache->buffer_blk != block_nr) {
+			retval = io_channel_read_blk(fs->io, block_nr, 1,
+						     fs->icache->buffer);
+			if (retval)
+				goto errout;
+			fs->icache->buffer_blk = block_nr;
+		}
+
+
+		memcpy((char *) fs->icache->buffer + (unsigned) offset,
+		       ptr, clen);
+
+		retval = io_channel_write_blk(fs->io, block_nr, 1,
+					      fs->icache->buffer);
+		if (retval)
+			goto errout;
+
+		offset = 0;
+		ptr += clen;
+		length -= clen;
+		block_nr++;
+	}
+
+	fs->flags |= EXT2_FLAG_CHANGED;
+errout:
+	if (w_inode && w_inode != &temp_inode)
+		free(w_inode);
+	return retval;
+}
+
+errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
+			     struct ext2_inode *inode)
+{
+	return ext2fs_write_inode_full(fs, ino, inode,
+				       sizeof(struct ext2_inode));
+}
+
+/*
+ * This function should be called when writing a new inode.  It makes
+ * sure that extra part of large inodes is initialized properly.
+ */
+errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
+				 struct ext2_inode *inode)
+{
+	struct ext2_inode	*buf;
+	int			size = EXT2_INODE_SIZE(fs->super);
+	struct ext2_inode_large	*large_inode;
+
+	if (size == sizeof(struct ext2_inode))
+		return ext2fs_write_inode_full(fs, ino, inode,
+					       sizeof(struct ext2_inode));
+
+	buf = xmalloc(size);
+
+	memset(buf, 0, size);
+	*buf = *inode;
+
+	large_inode = (struct ext2_inode_large *) buf;
+	large_inode->i_extra_isize = sizeof(struct ext2_inode_large) -
+		EXT2_GOOD_OLD_INODE_SIZE;
+
+	return ext2fs_write_inode_full(fs, ino, buf, size);
+}
+
+
+errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks)
+{
+	struct ext2_inode	inode;
+	int			i;
+	errcode_t		retval;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (ino > fs->super->s_inodes_count)
+		return EXT2_ET_BAD_INODE_NUM;
+
+	if (fs->get_blocks) {
+		if (!(*fs->get_blocks)(fs, ino, blocks))
+			return 0;
+	}
+	retval = ext2fs_read_inode(fs, ino, &inode);
+	if (retval)
+		return retval;
+	for (i=0; i < EXT2_N_BLOCKS; i++)
+		blocks[i] = inode.i_block[i];
+	return 0;
+}
+
+errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino)
+{
+	struct	ext2_inode	inode;
+	errcode_t		retval;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (ino > fs->super->s_inodes_count)
+		return EXT2_ET_BAD_INODE_NUM;
+
+	if (fs->check_directory) {
+		retval = (fs->check_directory)(fs, ino);
+		if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
+			return retval;
+	}
+	retval = ext2fs_read_inode(fs, ino, &inode);
+	if (retval)
+		return retval;
+	if (!LINUX_S_ISDIR(inode.i_mode))
+		return EXT2_ET_NO_DIRECTORY;
+	return 0;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/inode_io.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/inode_io.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/inode_io.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,270 @@
+/*
+ * inode_io.c --- This is allows an inode in an ext2 filesystem image
+ *	to be accessed via the I/O manager interface.
+ *
+ * Copyright (C) 2002 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <time.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * For checking structure magic numbers...
+ */
+
+#define EXT2_CHECK_MAGIC(struct, code) \
+	  if ((struct)->magic != (code)) return (code)
+
+struct inode_private_data {
+	int				magic;
+	char				name[32];
+	ext2_file_t			file;
+	ext2_filsys			fs;
+	ext2_ino_t			ino;
+	struct ext2_inode		inode;
+	int				flags;
+	struct inode_private_data	*next;
+};
+
+#define CHANNEL_HAS_INODE	0x8000
+
+static struct inode_private_data *top_intern;
+static int ino_unique = 0;
+
+static errcode_t inode_open(const char *name, int flags, io_channel *channel);
+static errcode_t inode_close(io_channel channel);
+static errcode_t inode_set_blksize(io_channel channel, int blksize);
+static errcode_t inode_read_blk(io_channel channel, unsigned long block,
+			       int count, void *data);
+static errcode_t inode_write_blk(io_channel channel, unsigned long block,
+				int count, const void *data);
+static errcode_t inode_flush(io_channel channel);
+static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
+				int size, const void *data);
+
+static struct struct_io_manager struct_inode_manager = {
+	EXT2_ET_MAGIC_IO_MANAGER,
+	"Inode I/O Manager",
+	inode_open,
+	inode_close,
+	inode_set_blksize,
+	inode_read_blk,
+	inode_write_blk,
+	inode_flush,
+	inode_write_byte
+};
+
+io_manager inode_io_manager = &struct_inode_manager;
+
+errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
+				  struct ext2_inode *inode,
+				  char **name)
+{
+	struct inode_private_data	*data;
+	errcode_t			retval;
+
+	if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data),
+				     &data)))
+		return retval;
+	data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL;
+	sprintf(data->name, "%u:%d", ino, ino_unique++);
+	data->file = 0;
+	data->fs = fs;
+	data->ino = ino;
+	data->flags = 0;
+	if (inode) {
+		memcpy(&data->inode, inode, sizeof(struct ext2_inode));
+		data->flags |= CHANNEL_HAS_INODE;
+	}
+	data->next = top_intern;
+	top_intern = data;
+	*name = data->name;
+	return 0;
+}
+
+errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
+				 char **name)
+{
+	return ext2fs_inode_io_intern2(fs, ino, NULL, name);
+}
+
+
+static errcode_t inode_open(const char *name, int flags, io_channel *channel)
+{
+	io_channel	io = NULL;
+	struct inode_private_data *prev, *data = NULL;
+	errcode_t	retval;
+	int		open_flags;
+
+	if (name == 0)
+		return EXT2_ET_BAD_DEVICE_NAME;
+
+	for (data = top_intern, prev = NULL; data;
+	     prev = data, data = data->next)
+		if (strcmp(name, data->name) == 0)
+			break;
+	if (!data)
+		return ENOENT;
+	if (prev)
+		prev->next = data->next;
+	else
+		top_intern = data->next;
+
+	retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
+	if (retval)
+		goto cleanup;
+	memset(io, 0, sizeof(struct struct_io_channel));
+
+	io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
+	io->manager = inode_io_manager;
+	retval = ext2fs_get_mem(strlen(name)+1, &io->name);
+	if (retval)
+		goto cleanup;
+
+	strcpy(io->name, name);
+	io->private_data = data;
+	io->block_size = 1024;
+	io->read_error = 0;
+	io->write_error = 0;
+	io->refcount = 1;
+
+	open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0;
+	retval = ext2fs_file_open2(data->fs, data->ino,
+				   (data->flags & CHANNEL_HAS_INODE) ?
+				   &data->inode : 0, open_flags,
+				   &data->file);
+	if (retval)
+		goto cleanup;
+
+	*channel = io;
+	return 0;
+
+cleanup:
+	if (data) {
+		ext2fs_free_mem(&data);
+	}
+	if (io)
+		ext2fs_free_mem(&io);
+	return retval;
+}
+
+static errcode_t inode_close(io_channel channel)
+{
+	struct inode_private_data *data;
+	errcode_t	retval = 0;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct inode_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
+
+	if (--channel->refcount > 0)
+		return 0;
+
+	retval = ext2fs_file_close(data->file);
+
+	ext2fs_free_mem(&channel->private_data);
+	if (channel->name)
+		ext2fs_free_mem(&channel->name);
+	ext2fs_free_mem(&channel);
+	return retval;
+}
+
+static errcode_t inode_set_blksize(io_channel channel, int blksize)
+{
+	struct inode_private_data *data;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct inode_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
+
+	channel->block_size = blksize;
+	return 0;
+}
+
+
+static errcode_t inode_read_blk(io_channel channel, unsigned long block,
+			       int count, void *buf)
+{
+	struct inode_private_data *data;
+	errcode_t	retval;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct inode_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
+
+	if ((retval = ext2fs_file_lseek(data->file,
+					block * channel->block_size,
+					EXT2_SEEK_SET, 0)))
+		return retval;
+
+	count = (count < 0) ? -count : (count * channel->block_size);
+
+	return ext2fs_file_read(data->file, buf, count, 0);
+}
+
+static errcode_t inode_write_blk(io_channel channel, unsigned long block,
+				int count, const void *buf)
+{
+	struct inode_private_data *data;
+	errcode_t	retval;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct inode_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
+
+	if ((retval = ext2fs_file_lseek(data->file,
+					block * channel->block_size,
+					EXT2_SEEK_SET, 0)))
+		return retval;
+
+	count = (count < 0) ? -count : (count * channel->block_size);
+
+	return ext2fs_file_write(data->file, buf, count, 0);
+}
+
+static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
+				 int size, const void *buf)
+{
+	struct inode_private_data *data;
+	errcode_t	retval = 0;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct inode_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
+
+	if ((retval = ext2fs_file_lseek(data->file, offset,
+					EXT2_SEEK_SET, 0)))
+		return retval;
+
+	return ext2fs_file_write(data->file, buf, size, 0);
+}
+
+/*
+ * Flush data buffers to disk.
+ */
+static errcode_t inode_flush(io_channel channel)
+{
+	struct inode_private_data *data;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct inode_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
+
+	return ext2fs_file_flush(data->file);
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/io_manager.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/io_manager.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/io_manager.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,69 @@
+/*
+ * io_manager.c --- the I/O manager abstraction
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+errcode_t io_channel_set_options(io_channel channel, const char *opts)
+{
+	errcode_t retval = 0;
+	char *next, *ptr, *options, *arg;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+
+	if (!opts)
+		return 0;
+
+	if (!channel->manager->set_option)
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	options = malloc(strlen(opts)+1);
+	if (!options)
+		return EXT2_ET_NO_MEMORY;
+	strcpy(options, opts);
+	ptr = options;
+
+	while (ptr && *ptr) {
+		next = strchr(ptr, '&');
+		if (next)
+			*next++ = 0;
+
+		arg = strchr(ptr, '=');
+		if (arg)
+			*arg++ = 0;
+
+		retval = (channel->manager->set_option)(channel, ptr, arg);
+		if (retval)
+			break;
+		ptr = next;
+	}
+	free(options);
+	return retval;
+}
+
+errcode_t io_channel_write_byte(io_channel channel, unsigned long offset,
+				int count, const void *data)
+{
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+
+	if (channel->manager->write_byte)
+		return channel->manager->write_byte(channel, offset,
+						    count, data);
+
+	return EXT2_ET_UNIMPLEMENTED;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/irel.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/irel.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/irel.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,114 @@
+/*
+ * irel.h
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+struct ext2_inode_reference {
+	blk_t	block;
+	__u16 offset;
+};
+
+struct ext2_inode_relocate_entry {
+	ext2_ino_t	new;
+	ext2_ino_t	orig;
+	__u16		flags;
+	__u16		max_refs;
+};
+
+typedef struct ext2_inode_relocation_table *ext2_irel;
+
+struct ext2_inode_relocation_table {
+	__u32	magic;
+	char	*name;
+	ext2_ino_t	current;
+	void	*priv_data;
+
+	/*
+	 * Add an inode relocation entry.
+	 */
+	errcode_t (*put)(ext2_irel irel, ext2_ino_t old,
+			      struct ext2_inode_relocate_entry *ent);
+	/*
+	 * Get an inode relocation entry.
+	 */
+	errcode_t (*get)(ext2_irel irel, ext2_ino_t old,
+			      struct ext2_inode_relocate_entry *ent);
+
+	/*
+	 * Get an inode relocation entry by its original inode number
+	 */
+	errcode_t (*get_by_orig)(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
+				 struct ext2_inode_relocate_entry *ent);
+
+	/*
+	 * Initialize for iterating over the inode relocation entries.
+	 */
+	errcode_t (*start_iter)(ext2_irel irel);
+
+	/*
+	 * The iterator function for the inode relocation entries.
+	 * Returns an inode number of 0 when out of entries.
+	 */
+	errcode_t (*next)(ext2_irel irel, ext2_ino_t *old,
+			  struct ext2_inode_relocate_entry *ent);
+
+	/*
+	 * Add an inode reference (i.e., note the fact that a
+	 * particular block/offset contains a reference to an inode)
+	 */
+	errcode_t (*add_ref)(ext2_irel irel, ext2_ino_t ino,
+			     struct ext2_inode_reference *ref);
+
+	/*
+	 * Initialize for iterating over the inode references for a
+	 * particular inode.
+	 */
+	errcode_t (*start_iter_ref)(ext2_irel irel, ext2_ino_t ino);
+
+	/*
+	 * The iterator function for the inode references for an
+	 * inode.  The references for only one inode can be interator
+	 * over at a time, as the iterator state is stored in ext2_irel.
+	 */
+	errcode_t (*next_ref)(ext2_irel irel,
+			      struct ext2_inode_reference *ref);
+
+	/*
+	 * Move the inode relocation table from one inode number to
+	 * another.  Note that the inode references also must move.
+	 */
+	errcode_t (*move)(ext2_irel irel, ext2_ino_t old, ext2_ino_t new);
+
+	/*
+	 * Remove an inode relocation entry, along with all of the
+	 * inode references.
+	 */
+	errcode_t (*delete)(ext2_irel irel, ext2_ino_t old);
+
+	/*
+	 * Free the inode relocation table.
+	 */
+	errcode_t (*free)(ext2_irel irel);
+};
+
+errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode,
+				    ext2_irel *irel);
+
+#define ext2fs_irel_put(irel, old, ent) ((irel)->put((irel), old, ent))
+#define ext2fs_irel_get(irel, old, ent) ((irel)->get((irel), old, ent))
+#define ext2fs_irel_get_by_orig(irel, orig, old, ent) \
+			((irel)->get_by_orig((irel), orig, old, ent))
+#define ext2fs_irel_start_iter(irel) ((irel)->start_iter((irel)))
+#define ext2fs_irel_next(irel, old, ent) ((irel)->next((irel), old, ent))
+#define ext2fs_irel_add_ref(irel, ino, ref) ((irel)->add_ref((irel), ino, ref))
+#define ext2fs_irel_start_iter_ref(irel, ino) ((irel)->start_iter_ref((irel), ino))
+#define ext2fs_irel_next_ref(irel, ref) ((irel)->next_ref((irel), ref))
+#define ext2fs_irel_move(irel, old, new) ((irel)->move((irel), old, new))
+#define ext2fs_irel_delete(irel, old) ((irel)->delete((irel), old))
+#define ext2fs_irel_free(irel) ((irel)->free((irel)))

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/irel_ma.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/irel_ma.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/irel_ma.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,366 @@
+/*
+ * irel_ma.c
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+#include "irel.h"
+
+static errcode_t ima_put(ext2_irel irel, ext2_ino_t old,
+			 struct ext2_inode_relocate_entry *ent);
+static errcode_t ima_get(ext2_irel irel, ext2_ino_t old,
+			 struct ext2_inode_relocate_entry *ent);
+static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
+				 struct ext2_inode_relocate_entry *ent);
+static errcode_t ima_start_iter(ext2_irel irel);
+static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old,
+			  struct ext2_inode_relocate_entry *ent);
+static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino,
+			     struct ext2_inode_reference *ref);
+static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino);
+static errcode_t ima_next_ref(ext2_irel irel, struct ext2_inode_reference *ref);
+static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new);
+static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old);
+static errcode_t ima_free(ext2_irel irel);
+
+/*
+ * This data structure stores the array of inode references; there is
+ * a structure for each inode.
+ */
+struct inode_reference_entry {
+	__u16 num;
+	struct ext2_inode_reference *refs;
+};
+
+struct irel_ma {
+	__u32 magic;
+	ext2_ino_t max_inode;
+	ext2_ino_t ref_current;
+	int   ref_iter;
+	ext2_ino_t	*orig_map;
+	struct ext2_inode_relocate_entry *entries;
+	struct inode_reference_entry *ref_entries;
+};
+
+errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode,
+				      ext2_irel *new_irel)
+{
+	ext2_irel		irel = 0;
+	errcode_t	retval;
+	struct irel_ma	*ma = 0;
+	size_t		size;
+
+	*new_irel = 0;
+
+	/*
+	 * Allocate memory structures
+	 */
+	retval = ext2fs_get_mem(sizeof(struct ext2_inode_relocation_table),
+				&irel);
+	if (retval)
+		goto errout;
+	memset(irel, 0, sizeof(struct ext2_inode_relocation_table));
+
+	retval = ext2fs_get_mem(strlen(name)+1, &irel->name);
+	if (retval)
+		goto errout;
+	strcpy(irel->name, name);
+
+	retval = ext2fs_get_mem(sizeof(struct irel_ma), &ma);
+	if (retval)
+		goto errout;
+	memset(ma, 0, sizeof(struct irel_ma));
+	irel->priv_data = ma;
+
+	size = (size_t) (sizeof(ext2_ino_t) * (max_inode+1));
+	retval = ext2fs_get_mem(size, &ma->orig_map);
+	if (retval)
+		goto errout;
+	memset(ma->orig_map, 0, size);
+
+	size = (size_t) (sizeof(struct ext2_inode_relocate_entry) *
+			 (max_inode+1));
+	retval = ext2fs_get_mem(size, &ma->entries);
+	if (retval)
+		goto errout;
+	memset(ma->entries, 0, size);
+
+	size = (size_t) (sizeof(struct inode_reference_entry) *
+			 (max_inode+1));
+	retval = ext2fs_get_mem(size, &ma->ref_entries);
+	if (retval)
+		goto errout;
+	memset(ma->ref_entries, 0, size);
+	ma->max_inode = max_inode;
+
+	/*
+	 * Fill in the irel data structure
+	 */
+	irel->put = ima_put;
+	irel->get = ima_get;
+	irel->get_by_orig = ima_get_by_orig;
+	irel->start_iter = ima_start_iter;
+	irel->next = ima_next;
+	irel->add_ref = ima_add_ref;
+	irel->start_iter_ref = ima_start_iter_ref;
+	irel->next_ref = ima_next_ref;
+	irel->move = ima_move;
+	irel->delete = ima_delete;
+	irel->free = ima_free;
+
+	*new_irel = irel;
+	return 0;
+
+errout:
+	ima_free(irel);
+	return retval;
+}
+
+static errcode_t ima_put(ext2_irel irel, ext2_ino_t old,
+			struct ext2_inode_relocate_entry *ent)
+{
+	struct inode_reference_entry	*ref_ent;
+	struct irel_ma			*ma;
+	errcode_t			retval;
+	size_t				size, old_size;
+
+	ma = irel->priv_data;
+	if (old > ma->max_inode)
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	/*
+	 * Force the orig field to the correct value; the application
+	 * program shouldn't be messing with this field.
+	 */
+	if (ma->entries[(unsigned) old].new == 0)
+		ent->orig = old;
+	else
+		ent->orig = ma->entries[(unsigned) old].orig;
+
+	/*
+	 * If max_refs has changed, reallocate the refs array
+	 */
+	ref_ent = ma->ref_entries + (unsigned) old;
+	if (ref_ent->refs && ent->max_refs !=
+	    ma->entries[(unsigned) old].max_refs) {
+		size = (sizeof(struct ext2_inode_reference) * ent->max_refs);
+		old_size = (sizeof(struct ext2_inode_reference) *
+			    ma->entries[(unsigned) old].max_refs);
+		retval = ext2fs_resize_mem(old_size, size, &ref_ent->refs);
+		if (retval)
+			return retval;
+	}
+
+	ma->entries[(unsigned) old] = *ent;
+	ma->orig_map[(unsigned) ent->orig] = old;
+	return 0;
+}
+
+static errcode_t ima_get(ext2_irel irel, ext2_ino_t old,
+			struct ext2_inode_relocate_entry *ent)
+{
+	struct irel_ma	*ma;
+
+	ma = irel->priv_data;
+	if (old > ma->max_inode)
+		return EXT2_ET_INVALID_ARGUMENT;
+	if (ma->entries[(unsigned) old].new == 0)
+		return ENOENT;
+	*ent = ma->entries[(unsigned) old];
+	return 0;
+}
+
+static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
+			struct ext2_inode_relocate_entry *ent)
+{
+	struct irel_ma	*ma;
+	ext2_ino_t	ino;
+
+	ma = irel->priv_data;
+	if (orig > ma->max_inode)
+		return EXT2_ET_INVALID_ARGUMENT;
+	ino = ma->orig_map[(unsigned) orig];
+	if (ino == 0)
+		return ENOENT;
+	*old = ino;
+	*ent = ma->entries[(unsigned) ino];
+	return 0;
+}
+
+static errcode_t ima_start_iter(ext2_irel irel)
+{
+	irel->current = 0;
+	return 0;
+}
+
+static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old,
+			 struct ext2_inode_relocate_entry *ent)
+{
+	struct irel_ma	*ma;
+
+	ma = irel->priv_data;
+	while (++irel->current < ma->max_inode) {
+		if (ma->entries[(unsigned) irel->current].new == 0)
+			continue;
+		*old = irel->current;
+		*ent = ma->entries[(unsigned) irel->current];
+		return 0;
+	}
+	*old = 0;
+	return 0;
+}
+
+static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino,
+			     struct ext2_inode_reference *ref)
+{
+	struct irel_ma	*ma;
+	size_t		size;
+	struct inode_reference_entry *ref_ent;
+	struct ext2_inode_relocate_entry *ent;
+	errcode_t		retval;
+
+	ma = irel->priv_data;
+	if (ino > ma->max_inode)
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	ref_ent = ma->ref_entries + (unsigned) ino;
+	ent = ma->entries + (unsigned) ino;
+
+	/*
+	 * If the inode reference array doesn't exist, create it.
+	 */
+	if (ref_ent->refs == 0) {
+		size = (size_t) ((sizeof(struct ext2_inode_reference) *
+				  ent->max_refs));
+		retval = ext2fs_get_mem(size, &ref_ent->refs);
+		if (retval)
+			return retval;
+		memset(ref_ent->refs, 0, size);
+		ref_ent->num = 0;
+	}
+
+	if (ref_ent->num >= ent->max_refs)
+		return EXT2_ET_TOO_MANY_REFS;
+
+	ref_ent->refs[(unsigned) ref_ent->num++] = *ref;
+	return 0;
+}
+
+static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino)
+{
+	struct irel_ma	*ma;
+
+	ma = irel->priv_data;
+	if (ino > ma->max_inode)
+		return EXT2_ET_INVALID_ARGUMENT;
+	if (ma->entries[(unsigned) ino].new == 0)
+		return ENOENT;
+	ma->ref_current = ino;
+	ma->ref_iter = 0;
+	return 0;
+}
+
+static errcode_t ima_next_ref(ext2_irel irel,
+			      struct ext2_inode_reference *ref)
+{
+	struct irel_ma	*ma;
+	struct inode_reference_entry *ref_ent;
+
+	ma = irel->priv_data;
+
+	ref_ent = ma->ref_entries + ma->ref_current;
+
+	if ((ref_ent->refs == NULL) ||
+	    (ma->ref_iter >= ref_ent->num)) {
+		ref->block = 0;
+		ref->offset = 0;
+		return 0;
+	}
+	*ref = ref_ent->refs[ma->ref_iter++];
+	return 0;
+}
+
+
+static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new)
+{
+	struct irel_ma	*ma;
+
+	ma = irel->priv_data;
+	if ((old > ma->max_inode) || (new > ma->max_inode))
+		return EXT2_ET_INVALID_ARGUMENT;
+	if (ma->entries[(unsigned) old].new == 0)
+		return ENOENT;
+
+	ma->entries[(unsigned) new] = ma->entries[(unsigned) old];
+	ext2fs_free_mem(&ma->ref_entries[(unsigned) new].refs);
+	ma->ref_entries[(unsigned) new] = ma->ref_entries[(unsigned) old];
+
+	ma->entries[(unsigned) old].new = 0;
+	ma->ref_entries[(unsigned) old].num = 0;
+	ma->ref_entries[(unsigned) old].refs = 0;
+
+	ma->orig_map[ma->entries[new].orig] = new;
+	return 0;
+}
+
+static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old)
+{
+	struct irel_ma	*ma;
+
+	ma = irel->priv_data;
+	if (old > ma->max_inode)
+		return EXT2_ET_INVALID_ARGUMENT;
+	if (ma->entries[(unsigned) old].new == 0)
+		return ENOENT;
+
+	ma->entries[old].new = 0;
+	ext2fs_free_mem(&ma->ref_entries[(unsigned) old].refs);
+	ma->orig_map[ma->entries[(unsigned) old].orig] = 0;
+
+	ma->ref_entries[(unsigned) old].num = 0;
+	ma->ref_entries[(unsigned) old].refs = 0;
+	return 0;
+}
+
+static errcode_t ima_free(ext2_irel irel)
+{
+	struct irel_ma	*ma;
+	ext2_ino_t	ino;
+
+	if (!irel)
+		return 0;
+
+	ma = irel->priv_data;
+
+	if (ma) {
+		ext2fs_free_mem(&ma->orig_map);
+		ext2fs_free_mem(&ma->entries);
+		if (ma->ref_entries) {
+			for (ino = 0; ino <= ma->max_inode; ino++) {
+				ext2fs_free_mem(&ma->ref_entries[(unsigned) ino].refs);
+			}
+			ext2fs_free_mem(&ma->ref_entries);
+		}
+		ext2fs_free_mem(&ma);
+	}
+	ext2fs_free_mem(&irel->name);
+	ext2fs_free_mem(&irel);
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ismounted.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ismounted.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/ismounted.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,356 @@
+/*
+ * ismounted.c --- Check to see if the filesystem was mounted
+ *
+ * Copyright (C) 1995,1996,1997,1998,1999,2000 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <fcntl.h>
+#ifdef HAVE_LINUX_FD_H
+#include <linux/fd.h>
+#endif
+#ifdef HAVE_MNTENT_H
+#include <mntent.h>
+#endif
+#ifdef HAVE_GETMNTINFO
+#include <paths.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#endif /* HAVE_GETMNTINFO */
+#include <string.h>
+#include <sys/stat.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#ifdef HAVE_MNTENT_H
+/*
+ * Helper function which checks a file in /etc/mtab format to see if a
+ * filesystem is mounted.  Returns an error if the file doesn't exist
+ * or can't be opened.
+ */
+static errcode_t check_mntent_file(const char *mtab_file, const char *file,
+				   int *mount_flags, char *mtpt, int mtlen)
+{
+	struct mntent	*mnt;
+	struct stat	st_buf;
+	errcode_t	retval = 0;
+	dev_t		file_dev=0, file_rdev=0;
+	ino_t		file_ino=0;
+	FILE		*f;
+	int		fd;
+
+	*mount_flags = 0;
+	if ((f = setmntent (mtab_file, "r")) == NULL)
+		return errno;
+	if (stat(file, &st_buf) == 0) {
+		if (S_ISBLK(st_buf.st_mode)) {
+#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
+			file_rdev = st_buf.st_rdev;
+#endif	/* __GNU__ */
+		} else {
+			file_dev = st_buf.st_dev;
+			file_ino = st_buf.st_ino;
+		}
+	}
+	while ((mnt = getmntent (f)) != NULL) {
+		if (strcmp(file, mnt->mnt_fsname) == 0)
+			break;
+		if (stat(mnt->mnt_fsname, &st_buf) == 0) {
+			if (S_ISBLK(st_buf.st_mode)) {
+#ifndef __GNU__
+				if (file_rdev && (file_rdev == st_buf.st_rdev))
+					break;
+#endif	/* __GNU__ */
+			} else {
+				if (file_dev && ((file_dev == st_buf.st_dev) &&
+						 (file_ino == st_buf.st_ino)))
+					break;
+			}
+		}
+	}
+
+	if (mnt == 0) {
+#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
+		/*
+		 * Do an extra check to see if this is the root device.  We
+		 * can't trust /etc/mtab, and /proc/mounts will only list
+		 * /dev/root for the root filesystem.  Argh.  Instead we
+		 * check if the given device has the same major/minor number
+		 * as the device that the root directory is on.
+		 */
+		if (file_rdev && stat("/", &st_buf) == 0) {
+			if (st_buf.st_dev == file_rdev) {
+				*mount_flags = EXT2_MF_MOUNTED;
+				if (mtpt)
+					strncpy(mtpt, "/", mtlen);
+				goto is_root;
+			}
+		}
+#endif	/* __GNU__ */
+		goto errout;
+	}
+#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
+	/* Validate the entry in case /etc/mtab is out of date */
+	/*
+	 * We need to be paranoid, because some broken distributions
+	 * (read: Slackware) don't initialize /etc/mtab before checking
+	 * all of the non-root filesystems on the disk.
+	 */
+	if (stat(mnt->mnt_dir, &st_buf) < 0) {
+		retval = errno;
+		if (retval == ENOENT) {
+#ifdef DEBUG
+			printf("Bogus entry in %s!  (%s does not exist)\n",
+			       mtab_file, mnt->mnt_dir);
+#endif /* DEBUG */
+			retval = 0;
+		}
+		goto errout;
+	}
+	if (file_rdev && (st_buf.st_dev != file_rdev)) {
+#ifdef DEBUG
+		printf("Bogus entry in %s!  (%s not mounted on %s)\n",
+		       mtab_file, file, mnt->mnt_dir);
+#endif /* DEBUG */
+		goto errout;
+	}
+#endif /* __GNU__ */
+	*mount_flags = EXT2_MF_MOUNTED;
+
+#ifdef MNTOPT_RO
+	/* Check to see if the ro option is set */
+	if (hasmntopt(mnt, MNTOPT_RO))
+		*mount_flags |= EXT2_MF_READONLY;
+#endif
+
+	if (mtpt)
+		strncpy(mtpt, mnt->mnt_dir, mtlen);
+	/*
+	 * Check to see if we're referring to the root filesystem.
+	 * If so, do a manual check to see if we can open /etc/mtab
+	 * read/write, since if the root is mounted read/only, the
+	 * contents of /etc/mtab may not be accurate.
+	 */
+	if (!strcmp(mnt->mnt_dir, "/")) {
+is_root:
+#define TEST_FILE "/.ismount-test-file"
+		*mount_flags |= EXT2_MF_ISROOT;
+		fd = open(TEST_FILE, O_RDWR|O_CREAT);
+		if (fd < 0) {
+			if (errno == EROFS)
+				*mount_flags |= EXT2_MF_READONLY;
+		} else
+			close(fd);
+		(void) unlink(TEST_FILE);
+	}
+	retval = 0;
+errout:
+	endmntent (f);
+	return retval;
+}
+
+static errcode_t check_mntent(const char *file, int *mount_flags,
+			      char *mtpt, int mtlen)
+{
+	errcode_t	retval;
+
+#ifdef DEBUG
+	retval = check_mntent_file("/tmp/mtab", file, mount_flags,
+				   mtpt, mtlen);
+	if (retval == 0)
+		return 0;
+#endif /* DEBUG */
+#ifdef __linux__
+	retval = check_mntent_file("/proc/mounts", file, mount_flags,
+				   mtpt, mtlen);
+	if (retval == 0 && (*mount_flags != 0))
+		return 0;
+#endif /* __linux__ */
+#if defined(MOUNTED) || defined(_PATH_MOUNTED)
+#ifndef MOUNTED
+#define MOUNTED _PATH_MOUNTED
+#endif /* MOUNTED */
+	retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen);
+	return retval;
+#else
+	*mount_flags = 0;
+	return 0;
+#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
+}
+
+#else
+#if defined(HAVE_GETMNTINFO)
+
+static errcode_t check_getmntinfo(const char *file, int *mount_flags,
+				  char *mtpt, int mtlen)
+{
+	struct statfs *mp;
+	int    len, n;
+	const  char   *s1;
+	char	*s2;
+
+	n = getmntinfo(&mp, MNT_NOWAIT);
+	if (n == 0)
+		return errno;
+
+	len = sizeof(_PATH_DEV) - 1;
+	s1 = file;
+	if (strncmp(_PATH_DEV, s1, len) == 0)
+		s1 += len;
+
+	*mount_flags = 0;
+	while (--n >= 0) {
+		s2 = mp->f_mntfromname;
+		if (strncmp(_PATH_DEV, s2, len) == 0) {
+			s2 += len - 1;
+			*s2 = 'r';
+		}
+		if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) {
+			*mount_flags = EXT2_MF_MOUNTED;
+			break;
+		}
+		++mp;
+	}
+	if (mtpt)
+		strncpy(mtpt, mp->f_mntonname, mtlen);
+	return 0;
+}
+#endif /* HAVE_GETMNTINFO */
+#endif /* HAVE_MNTENT_H */
+
+/*
+ * Check to see if we're dealing with the swap device.
+ */
+static int is_swap_device(const char *file)
+{
+	FILE		*f;
+	char		buf[1024], *cp;
+	dev_t		file_dev;
+	struct stat	st_buf;
+	int		ret = 0;
+
+	file_dev = 0;
+#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
+	if ((stat(file, &st_buf) == 0) &&
+	    S_ISBLK(st_buf.st_mode))
+		file_dev = st_buf.st_rdev;
+#endif	/* __GNU__ */
+
+	if (!(f = fopen("/proc/swaps", "r")))
+		return 0;
+	/* Skip the first line */
+	fgets(buf, sizeof(buf), f);
+	while (!feof(f)) {
+		if (!fgets(buf, sizeof(buf), f))
+			break;
+		if ((cp = strchr(buf, ' ')) != NULL)
+			*cp = 0;
+		if ((cp = strchr(buf, '\t')) != NULL)
+			*cp = 0;
+		if (strcmp(buf, file) == 0) {
+			ret++;
+			break;
+		}
+#ifndef __GNU__
+		if (file_dev && (stat(buf, &st_buf) == 0) &&
+		    S_ISBLK(st_buf.st_mode) &&
+		    file_dev == st_buf.st_rdev) {
+			ret++;
+			break;
+		}
+#endif	/* __GNU__ */
+	}
+	fclose(f);
+	return ret;
+}
+
+
+/*
+ * ext2fs_check_mount_point() returns 1 if the device is mounted, 0
+ * otherwise.  If mtpt is non-NULL, the directory where the device is
+ * mounted is copied to where mtpt is pointing, up to mtlen
+ * characters.
+ */
+#ifdef __TURBOC__
+# pragma argsused
+#endif
+errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
+				  char *mtpt, int mtlen)
+{
+	if (is_swap_device(device)) {
+		*mount_flags = EXT2_MF_MOUNTED | EXT2_MF_SWAP;
+		strncpy(mtpt, "<swap>", mtlen);
+		return 0;
+	}
+#ifdef HAVE_MNTENT_H
+	return check_mntent(device, mount_flags, mtpt, mtlen);
+#else
+#ifdef HAVE_GETMNTINFO
+	return check_getmntinfo(device, mount_flags, mtpt, mtlen);
+#else
+#ifdef __GNUC__
+ #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!"
+#endif
+	*mount_flags = 0;
+	return 0;
+#endif /* HAVE_GETMNTINFO */
+#endif /* HAVE_MNTENT_H */
+}
+
+/*
+ * ext2fs_check_if_mounted() sets the mount_flags EXT2_MF_MOUNTED,
+ * EXT2_MF_READONLY, and EXT2_MF_ROOT
+ *
+ */
+errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags)
+{
+	return ext2fs_check_mount_point(file, mount_flags, NULL, 0);
+}
+
+#ifdef DEBUG
+int main(int argc, char **argv)
+{
+	int	retval, mount_flags;
+	char	mntpt[80];
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s device\n", argv[0]);
+		exit(1);
+	}
+
+	mntpt[0] = 0;
+	retval = ext2fs_check_mount_point(argv[1], &mount_flags,
+					  mntpt, sizeof(mntpt));
+	if (retval) {
+		com_err(argv[0], retval,
+			"while calling ext2fs_check_if_mounted");
+		exit(1);
+	}
+	printf("Device %s reports flags %02x\n", argv[1], mount_flags);
+	if (mount_flags & EXT2_MF_BUSY)
+		printf("\t%s is apparently in use.\n", argv[1]);
+	if (mount_flags & EXT2_MF_MOUNTED)
+		printf("\t%s is mounted.\n", argv[1]);
+	if (mount_flags & EXT2_MF_SWAP)
+		printf("\t%s is a swap device.\n", argv[1]);
+	if (mount_flags & EXT2_MF_READONLY)
+		printf("\t%s is read-only.\n", argv[1]);
+	if (mount_flags & EXT2_MF_ISROOT)
+		printf("\t%s is the root filesystem.\n", argv[1]);
+	if (mntpt[0])
+		printf("\t%s is mounted on %s.\n", argv[1], mntpt);
+	exit(0);
+}
+#endif /* DEBUG */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/jfs_dat.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/jfs_dat.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/jfs_dat.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,64 @@
+/*
+ * jfs_dat.h --- stripped down header file which only contains the JFS
+ *	on-disk data structures
+ */
+
+#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */
+
+/*
+ * On-disk structures
+ */
+
+/*
+ * Descriptor block types:
+ */
+
+#define JFS_DESCRIPTOR_BLOCK	1
+#define JFS_COMMIT_BLOCK	2
+#define JFS_SUPERBLOCK		3
+
+/*
+ * Standard header for all descriptor blocks:
+ */
+typedef struct journal_header_s
+{
+	__u32		h_magic;
+	__u32		h_blocktype;
+	__u32		h_sequence;
+} journal_header_t;
+
+
+/*
+ * The block tag: used to describe a single buffer in the journal
+ */
+typedef struct journal_block_tag_s
+{
+	__u32		t_blocknr;	/* The on-disk block number */
+	__u32		t_flags;	/* See below */
+} journal_block_tag_t;
+
+/* Definitions for the journal tag flags word: */
+#define JFS_FLAG_ESCAPE		1	/* on-disk block is escaped */
+#define JFS_FLAG_SAME_UUID	2	/* block has same uuid as previous */
+#define JFS_FLAG_DELETED	4	/* block deleted by this transaction */
+#define JFS_FLAG_LAST_TAG	8	/* last tag in this descriptor block */
+
+
+/*
+ * The journal superblock
+ */
+typedef struct journal_superblock_s
+{
+	journal_header_t s_header;
+
+	/* Static information describing the journal */
+	__u32		s_blocksize;	/* journal device blocksize */
+	__u32		s_maxlen;	/* total blocks in journal file */
+	__u32		s_first;	/* first block of log information */
+
+	/* Dynamic information describing the current state of the log */
+	__u32		s_sequence;	/* first commit ID expected in log */
+	__u32		s_start;	/* blocknr of start of log */
+
+} journal_superblock_t;
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/kernel-jbd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/kernel-jbd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/kernel-jbd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,235 @@
+/*
+ * linux/include/linux/jbd.h
+ *
+ * Written by Stephen C. Tweedie <sct at redhat.com>
+ *
+ * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * Definitions for transaction data structures for the buffer cache
+ * filesystem journaling support.
+ */
+
+#ifndef _LINUX_JBD_H
+#define _LINUX_JBD_H
+
+#include <sys/types.h>
+#include <linux/types.h>
+#include "ext2fs.h"
+
+/*
+ * Standard header for all descriptor blocks:
+ */
+
+typedef struct journal_header_s
+{
+	__u32		h_magic;
+	__u32		h_blocktype;
+	__u32		h_sequence;
+} journal_header_t;
+
+/*
+ * This is the global e2fsck structure.
+ */
+typedef struct e2fsck_struct *e2fsck_t;
+
+
+struct inode {
+	e2fsck_t        i_ctx;
+	ext2_ino_t      i_ino;
+	struct ext2_inode i_ext2;
+};
+
+
+/*
+ * The journal superblock.  All fields are in big-endian byte order.
+ */
+typedef struct journal_superblock_s
+{
+/* 0x0000 */
+	journal_header_t s_header;
+
+/* 0x000C */
+	/* Static information describing the journal */
+	__u32	s_blocksize;		/* journal device blocksize */
+	__u32	s_maxlen;		/* total blocks in journal file */
+	__u32	s_first;		/* first block of log information */
+
+/* 0x0018 */
+	/* Dynamic information describing the current state of the log */
+	__u32	s_sequence;		/* first commit ID expected in log */
+	__u32	s_start;		/* blocknr of start of log */
+
+/* 0x0020 */
+	/* Error value, as set by journal_abort(). */
+	__s32	s_errno;
+
+/* 0x0024 */
+	/* Remaining fields are only valid in a version-2 superblock */
+	__u32	s_feature_compat;	/* compatible feature set */
+	__u32	s_feature_incompat;	/* incompatible feature set */
+	__u32	s_feature_ro_compat;	/* readonly-compatible feature set */
+/* 0x0030 */
+	__u8	s_uuid[16];		/* 128-bit uuid for journal */
+
+/* 0x0040 */
+	__u32	s_nr_users;		/* Nr of filesystems sharing log */
+
+	__u32	s_dynsuper;		/* Blocknr of dynamic superblock copy*/
+
+/* 0x0048 */
+	__u32	s_max_transaction;	/* Limit of journal blocks per trans.*/
+	__u32	s_max_trans_data;	/* Limit of data blocks per trans. */
+
+/* 0x0050 */
+	__u32	s_padding[44];
+
+/* 0x0100 */
+	__u8	s_users[16*48];		/* ids of all fs'es sharing the log */
+/* 0x0400 */
+} journal_superblock_t;
+
+
+extern int journal_blocks_per_page(struct inode *inode);
+extern int jbd_blocks_per_page(struct inode *inode);
+
+#define JFS_MIN_JOURNAL_BLOCKS 1024
+
+
+/*
+ * Internal structures used by the logging mechanism:
+ */
+
+#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */
+
+/*
+ * Descriptor block types:
+ */
+
+#define JFS_DESCRIPTOR_BLOCK	1
+#define JFS_COMMIT_BLOCK	2
+#define JFS_SUPERBLOCK_V1	3
+#define JFS_SUPERBLOCK_V2	4
+#define JFS_REVOKE_BLOCK	5
+
+/*
+ * The block tag: used to describe a single buffer in the journal
+ */
+typedef struct journal_block_tag_s
+{
+	__u32		t_blocknr;	/* The on-disk block number */
+	__u32		t_flags;	/* See below */
+} journal_block_tag_t;
+
+/*
+ * The revoke descriptor: used on disk to describe a series of blocks to
+ * be revoked from the log
+ */
+typedef struct journal_revoke_header_s
+{
+	journal_header_t r_header;
+	int		 r_count;	/* Count of bytes used in the block */
+} journal_revoke_header_t;
+
+
+/* Definitions for the journal tag flags word: */
+#define JFS_FLAG_ESCAPE		1	/* on-disk block is escaped */
+#define JFS_FLAG_SAME_UUID	2	/* block has same uuid as previous */
+#define JFS_FLAG_DELETED	4	/* block deleted by this transaction */
+#define JFS_FLAG_LAST_TAG	8	/* last tag in this descriptor block */
+
+
+
+
+#define JFS_HAS_COMPAT_FEATURE(j,mask)					\
+	((j)->j_format_version >= 2 &&					\
+	 ((j)->j_superblock->s_feature_compat & cpu_to_be32((mask))))
+#define JFS_HAS_RO_COMPAT_FEATURE(j,mask)				\
+	((j)->j_format_version >= 2 &&					\
+	 ((j)->j_superblock->s_feature_ro_compat & cpu_to_be32((mask))))
+#define JFS_HAS_INCOMPAT_FEATURE(j,mask)				\
+	((j)->j_format_version >= 2 &&					\
+	 ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask))))
+
+#define JFS_FEATURE_INCOMPAT_REVOKE	0x00000001
+
+/* Features known to this kernel version: */
+#define JFS_KNOWN_COMPAT_FEATURES	0
+#define JFS_KNOWN_ROCOMPAT_FEATURES	0
+#define JFS_KNOWN_INCOMPAT_FEATURES	JFS_FEATURE_INCOMPAT_REVOKE
+
+/* Comparison functions for transaction IDs: perform comparisons using
+ * modulo arithmetic so that they work over sequence number wraps. */
+
+
+/*
+ * Definitions which augment the buffer_head layer
+ */
+
+/* journaling buffer types */
+#define BJ_None		0	/* Not journaled */
+#define BJ_SyncData	1	/* Normal data: flush before commit */
+#define BJ_AsyncData	2	/* writepage data: wait on it before commit */
+#define BJ_Metadata	3	/* Normal journaled metadata */
+#define BJ_Forget	4	/* Buffer superceded by this transaction */
+#define BJ_IO		5	/* Buffer is for temporary IO use */
+#define BJ_Shadow	6	/* Buffer contents being shadowed to the log */
+#define BJ_LogCtl	7	/* Buffer contains log descriptors */
+#define BJ_Reserved	8	/* Buffer is reserved for access by journal */
+#define BJ_Types	9
+
+
+struct kdev_s {
+	e2fsck_t        k_ctx;
+	int             k_dev;
+};
+
+typedef struct kdev_s *kdev_t;
+typedef unsigned int tid_t;
+
+struct journal_s
+{
+	unsigned long		j_flags;
+	int			j_errno;
+	struct buffer_head *	j_sb_buffer;
+	struct journal_superblock_s *j_superblock;
+	int			j_format_version;
+	unsigned long		j_head;
+	unsigned long		j_tail;
+	unsigned long		j_free;
+	unsigned long		j_first, j_last;
+	kdev_t			j_dev;
+	kdev_t			j_fs_dev;
+	int			j_blocksize;
+	unsigned int		j_blk_offset;
+	unsigned int		j_maxlen;
+	struct inode *		j_inode;
+	tid_t			j_tail_sequence;
+	tid_t			j_transaction_sequence;
+	__u8			j_uuid[16];
+	struct jbd_revoke_table_s *j_revoke;
+};
+
+typedef struct journal_s journal_t;
+
+extern int	   journal_recover    (journal_t *journal);
+extern int	   journal_skip_recovery (journal_t *);
+
+/* Primary revoke support */
+extern int	   journal_init_revoke(journal_t *, int);
+extern void	   journal_destroy_revoke_caches(void);
+extern int	   journal_init_revoke_caches(void);
+
+/* Recovery revoke support */
+extern int	   journal_set_revoke(journal_t *, unsigned long, tid_t);
+extern int	   journal_test_revoke(journal_t *, unsigned long, tid_t);
+extern void	   journal_clear_revoke(journal_t *);
+extern void	   journal_brelse_array(struct buffer_head *b[], int n);
+
+extern void	   journal_destroy_revoke(journal_t *);
+
+
+#endif	/* _LINUX_JBD_H */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/kernel-list.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/kernel-list.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/kernel-list.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,112 @@
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+	struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+	struct list_head name = { &name, &name }
+
+#define INIT_LIST_HEAD(ptr) do { \
+	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+#if (!defined(__GNUC__) && !defined(__WATCOMC__))
+#define __inline__
+#endif
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_add(struct list_head * new,
+	struct list_head * prev,
+	struct list_head * next)
+{
+	next->prev = new;
+	new->next = next;
+	new->prev = prev;
+	prev->next = new;
+}
+
+/*
+ * Insert a new entry after the specified head..
+ */
+static __inline__ void list_add(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head, head->next);
+}
+
+/*
+ * Insert a new entry at the tail
+ */
+static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_del(struct list_head * prev,
+				  struct list_head * next)
+{
+	next->prev = prev;
+	prev->next = next;
+}
+
+static __inline__ void list_del(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+}
+
+static __inline__ int list_empty(struct list_head *head)
+{
+	return head->next == head;
+}
+
+/*
+ * Splice in "list" into "head"
+ */
+static __inline__ void list_splice(struct list_head *list, struct list_head *head)
+{
+	struct list_head *first = list->next;
+
+	if (first != list) {
+		struct list_head *last = list->prev;
+		struct list_head *at = head->next;
+
+		first->prev = head;
+		head->next = first;
+
+		last->next = at;
+		at->prev = last;
+	}
+}
+
+#define list_entry(ptr, type, member) \
+	((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+#define list_for_each(pos, head) \
+	for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/link.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/link.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/link.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,134 @@
+/*
+ * link.c --- create links in a ext2fs directory
+ *
+ * Copyright (C) 1993, 1994 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct link_struct  {
+	const char	*name;
+	int		namelen;
+	ext2_ino_t	inode;
+	int		flags;
+	int		done;
+	struct ext2_super_block *sb;
+};
+
+static int link_proc(struct ext2_dir_entry *dirent,
+		     int	offset,
+		     int	blocksize,
+		     char	*buf,
+		     void	*priv_data)
+{
+	struct link_struct *ls = (struct link_struct *) priv_data;
+	struct ext2_dir_entry *next;
+	int rec_len, min_rec_len;
+	int ret = 0;
+
+	rec_len = EXT2_DIR_REC_LEN(ls->namelen);
+
+	/*
+	 * See if the following directory entry (if any) is unused;
+	 * if so, absorb it into this one.
+	 */
+	next = (struct ext2_dir_entry *) (buf + offset + dirent->rec_len);
+	if ((offset + dirent->rec_len < blocksize - 8) &&
+	    (next->inode == 0) &&
+	    (offset + dirent->rec_len + next->rec_len <= blocksize)) {
+		dirent->rec_len += next->rec_len;
+		ret = DIRENT_CHANGED;
+	}
+
+	/*
+	 * If the directory entry is used, see if we can split the
+	 * directory entry to make room for the new name.  If so,
+	 * truncate it and return.
+	 */
+	if (dirent->inode) {
+		min_rec_len = EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
+		if (dirent->rec_len < (min_rec_len + rec_len))
+			return ret;
+		rec_len = dirent->rec_len - min_rec_len;
+		dirent->rec_len = min_rec_len;
+		next = (struct ext2_dir_entry *) (buf + offset +
+						  dirent->rec_len);
+		next->inode = 0;
+		next->name_len = 0;
+		next->rec_len = rec_len;
+		return DIRENT_CHANGED;
+	}
+
+	/*
+	 * If we get this far, then the directory entry is not used.
+	 * See if we can fit the request entry in.  If so, do it.
+	 */
+	if (dirent->rec_len < rec_len)
+		return ret;
+	dirent->inode = ls->inode;
+	dirent->name_len = ls->namelen;
+	strncpy(dirent->name, ls->name, ls->namelen);
+	if (ls->sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
+		dirent->name_len |= (ls->flags & 0x7) << 8;
+
+	ls->done++;
+	return DIRENT_ABORT|DIRENT_CHANGED;
+}
+
+/*
+ * Note: the low 3 bits of the flags field are used as the directory
+ * entry filetype.
+ */
+#ifdef __TURBOC__
+# pragma argsused
+#endif
+errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
+		      ext2_ino_t ino, int flags)
+{
+	errcode_t		retval;
+	struct link_struct	ls;
+	struct ext2_inode	inode;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (!(fs->flags & EXT2_FLAG_RW))
+		return EXT2_ET_RO_FILSYS;
+
+	ls.name = name;
+	ls.namelen = name ? strlen(name) : 0;
+	ls.inode = ino;
+	ls.flags = flags;
+	ls.done = 0;
+	ls.sb = fs->super;
+
+	retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
+				    0, link_proc, &ls);
+	if (retval)
+		return retval;
+
+	if (!ls.done)
+		return EXT2_ET_DIR_NO_SPACE;
+
+	if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0)
+		return retval;
+
+	if (inode.i_flags & EXT2_INDEX_FL) {
+		inode.i_flags &= ~EXT2_INDEX_FL;
+		if ((retval = ext2fs_write_inode(fs, dir, &inode)) != 0)
+			return retval;
+	}
+
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/lookup.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/lookup.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/lookup.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,69 @@
+/*
+ * lookup.c --- ext2fs directory lookup operations
+ *
+ * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct lookup_struct  {
+	const char	*name;
+	int		len;
+	ext2_ino_t	*inode;
+	int		found;
+};
+
+#ifdef __TURBOC__
+# pragma argsused
+#endif
+static int lookup_proc(struct ext2_dir_entry *dirent,
+		       int	offset EXT2FS_ATTR((unused)),
+		       int	blocksize EXT2FS_ATTR((unused)),
+		       char	*buf EXT2FS_ATTR((unused)),
+		       void	*priv_data)
+{
+	struct lookup_struct *ls = (struct lookup_struct *) priv_data;
+
+	if (ls->len != (dirent->name_len & 0xFF))
+		return 0;
+	if (strncmp(ls->name, dirent->name, (dirent->name_len & 0xFF)))
+		return 0;
+	*ls->inode = dirent->inode;
+	ls->found++;
+	return DIRENT_ABORT;
+}
+
+
+errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name,
+			int namelen, char *buf, ext2_ino_t *inode)
+{
+	errcode_t	retval;
+	struct lookup_struct ls;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	ls.name = name;
+	ls.len = namelen;
+	ls.inode = inode;
+	ls.found = 0;
+
+	retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls);
+	if (retval)
+		return retval;
+
+	return (ls.found) ? 0 : EXT2_ET_FILE_NOT_FOUND;
+}
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/mkdir.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/mkdir.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/mkdir.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,141 @@
+/*
+ * mkdir.c --- make a directory in the filesystem
+ *
+ * Copyright (C) 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#ifndef EXT2_FT_DIR
+#define EXT2_FT_DIR		2
+#endif
+
+errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
+		       const char *name)
+{
+	errcode_t		retval;
+	struct ext2_inode	parent_inode, inode;
+	ext2_ino_t		ino = inum;
+	ext2_ino_t		scratch_ino;
+	blk_t			blk;
+	char			*block = 0;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	/*
+	 * Allocate an inode, if necessary
+	 */
+	if (!ino) {
+		retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755,
+					  0, &ino);
+		if (retval)
+			goto cleanup;
+	}
+
+	/*
+	 * Allocate a data block for the directory
+	 */
+	retval = ext2fs_new_block(fs, 0, 0, &blk);
+	if (retval)
+		goto cleanup;
+
+	/*
+	 * Create a scratch template for the directory
+	 */
+	retval = ext2fs_new_dir_block(fs, ino, parent, &block);
+	if (retval)
+		goto cleanup;
+
+	/*
+	 * Get the parent's inode, if necessary
+	 */
+	if (parent != ino) {
+		retval = ext2fs_read_inode(fs, parent, &parent_inode);
+		if (retval)
+			goto cleanup;
+	} else
+		memset(&parent_inode, 0, sizeof(parent_inode));
+
+	/*
+	 * Create the inode structure....
+	 */
+	memset(&inode, 0, sizeof(struct ext2_inode));
+	inode.i_mode = LINUX_S_IFDIR | (0777 & ~fs->umask);
+	inode.i_uid = inode.i_gid = 0;
+	inode.i_blocks = fs->blocksize / 512;
+	inode.i_block[0] = blk;
+	inode.i_links_count = 2;
+	inode.i_ctime = inode.i_atime = inode.i_mtime = time(NULL);
+	inode.i_size = fs->blocksize;
+
+	/*
+	 * Write out the inode and inode data block
+	 */
+	retval = ext2fs_write_dir_block(fs, blk, block);
+	if (retval)
+		goto cleanup;
+	retval = ext2fs_write_new_inode(fs, ino, &inode);
+	if (retval)
+		goto cleanup;
+
+	/*
+	 * Link the directory into the filesystem hierarchy
+	 */
+	if (name) {
+		retval = ext2fs_lookup(fs, parent, name, strlen(name), 0,
+				       &scratch_ino);
+		if (!retval) {
+			retval = EXT2_ET_DIR_EXISTS;
+			name = 0;
+			goto cleanup;
+		}
+		if (retval != EXT2_ET_FILE_NOT_FOUND)
+			goto cleanup;
+		retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR);
+		if (retval)
+			goto cleanup;
+	}
+
+	/*
+	 * Update parent inode's counts
+	 */
+	if (parent != ino) {
+		parent_inode.i_links_count++;
+		retval = ext2fs_write_inode(fs, parent, &parent_inode);
+		if (retval)
+			goto cleanup;
+	}
+
+	/*
+	 * Update accounting....
+	 */
+	ext2fs_block_alloc_stats(fs, blk, +1);
+	ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
+
+cleanup:
+	ext2fs_free_mem(&block);
+	return retval;
+
+}
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/mkjournal.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/mkjournal.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/mkjournal.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,426 @@
+/*
+ * mkjournal.c --- make a journal for a filesystem
+ *
+ * Copyright (C) 2000 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#include "ext2_fs.h"
+#include "../e2p/e2p.h"
+#include "../e2fsck.h"
+#include "ext2fs.h"
+#include "kernel-jbd.h"
+
+/*
+ * This function automatically sets up the journal superblock and
+ * returns it as an allocated block.
+ */
+errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
+					   __u32 size, int flags,
+					   char  **ret_jsb)
+{
+	errcode_t		retval;
+	journal_superblock_t	*jsb;
+
+	if (size < 1024)
+		return EXT2_ET_JOURNAL_TOO_SMALL;
+
+	if ((retval = ext2fs_get_mem(fs->blocksize, &jsb)))
+		return retval;
+
+	memset (jsb, 0, fs->blocksize);
+
+	jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
+	if (flags & EXT2_MKJOURNAL_V1_SUPER)
+		jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V1);
+	else
+		jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
+	jsb->s_blocksize = htonl(fs->blocksize);
+	jsb->s_maxlen = htonl(size);
+	jsb->s_nr_users = htonl(1);
+	jsb->s_first = htonl(1);
+	jsb->s_sequence = htonl(1);
+	memcpy(jsb->s_uuid, fs->super->s_uuid, sizeof(fs->super->s_uuid));
+	/*
+	 * If we're creating an external journal device, we need to
+	 * adjust these fields.
+	 */
+	if (fs->super->s_feature_incompat &
+	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+		jsb->s_nr_users = 0;
+		if (fs->blocksize == 1024)
+			jsb->s_first = htonl(3);
+		else
+			jsb->s_first = htonl(2);
+	}
+
+	*ret_jsb = (char *) jsb;
+	return 0;
+}
+
+/*
+ * This function writes a journal using POSIX routines.  It is used
+ * for creating external journals and creating journals on live
+ * filesystems.
+ */
+static errcode_t write_journal_file(ext2_filsys fs, char *filename,
+				    blk_t size, int flags)
+{
+	errcode_t	retval;
+	char		*buf = 0;
+	int		fd, ret_size;
+	blk_t		i;
+
+	if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf)))
+		return retval;
+
+	/* Open the device or journal file */
+	if ((fd = open(filename, O_WRONLY)) < 0) {
+		retval = errno;
+		goto errout;
+	}
+
+	/* Write the superblock out */
+	retval = EXT2_ET_SHORT_WRITE;
+	ret_size = write(fd, buf, fs->blocksize);
+	if (ret_size < 0) {
+		retval = errno;
+		goto errout;
+	}
+	if (ret_size != (int) fs->blocksize)
+		goto errout;
+	memset(buf, 0, fs->blocksize);
+
+	for (i = 1; i < size; i++) {
+		ret_size = write(fd, buf, fs->blocksize);
+		if (ret_size < 0) {
+			retval = errno;
+			goto errout;
+		}
+		if (ret_size != (int) fs->blocksize)
+			goto errout;
+	}
+	close(fd);
+
+	retval = 0;
+errout:
+	ext2fs_free_mem(&buf);
+	return retval;
+}
+
+/*
+ * Helper function for creating the journal using direct I/O routines
+ */
+struct mkjournal_struct {
+	int		num_blocks;
+	int		newblocks;
+	char		*buf;
+	errcode_t	err;
+};
+
+static int mkjournal_proc(ext2_filsys	fs,
+			   blk_t	*blocknr,
+			   e2_blkcnt_t	blockcnt,
+			   blk_t	ref_block EXT2FS_ATTR((unused)),
+			   int		ref_offset EXT2FS_ATTR((unused)),
+			   void		*priv_data)
+{
+	struct mkjournal_struct *es = (struct mkjournal_struct *) priv_data;
+	blk_t	new_blk;
+	static blk_t	last_blk = 0;
+	errcode_t	retval;
+
+	if (*blocknr) {
+		last_blk = *blocknr;
+		return 0;
+	}
+	retval = ext2fs_new_block(fs, last_blk, 0, &new_blk);
+	if (retval) {
+		es->err = retval;
+		return BLOCK_ABORT;
+	}
+	if (blockcnt > 0)
+		es->num_blocks--;
+
+	es->newblocks++;
+	retval = io_channel_write_blk(fs->io, new_blk, 1, es->buf);
+
+	if (blockcnt == 0)
+		memset(es->buf, 0, fs->blocksize);
+
+	if (retval) {
+		es->err = retval;
+		return BLOCK_ABORT;
+	}
+	*blocknr = new_blk;
+	last_blk = new_blk;
+	ext2fs_block_alloc_stats(fs, new_blk, +1);
+
+	if (es->num_blocks == 0)
+		return (BLOCK_CHANGED | BLOCK_ABORT);
+	else
+		return BLOCK_CHANGED;
+
+}
+
+/*
+ * This function creates a journal using direct I/O routines.
+ */
+static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
+				     blk_t size, int flags)
+{
+	char			*buf;
+	errcode_t		retval;
+	struct ext2_inode	inode;
+	struct mkjournal_struct	es;
+
+	if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf)))
+		return retval;
+
+	if ((retval = ext2fs_read_bitmaps(fs)))
+		return retval;
+
+	if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
+		return retval;
+
+	if (inode.i_blocks > 0)
+		return EEXIST;
+
+	es.num_blocks = size;
+	es.newblocks = 0;
+	es.buf = buf;
+	es.err = 0;
+
+	retval = ext2fs_block_iterate2(fs, journal_ino, BLOCK_FLAG_APPEND,
+				       0, mkjournal_proc, &es);
+	if (es.err) {
+		retval = es.err;
+		goto errout;
+	}
+
+	if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
+		goto errout;
+
+	inode.i_size += fs->blocksize * size;
+	inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
+	inode.i_mtime = inode.i_ctime = time(0);
+	inode.i_links_count = 1;
+	inode.i_mode = LINUX_S_IFREG | 0600;
+
+	if ((retval = ext2fs_write_inode(fs, journal_ino, &inode)))
+		goto errout;
+	retval = 0;
+
+	memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4);
+	fs->super->s_jnl_blocks[16] = inode.i_size;
+	fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
+	ext2fs_mark_super_dirty(fs);
+
+errout:
+	ext2fs_free_mem(&buf);
+	return retval;
+}
+
+/*
+ * This function adds a journal device to a filesystem
+ */
+errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
+{
+	struct stat	st;
+	errcode_t	retval;
+	char		buf[1024];
+	journal_superblock_t	*jsb;
+	int		start;
+	__u32		i, nr_users;
+
+	/* Make sure the device exists and is a block device */
+	if (stat(journal_dev->device_name, &st) < 0)
+		return errno;
+
+	if (!S_ISBLK(st.st_mode))
+		return EXT2_ET_JOURNAL_NOT_BLOCK; /* Must be a block device */
+
+	/* Get the journal superblock */
+	start = 1;
+	if (journal_dev->blocksize == 1024)
+		start++;
+	if ((retval = io_channel_read_blk(journal_dev->io, start, -1024, buf)))
+		return retval;
+
+	jsb = (journal_superblock_t *) buf;
+	if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
+	    (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2)))
+		return EXT2_ET_NO_JOURNAL_SB;
+
+	if (ntohl(jsb->s_blocksize) != (unsigned long) fs->blocksize)
+		return EXT2_ET_UNEXPECTED_BLOCK_SIZE;
+
+	/* Check and see if this filesystem has already been added */
+	nr_users = ntohl(jsb->s_nr_users);
+	for (i=0; i < nr_users; i++) {
+		if (memcmp(fs->super->s_uuid,
+			   &jsb->s_users[i*16], 16) == 0)
+			break;
+	}
+	if (i >= nr_users) {
+		memcpy(&jsb->s_users[nr_users*16],
+		       fs->super->s_uuid, 16);
+		jsb->s_nr_users = htonl(nr_users+1);
+	}
+
+	/* Writeback the journal superblock */
+	if ((retval = io_channel_write_blk(journal_dev->io, start, -1024, buf)))
+		return retval;
+
+	fs->super->s_journal_inum = 0;
+	fs->super->s_journal_dev = st.st_rdev;
+	memcpy(fs->super->s_journal_uuid, jsb->s_uuid,
+	       sizeof(fs->super->s_journal_uuid));
+	fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+	ext2fs_mark_super_dirty(fs);
+	return 0;
+}
+
+/*
+ * This function adds a journal inode to a filesystem, using either
+ * POSIX routines if the filesystem is mounted, or using direct I/O
+ * functions if it is not.
+ */
+errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, int flags)
+{
+	errcode_t		retval;
+	ext2_ino_t		journal_ino;
+	struct stat		st;
+	char			jfile[1024];
+	int			fd, mount_flags, f;
+
+	if ((retval = ext2fs_check_mount_point(fs->device_name, &mount_flags,
+					       jfile, sizeof(jfile)-10)))
+		return retval;
+
+	if (mount_flags & EXT2_MF_MOUNTED) {
+		strcat(jfile, "/.journal");
+
+		/*
+		 * If .../.journal already exists, make sure any
+		 * immutable or append-only flags are cleared.
+		 */
+#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP)
+		(void) chflags (jfile, 0);
+#else
+#if HAVE_EXT2_IOCTLS
+		fd = open(jfile, O_RDONLY);
+		if (fd >= 0) {
+			f = 0;
+			ioctl(fd, EXT2_IOC_SETFLAGS, &f);
+			close(fd);
+		}
+#endif
+#endif
+
+		/* Create the journal file */
+		if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0)
+			return errno;
+
+		if ((retval = write_journal_file(fs, jfile, size, flags)))
+			goto errout;
+
+		/* Get inode number of the journal file */
+		if (fstat(fd, &st) < 0)
+			goto errout;
+
+#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP)
+		retval = fchflags (fd, UF_NODUMP|UF_IMMUTABLE);
+#else
+#if HAVE_EXT2_IOCTLS
+		f = EXT2_NODUMP_FL | EXT2_IMMUTABLE_FL;
+		retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f);
+#endif
+#endif
+		if (retval)
+			goto errout;
+
+		close(fd);
+		journal_ino = st.st_ino;
+	} else {
+		journal_ino = EXT2_JOURNAL_INO;
+		if ((retval = write_journal_inode(fs, journal_ino,
+						  size, flags)))
+			return retval;
+	}
+
+	fs->super->s_journal_inum = journal_ino;
+	fs->super->s_journal_dev = 0;
+	memset(fs->super->s_journal_uuid, 0,
+	       sizeof(fs->super->s_journal_uuid));
+	fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+
+	ext2fs_mark_super_dirty(fs);
+	return 0;
+errout:
+	close(fd);
+	return retval;
+}
+
+#ifdef DEBUG
+main(int argc, char **argv)
+{
+	errcode_t	retval;
+	char		*device_name;
+	ext2_filsys	fs;
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s filesystem\n", argv[0]);
+		exit(1);
+	}
+	device_name = argv[1];
+
+	retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0,
+			      unix_io_manager, &fs);
+	if (retval) {
+		com_err(argv[0], retval, "while opening %s", device_name);
+		exit(1);
+	}
+
+	retval = ext2fs_add_journal_inode(fs, 1024);
+	if (retval) {
+		com_err(argv[0], retval, "while adding journal to %s",
+			device_name);
+		exit(1);
+	}
+	retval = ext2fs_flush(fs);
+	if (retval) {
+		printf("Warning, had trouble writing out superblocks.\n");
+	}
+	ext2fs_close(fs);
+	exit(0);
+
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/namei.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/namei.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/namei.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,204 @@
+/*
+ * namei.c --- ext2fs directory lookup operations
+ *
+ * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* #define NAMEI_DEBUG */
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
+			    const char *pathname, size_t pathlen, int follow,
+			    int link_count, char *buf, ext2_ino_t *res_inode);
+
+static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
+			     ext2_ino_t inode, int link_count,
+			     char *buf, ext2_ino_t *res_inode)
+{
+	char *pathname;
+	char *buffer = 0;
+	errcode_t retval;
+	struct ext2_inode ei;
+
+#ifdef NAMEI_DEBUG
+	printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n",
+	       root, dir, inode, link_count);
+
+#endif
+	retval = ext2fs_read_inode (fs, inode, &ei);
+	if (retval) return retval;
+	if (!LINUX_S_ISLNK (ei.i_mode)) {
+		*res_inode = inode;
+		return 0;
+	}
+	if (link_count++ > 5) {
+		return EXT2_ET_SYMLINK_LOOP;
+	}
+	if (ext2fs_inode_data_blocks(fs,&ei)) {
+		retval = ext2fs_get_mem(fs->blocksize, &buffer);
+		if (retval)
+			return retval;
+		retval = io_channel_read_blk(fs->io, ei.i_block[0], 1, buffer);
+		if (retval) {
+			ext2fs_free_mem(&buffer);
+			return retval;
+		}
+		pathname = buffer;
+	} else
+		pathname = (char *)&(ei.i_block[0]);
+	retval = open_namei(fs, root, dir, pathname, ei.i_size, 1,
+			    link_count, buf, res_inode);
+	ext2fs_free_mem(&buffer);
+	return retval;
+}
+
+/*
+ * This routine interprets a pathname in the context of the current
+ * directory and the root directory, and returns the inode of the
+ * containing directory, and a pointer to the filename of the file
+ * (pointing into the pathname) and the length of the filename.
+ */
+static errcode_t dir_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
+			   const char *pathname, int pathlen,
+			   int link_count, char *buf,
+			   const char **name, int *namelen,
+			   ext2_ino_t *res_inode)
+{
+	char c;
+	const char *thisname;
+	int len;
+	ext2_ino_t inode;
+	errcode_t retval;
+
+	if ((c = *pathname) == '/') {
+		dir = root;
+		pathname++;
+		pathlen--;
+	}
+	while (1) {
+		thisname = pathname;
+		for (len=0; --pathlen >= 0;len++) {
+			c = *(pathname++);
+			if (c == '/')
+				break;
+		}
+		if (pathlen < 0)
+			break;
+		retval = ext2fs_lookup (fs, dir, thisname, len, buf, &inode);
+		if (retval) return retval;
+		retval = follow_link (fs, root, dir, inode,
+				      link_count, buf, &dir);
+		if (retval) return retval;
+	}
+	*name = thisname;
+	*namelen = len;
+	*res_inode = dir;
+	return 0;
+}
+
+static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
+			    const char *pathname, size_t pathlen, int follow,
+			    int link_count, char *buf, ext2_ino_t *res_inode)
+{
+	const char *basename;
+	int namelen;
+	ext2_ino_t dir, inode;
+	errcode_t retval;
+
+#ifdef NAMEI_DEBUG
+	printf("open_namei: root=%lu, dir=%lu, path=%*s, lc=%d\n",
+	       root, base, pathlen, pathname, link_count);
+#endif
+	retval = dir_namei(fs, root, base, pathname, pathlen,
+			   link_count, buf, &basename, &namelen, &dir);
+	if (retval) return retval;
+	if (!namelen) {                     /* special case: '/usr/' etc */
+		*res_inode=dir;
+		return 0;
+	}
+	retval = ext2fs_lookup (fs, dir, basename, namelen, buf, &inode);
+	if (retval)
+		return retval;
+	if (follow) {
+		retval = follow_link(fs, root, dir, inode, link_count,
+				     buf, &inode);
+		if (retval)
+			return retval;
+	}
+#ifdef NAMEI_DEBUG
+	printf("open_namei: (link_count=%d) returns %lu\n",
+	       link_count, inode);
+#endif
+	*res_inode = inode;
+	return 0;
+}
+
+errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
+		       const char *name, ext2_ino_t *inode)
+{
+	char *buf;
+	errcode_t retval;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	retval = ext2fs_get_mem(fs->blocksize, &buf);
+	if (retval)
+		return retval;
+
+	retval = open_namei(fs, root, cwd, name, strlen(name), 0, 0,
+			    buf, inode);
+
+	ext2fs_free_mem(&buf);
+	return retval;
+}
+
+errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
+			      const char *name, ext2_ino_t *inode)
+{
+	char *buf;
+	errcode_t retval;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	retval = ext2fs_get_mem(fs->blocksize, &buf);
+	if (retval)
+		return retval;
+
+	retval = open_namei(fs, root, cwd, name, strlen(name), 1, 0,
+			    buf, inode);
+
+	ext2fs_free_mem(&buf);
+	return retval;
+}
+
+errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd,
+			ext2_ino_t inode, ext2_ino_t *res_inode)
+{
+	char *buf;
+	errcode_t retval;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	retval = ext2fs_get_mem(fs->blocksize, &buf);
+	if (retval)
+		return retval;
+
+	retval = follow_link(fs, root, cwd, inode, 0, buf, res_inode);
+
+	ext2fs_free_mem(&buf);
+	return retval;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/newdir.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/newdir.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/newdir.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,72 @@
+/*
+ * newdir.c --- create a new directory block
+ *
+ * Copyright (C) 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#ifndef EXT2_FT_DIR
+#define EXT2_FT_DIR		2
+#endif
+
+/*
+ * Create new directory block
+ */
+errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
+			       ext2_ino_t parent_ino, char **block)
+{
+	struct ext2_dir_entry	*dir = NULL;
+	errcode_t		retval;
+	char			*buf;
+	int			rec_len;
+	int			filetype = 0;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	retval = ext2fs_get_mem(fs->blocksize, &buf);
+	if (retval)
+		return retval;
+	memset(buf, 0, fs->blocksize);
+	dir = (struct ext2_dir_entry *) buf;
+	dir->rec_len = fs->blocksize;
+
+	if (dir_ino) {
+		if (fs->super->s_feature_incompat &
+		    EXT2_FEATURE_INCOMPAT_FILETYPE)
+			filetype = EXT2_FT_DIR << 8;
+		/*
+		 * Set up entry for '.'
+		 */
+		dir->inode = dir_ino;
+		dir->name_len = 1 | filetype;
+		dir->name[0] = '.';
+		rec_len = dir->rec_len - EXT2_DIR_REC_LEN(1);
+		dir->rec_len = EXT2_DIR_REC_LEN(1);
+
+		/*
+		 * Set up entry for '..'
+		 */
+		dir = (struct ext2_dir_entry *) (buf + dir->rec_len);
+		dir->rec_len = rec_len;
+		dir->inode = parent_ino;
+		dir->name_len = 2 | filetype;
+		dir->name[0] = '.';
+		dir->name[1] = '.';
+
+	}
+	*block = buf;
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/openfs.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/openfs.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/openfs.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,329 @@
+/*
+ * openfs.c --- open an ext2 filesystem
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+
+
+#include "ext2fs.h"
+#include "e2image.h"
+
+blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i)
+{
+	int	bg;
+	int	has_super = 0;
+	int	ret_blk;
+
+	if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
+	    (i < fs->super->s_first_meta_bg))
+		return (group_block + i + 1);
+
+	bg = (fs->blocksize / sizeof (struct ext2_group_desc)) * i;
+	if (ext2fs_bg_has_super(fs, bg))
+		has_super = 1;
+	ret_blk = (fs->super->s_first_data_block + has_super +
+		   (bg * fs->super->s_blocks_per_group));
+	/*
+	 * If group_block is not the normal value, we're trying to use
+	 * the backup group descriptors and superblock --- so use the
+	 * alternate location of the second block group in the
+	 * metablock group.  Ideally we should be testing each bg
+	 * descriptor block individually for correctness, but we don't
+	 * have the infrastructure in place to do that.
+	 */
+	if (group_block != fs->super->s_first_data_block &&
+	    ((ret_blk + fs->super->s_blocks_per_group) <
+	     fs->super->s_blocks_count))
+		ret_blk += fs->super->s_blocks_per_group;
+	return ret_blk;
+}
+
+errcode_t ext2fs_open(const char *name, int flags, int superblock,
+		      unsigned int block_size, io_manager manager,
+		      ext2_filsys *ret_fs)
+{
+	return ext2fs_open2(name, 0, flags, superblock, block_size,
+			    manager, ret_fs);
+}
+
+/*
+ *  Note: if superblock is non-zero, block-size must also be non-zero.
+ *	Superblock and block_size can be zero to use the default size.
+ *
+ * Valid flags for ext2fs_open()
+ *
+ *	EXT2_FLAG_RW	- Open the filesystem for read/write.
+ *	EXT2_FLAG_FORCE - Open the filesystem even if some of the
+ *				features aren't supported.
+ *	EXT2_FLAG_JOURNAL_DEV_OK - Open an ext3 journal device
+ */
+errcode_t ext2fs_open2(const char *name, const char *io_options,
+		       int flags, int superblock,
+		       unsigned int block_size, io_manager manager,
+		       ext2_filsys *ret_fs)
+{
+	ext2_filsys	fs;
+	errcode_t	retval;
+	unsigned long	i;
+	int		groups_per_block, blocks_per_group;
+	blk_t		group_block, blk;
+	char		*dest, *cp;
+#if BB_BIG_ENDIAN
+	int j;
+	struct ext2_group_desc *gdp;
+#endif
+
+	EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER);
+
+	retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
+	if (retval)
+		return retval;
+
+	memset(fs, 0, sizeof(struct struct_ext2_filsys));
+	fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
+	fs->flags = flags;
+	fs->umask = 022;
+	retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name);
+	if (retval)
+		goto cleanup;
+	strcpy(fs->device_name, name);
+	cp = strchr(fs->device_name, '?');
+	if (!io_options && cp) {
+		*cp++ = 0;
+		io_options = cp;
+	}
+
+	retval = manager->open(fs->device_name,
+			       (flags & EXT2_FLAG_RW) ? IO_FLAG_RW : 0,
+			       &fs->io);
+	if (retval)
+		goto cleanup;
+	if (io_options &&
+	    (retval = io_channel_set_options(fs->io, io_options)))
+		goto cleanup;
+	fs->image_io = fs->io;
+	fs->io->app_data = fs;
+	retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super);
+	if (retval)
+		goto cleanup;
+	if (flags & EXT2_FLAG_IMAGE_FILE) {
+		retval = ext2fs_get_mem(sizeof(struct ext2_image_hdr),
+					&fs->image_header);
+		if (retval)
+			goto cleanup;
+		retval = io_channel_read_blk(fs->io, 0,
+					     -(int)sizeof(struct ext2_image_hdr),
+					     fs->image_header);
+		if (retval)
+			goto cleanup;
+		if (fs->image_header->magic_number != EXT2_ET_MAGIC_E2IMAGE)
+			return EXT2_ET_MAGIC_E2IMAGE;
+		superblock = 1;
+		block_size = fs->image_header->fs_blocksize;
+	}
+
+	/*
+	 * If the user specifies a specific block # for the
+	 * superblock, then he/she must also specify the block size!
+	 * Otherwise, read the master superblock located at offset
+	 * SUPERBLOCK_OFFSET from the start of the partition.
+	 *
+	 * Note: we only save a backup copy of the superblock if we
+	 * are reading the superblock from the primary superblock location.
+	 */
+	if (superblock) {
+		if (!block_size) {
+			retval = EXT2_ET_INVALID_ARGUMENT;
+			goto cleanup;
+		}
+		io_channel_set_blksize(fs->io, block_size);
+		group_block = superblock;
+		fs->orig_super = 0;
+	} else {
+		io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
+		superblock = 1;
+		group_block = 0;
+		retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super);
+		if (retval)
+			goto cleanup;
+	}
+	retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE,
+				     fs->super);
+	if (retval)
+		goto cleanup;
+	if (fs->orig_super)
+		memcpy(fs->orig_super, fs->super, SUPERBLOCK_SIZE);
+
+#if BB_BIG_ENDIAN
+	if ((fs->super->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) ||
+	    (fs->flags & EXT2_FLAG_SWAP_BYTES)) {
+		fs->flags |= EXT2_FLAG_SWAP_BYTES;
+
+		ext2fs_swap_super(fs->super);
+	}
+#endif
+
+	if (fs->super->s_magic != EXT2_SUPER_MAGIC) {
+		retval = EXT2_ET_BAD_MAGIC;
+		goto cleanup;
+	}
+	if (fs->super->s_rev_level > EXT2_LIB_CURRENT_REV) {
+		retval = EXT2_ET_REV_TOO_HIGH;
+		goto cleanup;
+	}
+
+	/*
+	 * Check for feature set incompatibility
+	 */
+	if (!(flags & EXT2_FLAG_FORCE)) {
+		if (fs->super->s_feature_incompat &
+		    ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
+			retval = EXT2_ET_UNSUPP_FEATURE;
+			goto cleanup;
+		}
+		if ((flags & EXT2_FLAG_RW) &&
+		    (fs->super->s_feature_ro_compat &
+		     ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) {
+			retval = EXT2_ET_RO_UNSUPP_FEATURE;
+			goto cleanup;
+		}
+		if (!(flags & EXT2_FLAG_JOURNAL_DEV_OK) &&
+		    (fs->super->s_feature_incompat &
+		     EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+			retval = EXT2_ET_UNSUPP_FEATURE;
+			goto cleanup;
+		}
+	}
+
+	fs->blocksize = EXT2_BLOCK_SIZE(fs->super);
+	if (fs->blocksize == 0) {
+		retval = EXT2_ET_CORRUPT_SUPERBLOCK;
+		goto cleanup;
+	}
+	fs->fragsize = EXT2_FRAG_SIZE(fs->super);
+	fs->inode_blocks_per_group = ((fs->super->s_inodes_per_group *
+				       EXT2_INODE_SIZE(fs->super) +
+				       EXT2_BLOCK_SIZE(fs->super) - 1) /
+				      EXT2_BLOCK_SIZE(fs->super));
+	if (block_size) {
+		if (block_size != fs->blocksize) {
+			retval = EXT2_ET_UNEXPECTED_BLOCK_SIZE;
+			goto cleanup;
+		}
+	}
+	/*
+	 * Set the blocksize to the filesystem's blocksize.
+	 */
+	io_channel_set_blksize(fs->io, fs->blocksize);
+
+	/*
+	 * If this is an external journal device, don't try to read
+	 * the group descriptors, because they're not there.
+	 */
+	if (fs->super->s_feature_incompat &
+	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+		fs->group_desc_count = 0;
+		*ret_fs = fs;
+		return 0;
+	}
+
+	/*
+	 * Read group descriptors
+	 */
+	blocks_per_group = EXT2_BLOCKS_PER_GROUP(fs->super);
+	if (blocks_per_group == 0 ||
+	    blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(fs->super) ||
+	    fs->inode_blocks_per_group > EXT2_MAX_INODES_PER_GROUP(fs->super)) {
+		retval = EXT2_ET_CORRUPT_SUPERBLOCK;
+		goto cleanup;
+	}
+	fs->group_desc_count = (fs->super->s_blocks_count -
+				fs->super->s_first_data_block +
+				blocks_per_group - 1) / blocks_per_group;
+	fs->desc_blocks = (fs->group_desc_count +
+			   EXT2_DESC_PER_BLOCK(fs->super) - 1)
+		/ EXT2_DESC_PER_BLOCK(fs->super);
+	retval = ext2fs_get_mem(fs->desc_blocks * fs->blocksize,
+				&fs->group_desc);
+	if (retval)
+		goto cleanup;
+	if (!group_block)
+		group_block = fs->super->s_first_data_block;
+	dest = (char *) fs->group_desc;
+	groups_per_block = fs->blocksize / sizeof(struct ext2_group_desc);
+	for (i=0 ; i < fs->desc_blocks; i++) {
+		blk = ext2fs_descriptor_block_loc(fs, group_block, i);
+		retval = io_channel_read_blk(fs->io, blk, 1, dest);
+		if (retval)
+			goto cleanup;
+#if BB_BIG_ENDIAN
+		if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
+			gdp = (struct ext2_group_desc *) dest;
+			for (j=0; j < groups_per_block; j++)
+				ext2fs_swap_group_desc(gdp++);
+		}
+#endif
+		dest += fs->blocksize;
+	}
+
+	*ret_fs = fs;
+	return 0;
+cleanup:
+	ext2fs_free(fs);
+	return retval;
+}
+
+/*
+ * Set/get the filesystem data I/O channel.
+ *
+ * These functions are only valid if EXT2_FLAG_IMAGE_FILE is true.
+ */
+errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io)
+{
+	if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
+		return EXT2_ET_NOT_IMAGE_FILE;
+	if (old_io) {
+		*old_io = (fs->image_io == fs->io) ? 0 : fs->io;
+	}
+	return 0;
+}
+
+errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io)
+{
+	if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
+		return EXT2_ET_NOT_IMAGE_FILE;
+	fs->io = new_io ? new_io : fs->image_io;
+	return 0;
+}
+
+errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io)
+{
+	if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
+		return EXT2_ET_NOT_IMAGE_FILE;
+	fs->io = fs->image_io = new_io;
+	fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_RW |
+		EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
+	fs->flags &= ~EXT2_FLAG_IMAGE_FILE;
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/read_bb.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/read_bb.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/read_bb.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,97 @@
+/*
+ * read_bb --- read the bad blocks inode
+ *
+ * Copyright (C) 1994 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct read_bb_record {
+	ext2_badblocks_list	bb_list;
+	errcode_t	err;
+};
+
+/*
+ * Helper function for ext2fs_read_bb_inode()
+ */
+#ifdef __TURBOC__
+# pragma argsused
+#endif
+static int mark_bad_block(ext2_filsys fs, blk_t *block_nr,
+			  e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
+			  blk_t ref_block EXT2FS_ATTR((unused)),
+			  int ref_offset EXT2FS_ATTR((unused)),
+			  void *priv_data)
+{
+	struct read_bb_record *rb = (struct read_bb_record *) priv_data;
+
+	if (blockcnt < 0)
+		return 0;
+
+	if ((*block_nr < fs->super->s_first_data_block) ||
+	    (*block_nr >= fs->super->s_blocks_count))
+		return 0;	/* Ignore illegal blocks */
+
+	rb->err = ext2fs_badblocks_list_add(rb->bb_list, *block_nr);
+	if (rb->err)
+		return BLOCK_ABORT;
+	return 0;
+}
+
+/*
+ * Reads the current bad blocks from the bad blocks inode.
+ */
+errcode_t ext2fs_read_bb_inode(ext2_filsys fs, ext2_badblocks_list *bb_list)
+{
+	errcode_t	retval;
+	struct read_bb_record rb;
+	struct ext2_inode inode;
+	blk_t	numblocks;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (!*bb_list) {
+		retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
+		if (retval)
+			return retval;
+		if (inode.i_blocks < 500)
+			numblocks = (inode.i_blocks /
+				     (fs->blocksize / 512)) + 20;
+		else
+			numblocks = 500;
+		retval = ext2fs_badblocks_list_create(bb_list, numblocks);
+		if (retval)
+			return retval;
+	}
+
+	rb.bb_list = *bb_list;
+	rb.err = 0;
+	retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, 0, 0,
+				      mark_bad_block, &rb);
+	if (retval)
+		return retval;
+
+	return rb.err;
+}
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/read_bb_file.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/read_bb_file.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/read_bb_file.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,97 @@
+/*
+ * read_bb_file.c --- read a list of bad blocks from a FILE *
+ *
+ * Copyright (C) 1994, 1995, 2000 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * Reads a list of bad blocks from  a FILE *
+ */
+errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f,
+			       ext2_badblocks_list *bb_list,
+			       void *priv_data,
+			       void (*invalid)(ext2_filsys fs,
+					       blk_t blk,
+					       char *badstr,
+					       void *priv_data))
+{
+	errcode_t	retval;
+	blk_t		blockno;
+	int		count;
+	char		buf[128];
+
+	if (fs)
+		EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (!*bb_list) {
+		retval = ext2fs_badblocks_list_create(bb_list, 10);
+		if (retval)
+			return retval;
+	}
+
+	while (!feof (f)) {
+		if (fgets(buf, sizeof(buf), f) == NULL)
+			break;
+		count = sscanf(buf, "%u", &blockno);
+		if (count <= 0)
+			continue;
+		if (fs &&
+		    ((blockno < fs->super->s_first_data_block) ||
+		    (blockno >= fs->super->s_blocks_count))) {
+			if (invalid)
+				(invalid)(fs, blockno, buf, priv_data);
+			continue;
+		}
+		retval = ext2fs_badblocks_list_add(*bb_list, blockno);
+		if (retval)
+			return retval;
+	}
+	return 0;
+}
+
+static void call_compat_invalid(ext2_filsys fs, blk_t blk,
+				char *badstr EXT2FS_ATTR((unused)),
+				void *priv_data)
+{
+	void (*invalid)(ext2_filsys, blk_t);
+
+	invalid = (void (*)(ext2_filsys, blk_t)) priv_data;
+	if (invalid)
+		invalid(fs, blk);
+}
+
+
+/*
+ * Reads a list of bad blocks from  a FILE *
+ */
+errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
+			      ext2_badblocks_list *bb_list,
+			      void (*invalid)(ext2_filsys fs, blk_t blk))
+{
+	return ext2fs_read_bb_FILE2(fs, f, bb_list, (void *) invalid,
+				    call_compat_invalid);
+}
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/res_gdt.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/res_gdt.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/res_gdt.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,220 @@
+/*
+ * res_gdt.c --- reserve blocks for growing the group descriptor table
+ *               during online resizing.
+ *
+ * Copyright (C) 2002 Andreas Dilger
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * Iterate through the groups which hold BACKUP superblock/GDT copies in an
+ * ext3 filesystem.  The counters should be initialized to 1, 5, and 7 before
+ * calling this for the first time.  In a sparse filesystem it will be the
+ * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ...
+ * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ...
+ */
+static unsigned int list_backups(ext2_filsys fs, unsigned int *three,
+				 unsigned int *five, unsigned int *seven)
+{
+	unsigned int *min = three;
+	int mult = 3;
+	unsigned int ret;
+
+	if (!(fs->super->s_feature_ro_compat &
+	      EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
+		ret = *min;
+		*min += 1;
+		return ret;
+	}
+
+	if (*five < *min) {
+		min = five;
+		mult = 5;
+	}
+	if (*seven < *min) {
+		min = seven;
+		mult = 7;
+	}
+
+	ret = *min;
+	*min *= mult;
+
+	return ret;
+}
+
+/*
+ * This code assumes that the reserved blocks have already been marked in-use
+ * during ext2fs_initialize(), so that they are not allocated for other
+ * uses before we can add them to the resize inode (which has to come
+ * after the creation of the inode table).
+ */
+errcode_t ext2fs_create_resize_inode(ext2_filsys fs)
+{
+	errcode_t		retval, retval2;
+	struct ext2_super_block	*sb;
+	struct ext2_inode	inode;
+	__u32			*dindir_buf, *gdt_buf;
+	int			rsv_add;
+	unsigned long long	apb, inode_size;
+	blk_t			dindir_blk, rsv_off, gdt_off, gdt_blk;
+	int			dindir_dirty = 0, inode_dirty = 0;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	sb = fs->super;
+
+	retval = ext2fs_get_mem(2 * fs->blocksize, (void *)&dindir_buf);
+	if (retval)
+		goto out_free;
+	gdt_buf = (__u32 *)((char *)dindir_buf + fs->blocksize);
+
+	retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
+	if (retval)
+		goto out_free;
+
+	/* Maximum possible file size (we donly use the dindirect blocks) */
+	apb = EXT2_ADDR_PER_BLOCK(sb);
+	rsv_add = fs->blocksize / 512;
+	if ((dindir_blk = inode.i_block[EXT2_DIND_BLOCK])) {
+#ifdef RES_GDT_DEBUG
+		printf("reading GDT dindir %u\n", dindir_blk);
+#endif
+		retval = ext2fs_read_ind_block(fs, dindir_blk, dindir_buf);
+		if (retval)
+			goto out_inode;
+	} else {
+		blk_t goal = 3 + sb->s_reserved_gdt_blocks +
+			fs->desc_blocks + fs->inode_blocks_per_group;
+
+		retval = ext2fs_alloc_block(fs, goal, 0, &dindir_blk);
+		if (retval)
+			goto out_free;
+		inode.i_mode = LINUX_S_IFREG | 0600;
+		inode.i_links_count = 1;
+		inode.i_block[EXT2_DIND_BLOCK] = dindir_blk;
+		inode.i_blocks = rsv_add;
+		memset(dindir_buf, 0, fs->blocksize);
+#ifdef RES_GDT_DEBUG
+		printf("allocated GDT dindir %u\n", dindir_blk);
+#endif
+		dindir_dirty = inode_dirty = 1;
+		inode_size = apb*apb + apb + EXT2_NDIR_BLOCKS;
+		inode_size *= fs->blocksize;
+		inode.i_size = inode_size & 0xFFFFFFFF;
+		inode.i_size_high = (inode_size >> 32) & 0xFFFFFFFF;
+		if(inode.i_size_high) {
+			sb->s_feature_ro_compat |=
+				EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
+		}
+		inode.i_ctime = time(0);
+	}
+
+	for (rsv_off = 0, gdt_off = fs->desc_blocks,
+	     gdt_blk = sb->s_first_data_block + 1 + fs->desc_blocks;
+	     rsv_off < sb->s_reserved_gdt_blocks;
+	     rsv_off++, gdt_off++, gdt_blk++) {
+		unsigned int three = 1, five = 5, seven = 7;
+		unsigned int grp, last = 0;
+		int gdt_dirty = 0;
+
+		gdt_off %= apb;
+		if (!dindir_buf[gdt_off]) {
+			/* FIXME XXX XXX
+			blk_t new_blk;
+
+			retval = ext2fs_new_block(fs, gdt_blk, 0, &new_blk);
+			if (retval)
+				goto out_free;
+			if (new_blk != gdt_blk) {
+				// XXX free block
+				retval = -1; // XXX
+			}
+			*/
+			gdt_dirty = dindir_dirty = inode_dirty = 1;
+			memset(gdt_buf, 0, fs->blocksize);
+			dindir_buf[gdt_off] = gdt_blk;
+			inode.i_blocks += rsv_add;
+#ifdef RES_GDT_DEBUG
+			printf("added primary GDT block %u at %u[%u]\n",
+			       gdt_blk, dindir_blk, gdt_off);
+#endif
+		} else if (dindir_buf[gdt_off] == gdt_blk) {
+#ifdef RES_GDT_DEBUG
+			printf("reading primary GDT block %u\n", gdt_blk);
+#endif
+			retval = ext2fs_read_ind_block(fs, gdt_blk, gdt_buf);
+			if (retval)
+				goto out_dindir;
+		} else {
+#ifdef RES_GDT_DEBUG
+			printf("bad primary GDT %u != %u at %u[%u]\n",
+			       dindir_buf[gdt_off], gdt_blk,dindir_blk,gdt_off);
+#endif
+			retval = EXT2_ET_RESIZE_INODE_CORRUPT;
+			goto out_dindir;
+		}
+
+		while ((grp = list_backups(fs, &three, &five, &seven)) <
+		       fs->group_desc_count) {
+			blk_t expect = gdt_blk + grp * sb->s_blocks_per_group;
+
+			if (!gdt_buf[last]) {
+#ifdef RES_GDT_DEBUG
+				printf("added backup GDT %u grp %u@%u[%u]\n",
+				       expect, grp, gdt_blk, last);
+#endif
+				gdt_buf[last] = expect;
+				inode.i_blocks += rsv_add;
+				gdt_dirty = inode_dirty = 1;
+			} else if (gdt_buf[last] != expect) {
+#ifdef RES_GDT_DEBUG
+				printf("bad backup GDT %u != %u at %u[%u]\n",
+				       gdt_buf[last], expect, gdt_blk, last);
+#endif
+				retval = EXT2_ET_RESIZE_INODE_CORRUPT;
+				goto out_dindir;
+			}
+			last++;
+		}
+		if (gdt_dirty) {
+#ifdef RES_GDT_DEBUG
+			printf("writing primary GDT block %u\n", gdt_blk);
+#endif
+			retval = ext2fs_write_ind_block(fs, gdt_blk, gdt_buf);
+			if (retval)
+				goto out_dindir;
+		}
+	}
+
+out_dindir:
+	if (dindir_dirty) {
+		retval2 = ext2fs_write_ind_block(fs, dindir_blk, dindir_buf);
+		if (!retval)
+			retval = retval2;
+	}
+out_inode:
+#ifdef RES_GDT_DEBUG
+	printf("inode.i_blocks = %u, i_size = %u\n", inode.i_blocks,
+	       inode.i_size);
+#endif
+	if (inode_dirty) {
+		inode.i_atime = inode.i_mtime = time(0);
+		retval2 = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode);
+		if (!retval)
+			retval = retval2;
+	}
+out_free:
+	ext2fs_free_mem((void *)&dindir_buf);
+	return retval;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/rs_bitmap.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/rs_bitmap.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/rs_bitmap.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,106 @@
+/*
+ * rs_bitmap.c --- routine for changing the size of a bitmap
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+errcode_t ext2fs_resize_generic_bitmap(__u32 new_end, __u32 new_real_end,
+				       ext2fs_generic_bitmap bmap)
+{
+	errcode_t	retval;
+	size_t		size, new_size;
+	__u32		bitno;
+
+	if (!bmap)
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_GENERIC_BITMAP);
+
+	/*
+	 * If we're expanding the bitmap, make sure all of the new
+	 * parts of the bitmap are zero.
+	 */
+	if (new_end > bmap->end) {
+		bitno = bmap->real_end;
+		if (bitno > new_end)
+			bitno = new_end;
+		for (; bitno > bmap->end; bitno--)
+			ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap);
+	}
+	if (new_real_end == bmap->real_end) {
+		bmap->end = new_end;
+		return 0;
+	}
+
+	size = ((bmap->real_end - bmap->start) / 8) + 1;
+	new_size = ((new_real_end - bmap->start) / 8) + 1;
+
+	if (size != new_size) {
+		retval = ext2fs_resize_mem(size, new_size, &bmap->bitmap);
+		if (retval)
+			return retval;
+	}
+	if (new_size > size)
+		memset(bmap->bitmap + size, 0, new_size - size);
+
+	bmap->end = new_end;
+	bmap->real_end = new_real_end;
+	return 0;
+}
+
+errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
+				     ext2fs_inode_bitmap bmap)
+{
+	errcode_t	retval;
+
+	if (!bmap)
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_INODE_BITMAP);
+
+	bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
+	retval = ext2fs_resize_generic_bitmap(new_end, new_real_end,
+					      bmap);
+	bmap->magic = EXT2_ET_MAGIC_INODE_BITMAP;
+	return retval;
+}
+
+errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
+				     ext2fs_block_bitmap bmap)
+{
+	errcode_t	retval;
+
+	if (!bmap)
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
+
+	bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
+	retval = ext2fs_resize_generic_bitmap(new_end, new_real_end,
+					      bmap);
+	bmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP;
+	return retval;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/rw_bitmaps.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/rw_bitmaps.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/rw_bitmaps.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,295 @@
+/*
+ * rw_bitmaps.c --- routines to read and write the  inode and block bitmaps.
+ *
+ * Copyright (C) 1993, 1994, 1994, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+#include "e2image.h"
+
+#if defined(__powerpc__) && BB_BIG_ENDIAN
+/*
+ * On the PowerPC, the big-endian variant of the ext2 filesystem
+ * has its bitmaps stored as 32-bit words with bit 0 as the LSB
+ * of each word.  Thus a bitmap with only bit 0 set would be, as
+ * a string of bytes, 00 00 00 01 00 ...
+ * To cope with this, we byte-reverse each word of a bitmap if
+ * we have a big-endian filesystem, that is, if we are *not*
+ * byte-swapping other word-sized numbers.
+ */
+#define EXT2_BIG_ENDIAN_BITMAPS
+#endif
+
+#ifdef EXT2_BIG_ENDIAN_BITMAPS
+static void ext2fs_swap_bitmap(ext2_filsys fs, char *bitmap, int nbytes)
+{
+	__u32 *p = (__u32 *) bitmap;
+	int n;
+
+	for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
+		*p = ext2fs_swab32(*p);
+}
+#endif
+
+errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs)
+{
+	dgrp_t		i;
+	size_t		nbytes;
+	errcode_t	retval;
+	char * inode_bitmap = fs->inode_map->bitmap;
+	char * bitmap_block = NULL;
+	blk_t		blk;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (!(fs->flags & EXT2_FLAG_RW))
+		return EXT2_ET_RO_FILSYS;
+	if (!inode_bitmap)
+		return 0;
+	nbytes = (size_t) ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
+
+	retval = ext2fs_get_mem(fs->blocksize, &bitmap_block);
+	if (retval)
+		return retval;
+	memset(bitmap_block, 0xff, fs->blocksize);
+	for (i = 0; i < fs->group_desc_count; i++) {
+		memcpy(bitmap_block, inode_bitmap, nbytes);
+		blk = fs->group_desc[i].bg_inode_bitmap;
+		if (blk) {
+#ifdef EXT2_BIG_ENDIAN_BITMAPS
+			if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+			      (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
+				ext2fs_swap_bitmap(fs, bitmap_block, nbytes);
+#endif
+			retval = io_channel_write_blk(fs->io, blk, 1,
+						      bitmap_block);
+			if (retval)
+				return EXT2_ET_INODE_BITMAP_WRITE;
+		}
+		inode_bitmap += nbytes;
+	}
+	fs->flags &= ~EXT2_FLAG_IB_DIRTY;
+	ext2fs_free_mem(&bitmap_block);
+	return 0;
+}
+
+errcode_t ext2fs_write_block_bitmap (ext2_filsys fs)
+{
+	dgrp_t		i;
+	unsigned int	j;
+	int		nbytes;
+	unsigned int	nbits;
+	errcode_t	retval;
+	char * block_bitmap = fs->block_map->bitmap;
+	char * bitmap_block = NULL;
+	blk_t		blk;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (!(fs->flags & EXT2_FLAG_RW))
+		return EXT2_ET_RO_FILSYS;
+	if (!block_bitmap)
+		return 0;
+	nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
+	retval = ext2fs_get_mem(fs->blocksize, &bitmap_block);
+	if (retval)
+		return retval;
+	memset(bitmap_block, 0xff, fs->blocksize);
+	for (i = 0; i < fs->group_desc_count; i++) {
+		memcpy(bitmap_block, block_bitmap, nbytes);
+		if (i == fs->group_desc_count - 1) {
+			/* Force bitmap padding for the last group */
+			nbits = ((fs->super->s_blocks_count
+				  - fs->super->s_first_data_block)
+				 % EXT2_BLOCKS_PER_GROUP(fs->super));
+			if (nbits)
+				for (j = nbits; j < fs->blocksize * 8; j++)
+					ext2fs_set_bit(j, bitmap_block);
+		}
+		blk = fs->group_desc[i].bg_block_bitmap;
+		if (blk) {
+#ifdef EXT2_BIG_ENDIAN_BITMAPS
+			if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+			      (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
+				ext2fs_swap_bitmap(fs, bitmap_block, nbytes);
+#endif
+			retval = io_channel_write_blk(fs->io, blk, 1,
+						      bitmap_block);
+			if (retval)
+				return EXT2_ET_BLOCK_BITMAP_WRITE;
+		}
+		block_bitmap += nbytes;
+	}
+	fs->flags &= ~EXT2_FLAG_BB_DIRTY;
+	ext2fs_free_mem(&bitmap_block);
+	return 0;
+}
+
+static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
+{
+	dgrp_t i;
+	char *block_bitmap = 0, *inode_bitmap = 0;
+	char *buf;
+	errcode_t retval;
+	int block_nbytes = (int) EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
+	int inode_nbytes = (int) EXT2_INODES_PER_GROUP(fs->super) / 8;
+	blk_t	blk;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	fs->write_bitmaps = ext2fs_write_bitmaps;
+
+	retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
+	if (retval)
+		return retval;
+	if (do_block) {
+		ext2fs_free_block_bitmap(fs->block_map);
+		sprintf(buf, "block bitmap for %s", fs->device_name);
+		retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
+		if (retval)
+			goto cleanup;
+		block_bitmap = fs->block_map->bitmap;
+	}
+	if (do_inode) {
+		ext2fs_free_inode_bitmap(fs->inode_map);
+		sprintf(buf, "inode bitmap for %s", fs->device_name);
+		retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
+		if (retval)
+			goto cleanup;
+		inode_bitmap = fs->inode_map->bitmap;
+	}
+	ext2fs_free_mem(&buf);
+
+	if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
+		if (inode_bitmap) {
+			blk = (fs->image_header->offset_inodemap /
+			       fs->blocksize);
+			retval = io_channel_read_blk(fs->image_io, blk,
+			     -(inode_nbytes * fs->group_desc_count),
+			     inode_bitmap);
+			if (retval)
+				goto cleanup;
+		}
+		if (block_bitmap) {
+			blk = (fs->image_header->offset_blockmap /
+			       fs->blocksize);
+			retval = io_channel_read_blk(fs->image_io, blk,
+			     -(block_nbytes * fs->group_desc_count),
+			     block_bitmap);
+			if (retval)
+				goto cleanup;
+		}
+		return 0;
+	}
+
+	for (i = 0; i < fs->group_desc_count; i++) {
+		if (block_bitmap) {
+			blk = fs->group_desc[i].bg_block_bitmap;
+			if (blk) {
+				retval = io_channel_read_blk(fs->io, blk,
+					     -block_nbytes, block_bitmap);
+				if (retval) {
+					retval = EXT2_ET_BLOCK_BITMAP_READ;
+					goto cleanup;
+				}
+#ifdef EXT2_BIG_ENDIAN_BITMAPS
+				if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+				      (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
+					ext2fs_swap_bitmap(fs, block_bitmap, block_nbytes);
+#endif
+			} else
+				memset(block_bitmap, 0, block_nbytes);
+			block_bitmap += block_nbytes;
+		}
+		if (inode_bitmap) {
+			blk = fs->group_desc[i].bg_inode_bitmap;
+			if (blk) {
+				retval = io_channel_read_blk(fs->io, blk,
+					     -inode_nbytes, inode_bitmap);
+				if (retval) {
+					retval = EXT2_ET_INODE_BITMAP_READ;
+					goto cleanup;
+				}
+#ifdef EXT2_BIG_ENDIAN_BITMAPS
+				if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
+				      (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)))
+					ext2fs_swap_bitmap(fs, inode_bitmap, inode_nbytes);
+#endif
+			} else
+				memset(inode_bitmap, 0, inode_nbytes);
+			inode_bitmap += inode_nbytes;
+		}
+	}
+	return 0;
+
+cleanup:
+	if (do_block) {
+		ext2fs_free_mem(&fs->block_map);
+	}
+	if (do_inode) {
+		ext2fs_free_mem(&fs->inode_map);
+	}
+	ext2fs_free_mem(&buf);
+	return retval;
+}
+
+errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs)
+{
+	return read_bitmaps(fs, 1, 0);
+}
+
+errcode_t ext2fs_read_block_bitmap(ext2_filsys fs)
+{
+	return read_bitmaps(fs, 0, 1);
+}
+
+errcode_t ext2fs_read_bitmaps(ext2_filsys fs)
+{
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (fs->inode_map && fs->block_map)
+		return 0;
+
+	return read_bitmaps(fs, !fs->inode_map, !fs->block_map);
+}
+
+errcode_t ext2fs_write_bitmaps(ext2_filsys fs)
+{
+	errcode_t	retval;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (fs->block_map && ext2fs_test_bb_dirty(fs)) {
+		retval = ext2fs_write_block_bitmap(fs);
+		if (retval)
+			return retval;
+	}
+	if (fs->inode_map && ext2fs_test_ib_dirty(fs)) {
+		retval = ext2fs_write_inode_bitmap(fs);
+		if (retval)
+			return retval;
+	}
+	return 0;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/sparse.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/sparse.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/sparse.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,78 @@
+/*
+ * sparse.c --- find the groups in an ext2 filesystem with metadata backups
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ * Copyright (C) 2002 Andreas Dilger.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+
+#include "ext2_fs.h"
+#include "ext2fsP.h"
+
+static int test_root(int a, int b)
+{
+	if (a == 0)
+		return 1;
+	while (1) {
+		if (a == 1)
+			return 1;
+		if (a % b)
+			return 0;
+		a = a / b;
+	}
+}
+
+int ext2fs_bg_has_super(ext2_filsys fs, int group_block)
+{
+	if (!(fs->super->s_feature_ro_compat &
+	      EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
+		return 1;
+
+	if (test_root(group_block, 3) || (test_root(group_block, 5)) ||
+	    test_root(group_block, 7))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * Iterate through the groups which hold BACKUP superblock/GDT copies in an
+ * ext3 filesystem.  The counters should be initialized to 1, 5, and 7 before
+ * calling this for the first time.  In a sparse filesystem it will be the
+ * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ...
+ * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ...
+ */
+unsigned int ext2fs_list_backups(ext2_filsys fs, unsigned int *three,
+				 unsigned int *five, unsigned int *seven)
+{
+	unsigned int *min = three;
+	int mult = 3;
+	unsigned int ret;
+
+	if (!(fs->super->s_feature_ro_compat &
+	      EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
+		ret = *min;
+		*min += 1;
+		return ret;
+	}
+
+	if (*five < *min) {
+		min = five;
+		mult = 5;
+	}
+	if (*seven < *min) {
+		min = seven;
+		mult = 7;
+	}
+
+	ret = *min;
+	*min *= mult;
+
+	return ret;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/swapfs.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/swapfs.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/swapfs.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,235 @@
+/*
+ * swapfs.c --- swap ext2 filesystem data structures
+ *
+ * Copyright (C) 1995, 1996, 2002 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+#include "ext2_ext_attr.h"
+
+#if BB_BIG_ENDIAN
+void ext2fs_swap_super(struct ext2_super_block * sb)
+{
+	int i;
+	sb->s_inodes_count = ext2fs_swab32(sb->s_inodes_count);
+	sb->s_blocks_count = ext2fs_swab32(sb->s_blocks_count);
+	sb->s_r_blocks_count = ext2fs_swab32(sb->s_r_blocks_count);
+	sb->s_free_blocks_count = ext2fs_swab32(sb->s_free_blocks_count);
+	sb->s_free_inodes_count = ext2fs_swab32(sb->s_free_inodes_count);
+	sb->s_first_data_block = ext2fs_swab32(sb->s_first_data_block);
+	sb->s_log_block_size = ext2fs_swab32(sb->s_log_block_size);
+	sb->s_log_frag_size = ext2fs_swab32(sb->s_log_frag_size);
+	sb->s_blocks_per_group = ext2fs_swab32(sb->s_blocks_per_group);
+	sb->s_frags_per_group = ext2fs_swab32(sb->s_frags_per_group);
+	sb->s_inodes_per_group = ext2fs_swab32(sb->s_inodes_per_group);
+	sb->s_mtime = ext2fs_swab32(sb->s_mtime);
+	sb->s_wtime = ext2fs_swab32(sb->s_wtime);
+	sb->s_mnt_count = ext2fs_swab16(sb->s_mnt_count);
+	sb->s_max_mnt_count = ext2fs_swab16(sb->s_max_mnt_count);
+	sb->s_magic = ext2fs_swab16(sb->s_magic);
+	sb->s_state = ext2fs_swab16(sb->s_state);
+	sb->s_errors = ext2fs_swab16(sb->s_errors);
+	sb->s_minor_rev_level = ext2fs_swab16(sb->s_minor_rev_level);
+	sb->s_lastcheck = ext2fs_swab32(sb->s_lastcheck);
+	sb->s_checkinterval = ext2fs_swab32(sb->s_checkinterval);
+	sb->s_creator_os = ext2fs_swab32(sb->s_creator_os);
+	sb->s_rev_level = ext2fs_swab32(sb->s_rev_level);
+	sb->s_def_resuid = ext2fs_swab16(sb->s_def_resuid);
+	sb->s_def_resgid = ext2fs_swab16(sb->s_def_resgid);
+	sb->s_first_ino = ext2fs_swab32(sb->s_first_ino);
+	sb->s_inode_size = ext2fs_swab16(sb->s_inode_size);
+	sb->s_block_group_nr = ext2fs_swab16(sb->s_block_group_nr);
+	sb->s_feature_compat = ext2fs_swab32(sb->s_feature_compat);
+	sb->s_feature_incompat = ext2fs_swab32(sb->s_feature_incompat);
+	sb->s_feature_ro_compat = ext2fs_swab32(sb->s_feature_ro_compat);
+	sb->s_algorithm_usage_bitmap = ext2fs_swab32(sb->s_algorithm_usage_bitmap);
+	sb->s_reserved_gdt_blocks = ext2fs_swab16(sb->s_reserved_gdt_blocks);
+	sb->s_journal_inum = ext2fs_swab32(sb->s_journal_inum);
+	sb->s_journal_dev = ext2fs_swab32(sb->s_journal_dev);
+	sb->s_last_orphan = ext2fs_swab32(sb->s_last_orphan);
+	sb->s_default_mount_opts = ext2fs_swab32(sb->s_default_mount_opts);
+	sb->s_first_meta_bg = ext2fs_swab32(sb->s_first_meta_bg);
+	sb->s_mkfs_time = ext2fs_swab32(sb->s_mkfs_time);
+	for (i=0; i < 4; i++)
+		sb->s_hash_seed[i] = ext2fs_swab32(sb->s_hash_seed[i]);
+	for (i=0; i < 17; i++)
+		sb->s_jnl_blocks[i] = ext2fs_swab32(sb->s_jnl_blocks[i]);
+
+}
+
+void ext2fs_swap_group_desc(struct ext2_group_desc *gdp)
+{
+	gdp->bg_block_bitmap = ext2fs_swab32(gdp->bg_block_bitmap);
+	gdp->bg_inode_bitmap = ext2fs_swab32(gdp->bg_inode_bitmap);
+	gdp->bg_inode_table = ext2fs_swab32(gdp->bg_inode_table);
+	gdp->bg_free_blocks_count = ext2fs_swab16(gdp->bg_free_blocks_count);
+	gdp->bg_free_inodes_count = ext2fs_swab16(gdp->bg_free_inodes_count);
+	gdp->bg_used_dirs_count = ext2fs_swab16(gdp->bg_used_dirs_count);
+}
+
+void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, int has_header)
+{
+	struct ext2_ext_attr_header *from_header =
+		(struct ext2_ext_attr_header *)from;
+	struct ext2_ext_attr_header *to_header =
+		(struct ext2_ext_attr_header *)to;
+	struct ext2_ext_attr_entry *from_entry, *to_entry;
+	char *from_end = (char *)from_header + bufsize;
+	int n;
+
+	if (to_header != from_header)
+		memcpy(to_header, from_header, bufsize);
+
+	from_entry = (struct ext2_ext_attr_entry *)from_header;
+	to_entry   = (struct ext2_ext_attr_entry *)to_header;
+
+	if (has_header) {
+		to_header->h_magic    = ext2fs_swab32(from_header->h_magic);
+		to_header->h_blocks   = ext2fs_swab32(from_header->h_blocks);
+		to_header->h_refcount = ext2fs_swab32(from_header->h_refcount);
+		for (n=0; n<4; n++)
+			to_header->h_reserved[n] =
+				ext2fs_swab32(from_header->h_reserved[n]);
+		from_entry = (struct ext2_ext_attr_entry *)(from_header+1);
+		to_entry   = (struct ext2_ext_attr_entry *)(to_header+1);
+	}
+
+	while ((char *)from_entry < from_end && *(__u32 *)from_entry) {
+		to_entry->e_value_offs  =
+			ext2fs_swab16(from_entry->e_value_offs);
+		to_entry->e_value_block =
+			ext2fs_swab32(from_entry->e_value_block);
+		to_entry->e_value_size  =
+			ext2fs_swab32(from_entry->e_value_size);
+		from_entry = EXT2_EXT_ATTR_NEXT(from_entry);
+		to_entry   = EXT2_EXT_ATTR_NEXT(to_entry);
+	}
+}
+
+void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
+			    struct ext2_inode_large *f, int hostorder,
+			    int bufsize)
+{
+	unsigned i;
+	int islnk = 0;
+	__u32 *eaf, *eat;
+
+	if (hostorder && LINUX_S_ISLNK(f->i_mode))
+		islnk = 1;
+	t->i_mode = ext2fs_swab16(f->i_mode);
+	if (!hostorder && LINUX_S_ISLNK(t->i_mode))
+		islnk = 1;
+	t->i_uid = ext2fs_swab16(f->i_uid);
+	t->i_size = ext2fs_swab32(f->i_size);
+	t->i_atime = ext2fs_swab32(f->i_atime);
+	t->i_ctime = ext2fs_swab32(f->i_ctime);
+	t->i_mtime = ext2fs_swab32(f->i_mtime);
+	t->i_dtime = ext2fs_swab32(f->i_dtime);
+	t->i_gid = ext2fs_swab16(f->i_gid);
+	t->i_links_count = ext2fs_swab16(f->i_links_count);
+	t->i_blocks = ext2fs_swab32(f->i_blocks);
+	t->i_flags = ext2fs_swab32(f->i_flags);
+	t->i_file_acl = ext2fs_swab32(f->i_file_acl);
+	t->i_dir_acl = ext2fs_swab32(f->i_dir_acl);
+	if (!islnk || ext2fs_inode_data_blocks(fs, (struct ext2_inode *)t)) {
+		for (i = 0; i < EXT2_N_BLOCKS; i++)
+			t->i_block[i] = ext2fs_swab32(f->i_block[i]);
+	} else if (t != f) {
+		for (i = 0; i < EXT2_N_BLOCKS; i++)
+			t->i_block[i] = f->i_block[i];
+	}
+	t->i_generation = ext2fs_swab32(f->i_generation);
+	t->i_faddr = ext2fs_swab32(f->i_faddr);
+
+	switch (fs->super->s_creator_os) {
+	case EXT2_OS_LINUX:
+		t->osd1.linux1.l_i_reserved1 =
+			ext2fs_swab32(f->osd1.linux1.l_i_reserved1);
+		t->osd2.linux2.l_i_frag = f->osd2.linux2.l_i_frag;
+		t->osd2.linux2.l_i_fsize = f->osd2.linux2.l_i_fsize;
+		t->osd2.linux2.i_pad1 = ext2fs_swab16(f->osd2.linux2.i_pad1);
+		t->osd2.linux2.l_i_uid_high =
+		  ext2fs_swab16 (f->osd2.linux2.l_i_uid_high);
+		t->osd2.linux2.l_i_gid_high =
+		  ext2fs_swab16 (f->osd2.linux2.l_i_gid_high);
+		t->osd2.linux2.l_i_reserved2 =
+			ext2fs_swab32(f->osd2.linux2.l_i_reserved2);
+		break;
+	case EXT2_OS_HURD:
+		t->osd1.hurd1.h_i_translator =
+		  ext2fs_swab32 (f->osd1.hurd1.h_i_translator);
+		t->osd2.hurd2.h_i_frag = f->osd2.hurd2.h_i_frag;
+		t->osd2.hurd2.h_i_fsize = f->osd2.hurd2.h_i_fsize;
+		t->osd2.hurd2.h_i_mode_high =
+		  ext2fs_swab16 (f->osd2.hurd2.h_i_mode_high);
+		t->osd2.hurd2.h_i_uid_high =
+		  ext2fs_swab16 (f->osd2.hurd2.h_i_uid_high);
+		t->osd2.hurd2.h_i_gid_high =
+		  ext2fs_swab16 (f->osd2.hurd2.h_i_gid_high);
+		t->osd2.hurd2.h_i_author =
+		  ext2fs_swab32 (f->osd2.hurd2.h_i_author);
+		break;
+	case EXT2_OS_MASIX:
+		t->osd1.masix1.m_i_reserved1 =
+			ext2fs_swab32(f->osd1.masix1.m_i_reserved1);
+		t->osd2.masix2.m_i_frag = f->osd2.masix2.m_i_frag;
+		t->osd2.masix2.m_i_fsize = f->osd2.masix2.m_i_fsize;
+		t->osd2.masix2.m_pad1 = ext2fs_swab16(f->osd2.masix2.m_pad1);
+		t->osd2.masix2.m_i_reserved2[0] =
+			ext2fs_swab32(f->osd2.masix2.m_i_reserved2[0]);
+		t->osd2.masix2.m_i_reserved2[1] =
+			ext2fs_swab32(f->osd2.masix2.m_i_reserved2[1]);
+		break;
+	}
+
+	if (bufsize < (int) (sizeof(struct ext2_inode) + sizeof(__u16)))
+		return; /* no i_extra_isize field */
+
+	t->i_extra_isize = ext2fs_swab16(f->i_extra_isize);
+	if (t->i_extra_isize > EXT2_INODE_SIZE(fs->super) -
+				sizeof(struct ext2_inode)) {
+		/* this is error case: i_extra_size is too large */
+		return;
+	}
+
+	i = sizeof(struct ext2_inode) + t->i_extra_isize + sizeof(__u32);
+	if (bufsize < (int) i)
+		return; /* no space for EA magic */
+
+	eaf = (__u32 *) (((char *) f) + sizeof(struct ext2_inode) +
+					f->i_extra_isize);
+
+	if (ext2fs_swab32(*eaf) != EXT2_EXT_ATTR_MAGIC)
+		return; /* it seems no magic here */
+
+	eat = (__u32 *) (((char *) t) + sizeof(struct ext2_inode) +
+					f->i_extra_isize);
+	*eat = ext2fs_swab32(*eaf);
+
+	/* convert EA(s) */
+	ext2fs_swap_ext_attr((char *) (eat + 1), (char *) (eaf + 1),
+			     bufsize - sizeof(struct ext2_inode) -
+			     t->i_extra_isize - sizeof(__u32), 0);
+
+}
+
+void ext2fs_swap_inode(ext2_filsys fs, struct ext2_inode *t,
+		       struct ext2_inode *f, int hostorder)
+{
+	ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) t,
+				(struct ext2_inode_large *) f, hostorder,
+				sizeof(struct ext2_inode));
+}
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/test_io.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/test_io.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/test_io.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,379 @@
+/*
+ * test_io.c --- This is the Test I/O interface.
+ *
+ * Copyright (C) 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * For checking structure magic numbers...
+ */
+
+#define EXT2_CHECK_MAGIC(struct, code) \
+	  if ((struct)->magic != (code)) return (code)
+
+struct test_private_data {
+	int	magic;
+	io_channel real;
+	int flags;
+	FILE *outfile;
+	unsigned long block;
+	int read_abort_count, write_abort_count;
+	void (*read_blk)(unsigned long block, int count, errcode_t err);
+	void (*write_blk)(unsigned long block, int count, errcode_t err);
+	void (*set_blksize)(int blksize, errcode_t err);
+	void (*write_byte)(unsigned long block, int count, errcode_t err);
+};
+
+static errcode_t test_open(const char *name, int flags, io_channel *channel);
+static errcode_t test_close(io_channel channel);
+static errcode_t test_set_blksize(io_channel channel, int blksize);
+static errcode_t test_read_blk(io_channel channel, unsigned long block,
+			       int count, void *data);
+static errcode_t test_write_blk(io_channel channel, unsigned long block,
+				int count, const void *data);
+static errcode_t test_flush(io_channel channel);
+static errcode_t test_write_byte(io_channel channel, unsigned long offset,
+				 int count, const void *buf);
+static errcode_t test_set_option(io_channel channel, const char *option,
+				 const char *arg);
+
+static struct struct_io_manager struct_test_manager = {
+	EXT2_ET_MAGIC_IO_MANAGER,
+	"Test I/O Manager",
+	test_open,
+	test_close,
+	test_set_blksize,
+	test_read_blk,
+	test_write_blk,
+	test_flush,
+	test_write_byte,
+	test_set_option
+};
+
+io_manager test_io_manager = &struct_test_manager;
+
+/*
+ * These global variable can be set by the test program as
+ * necessary *before* calling test_open
+ */
+io_manager test_io_backing_manager = 0;
+void (*test_io_cb_read_blk)
+	(unsigned long block, int count, errcode_t err) = 0;
+void (*test_io_cb_write_blk)
+	(unsigned long block, int count, errcode_t err) = 0;
+void (*test_io_cb_set_blksize)
+	(int blksize, errcode_t err) = 0;
+void (*test_io_cb_write_byte)
+	(unsigned long block, int count, errcode_t err) = 0;
+
+/*
+ * Test flags
+ */
+#define TEST_FLAG_READ			0x01
+#define TEST_FLAG_WRITE			0x02
+#define TEST_FLAG_SET_BLKSIZE		0x04
+#define TEST_FLAG_FLUSH			0x08
+#define TEST_FLAG_DUMP			0x10
+#define TEST_FLAG_SET_OPTION		0x20
+
+static void test_dump_block(io_channel channel,
+			    struct test_private_data *data,
+			    unsigned long block, const void *buf)
+{
+	const unsigned char *cp;
+	FILE *f = data->outfile;
+	int	i;
+	unsigned long	cksum = 0;
+
+	for (i=0, cp = buf; i < channel->block_size; i++, cp++) {
+		cksum += *cp;
+	}
+	fprintf(f, "Contents of block %lu, checksum %08lu: \n", block, cksum);
+	for (i=0, cp = buf; i < channel->block_size; i++, cp++) {
+		if ((i % 16) == 0)
+			fprintf(f, "%04x: ", i);
+		fprintf(f, "%02x%c", *cp, ((i % 16) == 15) ? '\n' : ' ');
+	}
+}
+
+static void test_abort(io_channel channel, unsigned long block)
+{
+	struct test_private_data *data;
+	FILE *f;
+
+	data = (struct test_private_data *) channel->private_data;
+	f = data->outfile;
+	test_flush(channel);
+
+	fprintf(f, "Aborting due to I/O to block %lu\n", block);
+	fflush(f);
+	abort();
+}
+
+static errcode_t test_open(const char *name, int flags, io_channel *channel)
+{
+	io_channel	io = NULL;
+	struct test_private_data *data = NULL;
+	errcode_t	retval;
+	char		*value;
+
+	if (name == 0)
+		return EXT2_ET_BAD_DEVICE_NAME;
+	retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
+	if (retval)
+		return retval;
+	memset(io, 0, sizeof(struct struct_io_channel));
+	io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
+	retval = ext2fs_get_mem(sizeof(struct test_private_data), &data);
+	if (retval) {
+		retval = EXT2_ET_NO_MEMORY;
+		goto cleanup;
+	}
+	io->manager = test_io_manager;
+	retval = ext2fs_get_mem(strlen(name)+1, &io->name);
+	if (retval)
+		goto cleanup;
+
+	strcpy(io->name, name);
+	io->private_data = data;
+	io->block_size = 1024;
+	io->read_error = 0;
+	io->write_error = 0;
+	io->refcount = 1;
+
+	memset(data, 0, sizeof(struct test_private_data));
+	data->magic = EXT2_ET_MAGIC_TEST_IO_CHANNEL;
+	if (test_io_backing_manager) {
+		retval = test_io_backing_manager->open(name, flags,
+						       &data->real);
+		if (retval)
+			goto cleanup;
+	} else
+		data->real = 0;
+	data->read_blk =	test_io_cb_read_blk;
+	data->write_blk =	test_io_cb_write_blk;
+	data->set_blksize =	test_io_cb_set_blksize;
+	data->write_byte =	test_io_cb_write_byte;
+
+	data->outfile = NULL;
+	if ((value = getenv("TEST_IO_LOGFILE")) != NULL)
+		data->outfile = fopen(value, "w");
+	if (!data->outfile)
+		data->outfile = stderr;
+
+	data->flags = 0;
+	if ((value = getenv("TEST_IO_FLAGS")) != NULL)
+		data->flags = strtoul(value, NULL, 0);
+
+	data->block = 0;
+	if ((value = getenv("TEST_IO_BLOCK")) != NULL)
+		data->block = strtoul(value, NULL, 0);
+
+	data->read_abort_count = 0;
+	if ((value = getenv("TEST_IO_READ_ABORT")) != NULL)
+		data->read_abort_count = strtoul(value, NULL, 0);
+
+	data->write_abort_count = 0;
+	if ((value = getenv("TEST_IO_WRITE_ABORT")) != NULL)
+		data->write_abort_count = strtoul(value, NULL, 0);
+
+	*channel = io;
+	return 0;
+
+cleanup:
+	ext2fs_free_mem(&io);
+	ext2fs_free_mem(&data);
+	return retval;
+}
+
+static errcode_t test_close(io_channel channel)
+{
+	struct test_private_data *data;
+	errcode_t	retval = 0;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct test_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+	if (--channel->refcount > 0)
+		return 0;
+
+	if (data->real)
+		retval = io_channel_close(data->real);
+
+	if (data->outfile && data->outfile != stderr)
+		fclose(data->outfile);
+
+	ext2fs_free_mem(&channel->private_data);
+	ext2fs_free_mem(&channel->name);
+	ext2fs_free_mem(&channel);
+	return retval;
+}
+
+static errcode_t test_set_blksize(io_channel channel, int blksize)
+{
+	struct test_private_data *data;
+	errcode_t	retval = 0;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct test_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+	if (data->real)
+		retval = io_channel_set_blksize(data->real, blksize);
+	if (data->set_blksize)
+		data->set_blksize(blksize, retval);
+	if (data->flags & TEST_FLAG_SET_BLKSIZE)
+		fprintf(data->outfile,
+			"Test_io: set_blksize(%d) returned %s\n",
+			blksize, retval ? error_message(retval) : "OK");
+	channel->block_size = blksize;
+	return retval;
+}
+
+
+static errcode_t test_read_blk(io_channel channel, unsigned long block,
+			       int count, void *buf)
+{
+	struct test_private_data *data;
+	errcode_t	retval = 0;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct test_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+	if (data->real)
+		retval = io_channel_read_blk(data->real, block, count, buf);
+	if (data->read_blk)
+		data->read_blk(block, count, retval);
+	if (data->flags & TEST_FLAG_READ)
+		fprintf(data->outfile,
+			"Test_io: read_blk(%lu, %d) returned %s\n",
+			block, count, retval ? error_message(retval) : "OK");
+	if (data->block && data->block == block) {
+		if (data->flags & TEST_FLAG_DUMP)
+			test_dump_block(channel, data, block, buf);
+		if (--data->read_abort_count == 0)
+			test_abort(channel, block);
+	}
+	return retval;
+}
+
+static errcode_t test_write_blk(io_channel channel, unsigned long block,
+			       int count, const void *buf)
+{
+	struct test_private_data *data;
+	errcode_t	retval = 0;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct test_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+	if (data->real)
+		retval = io_channel_write_blk(data->real, block, count, buf);
+	if (data->write_blk)
+		data->write_blk(block, count, retval);
+	if (data->flags & TEST_FLAG_WRITE)
+		fprintf(data->outfile,
+			"Test_io: write_blk(%lu, %d) returned %s\n",
+			block, count, retval ? error_message(retval) : "OK");
+	if (data->block && data->block == block) {
+		if (data->flags & TEST_FLAG_DUMP)
+			test_dump_block(channel, data, block, buf);
+		if (--data->write_abort_count == 0)
+			test_abort(channel, block);
+	}
+	return retval;
+}
+
+static errcode_t test_write_byte(io_channel channel, unsigned long offset,
+			       int count, const void *buf)
+{
+	struct test_private_data *data;
+	errcode_t	retval = 0;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct test_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+	if (data->real && data->real->manager->write_byte)
+		retval = io_channel_write_byte(data->real, offset, count, buf);
+	if (data->write_byte)
+		data->write_byte(offset, count, retval);
+	if (data->flags & TEST_FLAG_WRITE)
+		fprintf(data->outfile,
+			"Test_io: write_byte(%lu, %d) returned %s\n",
+			offset, count, retval ? error_message(retval) : "OK");
+	return retval;
+}
+
+/*
+ * Flush data buffers to disk.
+ */
+static errcode_t test_flush(io_channel channel)
+{
+	struct test_private_data *data;
+	errcode_t	retval = 0;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct test_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+	if (data->real)
+		retval = io_channel_flush(data->real);
+
+	if (data->flags & TEST_FLAG_FLUSH)
+		fprintf(data->outfile, "Test_io: flush() returned %s\n",
+			retval ? error_message(retval) : "OK");
+
+	return retval;
+}
+
+static errcode_t test_set_option(io_channel channel, const char *option,
+				 const char *arg)
+{
+	struct test_private_data *data;
+	errcode_t	retval = 0;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct test_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+
+	if (data->flags & TEST_FLAG_SET_OPTION)
+		fprintf(data->outfile, "Test_io: set_option(%s, %s) ",
+			option, arg);
+	if (data->real && data->real->manager->set_option) {
+		retval = (data->real->manager->set_option)(data->real,
+							   option, arg);
+		if (data->flags & TEST_FLAG_SET_OPTION)
+			fprintf(data->outfile, "returned %s\n",
+				retval ? error_message(retval) : "OK");
+	} else {
+		if (data->flags & TEST_FLAG_SET_OPTION)
+			fprintf(data->outfile, "not implemented\n");
+	}
+	return retval;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/unix_io.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/unix_io.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/unix_io.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,702 @@
+/*
+ * unix_io.c --- This is the Unix (well, really POSIX) implementation
+ *	of the I/O manager.
+ *
+ * Implements a one-block write-through cache.
+ *
+ * Includes support for Windows NT support under Cygwin.
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ *	2002 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#ifdef __linux__
+#include <sys/utsname.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <sys/resource.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * For checking structure magic numbers...
+ */
+
+#define EXT2_CHECK_MAGIC(struct, code) \
+	  if ((struct)->magic != (code)) return (code)
+
+struct unix_cache {
+	char		*buf;
+	unsigned long	block;
+	int		access_time;
+	unsigned	dirty:1;
+	unsigned	in_use:1;
+};
+
+#define CACHE_SIZE 8
+#define WRITE_DIRECT_SIZE 4	/* Must be smaller than CACHE_SIZE */
+#define READ_DIRECT_SIZE 4	/* Should be smaller than CACHE_SIZE */
+
+struct unix_private_data {
+	int	magic;
+	int	dev;
+	int	flags;
+	int	access_time;
+	ext2_loff_t offset;
+	struct unix_cache cache[CACHE_SIZE];
+};
+
+static errcode_t unix_open(const char *name, int flags, io_channel *channel);
+static errcode_t unix_close(io_channel channel);
+static errcode_t unix_set_blksize(io_channel channel, int blksize);
+static errcode_t unix_read_blk(io_channel channel, unsigned long block,
+			       int count, void *data);
+static errcode_t unix_write_blk(io_channel channel, unsigned long block,
+				int count, const void *data);
+static errcode_t unix_flush(io_channel channel);
+static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
+				int size, const void *data);
+static errcode_t unix_set_option(io_channel channel, const char *option,
+				 const char *arg);
+
+static void reuse_cache(io_channel channel, struct unix_private_data *data,
+		 struct unix_cache *cache, unsigned long block);
+
+/* __FreeBSD_kernel__ is defined by GNU/kFreeBSD - the FreeBSD kernel
+ * does not know buffered block devices - everything is raw. */
+#if defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#define NEED_BOUNCE_BUFFER
+#else
+#undef NEED_BOUNCE_BUFFER
+#endif
+
+static struct struct_io_manager struct_unix_manager = {
+	EXT2_ET_MAGIC_IO_MANAGER,
+	"Unix I/O Manager",
+	unix_open,
+	unix_close,
+	unix_set_blksize,
+	unix_read_blk,
+	unix_write_blk,
+	unix_flush,
+#ifdef NEED_BOUNCE_BUFFER
+	0,
+#else
+	unix_write_byte,
+#endif
+	unix_set_option
+};
+
+io_manager unix_io_manager = &struct_unix_manager;
+
+/*
+ * Here are the raw I/O functions
+ */
+#ifndef NEED_BOUNCE_BUFFER
+static errcode_t raw_read_blk(io_channel channel,
+			      struct unix_private_data *data,
+			      unsigned long block,
+			      int count, void *buf)
+{
+	errcode_t	retval;
+	ssize_t		size;
+	ext2_loff_t	location;
+	int		actual = 0;
+
+	size = (count < 0) ? -count : count * channel->block_size;
+	location = ((ext2_loff_t) block * channel->block_size) + data->offset;
+	if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
+		retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
+		goto error_out;
+	}
+	actual = read(data->dev, buf, size);
+	if (actual != size) {
+		if (actual < 0)
+			actual = 0;
+		retval = EXT2_ET_SHORT_READ;
+		goto error_out;
+	}
+	return 0;
+
+error_out:
+	memset((char *) buf+actual, 0, size-actual);
+	if (channel->read_error)
+		retval = (channel->read_error)(channel, block, count, buf,
+					       size, actual, retval);
+	return retval;
+}
+#else /* NEED_BOUNCE_BUFFER */
+/*
+ * Windows and FreeBSD block devices only allow sector alignment IO in offset and size
+ */
+static errcode_t raw_read_blk(io_channel channel,
+			      struct unix_private_data *data,
+			      unsigned long block,
+			      int count, void *buf)
+{
+	errcode_t	retval;
+	size_t		size, alignsize, fragment;
+	ext2_loff_t	location;
+	int		total = 0, actual;
+#define BLOCKALIGN 512
+	char		sector[BLOCKALIGN];
+
+	size = (count < 0) ? -count : count * channel->block_size;
+	location = ((ext2_loff_t) block * channel->block_size) + data->offset;
+#ifdef DEBUG
+	printf("count=%d, size=%d, block=%d, blk_size=%d, location=%lx\n",
+			count, size, block, channel->block_size, location);
+#endif
+	if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
+		retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
+		goto error_out;
+	}
+	fragment = size % BLOCKALIGN;
+	alignsize = size - fragment;
+	if (alignsize) {
+		actual = read(data->dev, buf, alignsize);
+		if (actual != alignsize)
+			goto short_read;
+	}
+	if (fragment) {
+		actual = read(data->dev, sector, BLOCKALIGN);
+		if (actual != BLOCKALIGN)
+			goto short_read;
+		memcpy(buf+alignsize, sector, fragment);
+	}
+	return 0;
+
+short_read:
+	if (actual>0)
+		total += actual;
+	retval = EXT2_ET_SHORT_READ;
+
+error_out:
+	memset((char *) buf+total, 0, size-actual);
+	if (channel->read_error)
+		retval = (channel->read_error)(channel, block, count, buf,
+					       size, actual, retval);
+	return retval;
+}
+#endif
+
+static errcode_t raw_write_blk(io_channel channel,
+			       struct unix_private_data *data,
+			       unsigned long block,
+			       int count, const void *buf)
+{
+	ssize_t		size;
+	ext2_loff_t	location;
+	int		actual = 0;
+	errcode_t	retval;
+
+	if (count == 1)
+		size = channel->block_size;
+	else {
+		if (count < 0)
+			size = -count;
+		else
+			size = count * channel->block_size;
+	}
+
+	location = ((ext2_loff_t) block * channel->block_size) + data->offset;
+	if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
+		retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
+		goto error_out;
+	}
+
+	actual = write(data->dev, buf, size);
+	if (actual != size) {
+		retval = EXT2_ET_SHORT_WRITE;
+		goto error_out;
+	}
+	return 0;
+
+error_out:
+	if (channel->write_error)
+		retval = (channel->write_error)(channel, block, count, buf,
+						size, actual, retval);
+	return retval;
+}
+
+
+/*
+ * Here we implement the cache functions
+ */
+
+/* Allocate the cache buffers */
+static errcode_t alloc_cache(io_channel channel,
+			     struct unix_private_data *data)
+{
+	errcode_t		retval;
+	struct unix_cache	*cache;
+	int			i;
+
+	data->access_time = 0;
+	for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
+		cache->block = 0;
+		cache->access_time = 0;
+		cache->dirty = 0;
+		cache->in_use = 0;
+		if ((retval = ext2fs_get_mem(channel->block_size,
+					     &cache->buf)))
+			return retval;
+	}
+	return 0;
+}
+
+/* Free the cache buffers */
+static void free_cache(struct unix_private_data *data)
+{
+	struct unix_cache	*cache;
+	int			i;
+
+	data->access_time = 0;
+	for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
+		cache->block = 0;
+		cache->access_time = 0;
+		cache->dirty = 0;
+		cache->in_use = 0;
+		ext2fs_free_mem(&cache->buf);
+		cache->buf = 0;
+	}
+}
+
+#ifndef NO_IO_CACHE
+/*
+ * Try to find a block in the cache.  If the block is not found, and
+ * eldest is a non-zero pointer, then fill in eldest with the cache
+ * entry to that should be reused.
+ */
+static struct unix_cache *find_cached_block(struct unix_private_data *data,
+					    unsigned long block,
+					    struct unix_cache **eldest)
+{
+	struct unix_cache	*cache, *unused_cache, *oldest_cache;
+	int			i;
+
+	unused_cache = oldest_cache = 0;
+	for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
+		if (!cache->in_use) {
+			if (!unused_cache)
+				unused_cache = cache;
+			continue;
+		}
+		if (cache->block == block) {
+			cache->access_time = ++data->access_time;
+			return cache;
+		}
+		if (!oldest_cache ||
+		    (cache->access_time < oldest_cache->access_time))
+			oldest_cache = cache;
+	}
+	if (eldest)
+		*eldest = (unused_cache) ? unused_cache : oldest_cache;
+	return 0;
+}
+
+/*
+ * Reuse a particular cache entry for another block.
+ */
+static void reuse_cache(io_channel channel, struct unix_private_data *data,
+		 struct unix_cache *cache, unsigned long block)
+{
+	if (cache->dirty && cache->in_use)
+		raw_write_blk(channel, data, cache->block, 1, cache->buf);
+
+	cache->in_use = 1;
+	cache->dirty = 0;
+	cache->block = block;
+	cache->access_time = ++data->access_time;
+}
+
+/*
+ * Flush all of the blocks in the cache
+ */
+static errcode_t flush_cached_blocks(io_channel channel,
+				     struct unix_private_data *data,
+				     int invalidate)
+
+{
+	struct unix_cache	*cache;
+	errcode_t		retval, retval2;
+	int			i;
+
+	retval2 = 0;
+	for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
+		if (!cache->in_use)
+			continue;
+
+		if (invalidate)
+			cache->in_use = 0;
+
+		if (!cache->dirty)
+			continue;
+
+		retval = raw_write_blk(channel, data,
+				       cache->block, 1, cache->buf);
+		if (retval)
+			retval2 = retval;
+		else
+			cache->dirty = 0;
+	}
+	return retval2;
+}
+#endif /* NO_IO_CACHE */
+
+static errcode_t unix_open(const char *name, int flags, io_channel *channel)
+{
+	io_channel	io = NULL;
+	struct unix_private_data *data = NULL;
+	errcode_t	retval;
+	int		open_flags;
+	struct stat	st;
+#ifdef __linux__
+	struct		utsname ut;
+#endif
+
+	if (name == 0)
+		return EXT2_ET_BAD_DEVICE_NAME;
+	retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
+	if (retval)
+		return retval;
+	memset(io, 0, sizeof(struct struct_io_channel));
+	io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
+	retval = ext2fs_get_mem(sizeof(struct unix_private_data), &data);
+	if (retval)
+		goto cleanup;
+
+	io->manager = unix_io_manager;
+	retval = ext2fs_get_mem(strlen(name)+1, &io->name);
+	if (retval)
+		goto cleanup;
+
+	strcpy(io->name, name);
+	io->private_data = data;
+	io->block_size = 1024;
+	io->read_error = 0;
+	io->write_error = 0;
+	io->refcount = 1;
+
+	memset(data, 0, sizeof(struct unix_private_data));
+	data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL;
+
+	if ((retval = alloc_cache(io, data)))
+		goto cleanup;
+
+	open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY;
+#ifdef CONFIG_LFS
+	data->dev = open64(io->name, open_flags);
+#else
+	data->dev = open(io->name, open_flags);
+#endif
+	if (data->dev < 0) {
+		retval = errno;
+		goto cleanup;
+	}
+
+#ifdef __linux__
+#undef RLIM_INFINITY
+#if (defined(__alpha__) || ((defined(__sparc__) || defined(__mips__)) && (SIZEOF_LONG == 4)))
+#define RLIM_INFINITY	((unsigned long)(~0UL>>1))
+#else
+#define RLIM_INFINITY  (~0UL)
+#endif
+	/*
+	 * Work around a bug in 2.4.10-2.4.18 kernels where writes to
+	 * block devices are wrongly getting hit by the filesize
+	 * limit.  This workaround isn't perfect, since it won't work
+	 * if glibc wasn't built against 2.2 header files.  (Sigh.)
+	 *
+	 */
+	if ((flags & IO_FLAG_RW) &&
+	    (uname(&ut) == 0) &&
+	    ((ut.release[0] == '2') && (ut.release[1] == '.') &&
+	     (ut.release[2] == '4') && (ut.release[3] == '.') &&
+	     (ut.release[4] == '1') && (ut.release[5] >= '0') &&
+	     (ut.release[5] < '8')) &&
+	    (fstat(data->dev, &st) == 0) &&
+	    (S_ISBLK(st.st_mode))) {
+		struct rlimit	rlim;
+
+		rlim.rlim_cur = rlim.rlim_max = (unsigned long) RLIM_INFINITY;
+		setrlimit(RLIMIT_FSIZE, &rlim);
+		getrlimit(RLIMIT_FSIZE, &rlim);
+		if (((unsigned long) rlim.rlim_cur) <
+		    ((unsigned long) rlim.rlim_max)) {
+			rlim.rlim_cur = rlim.rlim_max;
+			setrlimit(RLIMIT_FSIZE, &rlim);
+		}
+	}
+#endif
+	*channel = io;
+	return 0;
+
+cleanup:
+	if (data) {
+		free_cache(data);
+		ext2fs_free_mem(&data);
+	}
+	ext2fs_free_mem(&io);
+	return retval;
+}
+
+static errcode_t unix_close(io_channel channel)
+{
+	struct unix_private_data *data;
+	errcode_t	retval = 0;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct unix_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
+
+	if (--channel->refcount > 0)
+		return 0;
+
+#ifndef NO_IO_CACHE
+	retval = flush_cached_blocks(channel, data, 0);
+#endif
+
+	if (close(data->dev) < 0)
+		retval = errno;
+	free_cache(data);
+
+	ext2fs_free_mem(&channel->private_data);
+	ext2fs_free_mem(&channel->name);
+	ext2fs_free_mem(&channel);
+	return retval;
+}
+
+static errcode_t unix_set_blksize(io_channel channel, int blksize)
+{
+	struct unix_private_data *data;
+	errcode_t		retval;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct unix_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
+
+	if (channel->block_size != blksize) {
+#ifndef NO_IO_CACHE
+		if ((retval = flush_cached_blocks(channel, data, 0)))
+			return retval;
+#endif
+
+		channel->block_size = blksize;
+		free_cache(data);
+		if ((retval = alloc_cache(channel, data)))
+			return retval;
+	}
+	return 0;
+}
+
+
+static errcode_t unix_read_blk(io_channel channel, unsigned long block,
+			       int count, void *buf)
+{
+	struct unix_private_data *data;
+	struct unix_cache *cache, *reuse[READ_DIRECT_SIZE];
+	errcode_t	retval;
+	char		*cp;
+	int		i, j;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct unix_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
+
+#ifdef NO_IO_CACHE
+	return raw_read_blk(channel, data, block, count, buf);
+#else
+	/*
+	 * If we're doing an odd-sized read or a very large read,
+	 * flush out the cache and then do a direct read.
+	 */
+	if (count < 0 || count > WRITE_DIRECT_SIZE) {
+		if ((retval = flush_cached_blocks(channel, data, 0)))
+			return retval;
+		return raw_read_blk(channel, data, block, count, buf);
+	}
+
+	cp = buf;
+	while (count > 0) {
+		/* If it's in the cache, use it! */
+		if ((cache = find_cached_block(data, block, &reuse[0]))) {
+#ifdef DEBUG
+			printf("Using cached block %d\n", block);
+#endif
+			memcpy(cp, cache->buf, channel->block_size);
+			count--;
+			block++;
+			cp += channel->block_size;
+			continue;
+		}
+		/*
+		 * Find the number of uncached blocks so we can do a
+		 * single read request
+		 */
+		for (i=1; i < count; i++)
+			if (find_cached_block(data, block+i, &reuse[i]))
+				break;
+#ifdef DEBUG
+		printf("Reading %d blocks starting at %d\n", i, block);
+#endif
+		if ((retval = raw_read_blk(channel, data, block, i, cp)))
+			return retval;
+
+		/* Save the results in the cache */
+		for (j=0; j < i; j++) {
+			count--;
+			cache = reuse[j];
+			reuse_cache(channel, data, cache, block++);
+			memcpy(cache->buf, cp, channel->block_size);
+			cp += channel->block_size;
+		}
+	}
+	return 0;
+#endif /* NO_IO_CACHE */
+}
+
+static errcode_t unix_write_blk(io_channel channel, unsigned long block,
+				int count, const void *buf)
+{
+	struct unix_private_data *data;
+	struct unix_cache *cache, *reuse;
+	errcode_t	retval = 0;
+	const char	*cp;
+	int		writethrough;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct unix_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
+
+#ifdef NO_IO_CACHE
+	return raw_write_blk(channel, data, block, count, buf);
+#else
+	/*
+	 * If we're doing an odd-sized write or a very large write,
+	 * flush out the cache completely and then do a direct write.
+	 */
+	if (count < 0 || count > WRITE_DIRECT_SIZE) {
+		if ((retval = flush_cached_blocks(channel, data, 1)))
+			return retval;
+		return raw_write_blk(channel, data, block, count, buf);
+	}
+
+	/*
+	 * For a moderate-sized multi-block write, first force a write
+	 * if we're in write-through cache mode, and then fill the
+	 * cache with the blocks.
+	 */
+	writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH;
+	if (writethrough)
+		retval = raw_write_blk(channel, data, block, count, buf);
+
+	cp = buf;
+	while (count > 0) {
+		cache = find_cached_block(data, block, &reuse);
+		if (!cache) {
+			cache = reuse;
+			reuse_cache(channel, data, cache, block);
+		}
+		memcpy(cache->buf, cp, channel->block_size);
+		cache->dirty = !writethrough;
+		count--;
+		block++;
+		cp += channel->block_size;
+	}
+	return retval;
+#endif /* NO_IO_CACHE */
+}
+
+static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
+				 int size, const void *buf)
+{
+	struct unix_private_data *data;
+	errcode_t	retval = 0;
+	ssize_t		actual;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct unix_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
+
+#ifndef NO_IO_CACHE
+	/*
+	 * Flush out the cache completely
+	 */
+	if ((retval = flush_cached_blocks(channel, data, 1)))
+		return retval;
+#endif
+
+	if (lseek(data->dev, offset + data->offset, SEEK_SET) < 0)
+		return errno;
+
+	actual = write(data->dev, buf, size);
+	if (actual != size)
+		return EXT2_ET_SHORT_WRITE;
+
+	return 0;
+}
+
+/*
+ * Flush data buffers to disk.
+ */
+static errcode_t unix_flush(io_channel channel)
+{
+	struct unix_private_data *data;
+	errcode_t retval = 0;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct unix_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
+
+#ifndef NO_IO_CACHE
+	retval = flush_cached_blocks(channel, data, 0);
+#endif
+	fsync(data->dev);
+	return retval;
+}
+
+static errcode_t unix_set_option(io_channel channel, const char *option,
+				 const char *arg)
+{
+	struct unix_private_data *data;
+	unsigned long tmp;
+	char *end;
+
+	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+	data = (struct unix_private_data *) channel->private_data;
+	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
+
+	if (!strcmp(option, "offset")) {
+		if (!arg)
+			return EXT2_ET_INVALID_ARGUMENT;
+
+		tmp = strtoul(arg, &end, 0);
+		if (*end)
+			return EXT2_ET_INVALID_ARGUMENT;
+		data->offset = tmp;
+		return 0;
+	}
+	return EXT2_ET_INVALID_ARGUMENT;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/unlink.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/unlink.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/unlink.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,99 @@
+/*
+ * unlink.c --- delete links in a ext2fs directory
+ *
+ * Copyright (C) 1993, 1994, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+struct link_struct  {
+	const char	*name;
+	int		namelen;
+	ext2_ino_t	inode;
+	int		flags;
+	struct ext2_dir_entry *prev;
+	int		done;
+};
+
+#ifdef __TURBOC__
+# pragma argsused
+#endif
+static int unlink_proc(struct ext2_dir_entry *dirent,
+		     int	offset EXT2FS_ATTR((unused)),
+		     int	blocksize EXT2FS_ATTR((unused)),
+		     char	*buf EXT2FS_ATTR((unused)),
+		     void	*priv_data)
+{
+	struct link_struct *ls = (struct link_struct *) priv_data;
+	struct ext2_dir_entry *prev;
+
+	prev = ls->prev;
+	ls->prev = dirent;
+
+	if (ls->name) {
+		if ((dirent->name_len & 0xFF) != ls->namelen)
+			return 0;
+		if (strncmp(ls->name, dirent->name, dirent->name_len & 0xFF))
+			return 0;
+	}
+	if (ls->inode) {
+		if (dirent->inode != ls->inode)
+			return 0;
+	} else {
+		if (!dirent->inode)
+			return 0;
+	}
+
+	if (prev)
+		prev->rec_len += dirent->rec_len;
+	else
+		dirent->inode = 0;
+	ls->done++;
+	return DIRENT_ABORT|DIRENT_CHANGED;
+}
+
+#ifdef __TURBOC__
+ #pragma argsused
+#endif
+errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir,
+			const char *name, ext2_ino_t ino,
+			int flags EXT2FS_ATTR((unused)))
+{
+	errcode_t	retval;
+	struct link_struct ls;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if (!name && !ino)
+		return EXT2_ET_INVALID_ARGUMENT;
+
+	if (!(fs->flags & EXT2_FLAG_RW))
+		return EXT2_ET_RO_FILSYS;
+
+	ls.name = name;
+	ls.namelen = name ? strlen(name) : 0;
+	ls.inode = ino;
+	ls.flags = 0;
+	ls.done = 0;
+	ls.prev = 0;
+
+	retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
+				    0, unlink_proc, &ls);
+	if (retval)
+		return retval;
+
+	return (ls.done) ? 0 : EXT2_ET_DIR_NO_SPACE;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/valid_blk.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/valid_blk.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/valid_blk.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,56 @@
+/*
+ * valid_blk.c --- does the inode have valid blocks?
+ *
+ * Copyright 1997 by Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ *
+ */
+
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <time.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+/*
+ * This function returns 1 if the inode's block entries actually
+ * contain block entries.
+ */
+int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode)
+{
+	/*
+	 * Only directories, regular files, and some symbolic links
+	 * have valid block entries.
+	 */
+	if (!LINUX_S_ISDIR(inode->i_mode) && !LINUX_S_ISREG(inode->i_mode) &&
+	    !LINUX_S_ISLNK(inode->i_mode))
+		return 0;
+
+	/*
+	 * If the symbolic link is a "fast symlink", then the symlink
+	 * target is stored in the block entries.
+	 */
+	if (LINUX_S_ISLNK (inode->i_mode)) {
+		if (inode->i_file_acl == 0) {
+			/* With no EA block, we can rely on i_blocks */
+			if (inode->i_blocks == 0)
+				return 0;
+		} else {
+			/* With an EA block, life gets more tricky */
+			if (inode->i_size >= EXT2_N_BLOCKS*4)
+				return 1; /* definitely using i_block[] */
+			if (inode->i_size > 4 && inode->i_block[1] == 0)
+				return 1; /* definitely using i_block[] */
+			return 0; /* Probably a fast symlink */
+		}
+	}
+	return 1;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/version.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/version.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/version.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,52 @@
+/*
+ * version.c --- Return the version of the ext2 library
+ *
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+//#include "../../version.h"
+
+static const char *lib_version = E2FSPROGS_VERSION;
+static const char *lib_date = E2FSPROGS_DATE;
+
+int ext2fs_parse_version_string(const char *ver_string)
+{
+	const char *cp;
+	int version = 0;
+
+	for (cp = ver_string; *cp; cp++) {
+		if (*cp == '.')
+			continue;
+		if (!isdigit(*cp))
+			break;
+		version = (version * 10) + (*cp - '0');
+	}
+	return version;
+}
+
+
+int ext2fs_get_library_version(const char **ver_string,
+			       const char **date_string)
+{
+	if (ver_string)
+		*ver_string = lib_version;
+	if (date_string)
+		*date_string = lib_date;
+
+	return ext2fs_parse_version_string(lib_version);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/write_bb_file.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/write_bb_file.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/ext2fs/write_bb_file.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,34 @@
+/*
+ * write_bb_file.c --- write a list of bad blocks to a FILE *
+ *
+ * Copyright (C) 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
+			       unsigned int flags EXT2FS_ATTR((unused)),
+			       FILE *f)
+{
+	badblocks_iterate	bb_iter;
+	blk_t			blk;
+	errcode_t		retval;
+
+	retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
+	if (retval)
+		return retval;
+
+	while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) {
+		fprintf(f, "%d\n", blk);
+	}
+	ext2fs_badblocks_list_iterate_end(bb_iter);
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/fsck.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/fsck.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/fsck.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1400 @@
+/*
+ * pfsck --- A generic, parallelizing front-end for the fsck program.
+ * It will automatically try to run fsck programs in parallel if the
+ * devices are on separate spindles.  It is based on the same ideas as
+ * the generic front end for fsck by David Engel and Fred van Kempen,
+ * but it has been completely rewritten from scratch to support
+ * parallel execution.
+ *
+ * Written by Theodore Ts'o, <tytso at mit.edu>
+ *
+ * Miquel van Smoorenburg (miquels at drinkel.ow.org) 20-Oct-1994:
+ *   o Changed -t fstype to behave like with mount when -A (all file
+ *     systems) or -M (like mount) is specified.
+ *   o fsck looks if it can find the fsck.type program to decide
+ *     if it should ignore the fs type. This way more fsck programs
+ *     can be added without changing this front-end.
+ *   o -R flag skip root file system.
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ *      2001, 2002, 2003, 2004, 2005 by  Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <paths.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+
+#include "fsck.h"
+#include "blkid/blkid.h"
+
+#include "e2fsbb.h"
+
+#include "busybox.h"
+
+#ifndef _PATH_MNTTAB
+#define _PATH_MNTTAB    "/etc/fstab"
+#endif
+
+/*
+ * fsck.h
+ */
+
+#ifndef DEFAULT_FSTYPE
+#define DEFAULT_FSTYPE	"ext2"
+#endif
+
+#define MAX_DEVICES 32
+#define MAX_ARGS 32
+
+/*
+ * Internal structure for mount tabel entries.
+ */
+
+struct fs_info {
+	char  *device;
+	char  *mountpt;
+	char  *type;
+	char  *opts;
+	int   freq;
+	int   passno;
+	int   flags;
+	struct fs_info *next;
+};
+
+#define FLAG_DONE 1
+#define FLAG_PROGRESS 2
+
+/*
+ * Structure to allow exit codes to be stored
+ */
+struct fsck_instance {
+	int	pid;
+	int	flags;
+	int	exit_status;
+	time_t	start_time;
+	char *	prog;
+	char *	type;
+	char *	device;
+	char *	base_device;
+	struct fsck_instance *next;
+};
+
+/*
+ * base_device.c
+ *
+ * Return the "base device" given a particular device; this is used to
+ * assure that we only fsck one partition on a particular drive at any
+ * one time.  Otherwise, the disk heads will be seeking all over the
+ * place.  If the base device can not be determined, return NULL.
+ *
+ * The base_device() function returns an allocated string which must
+ * be freed.
+ *
+ */
+
+
+#ifdef CONFIG_FEATURE_DEVFS
+/*
+ * Required for the uber-silly devfs /dev/ide/host1/bus2/target3/lun3
+ * pathames.
+ */
+static const char * const devfs_hier[] = {
+	"host", "bus", "target", "lun", 0
+};
+#endif
+
+static char *base_device(const char *device)
+{
+	char *str, *cp;
+#ifdef CONFIG_FEATURE_DEVFS
+	const char * const *hier;
+	const char *disk;
+	int len;
+#endif
+
+	cp = str = bb_xstrdup(device);
+
+	/* Skip over /dev/; if it's not present, give up. */
+	if (strncmp(cp, "/dev/", 5) != 0)
+		goto errout;
+	cp += 5;
+
+#if 0	/* this is for old stuff no one uses anymore ? */
+	/* Skip over /dev/dsk/... */
+	if (strncmp(cp, "dsk/", 4) == 0)
+		cp += 4;
+#endif
+
+	/*
+	 * For md devices, we treat them all as if they were all
+	 * on one disk, since we don't know how to parallelize them.
+	 */
+	if (cp[0] == 'm' && cp[1] == 'd') {
+		*(cp+2) = 0;
+		return str;
+	}
+
+	/* Handle DAC 960 devices */
+	if (strncmp(cp, "rd/", 3) == 0) {
+		cp += 3;
+		if (cp[0] != 'c' || cp[2] != 'd' ||
+		    !isdigit(cp[1]) || !isdigit(cp[3]))
+			goto errout;
+		*(cp+4) = 0;
+		return str;
+	}
+
+	/* Now let's handle /dev/hd* and /dev/sd* devices.... */
+	if ((cp[0] == 'h' || cp[0] == 's') && (cp[1] == 'd')) {
+		cp += 2;
+		/* If there's a single number after /dev/hd, skip it */
+		if (isdigit(*cp))
+			cp++;
+		/* What follows must be an alpha char, or give up */
+		if (!isalpha(*cp))
+			goto errout;
+		*(cp + 1) = 0;
+		return str;
+	}
+
+#ifdef CONFIG_FEATURE_DEVFS
+	/* Now let's handle devfs (ugh) names */
+	len = 0;
+	if (strncmp(cp, "ide/", 4) == 0)
+		len = 4;
+	if (strncmp(cp, "scsi/", 5) == 0)
+		len = 5;
+	if (len) {
+		cp += len;
+		/*
+		 * Now we proceed down the expected devfs hierarchy.
+		 * i.e., .../host1/bus2/target3/lun4/...
+		 * If we don't find the expected token, followed by
+		 * some number of digits at each level, abort.
+		 */
+		for (hier = devfs_hier; *hier; hier++) {
+			len = strlen(*hier);
+			if (strncmp(cp, *hier, len) != 0)
+				goto errout;
+			cp += len;
+			while (*cp != '/' && *cp != 0) {
+				if (!isdigit(*cp))
+					goto errout;
+				cp++;
+			}
+			cp++;
+		}
+		*(cp - 1) = 0;
+		return str;
+	}
+
+	/* Now handle devfs /dev/disc or /dev/disk names */
+	disk = 0;
+	if (strncmp(cp, "discs/", 6) == 0)
+		disk = "disc";
+	else if (strncmp(cp, "disks/", 6) == 0)
+		disk = "disk";
+	if (disk) {
+		cp += 6;
+		if (strncmp(cp, disk, 4) != 0)
+			goto errout;
+		cp += 4;
+		while (*cp != '/' && *cp != 0) {
+			if (!isdigit(*cp))
+				goto errout;
+			cp++;
+		}
+		*cp = 0;
+		return str;
+	}
+#endif
+
+errout:
+	free(str);
+	return NULL;
+}
+
+
+static const char * const ignored_types[] = {
+	"ignore",
+	"iso9660",
+	"nfs",
+	"proc",
+	"sw",
+	"swap",
+	"tmpfs",
+	"devpts",
+	NULL
+};
+
+static const char * const really_wanted[] = {
+	"minix",
+	"ext2",
+	"ext3",
+	"jfs",
+	"reiserfs",
+	"xiafs",
+	"xfs",
+	NULL
+};
+
+#define BASE_MD "/dev/md"
+
+/*
+ * Global variables for options
+ */
+static char *devices[MAX_DEVICES];
+static char *args[MAX_ARGS];
+static int num_devices, num_args;
+
+static int verbose;
+static int doall;
+static int noexecute;
+static int serialize;
+static int skip_root;
+static int like_mount;
+static int notitle;
+static int parallel_root;
+static int progress;
+static int progress_fd;
+static int force_all_parallel;
+static int num_running;
+static int max_running;
+static volatile int cancel_requested;
+static int kill_sent;
+static char *fstype;
+static struct fs_info *filesys_info, *filesys_last;
+static struct fsck_instance *instance_list;
+static char *fsck_path;
+static blkid_cache cache;
+
+static char *string_copy(const char *s)
+{
+	char    *ret;
+
+	if (!s)
+		return 0;
+	ret = strdup(s);
+	return ret;
+}
+
+static int string_to_int(const char *s)
+{
+	long l;
+	char *p;
+
+	l = strtol(s, &p, 0);
+	if (*p || l == LONG_MIN || l == LONG_MAX || l < 0 || l > INT_MAX)
+		return -1;
+	else
+		return (int) l;
+}
+
+static char *skip_over_blank(char *cp)
+{
+	while (*cp && isspace(*cp))
+		cp++;
+	return cp;
+}
+
+static char *skip_over_word(char *cp)
+{
+	while (*cp && !isspace(*cp))
+		cp++;
+	return cp;
+}
+
+static void strip_line(char *line)
+{
+	char    *p;
+
+	while (*line) {
+		p = line + strlen(line) - 1;
+		if ((*p == '\n') || (*p == '\r'))
+			*p = 0;
+		else
+			break;
+	}
+}
+
+static char *parse_word(char **buf)
+{
+	char *word, *next;
+
+	word = *buf;
+	if (*word == 0)
+		return 0;
+
+	word = skip_over_blank(word);
+	next = skip_over_word(word);
+	if (*next)
+		*next++ = 0;
+	*buf = next;
+	return word;
+}
+
+static void parse_escape(char *word)
+{
+	char    *q, c;
+	const char *p;
+
+	if (!word)
+		return;
+
+	for (p = q = word; *p; q++) {
+		c = *p++;
+		if (c != '\\') {
+			*q = c;
+		} else {
+			*q = bb_process_escape_sequence(&p);
+		}
+	}
+	*q = 0;
+}
+
+static void free_instance(struct fsck_instance *i)
+{
+	if (i->prog)
+		free(i->prog);
+	if (i->device)
+		free(i->device);
+	if (i->base_device)
+		free(i->base_device);
+	free(i);
+	return;
+}
+
+static struct fs_info *create_fs_device(const char *device, const char *mntpnt,
+					const char *type, const char *opts,
+					int freq, int passno)
+{
+	struct fs_info *fs;
+
+	if (!(fs = malloc(sizeof(struct fs_info))))
+		return NULL;
+
+	fs->device = string_copy(device);
+	fs->mountpt = string_copy(mntpnt);
+	fs->type = string_copy(type);
+	fs->opts = string_copy(opts ? opts : "");
+	fs->freq = freq;
+	fs->passno = passno;
+	fs->flags = 0;
+	fs->next = NULL;
+
+	if (!filesys_info)
+		filesys_info = fs;
+	else
+		filesys_last->next = fs;
+	filesys_last = fs;
+
+	return fs;
+}
+
+
+
+static int parse_fstab_line(char *line, struct fs_info **ret_fs)
+{
+	char    *dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
+	struct fs_info *fs;
+
+	*ret_fs = 0;
+	strip_line(line);
+	if ((cp = strchr(line, '#')))
+		*cp = 0;        /* Ignore everything after the comment char */
+	cp = line;
+
+	device = parse_word(&cp);
+	mntpnt = parse_word(&cp);
+	type = parse_word(&cp);
+	opts = parse_word(&cp);
+	freq = parse_word(&cp);
+	passno = parse_word(&cp);
+
+	if (!device)
+		return 0;       /* Allow blank lines */
+
+	if (!mntpnt || !type)
+		return -1;
+
+	parse_escape(device);
+	parse_escape(mntpnt);
+	parse_escape(type);
+	parse_escape(opts);
+	parse_escape(freq);
+	parse_escape(passno);
+
+	dev = blkid_get_devname(cache, device, NULL);
+	if (dev)
+		device = dev;
+
+	if (strchr(type, ','))
+		type = 0;
+
+	fs = create_fs_device(device, mntpnt, type ? type : "auto", opts,
+			      freq ? atoi(freq) : -1,
+			      passno ? atoi(passno) : -1);
+	if (dev)
+		free(dev);
+
+	if (!fs)
+		return -1;
+	*ret_fs = fs;
+	return 0;
+}
+
+static void interpret_type(struct fs_info *fs)
+{
+	char    *t;
+
+	if (strcmp(fs->type, "auto") != 0)
+		return;
+	t = blkid_get_tag_value(cache, "TYPE", fs->device);
+	if (t) {
+		free(fs->type);
+		fs->type = t;
+	}
+}
+
+/*
+ * Load the filesystem database from /etc/fstab
+ */
+static void load_fs_info(const char *filename)
+{
+	FILE    *f;
+	char    buf[1024];
+	int     lineno = 0;
+	int     old_fstab = 1;
+	struct fs_info *fs;
+
+	if ((f = fopen(filename, "r")) == NULL) {
+		bb_perror_msg("WARNING: couldn't open %s", filename);
+		return;
+	}
+	while (!feof(f)) {
+		lineno++;
+		if (!fgets(buf, sizeof(buf), f))
+			break;
+		buf[sizeof(buf)-1] = 0;
+		if (parse_fstab_line(buf, &fs) < 0) {
+			bb_error_msg("WARNING: bad format "
+				"on line %d of %s\n", lineno, filename);
+			continue;
+		}
+		if (!fs)
+			continue;
+		if (fs->passno < 0)
+			fs->passno = 0;
+		else
+			old_fstab = 0;
+	}
+
+	fclose(f);
+
+	if (old_fstab) {
+		fputs("\007\007\007"
+		"WARNING: Your /etc/fstab does not contain the fsck passno\n"
+		"       field.  I will kludge around things for you, but you\n"
+		"       should fix your /etc/fstab file as soon as you can.\n\n", stderr);
+
+		for (fs = filesys_info; fs; fs = fs->next) {
+			fs->passno = 1;
+		}
+	}
+}
+
+/* Lookup filesys in /etc/fstab and return the corresponding entry. */
+static struct fs_info *lookup(char *filesys)
+{
+	struct fs_info *fs;
+
+	/* No filesys name given. */
+	if (filesys == NULL)
+		return NULL;
+
+	for (fs = filesys_info; fs; fs = fs->next) {
+		if (!strcmp(filesys, fs->device) ||
+		    (fs->mountpt && !strcmp(filesys, fs->mountpt)))
+			break;
+	}
+
+	return fs;
+}
+
+/* Find fsck program for a given fs type. */
+static char *find_fsck(char *type)
+{
+  char *s;
+  const char *tpl;
+  char *p = string_copy(fsck_path);
+  struct stat st;
+
+  /* Are we looking for a program or just a type? */
+  tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s");
+
+  for(s = strtok(p, ":"); s; s = strtok(NULL, ":")) {
+	s = bb_xasprintf(tpl, s, type);
+	if (stat(s, &st) == 0) break;
+	free(s);
+  }
+  free(p);
+  return(s);
+}
+
+static int progress_active(void)
+{
+	struct fsck_instance *inst;
+
+	for (inst = instance_list; inst; inst = inst->next) {
+		if (inst->flags & FLAG_DONE)
+			continue;
+		if (inst->flags & FLAG_PROGRESS)
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ * Execute a particular fsck program, and link it into the list of
+ * child processes we are waiting for.
+ */
+static int execute(const char *type, const char *device, const char *mntpt,
+		   int interactive)
+{
+	char *s, *argv[80];
+	char *prog;
+	int  argc, i;
+	struct fsck_instance *inst, *p;
+	pid_t   pid;
+
+	inst = malloc(sizeof(struct fsck_instance));
+	if (!inst)
+		return ENOMEM;
+	memset(inst, 0, sizeof(struct fsck_instance));
+
+	prog = bb_xasprintf("fsck.%s", type);
+	argv[0] = prog;
+	argc = 1;
+
+	for (i=0; i <num_args; i++)
+		argv[argc++] = string_copy(args[i]);
+
+	if (progress && !progress_active()) {
+		if ((strcmp(type, "ext2") == 0) ||
+		    (strcmp(type, "ext3") == 0)) {
+			char tmp[80];
+			snprintf(tmp, 80, "-C%d", progress_fd);
+			argv[argc++] = string_copy(tmp);
+			inst->flags |= FLAG_PROGRESS;
+		}
+	}
+
+	argv[argc++] = string_copy(device);
+	argv[argc] = 0;
+
+	s = find_fsck(prog);
+	if (s == NULL) {
+		bb_error_msg("%s: not found", prog);
+		return ENOENT;
+	}
+
+	if (verbose || noexecute) {
+		printf("[%s (%d) -- %s] ", s, num_running,
+		       mntpt ? mntpt : device);
+		for (i=0; i < argc; i++)
+			printf("%s ", argv[i]);
+		printf("\n");
+	}
+
+	/* Fork and execute the correct program. */
+	if (noexecute)
+		pid = -1;
+	else if ((pid = fork()) < 0) {
+		perror("fork");
+		return errno;
+	} else if (pid == 0) {
+		if (!interactive)
+			close(0);
+		(void) execv(s, argv);
+		bb_perror_msg_and_die("%s", argv[0]);
+	}
+
+	for (i = 1; i < argc; i++)
+		free(argv[i]);
+
+	free(s);
+	inst->pid = pid;
+	inst->prog = prog;
+	inst->type = string_copy(type);
+	inst->device = string_copy(device);
+	inst->base_device = base_device(device);
+	inst->start_time = time(0);
+	inst->next = NULL;
+
+	/*
+	 * Find the end of the list, so we add the instance on at the end.
+	 */
+	for (p = instance_list; p && p->next; p = p->next);
+
+	if (p)
+		p->next = inst;
+	else
+		instance_list = inst;
+
+	return 0;
+}
+
+/*
+ * Send a signal to all outstanding fsck child processes
+ */
+static int kill_all(int signum)
+{
+	struct fsck_instance *inst;
+	int     n = 0;
+
+	for (inst = instance_list; inst; inst = inst->next) {
+		if (inst->flags & FLAG_DONE)
+			continue;
+		kill(inst->pid, signum);
+		n++;
+	}
+	return n;
+}
+
+/*
+ * Wait for one child process to exit; when it does, unlink it from
+ * the list of executing child processes, and return it.
+ */
+static struct fsck_instance *wait_one(int flags)
+{
+	int     status;
+	int     sig;
+	struct fsck_instance *inst, *inst2, *prev;
+	pid_t   pid;
+
+	if (!instance_list)
+		return NULL;
+
+	if (noexecute) {
+		inst = instance_list;
+		prev = 0;
+#ifdef RANDOM_DEBUG
+		while (inst->next && (random() & 1)) {
+			prev = inst;
+			inst = inst->next;
+		}
+#endif
+		inst->exit_status = 0;
+		goto ret_inst;
+	}
+
+	/*
+	 * gcc -Wall fails saving throw against stupidity
+	 * (inst and prev are thought to be uninitialized variables)
+	 */
+	inst = prev = NULL;
+
+	do {
+		pid = waitpid(-1, &status, flags);
+		if (cancel_requested && !kill_sent) {
+			kill_all(SIGTERM);
+			kill_sent++;
+		}
+		if ((pid == 0) && (flags & WNOHANG))
+			return NULL;
+		if (pid < 0) {
+			if ((errno == EINTR) || (errno == EAGAIN))
+				continue;
+			if (errno == ECHILD) {
+				bb_error_msg("wait: No more child process?!?");
+				return NULL;
+			}
+			perror("wait");
+			continue;
+		}
+		for (prev = 0, inst = instance_list;
+		     inst;
+		     prev = inst, inst = inst->next) {
+			if (inst->pid == pid)
+				break;
+		}
+	} while (!inst);
+
+	if (WIFEXITED(status))
+		status = WEXITSTATUS(status);
+	else if (WIFSIGNALED(status)) {
+		sig = WTERMSIG(status);
+		if (sig == SIGINT) {
+			status = EXIT_UNCORRECTED;
+		} else {
+			printf("Warning... %s for device %s exited "
+			       "with signal %d.\n",
+			       inst->prog, inst->device, sig);
+			status = EXIT_ERROR;
+		}
+	} else {
+		printf("%s %s: status is %x, should never happen.\n",
+		       inst->prog, inst->device, status);
+		status = EXIT_ERROR;
+	}
+	inst->exit_status = status;
+	if (progress && (inst->flags & FLAG_PROGRESS) &&
+	    !progress_active()) {
+		for (inst2 = instance_list; inst2; inst2 = inst2->next) {
+			if (inst2->flags & FLAG_DONE)
+				continue;
+			if (strcmp(inst2->type, "ext2") &&
+			    strcmp(inst2->type, "ext3"))
+				continue;
+			/*
+			 * If we've just started the fsck, wait a tiny
+			 * bit before sending the kill, to give it
+			 * time to set up the signal handler
+			 */
+			if (inst2->start_time < time(0)+2) {
+				if (fork() == 0) {
+					sleep(1);
+					kill(inst2->pid, SIGUSR1);
+					exit(0);
+				}
+			} else
+				kill(inst2->pid, SIGUSR1);
+			inst2->flags |= FLAG_PROGRESS;
+			break;
+		}
+	}
+ret_inst:
+	if (prev)
+		prev->next = inst->next;
+	else
+		instance_list = inst->next;
+	if (verbose > 1)
+		printf("Finished with %s (exit status %d)\n",
+		       inst->device, inst->exit_status);
+	num_running--;
+	return inst;
+}
+
+#define FLAG_WAIT_ALL           0
+#define FLAG_WAIT_ATLEAST_ONE   1
+/*
+ * Wait until all executing child processes have exited; return the
+ * logical OR of all of their exit code values.
+ */
+static int wait_many(int flags)
+{
+	struct fsck_instance *inst;
+	int     global_status = 0;
+	int     wait_flags = 0;
+
+	while ((inst = wait_one(wait_flags))) {
+		global_status |= inst->exit_status;
+		free_instance(inst);
+#ifdef RANDOM_DEBUG
+		if (noexecute && (flags & WNOHANG) && !(random() % 3))
+			break;
+#endif
+		if (flags & FLAG_WAIT_ATLEAST_ONE)
+			wait_flags = WNOHANG;
+	}
+	return global_status;
+}
+
+/*
+ * Run the fsck program on a particular device
+ *
+ * If the type is specified using -t, and it isn't prefixed with "no"
+ * (as in "noext2") and only one filesystem type is specified, then
+ * use that type regardless of what is specified in /etc/fstab.
+ *
+ * If the type isn't specified by the user, then use either the type
+ * specified in /etc/fstab, or DEFAULT_FSTYPE.
+ */
+static void fsck_device(struct fs_info *fs, int interactive)
+{
+	const char *type;
+	int retval;
+
+	interpret_type(fs);
+
+	if (strcmp(fs->type, "auto") != 0)
+		type = fs->type;
+	else if (fstype && strncmp(fstype, "no", 2) &&
+	    strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) &&
+	    !strchr(fstype, ','))
+		type = fstype;
+	else
+		type = DEFAULT_FSTYPE;
+
+	num_running++;
+	retval = execute(type, fs->device, fs->mountpt, interactive);
+	if (retval) {
+		bb_error_msg("Error %d while executing fsck.%s for %s",
+						retval, type, fs->device);
+		num_running--;
+	}
+}
+
+
+/*
+ * Deal with the fsck -t argument.
+ */
+struct fs_type_compile {
+	char **list;
+	int *type;
+	int  negate;
+} fs_type_compiled;
+
+#define FS_TYPE_NORMAL  0
+#define FS_TYPE_OPT     1
+#define FS_TYPE_NEGOPT  2
+
+static const char fs_type_syntax_error[] =
+"Either all or none of the filesystem types passed to -t must be prefixed\n"
+   "with 'no' or '!'.";
+
+static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp)
+{
+	char    *cp, *list, *s;
+	int     num = 2;
+	int     negate, first_negate = 1;
+
+	if (fs_type) {
+		for (cp=fs_type; *cp; cp++) {
+			if (*cp == ',')
+				num++;
+		}
+	}
+
+	cmp->list = xcalloc(num, sizeof(char *));
+	cmp->type = xcalloc(num, sizeof(int));
+	cmp->negate = 0;
+
+	if (!fs_type)
+		return;
+
+	list = string_copy(fs_type);
+	num = 0;
+	s = strtok(list, ",");
+	while(s) {
+		negate = 0;
+		if (strncmp(s, "no", 2) == 0) {
+			s += 2;
+			negate = 1;
+		} else if (*s == '!') {
+			s++;
+			negate = 1;
+		}
+		if (strcmp(s, "loop") == 0)
+			/* loop is really short-hand for opts=loop */
+			goto loop_special_case;
+		else if (strncmp(s, "opts=", 5) == 0) {
+			s += 5;
+		loop_special_case:
+			cmp->type[num] = negate ? FS_TYPE_NEGOPT : FS_TYPE_OPT;
+		} else {
+			if (first_negate) {
+				cmp->negate = negate;
+				first_negate = 0;
+			}
+			if ((negate && !cmp->negate) ||
+			    (!negate && cmp->negate)) {
+				bb_error_msg_and_die("%s", fs_type_syntax_error);
+			}
+		}
+#if 0
+		printf("Adding %s to list (type %d).\n", s, cmp->type[num]);
+#endif
+		cmp->list[num++] = string_copy(s);
+		s = strtok(NULL, ",");
+	}
+	free(list);
+}
+
+/*
+ * This function returns true if a particular option appears in a
+ * comma-delimited options list
+ */
+static int opt_in_list(char *opt, char *optlist)
+{
+	char    *list, *s;
+
+	if (!optlist)
+		return 0;
+	list = string_copy(optlist);
+
+	s = strtok(list, ",");
+	while(s) {
+		if (strcmp(s, opt) == 0) {
+			free(list);
+			return 1;
+		}
+		s = strtok(NULL, ",");
+	}
+	free(list);
+	return 0;
+}
+
+/* See if the filesystem matches the criteria given by the -t option */
+static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp)
+{
+	int n, ret = 0, checked_type = 0;
+	char *cp;
+
+	if (cmp->list == 0 || cmp->list[0] == 0)
+		return 1;
+
+	for (n=0; (cp = cmp->list[n]); n++) {
+		switch (cmp->type[n]) {
+		case FS_TYPE_NORMAL:
+			checked_type++;
+			if (strcmp(cp, fs->type) == 0) {
+				ret = 1;
+			}
+			break;
+		case FS_TYPE_NEGOPT:
+			if (opt_in_list(cp, fs->opts))
+				return 0;
+			break;
+		case FS_TYPE_OPT:
+			if (!opt_in_list(cp, fs->opts))
+				return 0;
+			break;
+		}
+	}
+	if (checked_type == 0)
+		return 1;
+	return (cmp->negate ? !ret : ret);
+}
+
+/* Check if we should ignore this filesystem. */
+static int ignore(struct fs_info *fs)
+{
+	int wanted;
+	char *s;
+
+	/*
+	 * If the pass number is 0, ignore it.
+	 */
+	if (fs->passno == 0)
+		return 1;
+
+	interpret_type(fs);
+
+	/*
+	 * If a specific fstype is specified, and it doesn't match,
+	 * ignore it.
+	 */
+	if (!fs_match(fs, &fs_type_compiled)) return 1;
+
+	/* Are we ignoring this type? */
+	if(compare_string_array(ignored_types, fs->type) >= 0)
+		return 1;
+
+	/* Do we really really want to check this fs? */
+	wanted = compare_string_array(really_wanted, fs->type) >= 0;
+
+	/* See if the <fsck.fs> program is available. */
+	s = find_fsck(fs->type);
+	if (s == NULL) {
+		if (wanted)
+			bb_error_msg("cannot check %s: fsck.%s not found",
+				fs->device, fs->type);
+		return 1;
+	}
+	free(s);
+
+	/* We can and want to check this file system type. */
+	return 0;
+}
+
+/*
+ * Returns TRUE if a partition on the same disk is already being
+ * checked.
+ */
+static int device_already_active(char *device)
+{
+	struct fsck_instance *inst;
+	char *base;
+
+	if (force_all_parallel)
+		return 0;
+
+#ifdef BASE_MD
+	/* Don't check a soft raid disk with any other disk */
+	if (instance_list &&
+	    (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) ||
+	     !strncmp(device, BASE_MD, sizeof(BASE_MD)-1)))
+		return 1;
+#endif
+
+	base = base_device(device);
+	/*
+	 * If we don't know the base device, assume that the device is
+	 * already active if there are any fsck instances running.
+	 */
+	if (!base)
+		return (instance_list != 0);
+	for (inst = instance_list; inst; inst = inst->next) {
+		if (!inst->base_device || !strcmp(base, inst->base_device)) {
+			free(base);
+			return 1;
+		}
+	}
+	free(base);
+	return 0;
+}
+
+/* Check all file systems, using the /etc/fstab table. */
+static int check_all(void)
+{
+	struct fs_info *fs = NULL;
+	int status = EXIT_OK;
+	int not_done_yet = 1;
+	int passno = 1;
+	int pass_done;
+
+	if (verbose)
+		fputs("Checking all file systems.\n", stdout);
+
+	/*
+	 * Do an initial scan over the filesystem; mark filesystems
+	 * which should be ignored as done, and resolve any "auto"
+	 * filesystem types (done as a side-effect of calling ignore()).
+	 */
+	for (fs = filesys_info; fs; fs = fs->next) {
+		if (ignore(fs))
+			fs->flags |= FLAG_DONE;
+	}
+
+	/*
+	 * Find and check the root filesystem.
+	 */
+	if (!parallel_root) {
+		for (fs = filesys_info; fs; fs = fs->next) {
+			if (!strcmp(fs->mountpt, "/"))
+				break;
+		}
+		if (fs) {
+			if (!skip_root && !ignore(fs)) {
+				fsck_device(fs, 1);
+				status |= wait_many(FLAG_WAIT_ALL);
+				if (status > EXIT_NONDESTRUCT)
+					return status;
+			}
+			fs->flags |= FLAG_DONE;
+		}
+	}
+	/*
+	 * This is for the bone-headed user who enters the root
+	 * filesystem twice.  Skip root will skep all root entries.
+	 */
+	if (skip_root)
+		for (fs = filesys_info; fs; fs = fs->next)
+			if (!strcmp(fs->mountpt, "/"))
+				fs->flags |= FLAG_DONE;
+
+	while (not_done_yet) {
+		not_done_yet = 0;
+		pass_done = 1;
+
+		for (fs = filesys_info; fs; fs = fs->next) {
+			if (cancel_requested)
+				break;
+			if (fs->flags & FLAG_DONE)
+				continue;
+			/*
+			 * If the filesystem's pass number is higher
+			 * than the current pass number, then we don't
+			 * do it yet.
+			 */
+			if (fs->passno > passno) {
+				not_done_yet++;
+				continue;
+			}
+			/*
+			 * If a filesystem on a particular device has
+			 * already been spawned, then we need to defer
+			 * this to another pass.
+			 */
+			if (device_already_active(fs->device)) {
+				pass_done = 0;
+				continue;
+			}
+			/*
+			 * Spawn off the fsck process
+			 */
+			fsck_device(fs, serialize);
+			fs->flags |= FLAG_DONE;
+
+			/*
+			 * Only do one filesystem at a time, or if we
+			 * have a limit on the number of fsck's extant
+			 * at one time, apply that limit.
+			 */
+			if (serialize ||
+			    (max_running && (num_running >= max_running))) {
+				pass_done = 0;
+				break;
+			}
+		}
+		if (cancel_requested)
+			break;
+		if (verbose > 1)
+			printf("--waiting-- (pass %d)\n", passno);
+		status |= wait_many(pass_done ? FLAG_WAIT_ALL :
+				    FLAG_WAIT_ATLEAST_ONE);
+		if (pass_done) {
+			if (verbose > 1)
+				printf("----------------------------------\n");
+			passno++;
+		} else
+			not_done_yet++;
+	}
+	if (cancel_requested && !kill_sent) {
+		kill_all(SIGTERM);
+		kill_sent++;
+	}
+	status |= wait_many(FLAG_WAIT_ATLEAST_ONE);
+	return status;
+}
+
+static void signal_cancel(int sig FSCK_ATTR((unused)))
+{
+	cancel_requested++;
+}
+
+static void PRS(int argc, char *argv[])
+{
+	int     i, j;
+	char    *arg, *dev, *tmp = 0;
+	char    options[128];
+	int     opt = 0;
+	int     opts_for_fsck = 0;
+	struct sigaction        sa;
+
+	/*
+	 * Set up signal action
+	 */
+	memset(&sa, 0, sizeof(struct sigaction));
+	sa.sa_handler = signal_cancel;
+	sigaction(SIGINT, &sa, 0);
+	sigaction(SIGTERM, &sa, 0);
+
+	num_devices = 0;
+	num_args = 0;
+	instance_list = 0;
+
+	for (i=1; i < argc; i++) {
+		arg = argv[i];
+		if (!arg)
+			continue;
+		if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) {
+			if (num_devices >= MAX_DEVICES) {
+				bb_error_msg_and_die("too many devices");
+			}
+			dev = blkid_get_devname(cache, arg, NULL);
+			if (!dev && strchr(arg, '=')) {
+				/*
+				 * Check to see if we failed because
+				 * /proc/partitions isn't found.
+				 */
+				if (access("/proc/partitions", R_OK) < 0) {
+					bb_error_msg_and_die("Couldn't open /proc/partitions: %m\n"
+							"Is /proc mounted?");
+				}
+				/*
+				 * Check to see if this is because
+				 * we're not running as root
+				 */
+				if (geteuid())
+					bb_error_msg_and_die(
+		"Must be root to scan for matching filesystems: %s\n", arg);
+				else
+					bb_error_msg_and_die(
+		"Couldn't find matching filesystem: %s", arg);
+			}
+			devices[num_devices++] = dev ? dev : string_copy(arg);
+			continue;
+		}
+		if (arg[0] != '-' || opts_for_fsck) {
+			if (num_args >= MAX_ARGS) {
+				bb_error_msg_and_die("too many arguments");
+			}
+			args[num_args++] = string_copy(arg);
+			continue;
+		}
+		for (j=1; arg[j]; j++) {
+			if (opts_for_fsck) {
+				options[++opt] = arg[j];
+				continue;
+			}
+			switch (arg[j]) {
+			case 'A':
+				doall++;
+				break;
+			case 'C':
+				progress++;
+				if (arg[j+1]) {
+					progress_fd = string_to_int(arg+j+1);
+					if (progress_fd < 0)
+						progress_fd = 0;
+					else
+						goto next_arg;
+				} else if ((i+1) < argc &&
+					   !strncmp(argv[i+1], "-", 1) == 0) {
+					progress_fd = string_to_int(argv[i]);
+					if (progress_fd < 0)
+						progress_fd = 0;
+					else {
+						goto next_arg;
+						i++;
+					}
+				}
+				break;
+			case 'V':
+				verbose++;
+				break;
+			case 'N':
+				noexecute++;
+				break;
+			case 'R':
+				skip_root++;
+				break;
+			case 'T':
+				notitle++;
+				break;
+			case 'M':
+				like_mount++;
+				break;
+			case 'P':
+				parallel_root++;
+				break;
+			case 's':
+				serialize++;
+				break;
+			case 't':
+				tmp = 0;
+				if (fstype)
+					bb_show_usage();
+				if (arg[j+1])
+					tmp = arg+j+1;
+				else if ((i+1) < argc)
+					tmp = argv[++i];
+				else
+					bb_show_usage();
+				fstype = string_copy(tmp);
+				compile_fs_type(fstype, &fs_type_compiled);
+				goto next_arg;
+			case '-':
+				opts_for_fsck++;
+				break;
+			case '?':
+				bb_show_usage();
+				break;
+			default:
+				options[++opt] = arg[j];
+				break;
+			}
+		}
+	next_arg:
+		if (opt) {
+			options[0] = '-';
+			options[++opt] = '\0';
+			if (num_args >= MAX_ARGS) {
+				bb_error_msg("too many arguments");
+			}
+			args[num_args++] = string_copy(options);
+			opt = 0;
+		}
+	}
+	if (getenv("FSCK_FORCE_ALL_PARALLEL"))
+		force_all_parallel++;
+	if ((tmp = getenv("FSCK_MAX_INST")))
+	    max_running = atoi(tmp);
+}
+
+int fsck_main(int argc, char *argv[])
+{
+	int i, status = 0;
+	int interactive = 0;
+	const char *fstab;
+	struct fs_info *fs;
+
+	setvbuf(stdout, NULL, _IONBF, BUFSIZ);
+	setvbuf(stderr, NULL, _IONBF, BUFSIZ);
+
+	blkid_get_cache(&cache, NULL);
+	PRS(argc, argv);
+
+	if (!notitle)
+		printf("fsck %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
+
+	fstab = getenv("FSTAB_FILE");
+	if (!fstab)
+		fstab = _PATH_MNTTAB;
+	load_fs_info(fstab);
+
+	fsck_path = e2fs_set_sbin_path();
+
+	if ((num_devices == 1) || (serialize))
+		interactive = 1;
+
+	/* If -A was specified ("check all"), do that! */
+	if (doall)
+		return check_all();
+
+	if (num_devices == 0) {
+		serialize++;
+		interactive++;
+		return check_all();
+	}
+	for (i = 0 ; i < num_devices; i++) {
+		if (cancel_requested) {
+			if (!kill_sent) {
+				kill_all(SIGTERM);
+				kill_sent++;
+			}
+			break;
+		}
+		fs = lookup(devices[i]);
+		if (!fs) {
+			fs = create_fs_device(devices[i], 0, "auto",
+					      0, -1, -1);
+			if (!fs)
+				continue;
+		}
+		fsck_device(fs, interactive);
+		if (serialize ||
+		    (max_running && (num_running >= max_running))) {
+			struct fsck_instance *inst;
+
+			inst = wait_one(0);
+			if (inst) {
+				status |= inst->exit_status;
+				free_instance(inst);
+			}
+			if (verbose > 1)
+				printf("----------------------------------\n");
+		}
+	}
+	status |= wait_many(FLAG_WAIT_ALL);
+	blkid_put_cache(cache);
+	return status;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/fsck.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/fsck.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/fsck.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,15 @@
+/*
+ * fsck.h
+ */
+
+#define FSCK_ATTR(x) __attribute__(x)
+
+#define EXIT_OK          0
+#define EXIT_NONDESTRUCT 1
+#define EXIT_DESTRUCT    2
+#define EXIT_UNCORRECTED 4
+#define EXIT_ERROR       8
+#define EXIT_USAGE       16
+#define FSCK_CANCELED    32     /* Aborted with a signal or ^C */
+
+extern char *e2fs_set_sbin_path(void);

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/lsattr.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/lsattr.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/lsattr.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,135 @@
+/*
+ * lsattr.c		- List file attributes on an ext2 file system
+ *
+ * Copyright (C) 1993, 1994  Remy Card <card at masi.ibp.fr>
+ *                           Laboratoire MASI, Institut Blaise Pascal
+ *                           Universite Pierre et Marie Curie (Paris VI)
+ *
+ * This file can be redistributed under the terms of the GNU General
+ * Public License
+ */
+
+/*
+ * History:
+ * 93/10/30	- Creation
+ * 93/11/13	- Replace stat() calls by lstat() to avoid loops
+ * 94/02/27	- Integrated in Ted's distribution
+ * 98/12/29	- Display version info only when -V specified (G M Sipe)
+ */
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include "ext2fs/ext2_fs.h"
+#include "e2fsbb.h"
+#include "e2p/e2p.h"
+
+#define OPT_RECUR 1
+#define OPT_ALL 2
+#define OPT_DIRS_OPT 4
+#define OPT_PF_LONG 8
+#define OPT_GENERATION 16
+static int flags;
+
+#ifdef CONFIG_LFS
+# define LSTAT lstat64
+# define STRUCT_STAT struct stat64
+#else
+# define LSTAT lstat
+# define STRUCT_STAT struct stat
+#endif
+
+static void list_attributes(const char *name)
+{
+	unsigned long fsflags;
+	unsigned long generation;
+
+	if (fgetflags(name, &fsflags) == -1)
+		goto read_err;
+	if (flags & OPT_GENERATION) {
+		if (fgetversion(name, &generation) == -1)
+			goto read_err;
+		printf("%5lu ", generation);
+	}
+
+	if (flags & OPT_PF_LONG) {
+		printf("%-28s ", name);
+		print_flags(stdout, fsflags, PFOPT_LONG);
+		printf("\n");
+	} else {
+		print_flags(stdout, fsflags, 0);
+		printf(" %s\n", name);
+	}
+
+	return;
+read_err:
+	bb_perror_msg("reading %s", name);
+}
+
+static int lsattr_dir_proc(const char *, struct dirent *, void *);
+
+static void lsattr_args(const char *name)
+{
+	STRUCT_STAT	st;
+
+	if (LSTAT(name, &st) == -1) {
+		bb_perror_msg("stating %s", name);
+	} else {
+		if (S_ISDIR(st.st_mode) && !(flags & OPT_DIRS_OPT))
+			iterate_on_dir(name, lsattr_dir_proc, NULL);
+		else
+			list_attributes(name);
+	}
+}
+
+static int lsattr_dir_proc(const char *dir_name, struct dirent *de,
+			   void *private)
+{
+	STRUCT_STAT	st;
+	char *path;
+
+	path = concat_path_file(dir_name, de->d_name);
+
+	if (LSTAT(path, &st) == -1)
+		bb_perror_msg(path);
+	else {
+		if (de->d_name[0] != '.' || (flags & OPT_ALL)) {
+			list_attributes(path);
+			if (S_ISDIR(st.st_mode) && (flags & OPT_RECUR) &&
+			   (de->d_name[0] != '.' && (de->d_name[1] != '\0' ||
+			   (de->d_name[1] != '.' && de->d_name[2] != '\0')))) {
+				printf("\n%s:\n", path);
+				iterate_on_dir(path, lsattr_dir_proc, NULL);
+				printf("\n");
+			}
+		}
+	}
+
+	free(path);
+
+	return 0;
+}
+
+int lsattr_main(int argc, char **argv)
+{
+	int i;
+
+	flags = bb_getopt_ulflags(argc, argv, "Radlv");
+
+	if (optind > argc - 1)
+		lsattr_args(".");
+	else
+		for (i = optind; i < argc; i++)
+			lsattr_args(argv[i]);
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/mke2fs.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/mke2fs.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/mke2fs.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1364 @@
+/*
+ * mke2fs.c - Make a ext2fs filesystem.
+ *
+ * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+ *	2003, 2004, 2005 by Theodore Ts'o.
+ *
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ */
+
+/* Usage: mke2fs [options] device
+ *
+ * The device may be a block device or a image of one, but this isn't
+ * enforced (but it's not much fun on a character device :-).
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <time.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <mntent.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include "e2fsbb.h"
+#include "ext2fs/ext2_fs.h"
+#include "uuid/uuid.h"
+#include "e2p/e2p.h"
+#include "ext2fs/ext2fs.h"
+#include "util.h"
+
+#define STRIDE_LENGTH 8
+
+#ifndef __sparc__
+#define ZAP_BOOTBLOCK
+#endif
+
+static const char * device_name;
+
+/* Command line options */
+static int	cflag;
+static int	quiet;
+static int	super_only;
+static int	force;
+static int	noaction;
+static int	journal_size;
+static int	journal_flags;
+static const char *bad_blocks_filename;
+static __u32	fs_stride;
+
+static struct ext2_super_block param;
+static char *creator_os;
+static char *volume_label;
+static char *mount_dir;
+static char *journal_device = NULL;
+static int	sync_kludge; /* Set using the MKE2FS_SYNC env. option */
+
+static int sys_page_size = 4096;
+static int linux_version_code = 0;
+
+static int int_log2(int arg)
+{
+	int	l = 0;
+
+	arg >>= 1;
+	while (arg) {
+		l++;
+		arg >>= 1;
+	}
+	return l;
+}
+
+static int int_log10(unsigned int arg)
+{
+	int	l;
+
+	for (l=0; arg ; l++)
+		arg = arg / 10;
+	return l;
+}
+
+/*
+ * This function sets the default parameters for a filesystem
+ *
+ * The type is specified by the user.  The size is the maximum size
+ * (in megabytes) for which a set of parameters applies, with a size
+ * of zero meaning that it is the default parameter for the type.
+ * Note that order is important in the table below.
+ */
+#define DEF_MAX_BLOCKSIZE -1
+static const char default_str[] = "default";
+struct mke2fs_defaults {
+	const char	*type;
+	int		size;
+	int		blocksize;
+	int		inode_ratio;
+};
+
+static const struct mke2fs_defaults settings[] = {
+	{ default_str,	 0, 4096, 8192 },
+	{ default_str, 512, 1024, 4096 },
+	{ default_str,	 3, 1024, 8192 },
+	{ "journal",	 0, 4096, 8192 },
+	{ "news",	 0, 4096, 4096 },
+	{ "largefile",	 0, 4096, 1024 * 1024 },
+	{ "largefile4",  0, 4096, 4096 * 1024 },
+	{ 0,		 0,    0, 0},
+};
+
+static void set_fs_defaults(const char *fs_type,
+			    struct ext2_super_block *super,
+			    int blocksize, int sector_size,
+			    int *inode_ratio)
+{
+	int	megs;
+	int	ratio = 0;
+	const struct mke2fs_defaults *p;
+	int	use_bsize = 1024;
+
+	megs = super->s_blocks_count * (EXT2_BLOCK_SIZE(super) / 1024) / 1024;
+	if (inode_ratio)
+		ratio = *inode_ratio;
+	if (!fs_type)
+		fs_type = default_str;
+	for (p = settings; p->type; p++) {
+		if ((strcmp(p->type, fs_type) != 0) &&
+		    (strcmp(p->type, default_str) != 0))
+			continue;
+		if ((p->size != 0) && (megs > p->size))
+			continue;
+		if (ratio == 0)
+			*inode_ratio = p->inode_ratio < blocksize ?
+				blocksize : p->inode_ratio;
+		use_bsize = p->blocksize;
+	}
+	if (blocksize <= 0) {
+		if (use_bsize == DEF_MAX_BLOCKSIZE) {
+			use_bsize = sys_page_size;
+			if ((linux_version_code < (2*65536 + 6*256)) &&
+			    (use_bsize > 4096))
+				use_bsize = 4096;
+		}
+		if (sector_size && use_bsize < sector_size)
+			use_bsize = sector_size;
+		if ((blocksize < 0) && (use_bsize < (-blocksize)))
+			use_bsize = -blocksize;
+		blocksize = use_bsize;
+		super->s_blocks_count /= blocksize / 1024;
+	}
+	super->s_log_frag_size = super->s_log_block_size =
+		int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
+}
+
+
+/*
+ * Helper function for read_bb_file and test_disk
+ */
+static void invalid_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk_t blk)
+{
+	bb_error_msg("Bad block %u out of range; ignored", blk);
+	return;
+}
+
+/*
+ * Busybox stuff
+ */
+static void mke2fs_error_msg_and_die(int retval, const char *fmt, ...)__attribute__ ((format (printf, 2, 3)));
+static void mke2fs_error_msg_and_die(int retval, const char *fmt, ...)
+{
+	va_list ap;
+
+	if (retval) {
+		va_start(ap, fmt);
+		bb_fprintf(stderr,"\nCould not ");
+		bb_vfprintf(stderr, fmt, ap);
+		bb_fprintf(stderr, "\n");
+		va_end(ap);
+		exit(EXIT_FAILURE);
+	}
+}
+
+static void mke2fs_verbose(const char *fmt, ...)__attribute__ ((format (printf, 1, 2)));
+static void mke2fs_verbose(const char *fmt, ...)
+{
+	va_list ap;
+
+	if (!quiet) {
+		va_start(ap, fmt);
+		bb_vfprintf(stdout, fmt, ap);
+		fflush(stdout);
+		va_end(ap);
+	}
+}
+
+static void mke2fs_verbose_done(void)
+{
+	mke2fs_verbose("done\n");
+}
+
+static void mke2fs_warning_msg(int retval, char *fmt, ... )__attribute__ ((format (printf, 2, 3)));
+static void mke2fs_warning_msg(int retval, char *fmt, ... )
+{
+	va_list ap;
+
+	if (retval) {
+		va_start(ap, fmt);
+		bb_fprintf(stderr,"\nWarning: ");
+		bb_vfprintf(stderr, fmt, ap);
+		bb_fprintf(stderr, "\n");
+		va_end(ap);
+	}
+}
+
+/*
+ * Reads the bad blocks list from a file
+ */
+static void read_bb_file(ext2_filsys fs, badblocks_list *bb_list,
+			 const char *bad_blocks_file)
+{
+	FILE		*f;
+	errcode_t	retval;
+
+	f = bb_xfopen(bad_blocks_file, "r");
+	retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block);
+	fclose (f);
+	mke2fs_error_msg_and_die(retval, "read bad blocks from list");
+}
+
+/*
+ * Runs the badblocks program to test the disk
+ */
+static void test_disk(ext2_filsys fs, badblocks_list *bb_list)
+{
+	FILE		*f;
+	errcode_t	retval;
+	char		buf[1024];
+
+	sprintf(buf, "badblocks -b %d %s%s%s %d", fs->blocksize,
+		quiet ? "" : "-s ", (cflag > 1) ? "-w " : "",
+		fs->device_name, fs->super->s_blocks_count);
+	mke2fs_verbose("Running command: %s\n", buf);
+	f = popen(buf, "r");
+	if (!f) {
+		bb_perror_msg_and_die("Could not run '%s'", buf);
+	}
+	retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block);
+	pclose(f);
+	mke2fs_error_msg_and_die(retval, "read bad blocks from program");
+}
+
+static void handle_bad_blocks(ext2_filsys fs, badblocks_list bb_list)
+{
+	dgrp_t			i;
+	blk_t			j;
+	unsigned		must_be_good;
+	blk_t			blk;
+	badblocks_iterate	bb_iter;
+	errcode_t		retval;
+	blk_t			group_block;
+	int			group;
+	int			group_bad;
+
+	if (!bb_list)
+		return;
+
+	/*
+	 * The primary superblock and group descriptors *must* be
+	 * good; if not, abort.
+	 */
+	must_be_good = fs->super->s_first_data_block + 1 + fs->desc_blocks;
+	for (i = fs->super->s_first_data_block; i <= must_be_good; i++) {
+		if (ext2fs_badblocks_list_test(bb_list, i)) {
+			bb_error_msg_and_die(
+				"Block %d in primary superblock/group descriptor area bad\n"
+				"Blocks %d through %d must be good in order to build a filesystem\n"
+				"Aborting ...", i, fs->super->s_first_data_block, must_be_good);
+		}
+	}
+
+	/*
+	 * See if any of the bad blocks are showing up in the backup
+	 * superblocks and/or group descriptors.  If so, issue a
+	 * warning and adjust the block counts appropriately.
+	 */
+	group_block = fs->super->s_first_data_block +
+		fs->super->s_blocks_per_group;
+
+	for (i = 1; i < fs->group_desc_count; i++) {
+		group_bad = 0;
+		for (j=0; j < fs->desc_blocks+1; j++) {
+			if (ext2fs_badblocks_list_test(bb_list,
+						       group_block + j)) {
+				mke2fs_warning_msg(!group_bad,
+					"the backup superblock/group descriptors at block %d contain\n"
+					"bad blocks\n", group_block);
+				group_bad++;
+				group = ext2fs_group_of_blk(fs, group_block+j);
+				fs->group_desc[group].bg_free_blocks_count++;
+				fs->super->s_free_blocks_count++;
+			}
+		}
+		group_block += fs->super->s_blocks_per_group;
+	}
+
+	/*
+	 * Mark all the bad blocks as used...
+	 */
+	retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
+	mke2fs_error_msg_and_die(retval, "mark bad blocks as used");
+
+	while (ext2fs_badblocks_list_iterate(bb_iter, &blk))
+		ext2fs_mark_block_bitmap(fs->block_map, blk);
+	ext2fs_badblocks_list_iterate_end(bb_iter);
+}
+
+/*
+ * These functions implement a generalized progress meter.
+ */
+struct progress_struct {
+	char		format[20];
+	char		backup[80];
+	__u32		max;
+	int		skip_progress;
+};
+
+static void progress_init(struct progress_struct *progress,
+			  const char *label,__u32 max)
+{
+	int	i;
+
+	memset(progress, 0, sizeof(struct progress_struct));
+	if (quiet)
+		return;
+
+	/*
+	 * Figure out how many digits we need
+	 */
+	i = int_log10(max);
+	sprintf(progress->format, "%%%dd/%%%dld", i, i);
+	memset(progress->backup, '\b', sizeof(progress->backup)-1);
+	progress->backup[sizeof(progress->backup)-1] = 0;
+	if ((2*i)+1 < (int) sizeof(progress->backup))
+		progress->backup[(2*i)+1] = 0;
+	progress->max = max;
+
+	progress->skip_progress = 0;
+	if (getenv("MKE2FS_SKIP_PROGRESS"))
+		progress->skip_progress++;
+
+	fputs(label, stdout);
+	fflush(stdout);
+}
+
+static void progress_update(struct progress_struct *progress, __u32 val)
+{
+	if ((progress->format[0] == 0) || progress->skip_progress)
+		return;
+	printf(progress->format, val, progress->max);
+	fputs(progress->backup, stdout);
+}
+
+static void progress_close(struct progress_struct *progress)
+{
+	if (progress->format[0] == 0)
+		return;
+	printf("%-28s\n", "done");
+}
+
+
+/*
+ * Helper function which zeros out _num_ blocks starting at _blk_.  In
+ * case of an error, the details of the error is returned via _ret_blk_
+ * and _ret_count_ if they are non-NULL pointers.  Returns 0 on
+ * success, and an error code on an error.
+ *
+ * As a special case, if the first argument is NULL, then it will
+ * attempt to free the static zeroizing buffer.  (This is to keep
+ * programs that check for memory leaks happy.)
+ */
+static errcode_t zero_blocks(ext2_filsys fs, blk_t blk, int num,
+			     struct progress_struct *progress,
+			     blk_t *ret_blk, int *ret_count)
+{
+	int		j, count, next_update, next_update_incr;
+	static char	*buf;
+	errcode_t	retval;
+
+	/* If fs is null, clean up the static buffer and return */
+	if (!fs) {
+		if (buf) {
+			free(buf);
+			buf = 0;
+		}
+		return 0;
+	}
+	/* Allocate the zeroizing buffer if necessary */
+	if (!buf) {
+		buf = xcalloc(fs->blocksize, STRIDE_LENGTH);
+	}
+	/* OK, do the write loop */
+	next_update = 0;
+	next_update_incr = num / 100;
+	if (next_update_incr < 1)
+		next_update_incr = 1;
+	for (j=0; j < num; j += STRIDE_LENGTH, blk += STRIDE_LENGTH) {
+		count = num - j;
+		if (count > STRIDE_LENGTH)
+			count = STRIDE_LENGTH;
+		retval = io_channel_write_blk(fs->io, blk, count, buf);
+		if (retval) {
+			if (ret_count)
+				*ret_count = count;
+			if (ret_blk)
+				*ret_blk = blk;
+			return retval;
+		}
+		if (progress && j > next_update) {
+			next_update += num / 100;
+			progress_update(progress, blk);
+		}
+	}
+	return 0;
+}
+
+static void write_inode_tables(ext2_filsys fs)
+{
+	errcode_t	retval;
+	blk_t		blk;
+	dgrp_t		i;
+	int		num;
+	struct progress_struct progress;
+
+	if (quiet)
+		memset(&progress, 0, sizeof(progress));
+	else
+		progress_init(&progress, "Writing inode tables: ",
+			      fs->group_desc_count);
+
+	for (i = 0; i < fs->group_desc_count; i++) {
+		progress_update(&progress, i);
+
+		blk = fs->group_desc[i].bg_inode_table;
+		num = fs->inode_blocks_per_group;
+
+		retval = zero_blocks(fs, blk, num, 0, &blk, &num);
+		mke2fs_error_msg_and_die(retval,
+			"write %d blocks in inode table starting at %d.",
+			num, blk);
+		if (sync_kludge) {
+			if (sync_kludge == 1)
+				sync();
+			else if ((i % sync_kludge) == 0)
+				sync();
+		}
+	}
+	zero_blocks(0, 0, 0, 0, 0, 0);
+	progress_close(&progress);
+}
+
+static void create_root_dir(ext2_filsys fs)
+{
+	errcode_t		retval;
+	struct ext2_inode	inode;
+
+	retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 0);
+	mke2fs_error_msg_and_die(retval, "create root dir");
+	if (geteuid()) {
+		retval = ext2fs_read_inode(fs, EXT2_ROOT_INO, &inode);
+		mke2fs_error_msg_and_die(retval, "read root inode");
+		inode.i_uid = getuid();
+		if (inode.i_uid)
+			inode.i_gid = getgid();
+		retval = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
+		mke2fs_error_msg_and_die(retval, "set root inode ownership");
+	}
+}
+
+static void create_lost_and_found(ext2_filsys fs)
+{
+	errcode_t		retval;
+	ext2_ino_t		ino;
+	const char		*name = "lost+found";
+	int			i = 1;
+	char			*msg = "create";
+	int			lpf_size = 0;
+
+	fs->umask = 077;
+	retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, 0, name);
+	if (retval) {
+		goto CREATE_LOST_AND_FOUND_ERROR;
+	}
+
+	retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, strlen(name), 0, &ino);
+	if (retval) {
+		msg = "lookup";
+		goto CREATE_LOST_AND_FOUND_ERROR;
+	}
+
+	for (; i < EXT2_NDIR_BLOCKS; i++) {
+		if ((lpf_size += fs->blocksize) >= 16*1024)
+			break;
+		retval = ext2fs_expand_dir(fs, ino);
+		msg = "expand";
+CREATE_LOST_AND_FOUND_ERROR:
+		mke2fs_error_msg_and_die(retval, "%s %s", msg, name);
+	}
+}
+
+static void create_bad_block_inode(ext2_filsys fs, badblocks_list bb_list)
+{
+	errcode_t	retval;
+
+	ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_BAD_INO);
+	fs->group_desc[0].bg_free_inodes_count--;
+	fs->super->s_free_inodes_count--;
+	retval = ext2fs_update_bb_inode(fs, bb_list);
+	mke2fs_error_msg_and_die(retval, "set bad block inode");
+}
+
+static void reserve_inodes(ext2_filsys fs)
+{
+	ext2_ino_t	i;
+	int		group;
+
+	for (i = EXT2_ROOT_INO + 1; i < EXT2_FIRST_INODE(fs->super); i++) {
+		ext2fs_mark_inode_bitmap(fs->inode_map, i);
+		group = ext2fs_group_of_ino(fs, i);
+		fs->group_desc[group].bg_free_inodes_count--;
+		fs->super->s_free_inodes_count--;
+	}
+	ext2fs_mark_ib_dirty(fs);
+}
+
+#define BSD_DISKMAGIC   (0x82564557UL)  /* The disk magic number */
+#define BSD_MAGICDISK   (0x57455682UL)  /* The disk magic number reversed */
+#define BSD_LABEL_OFFSET        64
+
+static void zap_sector(ext2_filsys fs, int sect, int nsect)
+{
+	char *buf;
+	char *fmt = "could not %s %d";
+	int retval;
+	unsigned int *magic;
+
+	buf = xmalloc(512*nsect);
+
+	if (sect == 0) {
+		/* Check for a BSD disklabel, and don't erase it if so */
+		retval = io_channel_read_blk(fs->io, 0, -512, buf);
+		if (retval)
+			mke2fs_warning_msg(retval, fmt, "read block", 0);
+		else {
+			magic = (unsigned int *) (buf + BSD_LABEL_OFFSET);
+			if ((*magic == BSD_DISKMAGIC) ||
+			    (*magic == BSD_MAGICDISK))
+				return;
+		}
+	}
+
+	memset(buf, 0, 512*nsect);
+	io_channel_set_blksize(fs->io, 512);
+	retval = io_channel_write_blk(fs->io, sect, -512*nsect, buf);
+	io_channel_set_blksize(fs->io, fs->blocksize);
+	free(buf);
+	mke2fs_warning_msg(retval, fmt, "erase sector", sect);
+}
+
+static void create_journal_dev(ext2_filsys fs)
+{
+	struct progress_struct	progress;
+	errcode_t		retval;
+	char			*buf;
+	char			*fmt = "%s journal superblock";
+	blk_t			blk;
+	int			count;
+
+	retval = ext2fs_create_journal_superblock(fs,
+				  fs->super->s_blocks_count, 0, &buf);
+	mke2fs_error_msg_and_die(retval, fmt, "init");
+	if (quiet)
+		memset(&progress, 0, sizeof(progress));
+	else
+		progress_init(&progress, "Zeroing journal device: ",
+			      fs->super->s_blocks_count);
+
+	retval = zero_blocks(fs, 0, fs->super->s_blocks_count,
+			     &progress, &blk, &count);
+	mke2fs_error_msg_and_die(retval, "zero journal device (block %u, count %d)",
+			blk, count);
+	zero_blocks(0, 0, 0, 0, 0, 0);
+
+	retval = io_channel_write_blk(fs->io,
+				      fs->super->s_first_data_block+1,
+				      1, buf);
+	mke2fs_error_msg_and_die(retval, fmt, "write");
+	progress_close(&progress);
+}
+
+static void show_stats(ext2_filsys fs)
+{
+	struct ext2_super_block *s = fs->super;
+	char			*os;
+	blk_t			group_block;
+	dgrp_t			i;
+	int			need, col_left;
+
+	mke2fs_warning_msg((param.s_blocks_count != s->s_blocks_count),
+		"%d blocks unused\n", param.s_blocks_count - s->s_blocks_count);
+	os = e2p_os2string(fs->super->s_creator_os);
+	printf(	"Filesystem label=%.*s\n"
+			"OS type: %s\n"
+			"Block size=%u (log=%u)\n"
+			"Fragment size=%u (log=%u)\n"
+			"%u inodes, %u blocks\n"
+			"%u blocks (%2.2f%%) reserved for the super user\n"
+			"First data block=%u\n",
+			(int) sizeof(s->s_volume_name),
+			s->s_volume_name,
+			os,
+			fs->blocksize, s->s_log_block_size,
+			fs->fragsize, s->s_log_frag_size,
+			s->s_inodes_count, s->s_blocks_count,
+			s->s_r_blocks_count, 100.0 * s->s_r_blocks_count / s->s_blocks_count,
+			s->s_first_data_block);
+	free(os);
+	if (s->s_reserved_gdt_blocks) {
+		printf("Maximum filesystem blocks=%lu\n",
+		       (s->s_reserved_gdt_blocks + fs->desc_blocks) *
+		       (fs->blocksize / sizeof(struct ext2_group_desc)) *
+		       s->s_blocks_per_group);
+	}
+	printf(	"%u block group%s\n"
+			"%u blocks per group, %u fragments per group\n"
+			"%u inodes per group\n",
+			fs->group_desc_count, (fs->group_desc_count > 1) ? "s" : "",
+			s->s_blocks_per_group, s->s_frags_per_group,
+			s->s_inodes_per_group);
+	if (fs->group_desc_count == 1) {
+		puts("");
+		return;
+	}
+
+	printf("Superblock backups stored on blocks: ");
+	group_block = s->s_first_data_block;
+	col_left = 0;
+	for (i = 1; i < fs->group_desc_count; i++) {
+		group_block += s->s_blocks_per_group;
+		if (!ext2fs_bg_has_super(fs, i))
+			continue;
+		if (i != 1)
+			printf(", ");
+		need = int_log10(group_block) + 2;
+		if (need > col_left) {
+			printf("\n\t");
+			col_left = 72;
+		}
+		col_left -= need;
+		printf("%u", group_block);
+	}
+	puts("\n");
+}
+
+/*
+ * Set the S_CREATOR_OS field.  Return true if OS is known,
+ * otherwise, 0.
+ */
+static int set_os(struct ext2_super_block *sb, char *os)
+{
+	if (isdigit (*os)) {
+		sb->s_creator_os = atoi (os);
+		return 1;
+	}
+
+	if((sb->s_creator_os = e2p_string2os(os)) >= 0) {
+		return 1;
+	} else if (!strcasecmp("GNU", os)) {
+		sb->s_creator_os = EXT2_OS_HURD;
+		return 1;
+	}
+	return 0;
+}
+
+static void parse_extended_opts(struct ext2_super_block *sb_param,
+				const char *opts)
+{
+	char	*buf, *token, *next, *p, *arg;
+	int	r_usage = 0;
+
+	buf = bb_xstrdup(opts);
+	for (token = buf; token && *token; token = next) {
+		p = strchr(token, ',');
+		next = 0;
+		if (p) {
+			*p = 0;
+			next = p+1;
+		}
+		arg = strchr(token, '=');
+		if (arg) {
+			*arg = 0;
+			arg++;
+		}
+		if (strcmp(token, "stride") == 0) {
+			if (!arg) {
+				r_usage++;
+				continue;
+			}
+			fs_stride = strtoul(arg, &p, 0);
+			if (*p || (fs_stride == 0)) {
+				bb_error_msg("Invalid stride parameter: %s", arg);
+				r_usage++;
+				continue;
+			}
+		} else if (!strcmp(token, "resize")) {
+			unsigned long resize, bpg, rsv_groups;
+			unsigned long group_desc_count, desc_blocks;
+			unsigned int gdpb, blocksize;
+			int rsv_gdb;
+
+			if (!arg) {
+				r_usage++;
+				continue;
+			}
+
+			resize = parse_num_blocks(arg,
+						  sb_param->s_log_block_size);
+
+			if (resize == 0) {
+				bb_error_msg("Invalid resize parameter: %s", arg);
+				r_usage++;
+				continue;
+			}
+			if (resize <= sb_param->s_blocks_count) {
+				bb_error_msg("The resize maximum must be greater "
+				             "than the filesystem size");
+				r_usage++;
+				continue;
+			}
+
+			blocksize = EXT2_BLOCK_SIZE(sb_param);
+			bpg = sb_param->s_blocks_per_group;
+			if (!bpg)
+				bpg = blocksize * 8;
+			gdpb = blocksize / sizeof(struct ext2_group_desc);
+			group_desc_count = (sb_param->s_blocks_count +
+					    bpg - 1) / bpg;
+			desc_blocks = (group_desc_count +
+				       gdpb - 1) / gdpb;
+			rsv_groups = (resize + bpg - 1) / bpg;
+			rsv_gdb = (rsv_groups + gdpb - 1) / gdpb -
+				desc_blocks;
+			if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb_param))
+				rsv_gdb = EXT2_ADDR_PER_BLOCK(sb_param);
+
+			if (rsv_gdb > 0) {
+				sb_param->s_feature_compat |=
+					EXT2_FEATURE_COMPAT_RESIZE_INODE;
+
+				sb_param->s_reserved_gdt_blocks = rsv_gdb;
+			}
+		} else
+			r_usage++;
+	}
+	if (r_usage) {
+		bb_error_msg_and_die(
+			"\nBad options specified.\n\n"
+			"Extended options are separated by commas, "
+			"and may take an argument which\n"
+			"\tis set off by an equals ('=') sign.\n\n"
+			"Valid extended options are:\n"
+			"\tstride=<stride length in blocks>\n"
+			"\tresize=<resize maximum size in blocks>\n");
+	}
+}
+
+static __u32 ok_features[3] = {
+	EXT3_FEATURE_COMPAT_HAS_JOURNAL |
+		EXT2_FEATURE_COMPAT_RESIZE_INODE |
+		EXT2_FEATURE_COMPAT_DIR_INDEX,  /* Compat */
+	EXT2_FEATURE_INCOMPAT_FILETYPE|         /* Incompat */
+		EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|
+		EXT2_FEATURE_INCOMPAT_META_BG,
+	EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER     /* R/O compat */
+};
+
+static int PRS(int argc, char *argv[])
+{
+	int		b, c;
+	int		size;
+	char *		tmp;
+	int		blocksize = 0;
+	int		inode_ratio = 0;
+	int		inode_size = 0;
+	int		reserved_ratio = 5;
+	int		sector_size = 0;
+	int		show_version_only = 0;
+	ext2_ino_t	num_inodes = 0;
+	errcode_t	retval;
+	char *		extended_opts = 0;
+	const char *	fs_type = 0;
+	blk_t		dev_size;
+	long		sysval;
+
+	/* Update our PATH to include /sbin  */
+	e2fs_set_sbin_path();
+
+	tmp = getenv("MKE2FS_SYNC");
+	if (tmp)
+		sync_kludge = atoi(tmp);
+
+	/* Determine the system page size if possible */
+#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
+#define _SC_PAGESIZE _SC_PAGE_SIZE
+#endif
+#ifdef _SC_PAGESIZE
+	sysval = sysconf(_SC_PAGESIZE);
+	if (sysval > 0)
+		sys_page_size = sysval;
+#endif /* _SC_PAGESIZE */
+
+	setbuf(stdout, NULL);
+	setbuf(stderr, NULL);
+	memset(&param, 0, sizeof(struct ext2_super_block));
+	param.s_rev_level = 1;  /* Create revision 1 filesystems now */
+	param.s_feature_incompat |= EXT2_FEATURE_INCOMPAT_FILETYPE;
+	param.s_feature_ro_compat |= EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+#if 0
+	param.s_feature_compat |= EXT2_FEATURE_COMPAT_DIR_INDEX;
+#endif
+
+#ifdef __linux__
+	linux_version_code = get_linux_version_code();
+	if (linux_version_code && linux_version_code < KERNEL_VERSION(2,2,0)) {
+		param.s_rev_level = 0;
+		param.s_feature_incompat = 0;
+		param.s_feature_compat = 0;
+		param.s_feature_ro_compat = 0;
+	}
+#endif
+
+	/* If called as mkfs.ext3, create a journal inode */
+	if (last_char_is(bb_applet_name, '3'))
+		journal_size = -1;
+
+	while ((c = getopt (argc, argv,
+		    "b:cE:f:g:i:jl:m:no:qr:R:s:tvI:J:ST:FL:M:N:O:V")) != EOF) {
+		switch (c) {
+		case 'b':
+			if (safe_strtoi(optarg, &blocksize))
+				goto BLOCKSIZE_ERROR;
+			b = (blocksize > 0) ? blocksize : -blocksize;
+			if (b < EXT2_MIN_BLOCK_SIZE ||
+			    b > EXT2_MAX_BLOCK_SIZE) {
+BLOCKSIZE_ERROR:
+				bb_error_msg_and_die("invalid block size - %s", optarg);
+			}
+			mke2fs_warning_msg((blocksize > 4096),
+				"blocksize %d not usable on most systems",
+				blocksize);
+			if (blocksize > 0)
+				param.s_log_block_size =
+					int_log2(blocksize >>
+						 EXT2_MIN_BLOCK_LOG_SIZE);
+			break;
+		case 'c':	/* Check for bad blocks */
+		case 't':	/* deprecated */
+			cflag++;
+			break;
+		case 'f':
+			if (safe_strtoi(optarg, &size) || size < EXT2_MIN_BLOCK_SIZE || size > EXT2_MAX_BLOCK_SIZE ){
+				bb_error_msg_and_die("invalid fragment size - %s", optarg);
+			}
+			param.s_log_frag_size =
+				int_log2(size >> EXT2_MIN_BLOCK_LOG_SIZE);
+			mke2fs_warning_msg(1, "fragments not supported. Ignoring -f option");
+			break;
+		case 'g':
+			{
+			    int foo;
+			    if (safe_strtoi(optarg, &foo)) {
+				bb_error_msg_and_die("Illegal number for blocks per group");
+			    }
+			    param.s_blocks_per_group = foo;
+			}
+			if ((param.s_blocks_per_group % 8) != 0) {
+				bb_error_msg_and_die("blocks per group must be multiple of 8");
+			}
+			break;
+		case 'i':
+			if (safe_strtoi(optarg, &inode_ratio)
+				|| inode_ratio < EXT2_MIN_BLOCK_SIZE
+				|| inode_ratio > EXT2_MAX_BLOCK_SIZE * 1024) {
+				bb_error_msg_and_die("invalid inode ratio %s (min %d/max %d)",
+					optarg, EXT2_MIN_BLOCK_SIZE,
+					EXT2_MAX_BLOCK_SIZE);
+				}
+			break;
+		case 'J':
+			parse_journal_opts(&journal_device, &journal_flags, &journal_size, optarg);
+			break;
+		case 'j':
+			param.s_feature_compat |=
+				EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+			if (!journal_size)
+				journal_size = -1;
+			break;
+		case 'l':
+			bad_blocks_filename = optarg;
+			break;
+		case 'm':
+			if (safe_strtoi(optarg, &reserved_ratio) || reserved_ratio > 50 ) {
+				bb_error_msg_and_die("invalid reserved blocks percent - %s", optarg);
+			}
+			break;
+		case 'n':
+			noaction++;
+			break;
+		case 'o':
+			creator_os = optarg;
+			break;
+		case 'r':
+			param.s_rev_level = atoi(optarg);
+			if (param.s_rev_level == EXT2_GOOD_OLD_REV) {
+				param.s_feature_incompat = 0;
+				param.s_feature_compat = 0;
+				param.s_feature_ro_compat = 0;
+			}
+			break;
+		case 's':	/* deprecated */
+			if (atoi(optarg))
+				param.s_feature_ro_compat |=
+					EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+			else
+				param.s_feature_ro_compat &=
+					~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+			break;
+#ifdef EXT2_DYNAMIC_REV
+		case 'I':
+			if (safe_strtoi(optarg, &inode_size)) {
+				bb_error_msg_and_die("invalid inode size - %s", optarg);
+			}
+			break;
+#endif
+		case 'N':
+			num_inodes = atoi(optarg);
+			break;
+		case 'v':
+			quiet = 0;
+			break;
+		case 'q':
+			quiet = 1;
+			break;
+		case 'F':
+			force = 1;
+			break;
+		case 'L':
+			volume_label = optarg;
+			break;
+		case 'M':
+			mount_dir = optarg;
+			break;
+		case 'O':
+			if (!strcmp(optarg, "none")) {
+				param.s_feature_compat = 0;
+				param.s_feature_incompat = 0;
+				param.s_feature_ro_compat = 0;
+				break;
+			}
+			if (e2p_edit_feature(optarg,
+					    &param.s_feature_compat,
+					    ok_features)) {
+				bb_error_msg_and_die("Invalid filesystem option set: %s", optarg);
+			}
+			break;
+		case 'E':
+		case 'R':
+			extended_opts = optarg;
+			break;
+		case 'S':
+			super_only = 1;
+			break;
+		case 'T':
+			fs_type = optarg;
+			break;
+		case 'V':
+			/* Print version number and exit */
+			show_version_only = 1;
+			quiet = 0;
+			break;
+		default:
+			bb_show_usage();
+		}
+	}
+	if ((optind == argc) /*&& !show_version_only*/)
+		bb_show_usage();
+	device_name = argv[optind++];
+
+	mke2fs_verbose("mke2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
+
+	if (show_version_only) {
+		return 0;
+	}
+
+	/*
+	 * If there's no blocksize specified and there is a journal
+	 * device, use it to figure out the blocksize
+	 */
+	if (blocksize <= 0 && journal_device) {
+		ext2_filsys     jfs;
+		io_manager      io_ptr;
+
+#ifdef CONFIG_TESTIO_DEBUG
+		io_ptr = test_io_manager;
+		test_io_backing_manager = unix_io_manager;
+#else
+		io_ptr = unix_io_manager;
+#endif
+		retval = ext2fs_open(journal_device,
+				     EXT2_FLAG_JOURNAL_DEV_OK, 0,
+				     0, io_ptr, &jfs);
+		mke2fs_error_msg_and_die(retval, "open journal device %s", journal_device);
+		if ((blocksize < 0) && (jfs->blocksize < (unsigned) (-blocksize))) {
+			bb_error_msg_and_die(
+				"Journal dev blocksize (%d) smaller than "
+				"minimum blocksize %d\n", jfs->blocksize,
+				-blocksize);
+		}
+		blocksize = jfs->blocksize;
+		param.s_log_block_size =
+			int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
+		ext2fs_close(jfs);
+	}
+
+	if (blocksize > sys_page_size) {
+		mke2fs_warning_msg(1, "%d-byte blocks too big for system (max %d)",
+			blocksize, sys_page_size);
+		if (!force) {
+			proceed_question();
+		}
+		bb_error_msg("Forced to continue");
+	}
+	mke2fs_warning_msg(((blocksize > 4096) &&
+		(param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)),
+		"some 2.4 kernels do not support "
+		"blocksizes greater than 4096 using ext3.\n"
+		"Use -b 4096 if this is an issue for you\n");
+
+	if (optind < argc) {
+		param.s_blocks_count = parse_num_blocks(argv[optind++],
+				param.s_log_block_size);
+		mke2fs_error_msg_and_die(!param.s_blocks_count, "invalid blocks count - %s", argv[optind - 1]);
+	}
+	if (optind < argc)
+		bb_show_usage();
+
+	if (param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+		if (!fs_type)
+			fs_type = "journal";
+		reserved_ratio = 0;
+		param.s_feature_incompat = EXT3_FEATURE_INCOMPAT_JOURNAL_DEV;
+		param.s_feature_compat = 0;
+		param.s_feature_ro_compat = 0;
+	}
+	if (param.s_rev_level == EXT2_GOOD_OLD_REV &&
+	    (param.s_feature_compat || param.s_feature_ro_compat ||
+	     param.s_feature_incompat))
+		param.s_rev_level = 1;	/* Create a revision 1 filesystem */
+
+	check_plausibility(device_name , force);
+	check_mount(device_name, force, "filesystem");
+
+	param.s_log_frag_size = param.s_log_block_size;
+
+	if (noaction && param.s_blocks_count) {
+		dev_size = param.s_blocks_count;
+		retval = 0;
+	} else {
+	retry:
+		retval = ext2fs_get_device_size(device_name,
+						EXT2_BLOCK_SIZE(&param),
+						&dev_size);
+		if ((retval == EFBIG) &&
+		    (blocksize == 0) &&
+		    (param.s_log_block_size == 0)) {
+			param.s_log_block_size = 2;
+			blocksize = 4096;
+			goto retry;
+		}
+	}
+
+	mke2fs_error_msg_and_die((retval && (retval != EXT2_ET_UNIMPLEMENTED)),"determine filesystem size");
+
+	if (!param.s_blocks_count) {
+		if (retval == EXT2_ET_UNIMPLEMENTED) {
+			mke2fs_error_msg_and_die(1,
+				"determine device size; you "
+				"must specify\nthe size of the "
+				"filesystem");
+		} else {
+			if (dev_size == 0) {
+				bb_error_msg_and_die(
+					"Device size reported to be zero.  "
+					"Invalid partition specified, or\n\t"
+					"partition table wasn't reread "
+					"after running fdisk, due to\n\t"
+					"a modified partition being busy "
+					"and in use.  You may need to reboot\n\t"
+					"to re-read your partition table.\n"
+				);
+			}
+			param.s_blocks_count = dev_size;
+			if (sys_page_size > EXT2_BLOCK_SIZE(&param))
+				param.s_blocks_count &= ~((sys_page_size /
+							   EXT2_BLOCK_SIZE(&param))-1);
+		}
+
+	} else if (!force && (param.s_blocks_count > dev_size)) {
+		bb_error_msg("Filesystem larger than apparent device size");
+		proceed_question();
+	}
+
+	/*
+	 * If the user asked for HAS_JOURNAL, then make sure a journal
+	 * gets created.
+	 */
+	if ((param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
+	    !journal_size)
+		journal_size = -1;
+
+	/* Set first meta blockgroup via an environment variable */
+	/* (this is mostly for debugging purposes) */
+	if ((param.s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) &&
+	    ((tmp = getenv("MKE2FS_FIRST_META_BG"))))
+		param.s_first_meta_bg = atoi(tmp);
+
+	/* Get the hardware sector size, if available */
+	retval = ext2fs_get_device_sectsize(device_name, &sector_size);
+	mke2fs_error_msg_and_die(retval, "determine hardware sector size");
+
+	if ((tmp = getenv("MKE2FS_DEVICE_SECTSIZE")) != NULL)
+		sector_size = atoi(tmp);
+
+	set_fs_defaults(fs_type, &param, blocksize, sector_size, &inode_ratio);
+	blocksize = EXT2_BLOCK_SIZE(&param);
+
+	if (extended_opts)
+		parse_extended_opts(&param, extended_opts);
+
+	/* Since sparse_super is the default, we would only have a problem
+	 * here if it was explicitly disabled.
+	 */
+	if ((param.s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE) &&
+	    !(param.s_feature_ro_compat&EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
+		bb_error_msg_and_die("reserved online resize blocks not supported "
+			  "on non-sparse filesystem");
+	}
+
+	if (param.s_blocks_per_group) {
+		if (param.s_blocks_per_group < 256 ||
+		    param.s_blocks_per_group > 8 * (unsigned) blocksize) {
+			bb_error_msg_and_die("blocks per group count out of range");
+		}
+	}
+
+	if (!force && param.s_blocks_count >= (1 << 31)) {
+		bb_error_msg_and_die("Filesystem too large.  No more than 2**31-1 blocks\n"
+			"\t (8TB using a blocksize of 4k) are currently supported.");
+	}
+
+	if (inode_size) {
+		if (inode_size < EXT2_GOOD_OLD_INODE_SIZE ||
+		    inode_size > EXT2_BLOCK_SIZE(&param) ||
+		    inode_size & (inode_size - 1)) {
+			bb_error_msg_and_die("invalid inode size %d (min %d/max %d)",
+				inode_size, EXT2_GOOD_OLD_INODE_SIZE,
+				blocksize);
+		}
+		mke2fs_warning_msg((inode_size != EXT2_GOOD_OLD_INODE_SIZE),
+			"%d-byte inodes not usable on most systems",
+			inode_size);
+		param.s_inode_size = inode_size;
+	}
+
+	/*
+	 * Calculate number of inodes based on the inode ratio
+	 */
+	param.s_inodes_count = num_inodes ? num_inodes :
+		((__u64) param.s_blocks_count * blocksize)
+			/ inode_ratio;
+
+	/*
+	 * Calculate number of blocks to reserve
+	 */
+	param.s_r_blocks_count = (param.s_blocks_count * reserved_ratio) / 100;
+	return 1;
+}
+
+static void mke2fs_clean_up(void)
+{
+	if (ENABLE_FEATURE_CLEAN_UP && journal_device) free(journal_device);
+}
+
+int mke2fs_main (int argc, char *argv[])
+{
+	errcode_t	retval;
+	ext2_filsys	fs;
+	badblocks_list	bb_list = 0;
+	unsigned int	i;
+	int		val;
+	io_manager	io_ptr;
+
+	if (ENABLE_FEATURE_CLEAN_UP)
+		atexit(mke2fs_clean_up);
+	if(!PRS(argc, argv))
+		return 0;
+
+#ifdef CONFIG_TESTIO_DEBUG
+	io_ptr = test_io_manager;
+	test_io_backing_manager = unix_io_manager;
+#else
+	io_ptr = unix_io_manager;
+#endif
+
+	/*
+	 * Initialize the superblock....
+	 */
+	retval = ext2fs_initialize(device_name, 0, &param,
+				   io_ptr, &fs);
+	mke2fs_error_msg_and_die(retval, "set up superblock");
+
+	/*
+	 * Wipe out the old on-disk superblock
+	 */
+	if (!noaction)
+		zap_sector(fs, 2, 6);
+
+	/*
+	 * Generate a UUID for it...
+	 */
+	uuid_generate(fs->super->s_uuid);
+
+	/*
+	 * Initialize the directory index variables
+	 */
+	fs->super->s_def_hash_version = EXT2_HASH_TEA;
+	uuid_generate((unsigned char *) fs->super->s_hash_seed);
+
+	/*
+	 * Add "jitter" to the superblock's check interval so that we
+	 * don't check all the filesystems at the same time.  We use a
+	 * kludgy hack of using the UUID to derive a random jitter value.
+	 */
+	for (i = 0, val = 0 ; i < sizeof(fs->super->s_uuid); i++)
+		val += fs->super->s_uuid[i];
+	fs->super->s_max_mnt_count += val % EXT2_DFL_MAX_MNT_COUNT;
+
+	/*
+	 * Override the creator OS, if applicable
+	 */
+	if (creator_os && !set_os(fs->super, creator_os)) {
+		bb_error_msg_and_die("unknown os - %s", creator_os);
+	}
+
+	/*
+	 * For the Hurd, we will turn off filetype since it doesn't
+	 * support it.
+	 */
+	if (fs->super->s_creator_os == EXT2_OS_HURD)
+		fs->super->s_feature_incompat &=
+			~EXT2_FEATURE_INCOMPAT_FILETYPE;
+
+	/*
+	 * Set the volume label...
+	 */
+	if (volume_label) {
+		snprintf(fs->super->s_volume_name, sizeof(fs->super->s_volume_name), "%s", volume_label);
+	}
+
+	/*
+	 * Set the last mount directory
+	 */
+	if (mount_dir) {
+		snprintf(fs->super->s_last_mounted, sizeof(fs->super->s_last_mounted), "%s", mount_dir);
+	}
+
+	if (!quiet || noaction)
+		show_stats(fs);
+
+	if (noaction)
+		return 0;
+
+	if (fs->super->s_feature_incompat &
+	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+		create_journal_dev(fs);
+		return (ext2fs_close(fs) ? 1 : 0);
+	}
+
+	if (bad_blocks_filename)
+		read_bb_file(fs, &bb_list, bad_blocks_filename);
+	if (cflag)
+		test_disk(fs, &bb_list);
+
+	handle_bad_blocks(fs, bb_list);
+	fs->stride = fs_stride;
+	retval = ext2fs_allocate_tables(fs);
+	mke2fs_error_msg_and_die(retval, "allocate filesystem tables");
+	if (super_only) {
+		fs->super->s_state |= EXT2_ERROR_FS;
+		fs->flags &= ~(EXT2_FLAG_IB_DIRTY|EXT2_FLAG_BB_DIRTY);
+	} else {
+		/* rsv must be a power of two (64kB is MD RAID sb alignment) */
+		unsigned int rsv = 65536 / fs->blocksize;
+		unsigned long blocks = fs->super->s_blocks_count;
+		unsigned long start;
+		blk_t ret_blk;
+
+#ifdef ZAP_BOOTBLOCK
+		zap_sector(fs, 0, 2);
+#endif
+
+		/*
+		 * Wipe out any old MD RAID (or other) metadata at the end
+		 * of the device.  This will also verify that the device is
+		 * as large as we think.  Be careful with very small devices.
+		 */
+		start = (blocks & ~(rsv - 1));
+		if (start > rsv)
+			start -= rsv;
+		if (start > 0)
+			retval = zero_blocks(fs, start, blocks - start,
+					     NULL, &ret_blk, NULL);
+
+		mke2fs_warning_msg(retval, "could not zero block %u at end of filesystem", ret_blk);
+		write_inode_tables(fs);
+		create_root_dir(fs);
+		create_lost_and_found(fs);
+		reserve_inodes(fs);
+		create_bad_block_inode(fs, bb_list);
+		if (fs->super->s_feature_compat &
+		    EXT2_FEATURE_COMPAT_RESIZE_INODE) {
+			retval = ext2fs_create_resize_inode(fs);
+			mke2fs_error_msg_and_die(retval, "reserve blocks for online resize");
+		}
+	}
+
+	if (journal_device) {
+		make_journal_device(journal_device, fs, quiet, force);
+	} else if (journal_size) {
+		make_journal_blocks(fs, journal_size, journal_flags, quiet);
+	}
+
+	mke2fs_verbose("Writing superblocks and filesystem accounting information: ");
+	retval = ext2fs_flush(fs);
+	mke2fs_warning_msg(retval, "had trouble writing out superblocks");
+	mke2fs_verbose_done();
+	if (!quiet && !getenv("MKE2FS_SKIP_CHECK_MSG"))
+		print_check_message(fs);
+	val = ext2fs_close(fs);
+	return (retval || val) ? 1 : 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/tune2fs.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/tune2fs.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/tune2fs.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,736 @@
+/*
+ * tune2fs.c - Change the file system parameters on an ext2 file system
+ *
+ * Copyright (C) 1992, 1993, 1994  Remy Card <card at masi.ibp.fr>
+ *                                 Laboratoire MASI, Institut Blaise Pascal
+ *                                 Universite Pierre et Marie Curie (Paris VI)
+ *
+ * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+/*
+ * History:
+ * 93/06/01	- Creation
+ * 93/10/31	- Added the -c option to change the maximal mount counts
+ * 93/12/14	- Added -l flag to list contents of superblock
+ *                M.J.E. Mol (marcel at duteca.et.tudelft.nl)
+ *                F.W. ten Wolde (franky at duteca.et.tudelft.nl)
+ * 93/12/29	- Added the -e option to change errors behavior
+ * 94/02/27	- Ported to use the ext2fs library
+ * 94/03/06	- Added the checks interval from Uwe Ohse (uwe at tirka.gun.de)
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "e2fsbb.h"
+#include "ext2fs/ext2_fs.h"
+#include "ext2fs/ext2fs.h"
+#include "uuid/uuid.h"
+#include "e2p/e2p.h"
+#include "ext2fs/kernel-jbd.h"
+#include "util.h"
+#include "blkid/blkid.h"
+
+#include "busybox.h"
+#include "grp_.h"
+#include "pwd_.h"
+
+static char * device_name = NULL;
+static char * new_label, *new_last_mounted, *new_UUID;
+static char * io_options;
+static int c_flag, C_flag, e_flag, f_flag, g_flag, i_flag, l_flag, L_flag;
+static int m_flag, M_flag, r_flag, s_flag = -1, u_flag, U_flag, T_flag;
+static time_t last_check_time;
+static int print_label;
+static int max_mount_count, mount_count, mount_flags;
+static unsigned long interval, reserved_ratio, reserved_blocks;
+static unsigned long resgid, resuid;
+static unsigned short errors;
+static int open_flag;
+static char *features_cmd;
+static char *mntopts_cmd;
+
+static int journal_size, journal_flags;
+static char *journal_device = NULL;
+
+static const char *please_fsck = "Please run e2fsck on the filesystem\n";
+
+static __u32 ok_features[3] = {
+	EXT3_FEATURE_COMPAT_HAS_JOURNAL | EXT2_FEATURE_COMPAT_DIR_INDEX,
+	EXT2_FEATURE_INCOMPAT_FILETYPE,
+	EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
+};
+
+/*
+ * Remove an external journal from the filesystem
+ */
+static void remove_journal_device(ext2_filsys fs)
+{
+	char		*journal_path;
+	ext2_filsys	jfs;
+	char		buf[1024];
+	journal_superblock_t	*jsb;
+	int		i, nr_users;
+	errcode_t	retval;
+	int		commit_remove_journal = 0;
+	io_manager	io_ptr;
+
+	if (f_flag)
+		commit_remove_journal = 1; /* force removal even if error */
+
+	uuid_unparse(fs->super->s_journal_uuid, buf);
+	journal_path = blkid_get_devname(NULL, "UUID", buf);
+
+	if (!journal_path) {
+		journal_path =
+			ext2fs_find_block_device(fs->super->s_journal_dev);
+		if (!journal_path)
+			return;
+	}
+
+	io_ptr = unix_io_manager;
+	retval = ext2fs_open(journal_path, EXT2_FLAG_RW|
+			     EXT2_FLAG_JOURNAL_DEV_OK, 0,
+			     fs->blocksize, io_ptr, &jfs);
+	if (retval) {
+		bb_error_msg("Failed to open external journal");
+		goto no_valid_journal;
+	}
+	if (!(jfs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+		bb_error_msg("%s is not a journal device", journal_path);
+		goto no_valid_journal;
+	}
+
+	/* Get the journal superblock */
+	if ((retval = io_channel_read_blk(jfs->io, 1, -1024, buf))) {
+		bb_error_msg("Failed to read journal superblock");
+		goto no_valid_journal;
+	}
+
+	jsb = (journal_superblock_t *) buf;
+	if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
+	    (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) {
+		bb_error_msg("Journal superblock not found!");
+		goto no_valid_journal;
+	}
+
+	/* Find the filesystem UUID */
+	nr_users = ntohl(jsb->s_nr_users);
+	for (i=0; i < nr_users; i++) {
+		if (memcmp(fs->super->s_uuid,
+			   &jsb->s_users[i*16], 16) == 0)
+			break;
+	}
+	if (i >= nr_users) {
+		bb_error_msg("Filesystem's UUID not found on journal device");
+		commit_remove_journal = 1;
+		goto no_valid_journal;
+	}
+	nr_users--;
+	for (i=0; i < nr_users; i++)
+		memcpy(&jsb->s_users[i*16], &jsb->s_users[(i+1)*16], 16);
+	jsb->s_nr_users = htonl(nr_users);
+
+	/* Write back the journal superblock */
+	if ((retval = io_channel_write_blk(jfs->io, 1, -1024, buf))) {
+		bb_error_msg("Failed to write journal superblock");
+		goto no_valid_journal;
+	}
+
+	commit_remove_journal = 1;
+
+no_valid_journal:
+	if (commit_remove_journal == 0)
+		bb_error_msg_and_die("Journal NOT removed");
+	fs->super->s_journal_dev = 0;
+	uuid_clear(fs->super->s_journal_uuid);
+	ext2fs_mark_super_dirty(fs);
+	puts("Journal removed");
+	free(journal_path);
+}
+
+/* Helper function for remove_journal_inode */
+static int release_blocks_proc(ext2_filsys fs, blk_t *blocknr,
+			       int blockcnt EXT2FS_ATTR((unused)),
+			       void *private EXT2FS_ATTR((unused)))
+{
+	blk_t	block;
+	int	group;
+
+	block = *blocknr;
+	ext2fs_unmark_block_bitmap(fs->block_map,block);
+	group = ext2fs_group_of_blk(fs, block);
+	fs->group_desc[group].bg_free_blocks_count++;
+	fs->super->s_free_blocks_count++;
+	return 0;
+}
+
+/*
+ * Remove the journal inode from the filesystem
+ */
+static void remove_journal_inode(ext2_filsys fs)
+{
+	struct ext2_inode	inode;
+	errcode_t		retval;
+	ino_t			ino = fs->super->s_journal_inum;
+	char *msg = "to read";
+	char *s = "journal inode";
+
+	retval = ext2fs_read_inode(fs, ino,  &inode);
+	if (retval)
+		goto REMOVE_JOURNAL_INODE_ERROR;
+	if (ino == EXT2_JOURNAL_INO) {
+		retval = ext2fs_read_bitmaps(fs);
+		if (retval) {
+			msg = "to read bitmaps";
+			s = "";
+			goto REMOVE_JOURNAL_INODE_ERROR;
+		}
+		retval = ext2fs_block_iterate(fs, ino, 0, NULL,
+					      release_blocks_proc, NULL);
+		if (retval) {
+			msg = "clearing";
+			goto REMOVE_JOURNAL_INODE_ERROR;
+		}
+		memset(&inode, 0, sizeof(inode));
+		ext2fs_mark_bb_dirty(fs);
+		fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+	} else
+		inode.i_flags &= ~EXT2_IMMUTABLE_FL;
+	retval = ext2fs_write_inode(fs, ino, &inode);
+	if (retval) {
+		msg = "writing";
+REMOVE_JOURNAL_INODE_ERROR:
+		bb_error_msg_and_die("Failed %s %s", msg, s);
+	}
+	fs->super->s_journal_inum = 0;
+	ext2fs_mark_super_dirty(fs);
+}
+
+/*
+ * Update the default mount options
+ */
+static void update_mntopts(ext2_filsys fs, char *mntopts)
+{
+	struct ext2_super_block *sb= fs->super;
+
+	if (e2p_edit_mntopts(mntopts, &sb->s_default_mount_opts, ~0))
+		bb_error_msg_and_die("Invalid mount option set: %s", mntopts);
+	ext2fs_mark_super_dirty(fs);
+}
+
+/*
+ * Update the feature set as provided by the user.
+ */
+static void update_feature_set(ext2_filsys fs, char *features)
+{
+	int sparse, old_sparse, filetype, old_filetype;
+	int journal, old_journal, dxdir, old_dxdir;
+	struct ext2_super_block *sb= fs->super;
+	__u32	old_compat, old_incompat, old_ro_compat;
+
+	old_compat = sb->s_feature_compat;
+	old_ro_compat = sb->s_feature_ro_compat;
+	old_incompat = sb->s_feature_incompat;
+
+	old_sparse = sb->s_feature_ro_compat &
+		EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+	old_filetype = sb->s_feature_incompat &
+		EXT2_FEATURE_INCOMPAT_FILETYPE;
+	old_journal = sb->s_feature_compat &
+		EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+	old_dxdir = sb->s_feature_compat &
+		EXT2_FEATURE_COMPAT_DIR_INDEX;
+	if (e2p_edit_feature(features, &sb->s_feature_compat, ok_features))
+		bb_error_msg_and_die("Invalid filesystem option set: %s", features);
+	sparse = sb->s_feature_ro_compat &
+		EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+	filetype = sb->s_feature_incompat &
+		EXT2_FEATURE_INCOMPAT_FILETYPE;
+	journal = sb->s_feature_compat &
+		EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+	dxdir = sb->s_feature_compat &
+		EXT2_FEATURE_COMPAT_DIR_INDEX;
+	if (old_journal && !journal) {
+		if ((mount_flags & EXT2_MF_MOUNTED) &&
+		    !(mount_flags & EXT2_MF_READONLY)) {
+			bb_error_msg_and_die(
+				"The has_journal flag may only be "
+				"cleared when the filesystem is\n"
+				"unmounted or mounted "
+				"read-only");
+		}
+		if (sb->s_feature_incompat &
+		    EXT3_FEATURE_INCOMPAT_RECOVER) {
+			bb_error_msg_and_die(
+				"The needs_recovery flag is set.  "
+				"%s before clearing the has_journal flag.",
+				please_fsck);
+		}
+		if (sb->s_journal_inum) {
+			remove_journal_inode(fs);
+		}
+		if (sb->s_journal_dev) {
+			remove_journal_device(fs);
+		}
+	}
+	if (journal && !old_journal) {
+		/*
+		 * If adding a journal flag, let the create journal
+		 * code below handle creating setting the flag and
+		 * creating the journal.  We supply a default size if
+		 * necessary.
+		 */
+		if (!journal_size)
+			journal_size = -1;
+		sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+	}
+	if (dxdir && !old_dxdir) {
+		if (!sb->s_def_hash_version)
+			sb->s_def_hash_version = EXT2_HASH_TEA;
+		if (uuid_is_null((unsigned char *) sb->s_hash_seed))
+			uuid_generate((unsigned char *) sb->s_hash_seed);
+	}
+
+	if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
+	    (sb->s_feature_compat || sb->s_feature_ro_compat ||
+	     sb->s_feature_incompat))
+		ext2fs_update_dynamic_rev(fs);
+	if ((sparse != old_sparse) ||
+	    (filetype != old_filetype)) {
+		sb->s_state &= ~EXT2_VALID_FS;
+		printf("\n%s\n", please_fsck);
+	}
+	if ((old_compat != sb->s_feature_compat) ||
+	    (old_ro_compat != sb->s_feature_ro_compat) ||
+	    (old_incompat != sb->s_feature_incompat))
+		ext2fs_mark_super_dirty(fs);
+}
+
+/*
+ * Add a journal to the filesystem.
+ */
+static void add_journal(ext2_filsys fs)
+{
+	if (fs->super->s_feature_compat &
+	    EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
+		bb_error_msg_and_die("The filesystem already has a journal");
+	}
+	if (journal_device) {
+		make_journal_device(journal_device, fs, 0, 0);
+	} else if (journal_size) {
+		make_journal_blocks(fs, journal_size, journal_flags, 0);
+		/*
+		 * If the filesystem wasn't mounted, we need to force
+		 * the block group descriptors out.
+		 */
+		if ((mount_flags & EXT2_MF_MOUNTED) == 0)
+			fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+	}
+	print_check_message(fs);
+	return;
+}
+
+/*
+ * Busybox stuff
+ */
+static char * x_blkid_get_devname(const char *token)
+{
+	char * dev_name;
+
+	if (!(dev_name = blkid_get_devname(NULL, token, NULL)))
+		bb_error_msg_and_die("Unable to resolve '%s'", token);
+	return dev_name;
+}
+
+#ifdef CONFIG_E2LABEL
+static void parse_e2label_options(int argc, char ** argv)
+{
+	if ((argc < 2) || (argc > 3))
+		bb_show_usage();
+	io_options = strchr(argv[1], '?');
+	if (io_options)
+		*io_options++ = 0;
+	device_name = x_blkid_get_devname(argv[1]);
+	if (argc == 3) {
+		open_flag = EXT2_FLAG_RW | EXT2_FLAG_JOURNAL_DEV_OK;
+		L_flag = 1;
+		new_label = argv[2];
+	} else
+		print_label++;
+}
+#else
+#define parse_e2label_options(x,y)
+#endif
+
+static time_t parse_time(char *str)
+{
+	struct	tm	ts;
+
+	if (strcmp(str, "now") == 0) {
+		return (time(0));
+	}
+	memset(&ts, 0, sizeof(ts));
+#ifdef HAVE_STRPTIME
+	strptime(str, "%Y%m%d%H%M%S", &ts);
+#else
+	sscanf(str, "%4d%2d%2d%2d%2d%2d", &ts.tm_year, &ts.tm_mon,
+	       &ts.tm_mday, &ts.tm_hour, &ts.tm_min, &ts.tm_sec);
+	ts.tm_year -= 1900;
+	ts.tm_mon -= 1;
+	if (ts.tm_year < 0 || ts.tm_mon < 0 || ts.tm_mon > 11 ||
+	    ts.tm_mday < 0 || ts.tm_mday > 31 || ts.tm_hour > 23 ||
+	    ts.tm_min > 59 || ts.tm_sec > 61)
+		ts.tm_mday = 0;
+#endif
+	if (ts.tm_mday == 0) {
+		bb_error_msg_and_die("Couldn't parse date/time specifier: %s", str);
+	}
+	return (mktime(&ts));
+}
+
+static void parse_tune2fs_options(int argc, char **argv)
+{
+	int c;
+	char * tmp;
+
+	printf("tune2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
+	while ((c = getopt(argc, argv, "c:e:fg:i:jlm:o:r:s:u:C:J:L:M:O:T:U:")) != EOF)
+		switch (c)
+		{
+			case 'c':
+				if (safe_strtoi(optarg, &max_mount_count) ||  max_mount_count > 16000) {
+					goto MOUNTS_COUNT_ERROR;
+				}
+				if (max_mount_count == 0)
+					max_mount_count = -1;
+				c_flag = 1;
+				open_flag = EXT2_FLAG_RW;
+				break;
+			case 'C':
+				if (safe_strtoi(optarg, &mount_count) || mount_count > 16000) {
+MOUNTS_COUNT_ERROR:
+					bb_error_msg_and_die("bad mounts count - %s", optarg);
+				}
+				C_flag = 1;
+				open_flag = EXT2_FLAG_RW;
+				break;
+			case 'e':
+				if (strcmp (optarg, "continue") == 0)
+					errors = EXT2_ERRORS_CONTINUE;
+				else if (strcmp (optarg, "remount-ro") == 0)
+					errors = EXT2_ERRORS_RO;
+				else if (strcmp (optarg, "panic") == 0)
+					errors = EXT2_ERRORS_PANIC;
+				else {
+					bb_error_msg_and_die("bad error behavior - %s", optarg);
+				}
+				e_flag = 1;
+				open_flag = EXT2_FLAG_RW;
+				break;
+			case 'f': /* Force */
+				f_flag = 1;
+				break;
+			case 'g':
+				if (safe_strtoul(optarg, &resgid))
+					resgid = bb_xgetgrnam(optarg);
+				g_flag = 1;
+				open_flag = EXT2_FLAG_RW;
+				break;
+			case 'i':
+				interval = strtoul (optarg, &tmp, 0);
+				switch (*tmp) {
+				case 's':
+					tmp++;
+					break;
+				case '\0':
+				case 'd':
+				case 'D': /* days */
+					interval *= 86400;
+					if (*tmp != '\0')
+						tmp++;
+					break;
+				case 'm':
+				case 'M': /* months! */
+					interval *= 86400 * 30;
+					tmp++;
+					break;
+				case 'w':
+				case 'W': /* weeks */
+					interval *= 86400 * 7;
+					tmp++;
+					break;
+				}
+				if (*tmp || interval > (365 * 86400)) {
+					bb_error_msg_and_die("bad interval - %s", optarg);
+				}
+				i_flag = 1;
+				open_flag = EXT2_FLAG_RW;
+				break;
+			case 'j':
+				if (!journal_size)
+					journal_size = -1;
+				open_flag = EXT2_FLAG_RW;
+				break;
+			case 'J':
+				parse_journal_opts(&journal_device, &journal_flags, &journal_size, optarg);
+				open_flag = EXT2_FLAG_RW;
+				break;
+			case 'l':
+				l_flag = 1;
+				break;
+			case 'L':
+				new_label = optarg;
+				L_flag = 1;
+				open_flag = EXT2_FLAG_RW |
+					EXT2_FLAG_JOURNAL_DEV_OK;
+				break;
+			case 'm':
+				if(safe_strtoul(optarg, &reserved_ratio) || reserved_ratio > 50) {
+					bb_error_msg_and_die("bad reserved block ratio - %s", optarg);
+				}
+				m_flag = 1;
+				open_flag = EXT2_FLAG_RW;
+				break;
+			case 'M':
+				new_last_mounted = optarg;
+				M_flag = 1;
+				open_flag = EXT2_FLAG_RW;
+				break;
+			case 'o':
+				if (mntopts_cmd) {
+					bb_error_msg_and_die("-o may only be specified once");
+				}
+				mntopts_cmd = optarg;
+				open_flag = EXT2_FLAG_RW;
+				break;
+
+			case 'O':
+				if (features_cmd) {
+					bb_error_msg_and_die("-O may only be specified once");
+				}
+				features_cmd = optarg;
+				open_flag = EXT2_FLAG_RW;
+				break;
+			case 'r':
+				if(safe_strtoul(optarg, &reserved_blocks)) {
+					bb_error_msg_and_die("bad reserved blocks count - %s", optarg);
+				}
+				r_flag = 1;
+				open_flag = EXT2_FLAG_RW;
+				break;
+			case 's':
+				s_flag = atoi(optarg);
+				open_flag = EXT2_FLAG_RW;
+				break;
+			case 'T':
+				T_flag = 1;
+				last_check_time = parse_time(optarg);
+				open_flag = EXT2_FLAG_RW;
+				break;
+			case 'u':
+				if (safe_strtoul(optarg, &resuid))
+					resuid = bb_xgetpwnam(optarg);
+				u_flag = 1;
+				open_flag = EXT2_FLAG_RW;
+				break;
+			case 'U':
+				new_UUID = optarg;
+				U_flag = 1;
+				open_flag = EXT2_FLAG_RW |
+					EXT2_FLAG_JOURNAL_DEV_OK;
+				break;
+			default:
+				bb_show_usage();
+		}
+	if (optind < argc - 1 || optind == argc)
+		bb_show_usage();
+	if (!open_flag && !l_flag)
+		bb_show_usage();
+	io_options = strchr(argv[optind], '?');
+	if (io_options)
+		*io_options++ = 0;
+	device_name = x_blkid_get_devname(argv[optind]);
+}
+
+#ifdef CONFIG_FINDFS
+static ATTRIBUTE_NORETURN void do_findfs(int argc, char **argv)
+{
+	if ((argc != 2) ||
+	    (strncmp(argv[1], "LABEL=", 6) && strncmp(argv[1], "UUID=", 5)))
+		bb_show_usage();
+	device_name = x_blkid_get_devname(argv[1]);
+	puts(device_name);
+	exit(0);
+}
+#else
+#define do_findfs(x, y)
+#endif
+
+static void tune2fs_clean_up(void)
+{
+	if (ENABLE_FEATURE_CLEAN_UP && device_name) free(device_name);
+	if (ENABLE_FEATURE_CLEAN_UP && journal_device) free(journal_device);
+}
+
+int tune2fs_main(int argc, char **argv)
+{
+	errcode_t retval;
+	ext2_filsys fs;
+	struct ext2_super_block *sb;
+	io_manager io_ptr;
+
+	if (ENABLE_FEATURE_CLEAN_UP)
+		atexit(tune2fs_clean_up);
+
+	if (ENABLE_FINDFS && (bb_applet_name[0] == 'f')) /* findfs */
+		do_findfs(argc, argv);  /* no return */
+	else if (ENABLE_E2LABEL && (bb_applet_name[0] == 'e')) /* e2label */
+		parse_e2label_options(argc, argv);
+	else
+		parse_tune2fs_options(argc, argv);  /* tune2fs */
+
+	io_ptr = unix_io_manager;
+	retval = ext2fs_open2(device_name, io_options, open_flag,
+			      0, 0, io_ptr, &fs);
+	if (retval)
+		bb_error_msg_and_die("No valid superblock on %s", device_name);
+	sb = fs->super;
+	if (print_label) {
+		/* For e2label emulation */
+		printf("%.*s\n", (int) sizeof(sb->s_volume_name),
+		       sb->s_volume_name);
+		return 0;
+	}
+	retval = ext2fs_check_if_mounted(device_name, &mount_flags);
+	if (retval)
+		bb_error_msg_and_die("Could not determine if %s is mounted", device_name);
+	/* Normally we only need to write out the superblock */
+	fs->flags |= EXT2_FLAG_SUPER_ONLY;
+
+	if (c_flag) {
+		sb->s_max_mnt_count = max_mount_count;
+		ext2fs_mark_super_dirty(fs);
+		printf("Setting maximal mount count to %d\n", max_mount_count);
+	}
+	if (C_flag) {
+		sb->s_mnt_count = mount_count;
+		ext2fs_mark_super_dirty(fs);
+		printf("Setting current mount count to %d\n", mount_count);
+	}
+	if (e_flag) {
+		sb->s_errors = errors;
+		ext2fs_mark_super_dirty(fs);
+		printf("Setting error behavior to %d\n", errors);
+	}
+	if (g_flag) {
+		sb->s_def_resgid = resgid;
+		ext2fs_mark_super_dirty(fs);
+		printf("Setting reserved blocks gid to %lu\n", resgid);
+	}
+	if (i_flag) {
+		sb->s_checkinterval = interval;
+		ext2fs_mark_super_dirty(fs);
+		printf("Setting interval between check %lu seconds\n", interval);
+	}
+	if (m_flag) {
+		sb->s_r_blocks_count = (sb->s_blocks_count / 100)
+			* reserved_ratio;
+		ext2fs_mark_super_dirty(fs);
+		printf("Setting reserved blocks percentage to %lu (%u blocks)\n",
+			reserved_ratio, sb->s_r_blocks_count);
+	}
+	if (r_flag) {
+		if (reserved_blocks >= sb->s_blocks_count/2)
+			bb_error_msg_and_die("reserved blocks count is too big (%lu)", reserved_blocks);
+		sb->s_r_blocks_count = reserved_blocks;
+		ext2fs_mark_super_dirty(fs);
+		printf("Setting reserved blocks count to %lu\n", reserved_blocks);
+	}
+	if (s_flag == 1) {
+		if (sb->s_feature_ro_compat &
+		    EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
+			bb_error_msg("\nThe filesystem already has sparse superblocks\n");
+		else {
+			sb->s_feature_ro_compat |=
+				EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+			sb->s_state &= ~EXT2_VALID_FS;
+			ext2fs_mark_super_dirty(fs);
+			printf("\nSparse superblock flag set.  %s", please_fsck);
+		}
+	}
+	if (s_flag == 0) {
+		if (!(sb->s_feature_ro_compat &
+		      EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
+			bb_error_msg("\nThe filesystem already has sparse superblocks disabled\n");
+		else {
+			sb->s_feature_ro_compat &=
+				~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+			sb->s_state &= ~EXT2_VALID_FS;
+			fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
+			ext2fs_mark_super_dirty(fs);
+			printf("\nSparse superblock flag cleared.  %s", please_fsck);
+		}
+	}
+	if (T_flag) {
+		sb->s_lastcheck = last_check_time;
+		ext2fs_mark_super_dirty(fs);
+		printf("Setting time filesystem last checked to %s\n",
+		       ctime(&last_check_time));
+	}
+	if (u_flag) {
+		sb->s_def_resuid = resuid;
+		ext2fs_mark_super_dirty(fs);
+		printf("Setting reserved blocks uid to %lu\n", resuid);
+	}
+	if (L_flag) {
+		if (strlen(new_label) > sizeof(sb->s_volume_name))
+			bb_error_msg("Warning: label too long, truncating\n");
+		memset(sb->s_volume_name, 0, sizeof(sb->s_volume_name));
+		safe_strncpy(sb->s_volume_name, new_label,
+			sizeof(sb->s_volume_name));
+		ext2fs_mark_super_dirty(fs);
+	}
+	if (M_flag) {
+		memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted));
+		safe_strncpy(sb->s_last_mounted, new_last_mounted,
+			sizeof(sb->s_last_mounted));
+		ext2fs_mark_super_dirty(fs);
+	}
+	if (mntopts_cmd)
+		update_mntopts(fs, mntopts_cmd);
+	if (features_cmd)
+		update_feature_set(fs, features_cmd);
+	if (journal_size || journal_device)
+		add_journal(fs);
+
+	if (U_flag) {
+		if ((strcasecmp(new_UUID, "null") == 0) ||
+		    (strcasecmp(new_UUID, "clear") == 0)) {
+			uuid_clear(sb->s_uuid);
+		} else if (strcasecmp(new_UUID, "time") == 0) {
+			uuid_generate_time(sb->s_uuid);
+		} else if (strcasecmp(new_UUID, "random") == 0) {
+			uuid_generate(sb->s_uuid);
+		} else if (uuid_parse(new_UUID, sb->s_uuid)) {
+			bb_error_msg_and_die("Invalid UUID format");
+		}
+		ext2fs_mark_super_dirty(fs);
+	}
+
+	if (l_flag)
+		list_super (sb);
+	return (ext2fs_close (fs) ? 1 : 0);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/util.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/util.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/util.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,278 @@
+/*
+ * util.c --- helper functions used by tune2fs and mke2fs
+ *
+ * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <linux/major.h>
+#include <sys/stat.h>
+
+#include "e2fsbb.h"
+#include "e2p/e2p.h"
+#include "ext2fs/ext2_fs.h"
+#include "ext2fs/ext2fs.h"
+#include "blkid/blkid.h"
+#include "util.h"
+
+void proceed_question(void)
+{
+	fputs("Proceed anyway? (y,n) ", stdout);
+	if (bb_ask_confirmation() == 0)
+		exit(1);
+}
+
+void check_plausibility(const char *device, int force)
+{
+	int val;
+#ifdef CONFIG_LFS
+	struct stat64 s;
+	val = stat64(device, &s);
+#else
+	struct stat s;
+	val = stat(device, &s);
+#endif
+	if (force)
+		return;
+	if(val == -1)
+		bb_perror_msg_and_die("Could not stat %s", device);
+	if (!S_ISBLK(s.st_mode)) {
+		printf("%s is not a block special device.\n", device);
+		proceed_question();
+		return;
+	}
+
+#ifdef HAVE_LINUX_MAJOR_H
+#ifndef MAJOR
+#define MAJOR(dev)	((dev)>>8)
+#define MINOR(dev)	((dev) & 0xff)
+#endif
+#ifndef SCSI_BLK_MAJOR
+#ifdef SCSI_DISK0_MAJOR
+#ifdef SCSI_DISK8_MAJOR
+#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
+  ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) || \
+  ((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR))
+#else
+#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
+  ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
+#endif /* defined(SCSI_DISK8_MAJOR) */
+#define SCSI_BLK_MAJOR(M) (SCSI_DISK_MAJOR((M)) || (M) == SCSI_CDROM_MAJOR)
+#else
+#define SCSI_BLK_MAJOR(M)  ((M) == SCSI_DISK_MAJOR || (M) == SCSI_CDROM_MAJOR)
+#endif /* defined(SCSI_DISK0_MAJOR) */
+#endif /* defined(SCSI_BLK_MAJOR) */
+	if (((MAJOR(s.st_rdev) == HD_MAJOR &&
+	      MINOR(s.st_rdev)%64 == 0) ||
+	     (SCSI_BLK_MAJOR(MAJOR(s.st_rdev)) &&
+	      MINOR(s.st_rdev)%16 == 0))) {
+		printf("%s is entire device, not just one partition!\n", device);
+		proceed_question();
+	}
+#endif
+}
+
+void check_mount(const char *device, int force, const char *type)
+{
+	errcode_t retval;
+	int mount_flags;
+
+	retval = ext2fs_check_if_mounted(device, &mount_flags);
+	if (retval) {
+		bb_error_msg("Could not determine if %s is mounted", device);
+		return;
+	}
+	if (mount_flags & EXT2_MF_MOUNTED) {
+		bb_error_msg("%s is mounted !", device);
+force_check:
+		if (force)
+			bb_error_msg("badblocks forced anyways");
+		else
+			bb_error_msg_and_die("it's not safe to run badblocks!");
+	}
+
+	if (mount_flags & EXT2_MF_BUSY) {  
+		bb_error_msg("%s is apparently in use by the system", device);
+		goto force_check;
+	}
+
+}
+
+void parse_journal_opts(char **journal_device, int *journal_flags,
+			int *journal_size, const char *opts)
+{
+	char *buf, *token, *next, *p, *arg;
+	int journal_usage = 0;
+#if 0
+	int	len;
+	len = strlen(opts);
+	buf = xmalloc(len+1);
+	strcpy(buf, opts);
+#else
+	buf = bb_xstrdup(opts);
+#endif
+	for (token = buf; token && *token; token = next) {
+		p = strchr(token, ',');
+		next = 0;
+		if (p) {
+			*p = 0;
+			next = p+1;
+		}
+		arg = strchr(token, '=');
+		if (arg) {
+			*arg = 0;
+			arg++;
+		}
+		if (strcmp(token, "device") == 0) {
+			*journal_device = blkid_get_devname(NULL, arg, NULL);
+			if (!journal_device) {
+				journal_usage++;
+				continue;
+			}
+		} else if (strcmp(token, "size") == 0) {
+			if (!arg) {
+				journal_usage++;
+				continue;
+			}
+			(*journal_size) = strtoul(arg, &p, 0);
+			if (*p)
+				journal_usage++;
+		} else if (strcmp(token, "v1_superblock") == 0) {
+			(*journal_flags) |= EXT2_MKJOURNAL_V1_SUPER;
+			continue;
+		} else
+			journal_usage++;
+	}
+	if (journal_usage)
+		bb_error_msg_and_die(
+			"\nBad journal options specified.\n\n"
+			"Journal options are separated by commas, "
+			"and may take an argument which\n"
+			"\tis set off by an equals ('=') sign.\n\n"
+			"Valid journal options are:\n"
+			"\tsize=<journal size in megabytes>\n"
+			"\tdevice=<journal device>\n\n"
+			"The journal size must be between "
+			"1024 and 102400 filesystem blocks.\n\n");
+}
+
+/*
+ * Determine the number of journal blocks to use, either via
+ * user-specified # of megabytes, or via some intelligently selected
+ * defaults.
+ *
+ * Find a reasonable journal file size (in blocks) given the number of blocks
+ * in the filesystem.  For very small filesystems, it is not reasonable to
+ * have a journal that fills more than half of the filesystem.
+ */
+int figure_journal_size(int size, ext2_filsys fs)
+{
+	blk_t j_blocks;
+
+	if (fs->super->s_blocks_count < 2048) {
+		bb_error_msg("Filesystem too small for a journal");
+		return 0;
+	}
+
+	if (size >= 0) {
+		j_blocks = size * 1024 / (fs->blocksize	/ 1024);
+		if (j_blocks < 1024 || j_blocks > 102400)
+			bb_error_msg_and_die("\nThe requested journal "
+				"size is %d blocks;\n it must be "
+				"between 1024 and 102400 blocks; Aborting",
+				j_blocks);
+		if (j_blocks > fs->super->s_free_blocks_count)
+			bb_error_msg_and_die("Journal size too big for filesystem");
+		return j_blocks;
+	}
+
+	if (fs->super->s_blocks_count < 32768)
+		j_blocks = 1024;
+	else if (fs->super->s_blocks_count < 256*1024)
+		j_blocks = 4096;
+	else if (fs->super->s_blocks_count < 512*1024)
+		j_blocks = 8192;
+	else if (fs->super->s_blocks_count < 1024*1024)
+		j_blocks = 16384;
+	else
+		j_blocks = 32768;
+
+	return j_blocks;
+}
+
+void print_check_message(ext2_filsys fs)
+{
+	printf("This filesystem will be automatically "
+		 "checked every %d mounts or\n"
+		 "%g days, whichever comes first.  "
+		 "Use tune2fs -c or -i to override.\n",
+	       fs->super->s_max_mnt_count,
+	       (double)fs->super->s_checkinterval / (3600 * 24));
+}
+
+void make_journal_device(char *journal_device, ext2_filsys fs, int quiet, int force)
+{
+	errcode_t	retval;
+	ext2_filsys	jfs;
+	io_manager	io_ptr;
+
+	check_plausibility(journal_device, force);
+	check_mount(journal_device, force, "journal");
+	io_ptr = unix_io_manager;
+	retval = ext2fs_open(journal_device, EXT2_FLAG_RW|
+					EXT2_FLAG_JOURNAL_DEV_OK, 0,
+					fs->blocksize, io_ptr, &jfs);
+	if (retval)
+		bb_error_msg_and_die("Could not journal device %s", journal_device);
+	if(!quiet)
+		printf("Adding journal to device %s: ", journal_device);
+	fflush(stdout);
+	retval = ext2fs_add_journal_device(fs, jfs);
+	if(retval)
+		bb_error_msg_and_die("\nFailed to add journal to device %s", journal_device);
+	if(!quiet)
+		puts("done");
+	ext2fs_close(jfs);
+}
+
+void make_journal_blocks(ext2_filsys fs, int journal_size, int journal_flags, int quiet)
+{
+	unsigned long journal_blocks;
+	errcode_t	retval;
+
+	journal_blocks = figure_journal_size(journal_size, fs);
+	if (!journal_blocks) {
+		fs->super->s_feature_compat &=
+			~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+		return;
+	}
+	if(!quiet)
+		printf("Creating journal (%ld blocks): ", journal_blocks);
+	fflush(stdout);
+	retval = ext2fs_add_journal_inode(fs, journal_blocks,
+						  journal_flags);
+	if(retval)
+		bb_error_msg_and_die("Could not create journal");
+	if(!quiet)
+		puts("done");
+}
+
+char *e2fs_set_sbin_path(void)
+{
+	char *oldpath = getenv("PATH");
+	/* Update our PATH to include /sbin  */
+#define PATH_SET "/sbin"
+	if (oldpath)
+		oldpath = bb_xasprintf("%s:%s", PATH_SET, oldpath);
+	 else
+		oldpath = PATH_SET;
+	putenv (oldpath);
+	return oldpath;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/util.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/util.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/util.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,21 @@
+/*
+ * util.h --- header file defining prototypes for helper functions
+ * used by tune2fs and mke2fs
+ *
+ * Copyright 2000 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+extern void proceed_question(void);
+extern void check_plausibility(const char *device, int force);
+extern void parse_journal_opts(char **, int *, int *, const char *opts);
+extern void check_mount(const char *device, int force, const char *type);
+extern int figure_journal_size(int size, ext2_filsys fs);
+extern void print_check_message(ext2_filsys fs);
+extern void make_journal_device(char *journal_device, ext2_filsys fs, int quiet, int force);
+extern void make_journal_blocks(ext2_filsys fs, int journal_size, int journal_flags, int quiet);
+extern char *e2fs_set_sbin_path(void);

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/compare.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/compare.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/compare.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,54 @@
+/*
+ * compare.c --- compare whether or not two UUID's are the same
+ *
+ * Returns 0 if the two UUID's are different, and 1 if they are the same.
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#include "uuidP.h"
+#include <string.h>
+
+#define UUCMP(u1,u2) if (u1 != u2) return((u1 < u2) ? -1 : 1);
+
+int uuid_compare(const uuid_t uu1, const uuid_t uu2)
+{
+	struct uuid	uuid1, uuid2;
+
+	uuid_unpack(uu1, &uuid1);
+	uuid_unpack(uu2, &uuid2);
+
+	UUCMP(uuid1.time_low, uuid2.time_low);
+	UUCMP(uuid1.time_mid, uuid2.time_mid);
+	UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version);
+	UUCMP(uuid1.clock_seq, uuid2.clock_seq);
+	return memcmp(uuid1.node, uuid2.node, 6);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/gen_uuid.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/gen_uuid.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/gen_uuid.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,303 @@
+/*
+ * gen_uuid.c --- generate a DCE-compatible uuid
+ *
+ * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NET_IF_DL_H
+#include <net/if_dl.h>
+#endif
+
+#include "uuidP.h"
+
+#ifdef HAVE_SRANDOM
+#define srand(x)	srandom(x)
+#define rand()		random()
+#endif
+
+static int get_random_fd(void)
+{
+	struct timeval	tv;
+	static int	fd = -2;
+	int		i;
+
+	if (fd == -2) {
+		gettimeofday(&tv, 0);
+		fd = open("/dev/urandom", O_RDONLY);
+		if (fd == -1)
+			fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
+		srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
+	}
+	/* Crank the random number generator a few times */
+	gettimeofday(&tv, 0);
+	for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
+		rand();
+	return fd;
+}
+
+
+/*
+ * Generate a series of random bytes.  Use /dev/urandom if possible,
+ * and if not, use srandom/random.
+ */
+static void get_random_bytes(void *buf, int nbytes)
+{
+	int i, n = nbytes, fd = get_random_fd();
+	int lose_counter = 0;
+	unsigned char *cp = (unsigned char *) buf;
+
+	if (fd >= 0) {
+		while (n > 0) {
+			i = read(fd, cp, n);
+			if (i <= 0) {
+				if (lose_counter++ > 16)
+					break;
+				continue;
+			}
+			n -= i;
+			cp += i;
+			lose_counter = 0;
+		}
+	}
+
+	/*
+	 * We do this all the time, but this is the only source of
+	 * randomness if /dev/random/urandom is out to lunch.
+	 */
+	for (cp = buf, i = 0; i < nbytes; i++)
+		*cp++ ^= (rand() >> 7) & 0xFF;
+	return;
+}
+
+/*
+ * Get the ethernet hardware address, if we can find it...
+ */
+static int get_node_id(unsigned char *node_id)
+{
+#ifdef HAVE_NET_IF_H
+	int		sd;
+	struct ifreq	ifr, *ifrp;
+	struct ifconf	ifc;
+	char buf[1024];
+	int		n, i;
+	unsigned char	*a;
+#ifdef HAVE_NET_IF_DL_H
+	struct sockaddr_dl *sdlp;
+#endif
+
+/*
+ * BSD 4.4 defines the size of an ifreq to be
+ * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
+ * However, under earlier systems, sa_len isn't present, so the size is
+ * just sizeof(struct ifreq)
+ */
+#ifdef HAVE_SA_LEN
+#ifndef max
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#define ifreq_size(i) max(sizeof(struct ifreq),\
+     sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
+#else
+#define ifreq_size(i) sizeof(struct ifreq)
+#endif /* HAVE_SA_LEN*/
+
+	sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+	if (sd < 0) {
+		return -1;
+	}
+	memset(buf, 0, sizeof(buf));
+	ifc.ifc_len = sizeof(buf);
+	ifc.ifc_buf = buf;
+	if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
+		close(sd);
+		return -1;
+	}
+	n = ifc.ifc_len;
+	for (i = 0; i < n; i+= ifreq_size(*ifrp) ) {
+		ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
+		strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
+#ifdef SIOCGIFHWADDR
+		if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
+			continue;
+		a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
+#else
+#ifdef SIOCGENADDR
+		if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
+			continue;
+		a = (unsigned char *) ifr.ifr_enaddr;
+#else
+#ifdef HAVE_NET_IF_DL_H
+		sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr;
+		if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6))
+			continue;
+		a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen];
+#else
+		/*
+		 * XXX we don't have a way of getting the hardware
+		 * address
+		 */
+		close(sd);
+		return 0;
+#endif /* HAVE_NET_IF_DL_H */
+#endif /* SIOCGENADDR */
+#endif /* SIOCGIFHWADDR */
+		if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
+			continue;
+		if (node_id) {
+			memcpy(node_id, a, 6);
+			close(sd);
+			return 1;
+		}
+	}
+	close(sd);
+#endif
+	return 0;
+}
+
+/* Assume that the gettimeofday() has microsecond granularity */
+#define MAX_ADJUSTMENT 10
+
+static int get_clock(uint32_t *clock_high, uint32_t *clock_low, uint16_t *ret_clock_seq)
+{
+	static int			adjustment = 0;
+	static struct timeval		last = {0, 0};
+	static uint16_t			clock_seq;
+	struct timeval			tv;
+	unsigned long long		clock_reg;
+
+try_again:
+	gettimeofday(&tv, 0);
+	if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
+		get_random_bytes(&clock_seq, sizeof(clock_seq));
+		clock_seq &= 0x3FFF;
+		last = tv;
+		last.tv_sec--;
+	}
+	if ((tv.tv_sec < last.tv_sec) ||
+	    ((tv.tv_sec == last.tv_sec) &&
+	     (tv.tv_usec < last.tv_usec))) {
+		clock_seq = (clock_seq+1) & 0x3FFF;
+		adjustment = 0;
+		last = tv;
+	} else if ((tv.tv_sec == last.tv_sec) &&
+	    (tv.tv_usec == last.tv_usec)) {
+		if (adjustment >= MAX_ADJUSTMENT)
+			goto try_again;
+		adjustment++;
+	} else {
+		adjustment = 0;
+		last = tv;
+	}
+
+	clock_reg = tv.tv_usec*10 + adjustment;
+	clock_reg += ((unsigned long long) tv.tv_sec)*10000000;
+	clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
+
+	*clock_high = clock_reg >> 32;
+	*clock_low = clock_reg;
+	*ret_clock_seq = clock_seq;
+	return 0;
+}
+
+void uuid_generate_time(uuid_t out)
+{
+	static unsigned char node_id[6];
+	static int has_init = 0;
+	struct uuid uu;
+	uint32_t	clock_mid;
+
+	if (!has_init) {
+		if (get_node_id(node_id) <= 0) {
+			get_random_bytes(node_id, 6);
+			/*
+			 * Set multicast bit, to prevent conflicts
+			 * with IEEE 802 addresses obtained from
+			 * network cards
+			 */
+			node_id[0] |= 0x01;
+		}
+		has_init = 1;
+	}
+	get_clock(&clock_mid, &uu.time_low, &uu.clock_seq);
+	uu.clock_seq |= 0x8000;
+	uu.time_mid = (uint16_t) clock_mid;
+	uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000;
+	memcpy(uu.node, node_id, 6);
+	uuid_pack(&uu, out);
+}
+
+void uuid_generate_random(uuid_t out)
+{
+	uuid_t	buf;
+	struct uuid uu;
+
+	get_random_bytes(buf, sizeof(buf));
+	uuid_unpack(buf, &uu);
+
+	uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
+	uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000;
+	uuid_pack(&uu, out);
+}
+
+/*
+ * This is the generic front-end to uuid_generate_random and
+ * uuid_generate_time.  It uses uuid_generate_random only if
+ * /dev/urandom is available, since otherwise we won't have
+ * high-quality randomness.
+ */
+void uuid_generate(uuid_t out)
+{
+	if (get_random_fd() >= 0)
+		uuid_generate_random(out);
+	else
+		uuid_generate_time(out);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/pack.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/pack.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/pack.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,68 @@
+/*
+ * Internal routine for packing UUID's
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#include <string.h>
+#include "uuidP.h"
+
+void uuid_pack(const struct uuid *uu, uuid_t ptr)
+{
+	uint32_t tmp;
+	unsigned char *out = ptr;
+
+	tmp = uu->time_low;
+	out[3] = (unsigned char) tmp;
+	tmp >>= 8;
+	out[2] = (unsigned char) tmp;
+	tmp >>= 8;
+	out[1] = (unsigned char) tmp;
+	tmp >>= 8;
+	out[0] = (unsigned char) tmp;
+
+	tmp = uu->time_mid;
+	out[5] = (unsigned char) tmp;
+	tmp >>= 8;
+	out[4] = (unsigned char) tmp;
+
+	tmp = uu->time_hi_and_version;
+	out[7] = (unsigned char) tmp;
+	tmp >>= 8;
+	out[6] = (unsigned char) tmp;
+
+	tmp = uu->clock_seq;
+	out[9] = (unsigned char) tmp;
+	tmp >>= 8;
+	out[8] = (unsigned char) tmp;
+
+	memcpy(out+10, uu->node, 6);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/parse.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/parse.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/parse.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,79 @@
+/*
+ * parse.c --- UUID parsing
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "uuidP.h"
+
+int uuid_parse(const char *in, uuid_t uu)
+{
+	struct uuid	uuid;
+	int		i;
+	const char	*cp;
+	char		buf[3];
+
+	if (strlen(in) != 36)
+		return -1;
+	for (i=0, cp = in; i <= 36; i++,cp++) {
+		if ((i == 8) || (i == 13) || (i == 18) ||
+		    (i == 23)) {
+			if (*cp == '-')
+				continue;
+			else
+				return -1;
+		}
+		if (i== 36)
+			if (*cp == 0)
+				continue;
+		if (!isxdigit(*cp))
+			return -1;
+	}
+	uuid.time_low = strtoul(in, NULL, 16);
+	uuid.time_mid = strtoul(in+9, NULL, 16);
+	uuid.time_hi_and_version = strtoul(in+14, NULL, 16);
+	uuid.clock_seq = strtoul(in+19, NULL, 16);
+	cp = in+24;
+	buf[2] = 0;
+	for (i=0; i < 6; i++) {
+		buf[0] = *cp++;
+		buf[1] = *cp++;
+		uuid.node[i] = strtoul(buf, NULL, 16);
+	}
+
+	uuid_pack(&uuid, uu);
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/unpack.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/unpack.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/unpack.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,62 @@
+/*
+ * Internal routine for unpacking UUID
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#include <string.h>
+#include "uuidP.h"
+
+void uuid_unpack(const uuid_t in, struct uuid *uu)
+{
+	const uint8_t *ptr = in;
+	uint32_t tmp;
+
+	tmp = *ptr++;
+	tmp = (tmp << 8) | *ptr++;
+	tmp = (tmp << 8) | *ptr++;
+	tmp = (tmp << 8) | *ptr++;
+	uu->time_low = tmp;
+
+	tmp = *ptr++;
+	tmp = (tmp << 8) | *ptr++;
+	uu->time_mid = tmp;
+
+	tmp = *ptr++;
+	tmp = (tmp << 8) | *ptr++;
+	uu->time_hi_and_version = tmp;
+
+	tmp = *ptr++;
+	tmp = (tmp << 8) | *ptr++;
+	uu->clock_seq = tmp;
+
+	memcpy(uu->node, ptr, 6);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/unparse.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/unparse.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/unparse.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,76 @@
+/*
+ * unparse.c -- convert a UUID to string
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+
+#include "uuidP.h"
+
+static const char *fmt_lower =
+	"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
+
+static const char *fmt_upper =
+	"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X";
+
+#ifdef UUID_UNPARSE_DEFAULT_UPPER
+#define FMT_DEFAULT fmt_upper
+#else
+#define FMT_DEFAULT fmt_lower
+#endif
+
+static void uuid_unparse_x(const uuid_t uu, char *out, const char *fmt)
+{
+	struct uuid uuid;
+
+	uuid_unpack(uu, &uuid);
+	sprintf(out, fmt,
+		uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
+		uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
+		uuid.node[0], uuid.node[1], uuid.node[2],
+		uuid.node[3], uuid.node[4], uuid.node[5]);
+}
+
+void uuid_unparse_lower(const uuid_t uu, char *out)
+{
+	uuid_unparse_x(uu, out,	fmt_lower);
+}
+
+void uuid_unparse_upper(const uuid_t uu, char *out)
+{
+	uuid_unparse_x(uu, out,	fmt_upper);
+}
+
+void uuid_unparse(const uuid_t uu, char *out)
+{
+	uuid_unparse_x(uu, out, FMT_DEFAULT);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/uuid.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/uuid.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/uuid.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,103 @@
+/*
+ * Public include file for the UUID library
+ *
+ * Copyright (C) 1996, 1997, 1998 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#ifndef _UUID_UUID_H
+#define _UUID_UUID_H
+
+#include <sys/types.h>
+#include <time.h>
+
+typedef unsigned char uuid_t[16];
+
+/* UUID Variant definitions */
+#define UUID_VARIANT_NCS	0
+#define UUID_VARIANT_DCE	1
+#define UUID_VARIANT_MICROSOFT	2
+#define UUID_VARIANT_OTHER	3
+
+/* UUID Type definitions */
+#define UUID_TYPE_DCE_TIME   1
+#define UUID_TYPE_DCE_RANDOM 4
+
+/* Allow UUID constants to be defined */
+#ifdef __GNUC__
+#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \
+	static const uuid_t name ATTRIBUTE_UNUSED = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15}
+#else
+#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \
+	static const uuid_t name = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15}
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* clear.c */
+/*void uuid_clear(uuid_t uu);*/
+#define uuid_clear(uu) memset(uu, 0, sizeof(uu))
+
+/* compare.c */
+int uuid_compare(const uuid_t uu1, const uuid_t uu2);
+
+/* copy.c */
+/*void uuid_copy(uuid_t dst, const uuid_t src);*/
+#define uuid_copy(dst,src) memcpy(dst, src, sizeof(dst))
+
+/* gen_uuid.c */
+void uuid_generate(uuid_t out);
+void uuid_generate_random(uuid_t out);
+void uuid_generate_time(uuid_t out);
+
+/* isnull.c */
+/*int uuid_is_null(const uuid_t uu);*/
+#define uuid_is_null(uu) (!memcmp(uu, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(uu)))
+
+/* parse.c */
+int uuid_parse(const char *in, uuid_t uu);
+
+/* unparse.c */
+void uuid_unparse(const uuid_t uu, char *out);
+void uuid_unparse_lower(const uuid_t uu, char *out);
+void uuid_unparse_upper(const uuid_t uu, char *out);
+
+/* uuid_time.c */
+time_t uuid_time(const uuid_t uu, struct timeval *ret_tv);
+int uuid_type(const uuid_t uu);
+int uuid_variant(const uuid_t uu);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UUID_UUID_H */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/uuidP.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/uuidP.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/uuidP.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,59 @@
+/*
+ * uuid.h -- private header file for uuids
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#include <inttypes.h>
+#include <sys/types.h>
+
+#include "uuid.h"
+
+/*
+ * Offset between 15-Oct-1582 and 1-Jan-70
+ */
+#define TIME_OFFSET_HIGH 0x01B21DD2
+#define TIME_OFFSET_LOW  0x13814000
+
+struct uuid {
+	uint32_t	time_low;
+	uint16_t	time_mid;
+	uint16_t	time_hi_and_version;
+	uint16_t	clock_seq;
+	uint8_t	node[6];
+};
+
+
+/*
+ * prototypes
+ */
+void uuid_pack(const struct uuid *uu, uuid_t ptr);
+void uuid_unpack(const uuid_t in, struct uuid *uu);

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/uuid_time.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/uuid_time.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/e2fsprogs/uuid/uuid_time.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,160 @@
+/*
+ * uuid_time.c --- Interpret the time field from a uuid.  This program
+ *	violates the UUID abstraction barrier by reaching into the guts
+ *	of a UUID and interpreting it.
+ *
+ * Copyright (C) 1998, 1999 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include "uuidP.h"
+
+time_t uuid_time(const uuid_t uu, struct timeval *ret_tv)
+{
+	struct uuid		uuid;
+	uint32_t			high;
+	struct timeval		tv;
+	unsigned long long	clock_reg;
+
+	uuid_unpack(uu, &uuid);
+
+	high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16);
+	clock_reg = uuid.time_low | ((unsigned long long) high << 32);
+
+	clock_reg -= (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
+	tv.tv_sec = clock_reg / 10000000;
+	tv.tv_usec = (clock_reg % 10000000) / 10;
+
+	if (ret_tv)
+		*ret_tv = tv;
+
+	return tv.tv_sec;
+}
+
+int uuid_type(const uuid_t uu)
+{
+	struct uuid		uuid;
+
+	uuid_unpack(uu, &uuid);
+	return ((uuid.time_hi_and_version >> 12) & 0xF);
+}
+
+int uuid_variant(const uuid_t uu)
+{
+	struct uuid		uuid;
+	int			var;
+
+	uuid_unpack(uu, &uuid);
+	var = uuid.clock_seq;
+
+	if ((var & 0x8000) == 0)
+		return UUID_VARIANT_NCS;
+	if ((var & 0x4000) == 0)
+		return UUID_VARIANT_DCE;
+	if ((var & 0x2000) == 0)
+		return UUID_VARIANT_MICROSOFT;
+	return UUID_VARIANT_OTHER;
+}
+
+#ifdef DEBUG
+static const char *variant_string(int variant)
+{
+	switch (variant) {
+	case UUID_VARIANT_NCS:
+		return "NCS";
+	case UUID_VARIANT_DCE:
+		return "DCE";
+	case UUID_VARIANT_MICROSOFT:
+		return "Microsoft";
+	default:
+		return "Other";
+	}
+}
+
+
+int
+main(int argc, char **argv)
+{
+	uuid_t		buf;
+	time_t		time_reg;
+	struct timeval	tv;
+	int		type, variant;
+
+	if (argc != 2) {
+		fprintf(stderr, "Usage: %s uuid\n", argv[0]);
+		exit(1);
+	}
+	if (uuid_parse(argv[1], buf)) {
+		fprintf(stderr, "Invalid UUID: %s\n", argv[1]);
+		exit(1);
+	}
+	variant = uuid_variant(buf);
+	type = uuid_type(buf);
+	time_reg = uuid_time(buf, &tv);
+
+	printf("UUID variant is %d (%s)\n", variant, variant_string(variant));
+	if (variant != UUID_VARIANT_DCE) {
+		printf("Warning: This program only knows how to interpret "
+		       "DCE UUIDs.\n\tThe rest of the output is likely "
+		       "to be incorrect!!\n");
+	}
+	printf("UUID type is %d", type);
+	switch (type) {
+	case 1:
+		printf(" (time based)\n");
+		break;
+	case 2:
+		printf(" (DCE)\n");
+		break;
+	case 3:
+		printf(" (name-based)\n");
+		break;
+	case 4:
+		printf(" (random)\n");
+		break;
+	default:
+		printf("\n");
+	}
+	if (type != 1) {
+		printf("Warning: not a time-based UUID, so UUID time "
+		       "decoding will likely not work!\n");
+	}
+	printf("UUID time is: (%ld, %ld): %s\n", tv.tv_sec, tv.tv_usec,
+	       ctime(&time_reg));
+
+	return 0;
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,131 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Editors"
+
+config CONFIG_AWK
+	bool "awk"
+	default n
+	help
+	  Awk is used as a pattern scanning and processing language.  This is
+	  the BusyBox implementation of that programming language.
+
+config CONFIG_FEATURE_AWK_MATH
+	bool "Enable math functions (requires libm)"
+	default y
+	depends on CONFIG_AWK
+	help
+	  Enable math functions of the Awk programming language.
+	  NOTE: This will require libm to be present for linking.
+
+config CONFIG_ED
+	bool "ed"
+	default n
+	help
+	  The original 1970's Unix text editor, from the days of teletypes.
+	  Small, simple, evil.  Part of SUSv3.  If you're not already using
+	  this, you don't need it.
+
+config CONFIG_PATCH
+	bool "patch"
+	default n
+	help
+	  Apply a unified diff formatted patch.
+
+config CONFIG_SED
+	bool "sed"
+	default n
+	help
+	  sed is used to perform text transformations on a file
+	  or input from a pipeline.
+
+config CONFIG_VI
+	bool "vi"
+	default n
+	help
+	  'vi' is a text editor.  More specifically, it is the One True
+	  text editor <grin>.  It does, however, have a rather steep
+	  learning curve.  If you are not already comfortable with 'vi'
+	  you may wish to use something else.
+
+config CONFIG_FEATURE_VI_COLON
+	bool "Enable \":\" colon commands (no \"ex\" mode)"
+	default y
+	depends on CONFIG_VI
+	help
+	  Enable a limited set of colon commands for vi.  This does not
+	  provide an "ex" mode.
+
+config CONFIG_FEATURE_VI_YANKMARK
+	bool "Enable yank/put commands and mark cmds"
+	default y
+	depends on CONFIG_VI
+	help
+	  This will enable you to use yank and put, as well as mark in
+	  busybox vi.
+
+config CONFIG_FEATURE_VI_SEARCH
+	bool "Enable search and replace cmds"
+	default y
+	depends on CONFIG_VI
+	help
+	  Select this if you wish to be able to do search and replace in
+	  busybox vi.
+
+config CONFIG_FEATURE_VI_USE_SIGNALS
+	bool "Catch signals"
+	default y
+	depends on CONFIG_VI
+	help
+	  Selecting this option will make busybox vi signal aware.  This will
+	  make busybox vi support SIGWINCH to deal with Window Changes, catch
+	  Ctrl-Z and Ctrl-C and alarms.
+
+config CONFIG_FEATURE_VI_DOT_CMD
+	bool "Remember previous cmd and \".\" cmd"
+	default y
+	depends on CONFIG_VI
+	help
+	  Make busybox vi remember the last command and be able to repeat it.
+
+config CONFIG_FEATURE_VI_READONLY
+	bool "Enable -R option and \"view\" mode"
+	default y
+	depends on CONFIG_VI
+	help
+	  Enable the read-only command line option, which allows the user to
+	  open a file in read-only mode.
+
+config CONFIG_FEATURE_VI_SETOPTS
+	bool "Enable set-able options, ai ic showmatch"
+	default y
+	depends on CONFIG_VI
+	help
+	  Enable the editor to set some (ai, ic, showmatch) options.
+
+config CONFIG_FEATURE_VI_SET
+	bool "Support for :set"
+	default y
+	depends on CONFIG_VI
+	help
+	  Support for ":set".
+
+config CONFIG_FEATURE_VI_WIN_RESIZE
+	bool "Handle window resize"
+	default y
+	depends on CONFIG_VI
+	help
+	  Make busybox vi behave nicely with terminals that get resized.
+
+config CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
+	bool "Optimize cursor movement"
+	default y
+	depends on CONFIG_VI
+	help
+	  This will make the cursor movement faster, but requires more memory
+	  and it makes the applet a tiny bit larger.
+
+endmenu
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/editors
+EDITOR_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include $(srcdir)/Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,40 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+EDITOR_AR:=editors.a
+ifndef $(EDITOR_DIR)
+EDITOR_DIR:=$(top_builddir)/editors/
+endif
+srcdir=$(top_srcdir)/editors
+
+EDITOR-y:=
+EDITOR-$(CONFIG_AWK)       += awk.o
+EDITOR-$(CONFIG_ED)        += ed.o
+EDITOR-$(CONFIG_PATCH)     += patch.o
+EDITOR-$(CONFIG_SED)       += sed.o
+EDITOR-$(CONFIG_VI)        += vi.o
+
+ifneq ($(strip $(EDITOR-y)),)
+libraries-y+=$(EDITOR_DIR)$(EDITOR_AR)
+endif
+
+EDITOR_SRC-y:=$(patsubst %.o,$(srcdir)/%.c,$(EDITOR-y))
+EDITOR_SRC-a:=$(wildcard $(srcdir)/*.c)
+APPLET_SRC-y+=$(EDITOR_SRC-y)
+APPLET_SRC-a+=$(EDITOR_SRC-a)
+
+needlibm-y:=
+needlibm-$(CONFIG_FEATURE_AWK_MATH) := y
+
+ifeq ($(needlibm-y),y)
+  LIBRARIES := -lm $(filter-out -lm,$(LIBRARIES))
+endif
+
+$(EDITOR_DIR)$(EDITOR_AR): $(patsubst %,$(EDITOR_DIR)%, $(EDITOR-y))
+	$(do_ar)
+
+$(EDITOR_DIR)%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/awk.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/awk.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/awk.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2761 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * awk implementation for busybox
+ *
+ * Copyright (C) 2002 by Dmitry Zakharov <dmit at crp.bank.gov.ua>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+#include <time.h>
+#include <math.h>
+#include <ctype.h>
+#include <getopt.h>
+
+#include "xregex.h"
+#include "busybox.h"
+
+
+#define	MAXVARFMT	240
+#define	MINNVBLOCK	64
+
+/* variable flags */
+#define	VF_NUMBER	0x0001	/* 1 = primary type is number */
+#define	VF_ARRAY	0x0002	/* 1 = it's an array */
+
+#define	VF_CACHED	0x0100	/* 1 = num/str value has cached str/num eq */
+#define	VF_USER		0x0200	/* 1 = user input (may be numeric string) */
+#define	VF_SPECIAL	0x0400	/* 1 = requires extra handling when changed */
+#define	VF_WALK		0x0800	/* 1 = variable has alloc'd x.walker list */
+#define	VF_FSTR		0x1000	/* 1 = string points to fstring buffer */
+#define	VF_CHILD	0x2000	/* 1 = function arg; x.parent points to source */
+#define	VF_DIRTY	0x4000	/* 1 = variable was set explicitly */
+
+/* these flags are static, don't change them when value is changed */
+#define	VF_DONTTOUCH (VF_ARRAY | VF_SPECIAL | VF_WALK | VF_CHILD | VF_DIRTY)
+
+/* Variable */
+typedef struct var_s {
+	unsigned short type;		/* flags */
+	double number;
+	char *string;
+	union {
+		int aidx;				/* func arg idx (for compilation stage) */
+		struct xhash_s *array;	/* array ptr */
+		struct var_s *parent;	/* for func args, ptr to actual parameter */
+		char **walker;			/* list of array elements (for..in) */
+	} x;
+} var;
+
+/* Node chain (pattern-action chain, BEGIN, END, function bodies) */
+typedef struct chain_s {
+	struct node_s *first;
+	struct node_s *last;
+	char *programname;
+} chain;
+
+/* Function */
+typedef struct func_s {
+	unsigned short nargs;
+	struct chain_s body;
+} func;
+
+/* I/O stream */
+typedef struct rstream_s {
+	FILE *F;
+	char *buffer;
+	int adv;
+	int size;
+	int pos;
+	unsigned short is_pipe;
+} rstream;
+
+typedef struct hash_item_s {
+	union {
+		struct var_s v;			/* variable/array hash */
+		struct rstream_s rs;	/* redirect streams hash */
+		struct func_s f;		/* functions hash */
+	} data;
+	struct hash_item_s *next;	/* next in chain */
+	char name[1];				/* really it's longer */
+} hash_item;
+
+typedef struct xhash_s {
+	unsigned int nel;					/* num of elements */
+	unsigned int csize;					/* current hash size */
+	unsigned int nprime;				/* next hash size in PRIMES[] */
+	unsigned int glen;					/* summary length of item names */
+	struct hash_item_s **items;
+} xhash;
+
+/* Tree node */
+typedef struct node_s {
+	uint32_t info;
+	unsigned short lineno;
+	union {
+		struct node_s *n;
+		var *v;
+		int i;
+		char *s;
+		regex_t *re;
+	} l;
+	union {
+		struct node_s *n;
+		regex_t *ire;
+		func *f;
+		int argno;
+	} r;
+	union {
+		struct node_s *n;
+	} a;
+} node;
+
+/* Block of temporary variables */
+typedef struct nvblock_s {
+	int size;
+	var *pos;
+	struct nvblock_s *prev;
+	struct nvblock_s *next;
+	var nv[0];
+} nvblock;
+
+typedef struct tsplitter_s {
+	node n;
+	regex_t re[2];
+} tsplitter;
+
+/* simple token classes */
+/* Order and hex values are very important!!!  See next_token() */
+#define	TC_SEQSTART	 1				/* ( */
+#define	TC_SEQTERM	(1 << 1)		/* ) */
+#define	TC_REGEXP	(1 << 2)		/* /.../ */
+#define	TC_OUTRDR	(1 << 3)		/* | > >> */
+#define	TC_UOPPOST	(1 << 4)		/* unary postfix operator */
+#define	TC_UOPPRE1	(1 << 5)		/* unary prefix operator */
+#define	TC_BINOPX	(1 << 6)		/* two-opnd operator */
+#define	TC_IN		(1 << 7)
+#define	TC_COMMA	(1 << 8)
+#define	TC_PIPE		(1 << 9)		/* input redirection pipe */
+#define	TC_UOPPRE2	(1 << 10)		/* unary prefix operator */
+#define	TC_ARRTERM	(1 << 11)		/* ] */
+#define	TC_GRPSTART	(1 << 12)		/* { */
+#define	TC_GRPTERM	(1 << 13)		/* } */
+#define	TC_SEMICOL	(1 << 14)
+#define	TC_NEWLINE	(1 << 15)
+#define	TC_STATX	(1 << 16)		/* ctl statement (for, next...) */
+#define	TC_WHILE	(1 << 17)
+#define	TC_ELSE		(1 << 18)
+#define	TC_BUILTIN	(1 << 19)
+#define	TC_GETLINE	(1 << 20)
+#define	TC_FUNCDECL	(1 << 21)		/* `function' `func' */
+#define	TC_BEGIN	(1 << 22)
+#define	TC_END		(1 << 23)
+#define	TC_EOF		(1 << 24)
+#define	TC_VARIABLE	(1 << 25)
+#define	TC_ARRAY	(1 << 26)
+#define	TC_FUNCTION	(1 << 27)
+#define	TC_STRING	(1 << 28)
+#define	TC_NUMBER	(1 << 29)
+
+#define	TC_UOPPRE	(TC_UOPPRE1 | TC_UOPPRE2)
+
+/* combined token classes */
+#define	TC_BINOP	(TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN)
+#define	TC_UNARYOP	(TC_UOPPRE | TC_UOPPOST)
+#define	TC_OPERAND	(TC_VARIABLE | TC_ARRAY | TC_FUNCTION | \
+	TC_BUILTIN | TC_GETLINE | TC_SEQSTART | TC_STRING | TC_NUMBER)
+
+#define	TC_STATEMNT	(TC_STATX | TC_WHILE)
+#define	TC_OPTERM	(TC_SEMICOL | TC_NEWLINE)
+
+/* word tokens, cannot mean something else if not expected */
+#define	TC_WORD		(TC_IN | TC_STATEMNT | TC_ELSE | TC_BUILTIN | \
+	TC_GETLINE | TC_FUNCDECL | TC_BEGIN | TC_END)
+
+/* discard newlines after these */
+#define	TC_NOTERM	(TC_COMMA | TC_GRPSTART | TC_GRPTERM | \
+	TC_BINOP | TC_OPTERM)
+
+/* what can expression begin with */
+#define	TC_OPSEQ	(TC_OPERAND | TC_UOPPRE | TC_REGEXP)
+/* what can group begin with */
+#define	TC_GRPSEQ	(TC_OPSEQ | TC_OPTERM | TC_STATEMNT | TC_GRPSTART)
+
+/* if previous token class is CONCAT1 and next is CONCAT2, concatenation */
+/* operator is inserted between them */
+#define	TC_CONCAT1	(TC_VARIABLE | TC_ARRTERM | TC_SEQTERM | \
+	TC_STRING | TC_NUMBER | TC_UOPPOST)
+#define	TC_CONCAT2	(TC_OPERAND | TC_UOPPRE)
+
+#define	OF_RES1		0x010000
+#define	OF_RES2		0x020000
+#define	OF_STR1		0x040000
+#define	OF_STR2		0x080000
+#define	OF_NUM1		0x100000
+#define	OF_CHECKED	0x200000
+
+/* combined operator flags */
+#define	xx	0
+#define	xV	OF_RES2
+#define	xS	(OF_RES2 | OF_STR2)
+#define	Vx	OF_RES1
+#define	VV	(OF_RES1 | OF_RES2)
+#define	Nx	(OF_RES1 | OF_NUM1)
+#define	NV	(OF_RES1 | OF_NUM1 | OF_RES2)
+#define	Sx	(OF_RES1 | OF_STR1)
+#define	SV	(OF_RES1 | OF_STR1 | OF_RES2)
+#define	SS	(OF_RES1 | OF_STR1 | OF_RES2 | OF_STR2)
+
+#define	OPCLSMASK	0xFF00
+#define	OPNMASK		0x007F
+
+/* operator priority is a highest byte (even: r->l, odd: l->r grouping)
+ * For builtins it has different meaning: n n s3 s2 s1 v3 v2 v1,
+ * n - min. number of args, vN - resolve Nth arg to var, sN - resolve to string
+ */
+#define	P(x)	(x << 24)
+#define	PRIMASK		0x7F000000
+#define	PRIMASK2	0x7E000000
+
+/* Operation classes */
+
+#define	SHIFT_TIL_THIS	0x0600
+#define	RECUR_FROM_THIS	0x1000
+
+enum {
+	OC_DELETE=0x0100,	OC_EXEC=0x0200,		OC_NEWSOURCE=0x0300,
+	OC_PRINT=0x0400,	OC_PRINTF=0x0500,	OC_WALKINIT=0x0600,
+
+	OC_BR=0x0700,		OC_BREAK=0x0800,	OC_CONTINUE=0x0900,
+	OC_EXIT=0x0a00,		OC_NEXT=0x0b00,		OC_NEXTFILE=0x0c00,
+	OC_TEST=0x0d00,		OC_WALKNEXT=0x0e00,
+
+	OC_BINARY=0x1000,	OC_BUILTIN=0x1100,	OC_COLON=0x1200,
+	OC_COMMA=0x1300,	OC_COMPARE=0x1400,	OC_CONCAT=0x1500,
+	OC_FBLTIN=0x1600,	OC_FIELD=0x1700,	OC_FNARG=0x1800,
+	OC_FUNC=0x1900,		OC_GETLINE=0x1a00,	OC_IN=0x1b00,
+	OC_LAND=0x1c00,		OC_LOR=0x1d00,		OC_MATCH=0x1e00,
+	OC_MOVE=0x1f00,		OC_PGETLINE=0x2000,	OC_REGEXP=0x2100,
+	OC_REPLACE=0x2200,	OC_RETURN=0x2300,	OC_SPRINTF=0x2400,
+	OC_TERNARY=0x2500,	OC_UNARY=0x2600,	OC_VAR=0x2700,
+	OC_DONE=0x2800,
+
+	ST_IF=0x3000,		ST_DO=0x3100,		ST_FOR=0x3200,
+	ST_WHILE=0x3300
+};
+
+/* simple builtins */
+enum {
+	F_in=0,	F_rn,	F_co,	F_ex,	F_lg,	F_si,	F_sq,	F_sr,
+	F_ti,	F_le,	F_sy,	F_ff,	F_cl
+};
+
+/* builtins */
+enum {
+	B_a2=0,	B_ix,	B_ma,	B_sp,	B_ss,	B_ti,	B_lo,	B_up,
+	B_ge,	B_gs,	B_su
+};
+
+/* tokens and their corresponding info values */
+
+#define	NTC		"\377"		/* switch to next token class (tc<<1) */
+#define	NTCC	'\377'
+
+#define	OC_B	OC_BUILTIN
+
+static char * const tokenlist =
+	"\1("		NTC
+	"\1)"		NTC
+	"\1/"		NTC									/* REGEXP */
+	"\2>>"		"\1>"		"\1|"		NTC			/* OUTRDR */
+	"\2++"		"\2--"		NTC						/* UOPPOST */
+	"\2++"		"\2--"		"\1$"		NTC			/* UOPPRE1 */
+	"\2=="		"\1="		"\2+="		"\2-="		/* BINOPX */
+	"\2*="		"\2/="		"\2%="		"\2^="
+	"\1+"		"\1-"		"\3**="		"\2**"
+	"\1/"		"\1%"		"\1^"		"\1*"
+	"\2!="		"\2>="		"\2<="		"\1>"
+	"\1<"		"\2!~"		"\1~"		"\2&&"
+	"\2||"		"\1?"		"\1:"		NTC
+	"\2in"		NTC
+	"\1,"		NTC
+	"\1|"		NTC
+	"\1+"		"\1-"		"\1!"		NTC			/* UOPPRE2 */
+	"\1]"		NTC
+	"\1{"		NTC
+	"\1}"		NTC
+	"\1;"		NTC
+	"\1\n"		NTC
+	"\2if"		"\2do"		"\3for"		"\5break"	/* STATX */
+	"\10continue"			"\6delete"	"\5print"
+	"\6printf"	"\4next"	"\10nextfile"
+	"\6return"	"\4exit"	NTC
+	"\5while"	NTC
+	"\4else"	NTC
+
+	"\5close"	"\6system"	"\6fflush"	"\5atan2"	/* BUILTIN */
+	"\3cos"		"\3exp"		"\3int"		"\3log"
+	"\4rand"	"\3sin"		"\4sqrt"	"\5srand"
+	"\6gensub"	"\4gsub"	"\5index"	"\6length"
+	"\5match"	"\5split"	"\7sprintf"	"\3sub"
+	"\6substr"	"\7systime"	"\10strftime"
+	"\7tolower"	"\7toupper"	NTC
+	"\7getline"	NTC
+	"\4func"	"\10function"	NTC
+	"\5BEGIN"	NTC
+	"\3END"		"\0"
+	;
+
+static const uint32_t tokeninfo[] = {
+
+	0,
+	0,
+	OC_REGEXP,
+	xS|'a',		xS|'w',		xS|'|',
+	OC_UNARY|xV|P(9)|'p',		OC_UNARY|xV|P(9)|'m',
+	OC_UNARY|xV|P(9)|'P',		OC_UNARY|xV|P(9)|'M',
+		OC_FIELD|xV|P(5),
+	OC_COMPARE|VV|P(39)|5,		OC_MOVE|VV|P(74),
+		OC_REPLACE|NV|P(74)|'+',	OC_REPLACE|NV|P(74)|'-',
+	OC_REPLACE|NV|P(74)|'*',	OC_REPLACE|NV|P(74)|'/',
+		OC_REPLACE|NV|P(74)|'%',	OC_REPLACE|NV|P(74)|'&',
+	OC_BINARY|NV|P(29)|'+',		OC_BINARY|NV|P(29)|'-',
+		OC_REPLACE|NV|P(74)|'&',	OC_BINARY|NV|P(15)|'&',
+	OC_BINARY|NV|P(25)|'/',		OC_BINARY|NV|P(25)|'%',
+		OC_BINARY|NV|P(15)|'&',		OC_BINARY|NV|P(25)|'*',
+	OC_COMPARE|VV|P(39)|4,		OC_COMPARE|VV|P(39)|3,
+		OC_COMPARE|VV|P(39)|0,		OC_COMPARE|VV|P(39)|1,
+	OC_COMPARE|VV|P(39)|2,		OC_MATCH|Sx|P(45)|'!',
+		OC_MATCH|Sx|P(45)|'~',		OC_LAND|Vx|P(55),
+	OC_LOR|Vx|P(59),			OC_TERNARY|Vx|P(64)|'?',
+		OC_COLON|xx|P(67)|':',
+	OC_IN|SV|P(49),
+	OC_COMMA|SS|P(80),
+	OC_PGETLINE|SV|P(37),
+	OC_UNARY|xV|P(19)|'+',		OC_UNARY|xV|P(19)|'-',
+		OC_UNARY|xV|P(19)|'!',
+	0,
+	0,
+	0,
+	0,
+	0,
+	ST_IF,			ST_DO,			ST_FOR,			OC_BREAK,
+	OC_CONTINUE,					OC_DELETE|Vx,	OC_PRINT,
+	OC_PRINTF,		OC_NEXT,		OC_NEXTFILE,
+	OC_RETURN|Vx,	OC_EXIT|Nx,
+	ST_WHILE,
+	0,
+
+	OC_FBLTIN|Sx|F_cl, OC_FBLTIN|Sx|F_sy, OC_FBLTIN|Sx|F_ff, OC_B|B_a2|P(0x83),
+	OC_FBLTIN|Nx|F_co, OC_FBLTIN|Nx|F_ex, OC_FBLTIN|Nx|F_in, OC_FBLTIN|Nx|F_lg,
+	OC_FBLTIN|F_rn,    OC_FBLTIN|Nx|F_si, OC_FBLTIN|Nx|F_sq, OC_FBLTIN|Nx|F_sr,
+	OC_B|B_ge|P(0xd6), OC_B|B_gs|P(0xb6), OC_B|B_ix|P(0x9b), OC_FBLTIN|Sx|F_le,
+	OC_B|B_ma|P(0x89), OC_B|B_sp|P(0x8b), OC_SPRINTF,        OC_B|B_su|P(0xb6),
+	OC_B|B_ss|P(0x8f), OC_FBLTIN|F_ti,    OC_B|B_ti|P(0x0b),
+	OC_B|B_lo|P(0x49), OC_B|B_up|P(0x49),
+	OC_GETLINE|SV|P(0),
+	0,	0,
+	0,
+	0
+};
+
+/* internal variable names and their initial values       */
+/* asterisk marks SPECIAL vars; $ is just no-named Field0 */
+enum {
+	CONVFMT=0,	OFMT,		FS,			OFS,
+	ORS,		RS,			RT,			FILENAME,
+	SUBSEP,		ARGIND,		ARGC,		ARGV,
+	ERRNO,		FNR,
+	NR,			NF,			IGNORECASE,
+	ENVIRON,	F0,			_intvarcount_
+};
+
+static char * vNames =
+	"CONVFMT\0"	"OFMT\0"	"FS\0*"		"OFS\0"
+	"ORS\0"		"RS\0*"		"RT\0"		"FILENAME\0"
+	"SUBSEP\0"	"ARGIND\0"	"ARGC\0"	"ARGV\0"
+	"ERRNO\0"	"FNR\0"
+	"NR\0"		"NF\0*"		"IGNORECASE\0*"
+	"ENVIRON\0"	"$\0*"		"\0";
+
+static char * vValues =
+	"%.6g\0"	"%.6g\0"	" \0"		" \0"
+	"\n\0"		"\n\0"		"\0"		"\0"
+	"\034\0"
+	"\377";
+
+/* hash size may grow to these values */
+#define FIRST_PRIME 61;
+static const unsigned int PRIMES[] = { 251, 1021, 4093, 16381, 65521 };
+enum { NPRIMES = sizeof(PRIMES) / sizeof(unsigned int) };
+
+/* globals */
+
+extern char **environ;
+
+static var * V[_intvarcount_];
+static chain beginseq, mainseq, endseq, *seq;
+static int nextrec, nextfile;
+static node *break_ptr, *continue_ptr;
+static rstream *iF;
+static xhash *vhash, *ahash, *fdhash, *fnhash;
+static char *programname;
+static short lineno;
+static int is_f0_split;
+static int nfields;
+static var *Fields;
+static tsplitter fsplitter, rsplitter;
+static nvblock *cb;
+static char *pos;
+static char *buf;
+static int icase;
+static int exiting;
+
+static struct {
+	uint32_t tclass;
+	uint32_t info;
+	char *string;
+	double number;
+	short lineno;
+	int rollback;
+} t;
+
+/* function prototypes */
+static void handle_special(var *);
+static node *parse_expr(uint32_t);
+static void chain_group(void);
+static var *evaluate(node *, var *);
+static rstream *next_input_file(void);
+static int fmt_num(char *, int, const char *, double, int);
+static int awk_exit(int) ATTRIBUTE_NORETURN;
+
+/* ---- error handling ---- */
+
+static const char EMSG_INTERNAL_ERROR[] = "Internal error";
+static const char EMSG_UNEXP_EOS[] = "Unexpected end of string";
+static const char EMSG_UNEXP_TOKEN[] = "Unexpected token";
+static const char EMSG_DIV_BY_ZERO[] = "Division by zero";
+static const char EMSG_INV_FMT[] = "Invalid format specifier";
+static const char EMSG_TOO_FEW_ARGS[] = "Too few arguments for builtin";
+static const char EMSG_NOT_ARRAY[] = "Not an array";
+static const char EMSG_POSSIBLE_ERROR[] = "Possible syntax error";
+static const char EMSG_UNDEF_FUNC[] = "Call to undefined function";
+#ifndef CONFIG_FEATURE_AWK_MATH
+static const char EMSG_NO_MATH[] = "Math support is not compiled in";
+#endif
+
+static void syntax_error(const char * const message) ATTRIBUTE_NORETURN;
+static void syntax_error(const char * const message)
+{
+	bb_error_msg_and_die("%s:%i: %s", programname, lineno, message);
+}
+
+#define runtime_error(x) syntax_error(x)
+
+
+/* ---- hash stuff ---- */
+
+static unsigned int hashidx(const char *name)
+{
+	register unsigned int idx=0;
+
+	while (*name)  idx = *name++ + (idx << 6) - idx;
+	return idx;
+}
+
+/* create new hash */
+static xhash *hash_init(void)
+{
+	xhash *newhash;
+
+	newhash = (xhash *)xzalloc(sizeof(xhash));
+	newhash->csize = FIRST_PRIME;
+	newhash->items = (hash_item **)xzalloc(newhash->csize * sizeof(hash_item *));
+
+	return newhash;
+}
+
+/* find item in hash, return ptr to data, NULL if not found */
+static void *hash_search(xhash *hash, const char *name)
+{
+	hash_item *hi;
+
+	hi = hash->items [ hashidx(name) % hash->csize ];
+	while (hi) {
+		if (strcmp(hi->name, name) == 0)
+			return &(hi->data);
+		hi = hi->next;
+	}
+	return NULL;
+}
+
+/* grow hash if it becomes too big */
+static void hash_rebuild(xhash *hash)
+{
+	unsigned int newsize, i, idx;
+	hash_item **newitems, *hi, *thi;
+
+	if (hash->nprime == NPRIMES)
+		return;
+
+	newsize = PRIMES[hash->nprime++];
+	newitems = (hash_item **)xzalloc(newsize * sizeof(hash_item *));
+
+	for (i=0; i<hash->csize; i++) {
+		hi = hash->items[i];
+		while (hi) {
+			thi = hi;
+			hi = thi->next;
+			idx = hashidx(thi->name) % newsize;
+			thi->next = newitems[idx];
+			newitems[idx] = thi;
+		}
+	}
+
+	free(hash->items);
+	hash->csize = newsize;
+	hash->items = newitems;
+}
+
+/* find item in hash, add it if necessary. Return ptr to data */
+static void *hash_find(xhash *hash, const char *name)
+{
+	hash_item *hi;
+	unsigned int idx;
+	int l;
+
+	hi = hash_search(hash, name);
+	if (! hi) {
+		if (++hash->nel / hash->csize > 10)
+			hash_rebuild(hash);
+
+		l = strlen(name) + 1;
+		hi = xzalloc(sizeof(hash_item) + l);
+		memcpy(hi->name, name, l);
+
+		idx = hashidx(name) % hash->csize;
+		hi->next = hash->items[idx];
+		hash->items[idx] = hi;
+		hash->glen += l;
+	}
+	return &(hi->data);
+}
+
+#define findvar(hash, name) (var *) hash_find ( (hash) , (name) )
+#define newvar(name) (var *) hash_find ( vhash , (name) )
+#define newfile(name) (rstream *) hash_find ( fdhash , (name) )
+#define newfunc(name) (func *) hash_find ( fnhash , (name) )
+
+static void hash_remove(xhash *hash, const char *name)
+{
+	hash_item *hi, **phi;
+
+	phi = &(hash->items[ hashidx(name) % hash->csize ]);
+	while (*phi) {
+		hi = *phi;
+		if (strcmp(hi->name, name) == 0) {
+			hash->glen -= (strlen(name) + 1);
+			hash->nel--;
+			*phi = hi->next;
+			free(hi);
+			break;
+		}
+		phi = &(hi->next);
+	}
+}
+
+/* ------ some useful functions ------ */
+
+static void skip_spaces(char **s)
+{
+	register char *p = *s;
+
+	while(*p == ' ' || *p == '\t' ||
+			(*p == '\\' && *(p+1) == '\n' && (++p, ++t.lineno))) {
+		p++;
+	}
+	*s = p;
+}
+
+static char *nextword(char **s)
+{
+	register char *p = *s;
+
+	while (*(*s)++) ;
+
+	return p;
+}
+
+static char nextchar(char **s)
+{
+	register char c, *pps;
+
+	c = *((*s)++);
+	pps = *s;
+	if (c == '\\') c = bb_process_escape_sequence((const char**)s);
+	if (c == '\\' && *s == pps) c = *((*s)++);
+	return c;
+}
+
+static inline int isalnum_(int c)
+{
+	return (isalnum(c) || c == '_');
+}
+
+static FILE *afopen(const char *path, const char *mode)
+{
+	return (*path == '-' && *(path+1) == '\0') ? stdin : bb_xfopen(path, mode);
+}
+
+/* -------- working with variables (set/get/copy/etc) -------- */
+
+static xhash *iamarray(var *v)
+{
+	var *a = v;
+
+	while (a->type & VF_CHILD)
+		a = a->x.parent;
+
+	if (! (a->type & VF_ARRAY)) {
+		a->type |= VF_ARRAY;
+		a->x.array = hash_init();
+	}
+	return a->x.array;
+}
+
+static void clear_array(xhash *array)
+{
+	unsigned int i;
+	hash_item *hi, *thi;
+
+	for (i=0; i<array->csize; i++) {
+		hi = array->items[i];
+		while (hi) {
+			thi = hi;
+			hi = hi->next;
+			free(thi->data.v.string);
+			free(thi);
+		}
+		array->items[i] = NULL;
+	}
+	array->glen = array->nel = 0;
+}
+
+/* clear a variable */
+static var *clrvar(var *v)
+{
+	if (!(v->type & VF_FSTR))
+		free(v->string);
+
+	v->type &= VF_DONTTOUCH;
+	v->type |= VF_DIRTY;
+	v->string = NULL;
+	return v;
+}
+
+/* assign string value to variable */
+static var *setvar_p(var *v, char *value)
+{
+	clrvar(v);
+	v->string = value;
+	handle_special(v);
+
+	return v;
+}
+
+/* same as setvar_p but make a copy of string */
+static var *setvar_s(var *v, const char *value)
+{
+	return setvar_p(v, (value && *value) ? bb_xstrdup(value) : NULL);
+}
+
+/* same as setvar_s but set USER flag */
+static var *setvar_u(var *v, const char *value)
+{
+	setvar_s(v, value);
+	v->type |= VF_USER;
+	return v;
+}
+
+/* set array element to user string */
+static void setari_u(var *a, int idx, const char *s)
+{
+	register var *v;
+	static char sidx[12];
+
+	sprintf(sidx, "%d", idx);
+	v = findvar(iamarray(a), sidx);
+	setvar_u(v, s);
+}
+
+/* assign numeric value to variable */
+static var *setvar_i(var *v, double value)
+{
+	clrvar(v);
+	v->type |= VF_NUMBER;
+	v->number = value;
+	handle_special(v);
+	return v;
+}
+
+static char *getvar_s(var *v)
+{
+	/* if v is numeric and has no cached string, convert it to string */
+	if ((v->type & (VF_NUMBER | VF_CACHED)) == VF_NUMBER) {
+		fmt_num(buf, MAXVARFMT, getvar_s(V[CONVFMT]), v->number, TRUE);
+		v->string = bb_xstrdup(buf);
+		v->type |= VF_CACHED;
+	}
+	return (v->string == NULL) ? "" : v->string;
+}
+
+static double getvar_i(var *v)
+{
+	char *s;
+
+	if ((v->type & (VF_NUMBER | VF_CACHED)) == 0) {
+		v->number = 0;
+		s = v->string;
+		if (s && *s) {
+			v->number = strtod(s, &s);
+			if (v->type & VF_USER) {
+				skip_spaces(&s);
+				if (*s != '\0')
+					v->type &= ~VF_USER;
+			}
+		} else {
+			v->type &= ~VF_USER;
+		}
+		v->type |= VF_CACHED;
+	}
+	return v->number;
+}
+
+static var *copyvar(var *dest, const var *src)
+{
+	if (dest != src) {
+		clrvar(dest);
+		dest->type |= (src->type & ~VF_DONTTOUCH);
+		dest->number = src->number;
+		if (src->string)
+			dest->string = bb_xstrdup(src->string);
+	}
+	handle_special(dest);
+	return dest;
+}
+
+static var *incvar(var *v)
+{
+	return setvar_i(v, getvar_i(v)+1.);
+}
+
+/* return true if v is number or numeric string */
+static int is_numeric(var *v)
+{
+	getvar_i(v);
+	return ((v->type ^ VF_DIRTY) & (VF_NUMBER | VF_USER | VF_DIRTY));
+}
+
+/* return 1 when value of v corresponds to true, 0 otherwise */
+static int istrue(var *v)
+{
+	if (is_numeric(v))
+		return (v->number == 0) ? 0 : 1;
+	else
+		return (v->string && *(v->string)) ? 1 : 0;
+}
+
+/* temporary variables allocator. Last allocated should be first freed */
+static var *nvalloc(int n)
+{
+	nvblock *pb = NULL;
+	var *v, *r;
+	int size;
+
+	while (cb) {
+		pb = cb;
+		if ((cb->pos - cb->nv) + n <= cb->size) break;
+		cb = cb->next;
+	}
+
+	if (! cb) {
+		size = (n <= MINNVBLOCK) ? MINNVBLOCK : n;
+		cb = (nvblock *)xmalloc(sizeof(nvblock) + size * sizeof(var));
+		cb->size = size;
+		cb->pos = cb->nv;
+		cb->prev = pb;
+		cb->next = NULL;
+		if (pb) pb->next = cb;
+	}
+
+	v = r = cb->pos;
+	cb->pos += n;
+
+	while (v < cb->pos) {
+		v->type = 0;
+		v->string = NULL;
+		v++;
+	}
+
+	return r;
+}
+
+static void nvfree(var *v)
+{
+	var *p;
+
+	if (v < cb->nv || v >= cb->pos)
+		runtime_error(EMSG_INTERNAL_ERROR);
+
+	for (p=v; p<cb->pos; p++) {
+		if ((p->type & (VF_ARRAY|VF_CHILD)) == VF_ARRAY) {
+			clear_array(iamarray(p));
+			free(p->x.array->items);
+			free(p->x.array);
+		}
+		if (p->type & VF_WALK)
+			free(p->x.walker);
+
+		clrvar(p);
+	}
+
+	cb->pos = v;
+	while (cb->prev && cb->pos == cb->nv) {
+		cb = cb->prev;
+	}
+}
+
+/* ------- awk program text parsing ------- */
+
+/* Parse next token pointed by global pos, place results into global t.
+ * If token isn't expected, give away. Return token class
+ */
+static uint32_t next_token(uint32_t expected)
+{
+	char *p, *pp, *s;
+	char *tl;
+	uint32_t tc;
+	const uint32_t *ti;
+	int l;
+	static int concat_inserted;
+	static uint32_t save_tclass, save_info;
+	static uint32_t ltclass = TC_OPTERM;
+
+	if (t.rollback) {
+
+		t.rollback = FALSE;
+
+	} else if (concat_inserted) {
+
+		concat_inserted = FALSE;
+		t.tclass = save_tclass;
+		t.info = save_info;
+
+	} else {
+
+		p = pos;
+
+	readnext:
+		skip_spaces(&p);
+		lineno = t.lineno;
+		if (*p == '#')
+			while (*p != '\n' && *p != '\0') p++;
+
+		if (*p == '\n')
+			t.lineno++;
+
+		if (*p == '\0') {
+			tc = TC_EOF;
+
+		} else if (*p == '\"') {
+			/* it's a string */
+			t.string = s = ++p;
+			while (*p != '\"') {
+				if (*p == '\0' || *p == '\n')
+					syntax_error(EMSG_UNEXP_EOS);
+				*(s++) = nextchar(&p);
+			}
+			p++;
+			*s = '\0';
+			tc = TC_STRING;
+
+		} else if ((expected & TC_REGEXP) && *p == '/') {
+			/* it's regexp */
+			t.string = s = ++p;
+			while (*p != '/') {
+				if (*p == '\0' || *p == '\n')
+					syntax_error(EMSG_UNEXP_EOS);
+				if ((*s++ = *p++) == '\\') {
+					pp = p;
+					*(s-1) = bb_process_escape_sequence((const char **)&p);
+					if (*pp == '\\') *s++ = '\\';
+					if (p == pp) *s++ = *p++;
+				}
+			}
+			p++;
+			*s = '\0';
+			tc = TC_REGEXP;
+
+		} else if (*p == '.' || isdigit(*p)) {
+			/* it's a number */
+			t.number = strtod(p, &p);
+			if (*p == '.')
+				syntax_error(EMSG_UNEXP_TOKEN);
+			tc = TC_NUMBER;
+
+		} else {
+			/* search for something known */
+			tl = tokenlist;
+			tc = 0x00000001;
+			ti = tokeninfo;
+			while (*tl) {
+				l = *(tl++);
+				if (l == NTCC) {
+					tc <<= 1;
+					continue;
+				}
+				/* if token class is expected, token
+				 * matches and it's not a longer word,
+				 * then this is what we are looking for
+				 */
+				if ((tc & (expected | TC_WORD | TC_NEWLINE)) &&
+				*tl == *p && strncmp(p, tl, l) == 0 &&
+				!((tc & TC_WORD) && isalnum_(*(p + l)))) {
+					t.info = *ti;
+					p += l;
+					break;
+				}
+				ti++;
+				tl += l;
+			}
+
+			if (! *tl) {
+				/* it's a name (var/array/function),
+				 * otherwise it's something wrong
+				 */
+				if (! isalnum_(*p))
+					syntax_error(EMSG_UNEXP_TOKEN);
+
+				t.string = --p;
+				while(isalnum_(*(++p))) {
+					*(p-1) = *p;
+				}
+				*(p-1) = '\0';
+				tc = TC_VARIABLE;
+				/* also consume whitespace between functionname and bracket */
+				if (! (expected & TC_VARIABLE)) skip_spaces(&p);
+				if (*p == '(') {
+					tc = TC_FUNCTION;
+				} else {
+					if (*p == '[') {
+						p++;
+						tc = TC_ARRAY;
+					}
+				}
+			}
+		}
+		pos = p;
+
+		/* skipping newlines in some cases */
+		if ((ltclass & TC_NOTERM) && (tc & TC_NEWLINE))
+			goto readnext;
+
+		/* insert concatenation operator when needed */
+		if ((ltclass&TC_CONCAT1) && (tc&TC_CONCAT2) && (expected&TC_BINOP)) {
+			concat_inserted = TRUE;
+			save_tclass = tc;
+			save_info = t.info;
+			tc = TC_BINOP;
+			t.info = OC_CONCAT | SS | P(35);
+		}
+
+		t.tclass = tc;
+	}
+	ltclass = t.tclass;
+
+	/* Are we ready for this? */
+	if (! (ltclass & expected))
+		syntax_error((ltclass & (TC_NEWLINE | TC_EOF)) ?
+								EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN);
+
+	return ltclass;
+}
+
+static void rollback_token(void) { t.rollback = TRUE; }
+
+static node *new_node(uint32_t info)
+{
+	register node *n;
+
+	n = (node *)xzalloc(sizeof(node));
+	n->info = info;
+	n->lineno = lineno;
+	return n;
+}
+
+static node *mk_re_node(char *s, node *n, regex_t *re)
+{
+	n->info = OC_REGEXP;
+	n->l.re = re;
+	n->r.ire = re + 1;
+	xregcomp(re, s, REG_EXTENDED);
+	xregcomp(re+1, s, REG_EXTENDED | REG_ICASE);
+
+	return n;
+}
+
+static node *condition(void)
+{
+	next_token(TC_SEQSTART);
+	return parse_expr(TC_SEQTERM);
+}
+
+/* parse expression terminated by given argument, return ptr
+ * to built subtree. Terminator is eaten by parse_expr */
+static node *parse_expr(uint32_t iexp)
+{
+	node sn;
+	node *cn = &sn;
+	node *vn, *glptr;
+	uint32_t tc, xtc;
+	var *v;
+
+	sn.info = PRIMASK;
+	sn.r.n = glptr = NULL;
+	xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp;
+
+	while (! ((tc = next_token(xtc)) & iexp)) {
+		if (glptr && (t.info == (OC_COMPARE|VV|P(39)|2))) {
+			/* input redirection (<) attached to glptr node */
+			cn = glptr->l.n = new_node(OC_CONCAT|SS|P(37));
+			cn->a.n = glptr;
+			xtc = TC_OPERAND | TC_UOPPRE;
+			glptr = NULL;
+
+		} else if (tc & (TC_BINOP | TC_UOPPOST)) {
+			/* for binary and postfix-unary operators, jump back over
+			 * previous operators with higher priority */
+			vn = cn;
+			while ( ((t.info & PRIMASK) > (vn->a.n->info & PRIMASK2)) ||
+			  ((t.info == vn->info) && ((t.info & OPCLSMASK) == OC_COLON)) )
+				vn = vn->a.n;
+			if ((t.info & OPCLSMASK) == OC_TERNARY)
+				t.info += P(6);
+			cn = vn->a.n->r.n = new_node(t.info);
+			cn->a.n = vn->a.n;
+			if (tc & TC_BINOP) {
+				cn->l.n = vn;
+				xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP;
+				if ((t.info & OPCLSMASK) == OC_PGETLINE) {
+					/* it's a pipe */
+					next_token(TC_GETLINE);
+					/* give maximum priority to this pipe */
+					cn->info &= ~PRIMASK;
+					xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp;
+				}
+			} else {
+				cn->r.n = vn;
+				xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp;
+			}
+			vn->a.n = cn;
+
+		} else {
+			/* for operands and prefix-unary operators, attach them
+			 * to last node */
+			vn = cn;
+			cn = vn->r.n = new_node(t.info);
+			cn->a.n = vn;
+			xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP;
+			if (tc & (TC_OPERAND | TC_REGEXP)) {
+				xtc = TC_UOPPRE | TC_UOPPOST | TC_BINOP | TC_OPERAND | iexp;
+				/* one should be very careful with switch on tclass -
+				 * only simple tclasses should be used! */
+				switch (tc) {
+				  case TC_VARIABLE:
+				  case TC_ARRAY:
+					cn->info = OC_VAR;
+					if ((v = hash_search(ahash, t.string)) != NULL) {
+						cn->info = OC_FNARG;
+						cn->l.i = v->x.aidx;
+					} else {
+						cn->l.v = newvar(t.string);
+					}
+					if (tc & TC_ARRAY) {
+						cn->info |= xS;
+						cn->r.n = parse_expr(TC_ARRTERM);
+					}
+					break;
+
+				  case TC_NUMBER:
+				  case TC_STRING:
+					cn->info = OC_VAR;
+					v = cn->l.v = xzalloc(sizeof(var));
+					if (tc & TC_NUMBER)
+						setvar_i(v, t.number);
+					else
+						setvar_s(v, t.string);
+					break;
+
+				  case TC_REGEXP:
+					mk_re_node(t.string, cn,
+									(regex_t *)xzalloc(sizeof(regex_t)*2));
+					break;
+
+				  case TC_FUNCTION:
+					cn->info = OC_FUNC;
+					cn->r.f = newfunc(t.string);
+					cn->l.n = condition();
+					break;
+
+				  case TC_SEQSTART:
+					cn = vn->r.n = parse_expr(TC_SEQTERM);
+					cn->a.n = vn;
+					break;
+
+				  case TC_GETLINE:
+					glptr = cn;
+					xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp;
+					break;
+
+				  case TC_BUILTIN:
+					cn->l.n = condition();
+					break;
+				}
+			}
+		}
+	}
+	return sn.r.n;
+}
+
+/* add node to chain. Return ptr to alloc'd node */
+static node *chain_node(uint32_t info)
+{
+	register node *n;
+
+	if (! seq->first)
+		seq->first = seq->last = new_node(0);
+
+	if (seq->programname != programname) {
+		seq->programname = programname;
+		n = chain_node(OC_NEWSOURCE);
+		n->l.s = bb_xstrdup(programname);
+	}
+
+	n = seq->last;
+	n->info = info;
+	seq->last = n->a.n = new_node(OC_DONE);
+
+	return n;
+}
+
+static void chain_expr(uint32_t info)
+{
+	node *n;
+
+	n = chain_node(info);
+	n->l.n = parse_expr(TC_OPTERM | TC_GRPTERM);
+	if (t.tclass & TC_GRPTERM)
+		rollback_token();
+}
+
+static node *chain_loop(node *nn)
+{
+	node *n, *n2, *save_brk, *save_cont;
+
+	save_brk = break_ptr;
+	save_cont = continue_ptr;
+
+	n = chain_node(OC_BR | Vx);
+	continue_ptr = new_node(OC_EXEC);
+	break_ptr = new_node(OC_EXEC);
+	chain_group();
+	n2 = chain_node(OC_EXEC | Vx);
+	n2->l.n = nn;
+	n2->a.n = n;
+	continue_ptr->a.n = n2;
+	break_ptr->a.n = n->r.n = seq->last;
+
+	continue_ptr = save_cont;
+	break_ptr = save_brk;
+
+	return n;
+}
+
+/* parse group and attach it to chain */
+static void chain_group(void)
+{
+	uint32_t c;
+	node *n, *n2, *n3;
+
+	do {
+		c = next_token(TC_GRPSEQ);
+	} while (c & TC_NEWLINE);
+
+	if (c & TC_GRPSTART) {
+		while(next_token(TC_GRPSEQ | TC_GRPTERM) != TC_GRPTERM) {
+			if (t.tclass & TC_NEWLINE) continue;
+			rollback_token();
+			chain_group();
+		}
+	} else if (c & (TC_OPSEQ | TC_OPTERM)) {
+		rollback_token();
+		chain_expr(OC_EXEC | Vx);
+	} else {						/* TC_STATEMNT */
+		switch (t.info & OPCLSMASK) {
+			case ST_IF:
+				n = chain_node(OC_BR | Vx);
+				n->l.n = condition();
+				chain_group();
+				n2 = chain_node(OC_EXEC);
+				n->r.n = seq->last;
+				if (next_token(TC_GRPSEQ | TC_GRPTERM | TC_ELSE)==TC_ELSE) {
+					chain_group();
+					n2->a.n = seq->last;
+				} else {
+					rollback_token();
+				}
+				break;
+
+			case ST_WHILE:
+				n2 = condition();
+				n = chain_loop(NULL);
+				n->l.n = n2;
+				break;
+
+			case ST_DO:
+				n2 = chain_node(OC_EXEC);
+				n = chain_loop(NULL);
+				n2->a.n = n->a.n;
+				next_token(TC_WHILE);
+				n->l.n = condition();
+				break;
+
+			case ST_FOR:
+				next_token(TC_SEQSTART);
+				n2 = parse_expr(TC_SEMICOL | TC_SEQTERM);
+				if (t.tclass & TC_SEQTERM) {				/* for-in */
+					if ((n2->info & OPCLSMASK) != OC_IN)
+						syntax_error(EMSG_UNEXP_TOKEN);
+					n = chain_node(OC_WALKINIT | VV);
+					n->l.n = n2->l.n;
+					n->r.n = n2->r.n;
+					n = chain_loop(NULL);
+					n->info = OC_WALKNEXT | Vx;
+					n->l.n = n2->l.n;
+				} else {									/* for(;;) */
+					n = chain_node(OC_EXEC | Vx);
+					n->l.n = n2;
+					n2 = parse_expr(TC_SEMICOL);
+					n3 = parse_expr(TC_SEQTERM);
+					n = chain_loop(n3);
+					n->l.n = n2;
+					if (! n2)
+						n->info = OC_EXEC;
+				}
+				break;
+
+			case OC_PRINT:
+			case OC_PRINTF:
+				n = chain_node(t.info);
+				n->l.n = parse_expr(TC_OPTERM | TC_OUTRDR | TC_GRPTERM);
+				if (t.tclass & TC_OUTRDR) {
+					n->info |= t.info;
+					n->r.n = parse_expr(TC_OPTERM | TC_GRPTERM);
+				}
+				if (t.tclass & TC_GRPTERM)
+					rollback_token();
+				break;
+
+			case OC_BREAK:
+				n = chain_node(OC_EXEC);
+				n->a.n = break_ptr;
+				break;
+
+			case OC_CONTINUE:
+				n = chain_node(OC_EXEC);
+				n->a.n = continue_ptr;
+				break;
+
+			/* delete, next, nextfile, return, exit */
+			default:
+				chain_expr(t.info);
+
+		}
+	}
+}
+
+static void parse_program(char *p)
+{
+	uint32_t tclass;
+	node *cn;
+	func *f;
+	var *v;
+
+	pos = p;
+	t.lineno = 1;
+	while((tclass = next_token(TC_EOF | TC_OPSEQ | TC_GRPSTART |
+				TC_OPTERM | TC_BEGIN | TC_END | TC_FUNCDECL)) != TC_EOF) {
+
+		if (tclass & TC_OPTERM)
+			continue;
+
+		seq = &mainseq;
+		if (tclass & TC_BEGIN) {
+			seq = &beginseq;
+			chain_group();
+
+		} else if (tclass & TC_END) {
+			seq = &endseq;
+			chain_group();
+
+		} else if (tclass & TC_FUNCDECL) {
+			next_token(TC_FUNCTION);
+			pos++;
+			f = newfunc(t.string);
+			f->body.first = NULL;
+			f->nargs = 0;
+			while(next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) {
+				v = findvar(ahash, t.string);
+				v->x.aidx = (f->nargs)++;
+
+				if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM)
+					break;
+			}
+			seq = &(f->body);
+			chain_group();
+			clear_array(ahash);
+
+		} else if (tclass & TC_OPSEQ) {
+			rollback_token();
+			cn = chain_node(OC_TEST);
+			cn->l.n = parse_expr(TC_OPTERM | TC_EOF | TC_GRPSTART);
+			if (t.tclass & TC_GRPSTART) {
+				rollback_token();
+				chain_group();
+			} else {
+				chain_node(OC_PRINT);
+			}
+			cn->r.n = mainseq.last;
+
+		} else /* if (tclass & TC_GRPSTART) */ {
+			rollback_token();
+			chain_group();
+		}
+	}
+}
+
+
+/* -------- program execution part -------- */
+
+static node *mk_splitter(char *s, tsplitter *spl)
+{
+	register regex_t *re, *ire;
+	node *n;
+
+	re = &spl->re[0];
+	ire = &spl->re[1];
+	n = &spl->n;
+	if ((n->info && OPCLSMASK) == OC_REGEXP) {
+		regfree(re);
+		regfree(ire);
+	}
+	if (strlen(s) > 1) {
+		mk_re_node(s, n, re);
+	} else {
+		n->info = (uint32_t) *s;
+	}
+
+	return n;
+}
+
+/* use node as a regular expression. Supplied with node ptr and regex_t
+ * storage space. Return ptr to regex (if result points to preg, it should
+ * be later regfree'd manually
+ */
+static regex_t *as_regex(node *op, regex_t *preg)
+{
+	var *v;
+	char *s;
+
+	if ((op->info & OPCLSMASK) == OC_REGEXP) {
+		return icase ? op->r.ire : op->l.re;
+	} else {
+		v = nvalloc(1);
+		s = getvar_s(evaluate(op, v));
+		xregcomp(preg, s, icase ? REG_EXTENDED | REG_ICASE : REG_EXTENDED);
+		nvfree(v);
+		return preg;
+	}
+}
+
+/* gradually increasing buffer */
+static void qrealloc(char **b, int n, int *size)
+{
+	if (! *b || n >= *size)
+		*b = xrealloc(*b, *size = n + (n>>1) + 80);
+}
+
+/* resize field storage space */
+static void fsrealloc(int size)
+{
+	static int maxfields = 0;
+	int i;
+
+	if (size >= maxfields) {
+		i = maxfields;
+		maxfields = size + 16;
+		Fields = (var *)xrealloc(Fields, maxfields * sizeof(var));
+		for (; i<maxfields; i++) {
+			Fields[i].type = VF_SPECIAL;
+			Fields[i].string = NULL;
+		}
+	}
+
+	if (size < nfields) {
+		for (i=size; i<nfields; i++) {
+			clrvar(Fields+i);
+		}
+	}
+	nfields = size;
+}
+
+static int awk_split(char *s, node *spl, char **slist)
+{
+	int l, n=0;
+	char c[4];
+	char *s1;
+	regmatch_t pmatch[2];
+
+	/* in worst case, each char would be a separate field */
+	*slist = s1 = bb_xstrndup(s, strlen(s) * 2 + 3);
+
+	c[0] = c[1] = (char)spl->info;
+	c[2] = c[3] = '\0';
+	if (*getvar_s(V[RS]) == '\0') c[2] = '\n';
+
+	if ((spl->info & OPCLSMASK) == OC_REGEXP) {		/* regex split */
+		while (*s) {
+			l = strcspn(s, c+2);
+			if (regexec(icase ? spl->r.ire : spl->l.re, s, 1, pmatch, 0) == 0 &&
+			pmatch[0].rm_so <= l) {
+				l = pmatch[0].rm_so;
+				if (pmatch[0].rm_eo == 0) { l++; pmatch[0].rm_eo++; }
+			} else {
+				pmatch[0].rm_eo = l;
+				if (*(s+l)) pmatch[0].rm_eo++;
+			}
+
+			memcpy(s1, s, l);
+			*(s1+l) = '\0';
+			nextword(&s1);
+			s += pmatch[0].rm_eo;
+			n++;
+		}
+	} else if (c[0] == '\0') {		/* null split */
+		while(*s) {
+			*(s1++) = *(s++);
+			*(s1++) = '\0';
+			n++;
+		}
+	} else if (c[0] != ' ') {		/* single-character split */
+		if (icase) {
+			c[0] = toupper(c[0]);
+			c[1] = tolower(c[1]);
+		}
+		if (*s1) n++;
+		while ((s1 = strpbrk(s1, c))) {
+			*(s1++) = '\0';
+			n++;
+		}
+	} else {				/* space split */
+		while (*s) {
+			while (isspace(*s)) s++;
+			if (! *s) break;
+			n++;
+			while (*s && !isspace(*s))
+				*(s1++) = *(s++);
+			*(s1++) = '\0';
+		}
+	}
+	return n;
+}
+
+static void split_f0(void)
+{
+	static char *fstrings = NULL;
+	int i, n;
+	char *s;
+
+	if (is_f0_split)
+		return;
+
+	is_f0_split = TRUE;
+	free(fstrings);
+	fsrealloc(0);
+	n = awk_split(getvar_s(V[F0]), &fsplitter.n, &fstrings);
+	fsrealloc(n);
+	s = fstrings;
+	for (i=0; i<n; i++) {
+		Fields[i].string = nextword(&s);
+		Fields[i].type |= (VF_FSTR | VF_USER | VF_DIRTY);
+	}
+
+	/* set NF manually to avoid side effects */
+	clrvar(V[NF]);
+	V[NF]->type = VF_NUMBER | VF_SPECIAL;
+	V[NF]->number = nfields;
+}
+
+/* perform additional actions when some internal variables changed */
+static void handle_special(var *v)
+{
+	int n;
+	char *b, *sep, *s;
+	int sl, l, len, i, bsize;
+
+	if (! (v->type & VF_SPECIAL))
+		return;
+
+	if (v == V[NF]) {
+		n = (int)getvar_i(v);
+		fsrealloc(n);
+
+		/* recalculate $0 */
+		sep = getvar_s(V[OFS]);
+		sl = strlen(sep);
+		b = NULL;
+		len = 0;
+		for (i=0; i<n; i++) {
+			s = getvar_s(&Fields[i]);
+			l = strlen(s);
+			if (b) {
+				memcpy(b+len, sep, sl);
+				len += sl;
+			}
+			qrealloc(&b, len+l+sl, &bsize);
+			memcpy(b+len, s, l);
+			len += l;
+		}
+		if (b) b[len] = '\0';
+		setvar_p(V[F0], b);
+		is_f0_split = TRUE;
+
+	} else if (v == V[F0]) {
+		is_f0_split = FALSE;
+
+	} else if (v == V[FS]) {
+		mk_splitter(getvar_s(v), &fsplitter);
+
+	} else if (v == V[RS]) {
+		mk_splitter(getvar_s(v), &rsplitter);
+
+	} else if (v == V[IGNORECASE]) {
+		icase = istrue(v);
+
+	} else {						/* $n */
+		n = getvar_i(V[NF]);
+		setvar_i(V[NF], n > v-Fields ? n : v-Fields+1);
+		/* right here v is invalid. Just to note... */
+	}
+}
+
+/* step through func/builtin/etc arguments */
+static node *nextarg(node **pn)
+{
+	node *n;
+
+	n = *pn;
+	if (n && (n->info & OPCLSMASK) == OC_COMMA) {
+		*pn = n->r.n;
+		n = n->l.n;
+	} else {
+		*pn = NULL;
+	}
+	return n;
+}
+
+static void hashwalk_init(var *v, xhash *array)
+{
+	char **w;
+	hash_item *hi;
+	int i;
+
+	if (v->type & VF_WALK)
+		free(v->x.walker);
+
+	v->type |= VF_WALK;
+	w = v->x.walker = (char **)xzalloc(2 + 2*sizeof(char *) + array->glen);
+	*w = *(w+1) = (char *)(w + 2);
+	for (i=0; i<array->csize; i++) {
+		hi = array->items[i];
+		while(hi) {
+			strcpy(*w, hi->name);
+			nextword(w);
+			hi = hi->next;
+		}
+	}
+}
+
+static int hashwalk_next(var *v)
+{
+	char **w;
+
+	w = v->x.walker;
+	if (*(w+1) == *w)
+		return FALSE;
+
+	setvar_s(v, nextword(w+1));
+	return TRUE;
+}
+
+/* evaluate node, return 1 when result is true, 0 otherwise */
+static int ptest(node *pattern)
+{
+	static var v;
+	return istrue(evaluate(pattern, &v));
+}
+
+/* read next record from stream rsm into a variable v */
+static int awk_getline(rstream *rsm, var *v)
+{
+	char *b;
+	regmatch_t pmatch[2];
+	int a, p, pp=0, size;
+	int fd, so, eo, r, rp;
+	char c, *m, *s;
+
+	/* we're using our own buffer since we need access to accumulating
+	 * characters
+	 */
+	fd = fileno(rsm->F);
+	m = rsm->buffer;
+	a = rsm->adv;
+	p = rsm->pos;
+	size = rsm->size;
+	c = (char) rsplitter.n.info;
+	rp = 0;
+
+	if (! m) qrealloc(&m, 256, &size);
+	do {
+		b = m + a;
+		so = eo = p;
+		r = 1;
+		if (p > 0) {
+			if ((rsplitter.n.info & OPCLSMASK) == OC_REGEXP) {
+				if (regexec(icase ? rsplitter.n.r.ire : rsplitter.n.l.re,
+												b, 1, pmatch, 0) == 0) {
+					so = pmatch[0].rm_so;
+					eo = pmatch[0].rm_eo;
+					if (b[eo] != '\0')
+						break;
+				}
+			} else if (c != '\0') {
+				s = strchr(b+pp, c);
+				if (! s) s = memchr(b+pp, '\0', p - pp);
+				if (s) {
+					so = eo = s-b;
+					eo++;
+					break;
+				}
+			} else {
+				while (b[rp] == '\n')
+					rp++;
+				s = strstr(b+rp, "\n\n");
+				if (s) {
+					so = eo = s-b;
+					while (b[eo] == '\n') eo++;
+					if (b[eo] != '\0')
+						break;
+				}
+			}
+		}
+
+		if (a > 0) {
+			memmove(m, (const void *)(m+a), p+1);
+			b = m;
+			a = 0;
+		}
+
+		qrealloc(&m, a+p+128, &size);
+		b = m + a;
+		pp = p;
+		p += safe_read(fd, b+p, size-p-1);
+		if (p < pp) {
+			p = 0;
+			r = 0;
+			setvar_i(V[ERRNO], errno);
+		}
+		b[p] = '\0';
+
+	} while (p > pp);
+
+	if (p == 0) {
+		r--;
+	} else {
+		c = b[so]; b[so] = '\0';
+		setvar_s(v, b+rp);
+		v->type |= VF_USER;
+		b[so] = c;
+		c = b[eo]; b[eo] = '\0';
+		setvar_s(V[RT], b+so);
+		b[eo] = c;
+	}
+
+	rsm->buffer = m;
+	rsm->adv = a + eo;
+	rsm->pos = p - eo;
+	rsm->size = size;
+
+	return r;
+}
+
+static int fmt_num(char *b, int size, const char *format, double n, int int_as_int)
+{
+	int r=0;
+	char c;
+	const char *s=format;
+
+	if (int_as_int && n == (int)n) {
+		r = snprintf(b, size, "%d", (int)n);
+	} else {
+		do { c = *s; } while (*s && *++s);
+		if (strchr("diouxX", c)) {
+			r = snprintf(b, size, format, (int)n);
+		} else if (strchr("eEfgG", c)) {
+			r = snprintf(b, size, format, n);
+		} else {
+			runtime_error(EMSG_INV_FMT);
+		}
+	}
+	return r;
+}
+
+
+/* formatted output into an allocated buffer, return ptr to buffer */
+static char *awk_printf(node *n)
+{
+	char *b = NULL;
+	char *fmt, *s, *s1, *f;
+	int i, j, incr, bsize;
+	char c, c1;
+	var *v, *arg;
+
+	v = nvalloc(1);
+	fmt = f = bb_xstrdup(getvar_s(evaluate(nextarg(&n), v)));
+
+	i = 0;
+	while (*f) {
+		s = f;
+		while (*f && (*f != '%' || *(++f) == '%'))
+			f++;
+		while (*f && !isalpha(*f))
+			f++;
+
+		incr = (f - s) + MAXVARFMT;
+		qrealloc(&b, incr+i, &bsize);
+		c = *f; if (c != '\0') f++;
+		c1 = *f ; *f = '\0';
+		arg = evaluate(nextarg(&n), v);
+
+		j = i;
+		if (c == 'c' || !c) {
+			i += sprintf(b+i, s,
+					is_numeric(arg) ? (char)getvar_i(arg) : *getvar_s(arg));
+
+		} else if (c == 's') {
+		    s1 = getvar_s(arg);
+			qrealloc(&b, incr+i+strlen(s1), &bsize);
+			i += sprintf(b+i, s, s1);
+
+		} else {
+			i += fmt_num(b+i, incr, s, getvar_i(arg), FALSE);
+		}
+		*f = c1;
+
+		/* if there was an error while sprintf, return value is negative */
+		if (i < j) i = j;
+
+	}
+
+	b = xrealloc(b, i+1);
+	free(fmt);
+	nvfree(v);
+	b[i] = '\0';
+	return b;
+}
+
+/* common substitution routine
+ * replace (nm) substring of (src) that match (n) with (repl), store
+ * result into (dest), return number of substitutions. If nm=0, replace
+ * all matches. If src or dst is NULL, use $0. If ex=TRUE, enable
+ * subexpression matching (\1-\9)
+ */
+static int awk_sub(node *rn, char *repl, int nm, var *src, var *dest, int ex)
+{
+	char *ds = NULL;
+	char *sp, *s;
+	int c, i, j, di, rl, so, eo, nbs, n, dssize;
+	regmatch_t pmatch[10];
+	regex_t sreg, *re;
+
+	re = as_regex(rn, &sreg);
+	if (! src) src = V[F0];
+	if (! dest) dest = V[F0];
+
+	i = di = 0;
+	sp = getvar_s(src);
+	rl = strlen(repl);
+	while (regexec(re, sp, 10, pmatch, sp==getvar_s(src) ? 0:REG_NOTBOL) == 0) {
+		so = pmatch[0].rm_so;
+		eo = pmatch[0].rm_eo;
+
+		qrealloc(&ds, di + eo + rl, &dssize);
+		memcpy(ds + di, sp, eo);
+		di += eo;
+		if (++i >= nm) {
+			/* replace */
+			di -= (eo - so);
+			nbs = 0;
+			for (s = repl; *s; s++) {
+				ds[di++] = c = *s;
+				if (c == '\\') {
+					nbs++;
+					continue;
+				}
+				if (c == '&' || (ex && c >= '0' && c <= '9')) {
+					di -= ((nbs + 3) >> 1);
+					j = 0;
+					if (c != '&') {
+						j = c - '0';
+						nbs++;
+					}
+					if (nbs % 2) {
+						ds[di++] = c;
+					} else {
+						n = pmatch[j].rm_eo - pmatch[j].rm_so;
+						qrealloc(&ds, di + rl + n, &dssize);
+						memcpy(ds + di, sp + pmatch[j].rm_so, n);
+						di += n;
+					}
+				}
+				nbs = 0;
+			}
+		}
+
+		sp += eo;
+		if (i == nm) break;
+		if (eo == so) {
+			if (! (ds[di++] = *sp++)) break;
+		}
+	}
+
+	qrealloc(&ds, di + strlen(sp), &dssize);
+	strcpy(ds + di, sp);
+	setvar_p(dest, ds);
+	if (re == &sreg) regfree(re);
+	return i;
+}
+
+static var *exec_builtin(node *op, var *res)
+{
+	int (*to_xxx)(int);
+	var *tv;
+	node *an[4];
+	var  *av[4];
+	char *as[4];
+	regmatch_t pmatch[2];
+	regex_t sreg, *re;
+	static tsplitter tspl;
+	node *spl;
+	uint32_t isr, info;
+	int nargs;
+	time_t tt;
+	char *s, *s1;
+	int i, l, ll, n;
+
+	tv = nvalloc(4);
+	isr = info = op->info;
+	op = op->l.n;
+
+	av[2] = av[3] = NULL;
+	for (i=0 ; i<4 && op ; i++) {
+		an[i] = nextarg(&op);
+		if (isr & 0x09000000) av[i] = evaluate(an[i], &tv[i]);
+		if (isr & 0x08000000) as[i] = getvar_s(av[i]);
+		isr >>= 1;
+	}
+
+	nargs = i;
+	if (nargs < (info >> 30))
+		runtime_error(EMSG_TOO_FEW_ARGS);
+
+	switch (info & OPNMASK) {
+
+	  case B_a2:
+#ifdef CONFIG_FEATURE_AWK_MATH
+		setvar_i(res, atan2(getvar_i(av[i]), getvar_i(av[1])));
+#else
+		runtime_error(EMSG_NO_MATH);
+#endif
+		break;
+
+	  case B_sp:
+		if (nargs > 2) {
+			spl = (an[2]->info & OPCLSMASK) == OC_REGEXP ?
+				an[2] : mk_splitter(getvar_s(evaluate(an[2], &tv[2])), &tspl);
+		} else {
+			spl = &fsplitter.n;
+		}
+
+		n = awk_split(as[0], spl, &s);
+		s1 = s;
+		clear_array(iamarray(av[1]));
+		for (i=1; i<=n; i++)
+			setari_u(av[1], i, nextword(&s1));
+		free(s);
+		setvar_i(res, n);
+		break;
+
+	  case B_ss:
+		l = strlen(as[0]);
+		i = getvar_i(av[1]) - 1;
+		if (i>l) i=l; if (i<0) i=0;
+		n = (nargs > 2) ? getvar_i(av[2]) : l-i;
+		if (n<0) n=0;
+		s = xmalloc(n+1);
+		strncpy(s, as[0]+i, n);
+		s[n] = '\0';
+		setvar_p(res, s);
+		break;
+
+	  case B_lo:
+		to_xxx = tolower;
+		goto lo_cont;
+
+	  case B_up:
+		to_xxx = toupper;
+lo_cont:
+		s1 = s = bb_xstrdup(as[0]);
+		while (*s1) {
+			*s1 = (*to_xxx)(*s1);
+			s1++;
+		}
+		setvar_p(res, s);
+		break;
+
+	  case B_ix:
+		n = 0;
+		ll = strlen(as[1]);
+		l = strlen(as[0]) - ll;
+		if (ll > 0 && l >= 0) {
+			if (! icase) {
+				s = strstr(as[0], as[1]);
+				if (s) n = (s - as[0]) + 1;
+			} else {
+				/* this piece of code is terribly slow and
+				 * really should be rewritten
+				 */
+				for (i=0; i<=l; i++) {
+					if (strncasecmp(as[0]+i, as[1], ll) == 0) {
+						n = i+1;
+						break;
+					}
+				}
+			}
+		}
+		setvar_i(res, n);
+		break;
+
+	  case B_ti:
+		if (nargs > 1)
+			tt = getvar_i(av[1]);
+		else
+			time(&tt);
+		s = (nargs > 0) ? as[0] : "%a %b %d %H:%M:%S %Z %Y";
+		i = strftime(buf, MAXVARFMT, s, localtime(&tt));
+		buf[i] = '\0';
+		setvar_s(res, buf);
+		break;
+
+	  case B_ma:
+		re = as_regex(an[1], &sreg);
+		n = regexec(re, as[0], 1, pmatch, 0);
+		if (n == 0) {
+			pmatch[0].rm_so++;
+			pmatch[0].rm_eo++;
+		} else {
+			pmatch[0].rm_so = 0;
+			pmatch[0].rm_eo = -1;
+		}
+		setvar_i(newvar("RSTART"), pmatch[0].rm_so);
+		setvar_i(newvar("RLENGTH"), pmatch[0].rm_eo - pmatch[0].rm_so);
+		setvar_i(res, pmatch[0].rm_so);
+		if (re == &sreg) regfree(re);
+		break;
+
+	  case B_ge:
+		awk_sub(an[0], as[1], getvar_i(av[2]), av[3], res, TRUE);
+		break;
+
+	  case B_gs:
+		setvar_i(res, awk_sub(an[0], as[1], 0, av[2], av[2], FALSE));
+		break;
+
+	  case B_su:
+		setvar_i(res, awk_sub(an[0], as[1], 1, av[2], av[2], FALSE));
+		break;
+	}
+
+	nvfree(tv);
+	return res;
+}
+
+/*
+ * Evaluate node - the heart of the program. Supplied with subtree
+ * and place where to store result. returns ptr to result.
+ */
+#define XC(n) ((n) >> 8)
+
+static var *evaluate(node *op, var *res)
+{
+	/* This procedure is recursive so we should count every byte */
+	static var *fnargs = NULL;
+	static unsigned int seed = 1;
+	static regex_t sreg;
+	node *op1;
+	var *v1;
+	union {
+		var *v;
+		char *s;
+		double d;
+		int i;
+	} L, R;
+	uint32_t opinfo;
+	short opn;
+	union {
+		char *s;
+		rstream *rsm;
+		FILE *F;
+		var *v;
+		regex_t *re;
+		uint32_t info;
+	} X;
+
+	if (! op)
+		return setvar_s(res, NULL);
+
+	v1 = nvalloc(2);
+
+	while (op) {
+
+		opinfo = op->info;
+		opn = (short)(opinfo & OPNMASK);
+		lineno = op->lineno;
+
+		/* execute inevitable things */
+		op1 = op->l.n;
+		if (opinfo & OF_RES1) X.v = L.v = evaluate(op1, v1);
+		if (opinfo & OF_RES2) R.v = evaluate(op->r.n, v1+1);
+		if (opinfo & OF_STR1) L.s = getvar_s(L.v);
+		if (opinfo & OF_STR2) R.s = getvar_s(R.v);
+		if (opinfo & OF_NUM1) L.d = getvar_i(L.v);
+
+		switch (XC(opinfo & OPCLSMASK)) {
+
+		  /* -- iterative node type -- */
+
+		  /* test pattern */
+		  case XC( OC_TEST ):
+			if ((op1->info & OPCLSMASK) == OC_COMMA) {
+				/* it's range pattern */
+				if ((opinfo & OF_CHECKED) || ptest(op1->l.n)) {
+					op->info |= OF_CHECKED;
+					if (ptest(op1->r.n))
+						op->info &= ~OF_CHECKED;
+
+					op = op->a.n;
+				} else {
+					op = op->r.n;
+				}
+			} else {
+				op = (ptest(op1)) ? op->a.n : op->r.n;
+			}
+			break;
+
+		  /* just evaluate an expression, also used as unconditional jump */
+		  case XC( OC_EXEC ):
+			break;
+
+		  /* branch, used in if-else and various loops */
+		  case XC( OC_BR ):
+			op = istrue(L.v) ? op->a.n : op->r.n;
+			break;
+
+		  /* initialize for-in loop */
+		  case XC( OC_WALKINIT ):
+			hashwalk_init(L.v, iamarray(R.v));
+			break;
+
+		  /* get next array item */
+		  case XC( OC_WALKNEXT ):
+			op = hashwalk_next(L.v) ? op->a.n : op->r.n;
+			break;
+
+		  case XC( OC_PRINT ):
+		  case XC( OC_PRINTF ):
+			X.F = stdout;
+			if (op->r.n) {
+				X.rsm = newfile(R.s);
+				if (! X.rsm->F) {
+					if (opn == '|') {
+						if((X.rsm->F = popen(R.s, "w")) == NULL)
+							bb_perror_msg_and_die("popen");
+						X.rsm->is_pipe = 1;
+					} else {
+						X.rsm->F = bb_xfopen(R.s, opn=='w' ? "w" : "a");
+					}
+				}
+				X.F = X.rsm->F;
+			}
+
+			if ((opinfo & OPCLSMASK) == OC_PRINT) {
+				if (! op1) {
+					fputs(getvar_s(V[F0]), X.F);
+				} else {
+					while (op1) {
+						L.v = evaluate(nextarg(&op1), v1);
+						if (L.v->type & VF_NUMBER) {
+							fmt_num(buf, MAXVARFMT, getvar_s(V[OFMT]),
+														getvar_i(L.v), TRUE);
+							fputs(buf, X.F);
+						} else {
+							fputs(getvar_s(L.v), X.F);
+						}
+
+						if (op1) fputs(getvar_s(V[OFS]), X.F);
+					}
+				}
+				fputs(getvar_s(V[ORS]), X.F);
+
+			} else {	/* OC_PRINTF */
+				L.s = awk_printf(op1);
+				fputs(L.s, X.F);
+				free(L.s);
+			}
+			fflush(X.F);
+			break;
+
+		  case XC( OC_DELETE ):
+			X.info = op1->info & OPCLSMASK;
+			if (X.info == OC_VAR) {
+				R.v = op1->l.v;
+			} else if (X.info == OC_FNARG) {
+				R.v = &fnargs[op1->l.i];
+			} else {
+				runtime_error(EMSG_NOT_ARRAY);
+			}
+
+			if (op1->r.n) {
+				clrvar(L.v);
+				L.s = getvar_s(evaluate(op1->r.n, v1));
+				hash_remove(iamarray(R.v), L.s);
+			} else {
+				clear_array(iamarray(R.v));
+			}
+			break;
+
+		  case XC( OC_NEWSOURCE ):
+			programname = op->l.s;
+			break;
+
+		  case XC( OC_RETURN ):
+			copyvar(res, L.v);
+			break;
+
+		  case XC( OC_NEXTFILE ):
+			nextfile = TRUE;
+		  case XC( OC_NEXT ):
+			nextrec = TRUE;
+		  case XC( OC_DONE ):
+			clrvar(res);
+			break;
+
+		  case XC( OC_EXIT ):
+			awk_exit(L.d);
+
+		  /* -- recursive node type -- */
+
+		  case XC( OC_VAR ):
+			L.v = op->l.v;
+			if (L.v == V[NF])
+				split_f0();
+			goto v_cont;
+
+		  case XC( OC_FNARG ):
+			L.v = &fnargs[op->l.i];
+
+v_cont:
+			res = (op->r.n) ? findvar(iamarray(L.v), R.s) : L.v;
+			break;
+
+		  case XC( OC_IN ):
+			setvar_i(res, hash_search(iamarray(R.v), L.s) ? 1 : 0);
+			break;
+
+		  case XC( OC_REGEXP ):
+			op1 = op;
+			L.s = getvar_s(V[F0]);
+			goto re_cont;
+
+		  case XC( OC_MATCH ):
+			op1 = op->r.n;
+re_cont:
+			X.re = as_regex(op1, &sreg);
+			R.i = regexec(X.re, L.s, 0, NULL, 0);
+			if (X.re == &sreg) regfree(X.re);
+			setvar_i(res, (R.i == 0 ? 1 : 0) ^ (opn == '!' ? 1 : 0));
+			break;
+
+		  case XC( OC_MOVE ):
+			/* if source is a temporary string, jusk relink it to dest */
+			if (R.v == v1+1 && R.v->string) {
+				res = setvar_p(L.v, R.v->string);
+				R.v->string = NULL;
+			} else {
+				res = copyvar(L.v, R.v);
+			}
+			break;
+
+		  case XC( OC_TERNARY ):
+			if ((op->r.n->info & OPCLSMASK) != OC_COLON)
+				runtime_error(EMSG_POSSIBLE_ERROR);
+			res = evaluate(istrue(L.v) ? op->r.n->l.n : op->r.n->r.n, res);
+			break;
+
+		  case XC( OC_FUNC ):
+			if (! op->r.f->body.first)
+				runtime_error(EMSG_UNDEF_FUNC);
+
+			X.v = R.v = nvalloc(op->r.f->nargs+1);
+			while (op1) {
+				L.v = evaluate(nextarg(&op1), v1);
+				copyvar(R.v, L.v);
+				R.v->type |= VF_CHILD;
+				R.v->x.parent = L.v;
+				if (++R.v - X.v >= op->r.f->nargs)
+					break;
+			}
+
+			R.v = fnargs;
+			fnargs = X.v;
+
+			L.s = programname;
+			res = evaluate(op->r.f->body.first, res);
+			programname = L.s;
+
+			nvfree(fnargs);
+			fnargs = R.v;
+			break;
+
+		  case XC( OC_GETLINE ):
+		  case XC( OC_PGETLINE ):
+			if (op1) {
+				X.rsm = newfile(L.s);
+				if (! X.rsm->F) {
+					if ((opinfo & OPCLSMASK) == OC_PGETLINE) {
+						X.rsm->F = popen(L.s, "r");
+						X.rsm->is_pipe = TRUE;
+					} else {
+						X.rsm->F = fopen(L.s, "r");		/* not bb_xfopen! */
+					}
+				}
+			} else {
+				if (! iF) iF = next_input_file();
+				X.rsm = iF;
+			}
+
+			if (! X.rsm->F) {
+				setvar_i(V[ERRNO], errno);
+				setvar_i(res, -1);
+				break;
+			}
+
+			if (! op->r.n)
+				R.v = V[F0];
+
+			L.i = awk_getline(X.rsm, R.v);
+			if (L.i > 0) {
+				if (! op1) {
+					incvar(V[FNR]);
+					incvar(V[NR]);
+				}
+			}
+			setvar_i(res, L.i);
+			break;
+
+		  /* simple builtins */
+		  case XC( OC_FBLTIN ):
+			switch (opn) {
+
+			  case F_in:
+				R.d = (int)L.d;
+				break;
+
+			  case F_rn:
+				R.d =  (double)rand() / (double)RAND_MAX;
+				break;
+
+#ifdef CONFIG_FEATURE_AWK_MATH
+			  case F_co:
+				R.d = cos(L.d);
+				break;
+
+			  case F_ex:
+				R.d = exp(L.d);
+				break;
+
+			  case F_lg:
+				R.d = log(L.d);
+				break;
+
+			  case F_si:
+				R.d = sin(L.d);
+				break;
+
+			  case F_sq:
+				R.d = sqrt(L.d);
+				break;
+#else
+			  case F_co:
+			  case F_ex:
+			  case F_lg:
+			  case F_si:
+			  case F_sq:
+				runtime_error(EMSG_NO_MATH);
+				break;
+#endif
+
+			  case F_sr:
+				R.d = (double)seed;
+				seed = op1 ? (unsigned int)L.d : (unsigned int)time(NULL);
+				srand(seed);
+				break;
+
+			  case F_ti:
+				R.d = time(NULL);
+				break;
+
+			  case F_le:
+				if (! op1)
+					L.s = getvar_s(V[F0]);
+				R.d = strlen(L.s);
+				break;
+
+			  case F_sy:
+				fflush(NULL);
+				R.d = (L.s && *L.s) ? (system(L.s) >> 8) : 0;
+				break;
+
+			  case F_ff:
+				if (! op1)
+					fflush(stdout);
+				else {
+					if (L.s && *L.s) {
+						X.rsm = newfile(L.s);
+						fflush(X.rsm->F);
+					} else {
+						fflush(NULL);
+					}
+				}
+				break;
+
+			  case F_cl:
+				X.rsm = (rstream *)hash_search(fdhash, L.s);
+				if (X.rsm) {
+					R.i = X.rsm->is_pipe ? pclose(X.rsm->F) : fclose(X.rsm->F);
+					free(X.rsm->buffer);
+					hash_remove(fdhash, L.s);
+				}
+				if (R.i != 0)
+					setvar_i(V[ERRNO], errno);
+				R.d = (double)R.i;
+				break;
+			}
+			setvar_i(res, R.d);
+			break;
+
+		  case XC( OC_BUILTIN ):
+			res = exec_builtin(op, res);
+			break;
+
+		  case XC( OC_SPRINTF ):
+			setvar_p(res, awk_printf(op1));
+			break;
+
+		  case XC( OC_UNARY ):
+			X.v = R.v;
+			L.d = R.d = getvar_i(R.v);
+			switch (opn) {
+			  case 'P':
+				L.d = ++R.d;
+				goto r_op_change;
+			  case 'p':
+				R.d++;
+				goto r_op_change;
+			  case 'M':
+				L.d = --R.d;
+				goto r_op_change;
+			  case 'm':
+				R.d--;
+				goto r_op_change;
+			  case '!':
+			    L.d = istrue(X.v) ? 0 : 1;
+				break;
+			  case '-':
+				L.d = -R.d;
+				break;
+			r_op_change:
+				setvar_i(X.v, R.d);
+			}
+			setvar_i(res, L.d);
+			break;
+
+		  case XC( OC_FIELD ):
+			R.i = (int)getvar_i(R.v);
+			if (R.i == 0) {
+				res = V[F0];
+			} else {
+				split_f0();
+				if (R.i > nfields)
+					fsrealloc(R.i);
+
+				res = &Fields[R.i-1];
+			}
+			break;
+
+		  /* concatenation (" ") and index joining (",") */
+		  case XC( OC_CONCAT ):
+		  case XC( OC_COMMA ):
+			opn = strlen(L.s) + strlen(R.s) + 2;
+			X.s = (char *)xmalloc(opn);
+			strcpy(X.s, L.s);
+			if ((opinfo & OPCLSMASK) == OC_COMMA) {
+				L.s = getvar_s(V[SUBSEP]);
+				X.s = (char *)xrealloc(X.s, opn + strlen(L.s));
+				strcat(X.s, L.s);
+			}
+			strcat(X.s, R.s);
+			setvar_p(res, X.s);
+			break;
+
+		  case XC( OC_LAND ):
+			setvar_i(res, istrue(L.v) ? ptest(op->r.n) : 0);
+			break;
+
+		  case XC( OC_LOR ):
+			setvar_i(res, istrue(L.v) ? 1 : ptest(op->r.n));
+			break;
+
+		  case XC( OC_BINARY ):
+		  case XC( OC_REPLACE ):
+			R.d = getvar_i(R.v);
+			switch (opn) {
+			  case '+':
+				L.d += R.d;
+				break;
+			  case '-':
+				L.d -= R.d;
+				break;
+			  case '*':
+				L.d *= R.d;
+				break;
+			  case '/':
+				if (R.d == 0) runtime_error(EMSG_DIV_BY_ZERO);
+				L.d /= R.d;
+				break;
+			  case '&':
+#ifdef CONFIG_FEATURE_AWK_MATH
+				L.d = pow(L.d, R.d);
+#else
+				runtime_error(EMSG_NO_MATH);
+#endif
+				break;
+			  case '%':
+				if (R.d == 0) runtime_error(EMSG_DIV_BY_ZERO);
+				L.d -= (int)(L.d / R.d) * R.d;
+				break;
+			}
+			res = setvar_i(((opinfo&OPCLSMASK) == OC_BINARY) ? res : X.v, L.d);
+			break;
+
+		  case XC( OC_COMPARE ):
+			if (is_numeric(L.v) && is_numeric(R.v)) {
+				L.d = getvar_i(L.v) - getvar_i(R.v);
+			} else {
+				L.s = getvar_s(L.v);
+				R.s = getvar_s(R.v);
+				L.d = icase ? strcasecmp(L.s, R.s) : strcmp(L.s, R.s);
+			}
+			switch (opn & 0xfe) {
+			  case 0:
+				R.i = (L.d > 0);
+				break;
+			  case 2:
+				R.i = (L.d >= 0);
+				break;
+			  case 4:
+				R.i = (L.d == 0);
+				break;
+			}
+			setvar_i(res, (opn & 0x1 ? R.i : !R.i) ? 1 : 0);
+			break;
+
+		  default:
+			runtime_error(EMSG_POSSIBLE_ERROR);
+		}
+		if ((opinfo & OPCLSMASK) <= SHIFT_TIL_THIS)
+			op = op->a.n;
+		if ((opinfo & OPCLSMASK) >= RECUR_FROM_THIS)
+			break;
+		if (nextrec)
+			break;
+	}
+	nvfree(v1);
+	return res;
+}
+
+
+/* -------- main & co. -------- */
+
+static int awk_exit(int r)
+{
+	unsigned int i;
+	hash_item *hi;
+	static var tv;
+
+	if (! exiting) {
+		exiting = TRUE;
+		nextrec = FALSE;
+		evaluate(endseq.first, &tv);
+	}
+
+	/* waiting for children */
+	for (i=0; i<fdhash->csize; i++) {
+		hi = fdhash->items[i];
+		while(hi) {
+			if (hi->data.rs.F && hi->data.rs.is_pipe)
+				pclose(hi->data.rs.F);
+			hi = hi->next;
+		}
+	}
+
+	exit(r);
+}
+
+/* if expr looks like "var=value", perform assignment and return 1,
+ * otherwise return 0 */
+static int is_assignment(const char *expr)
+{
+	char *exprc, *s, *s0, *s1;
+
+	exprc = bb_xstrdup(expr);
+	if (!isalnum_(*exprc) || (s = strchr(exprc, '=')) == NULL) {
+		free(exprc);
+		return FALSE;
+	}
+
+	*(s++) = '\0';
+	s0 = s1 = s;
+	while (*s)
+		*(s1++) = nextchar(&s);
+
+	*s1 = '\0';
+	setvar_u(newvar(exprc), s0);
+	free(exprc);
+	return TRUE;
+}
+
+/* switch to next input file */
+static rstream *next_input_file(void)
+{
+	static rstream rsm;
+	FILE *F = NULL;
+	char *fname, *ind;
+	static int files_happen = FALSE;
+
+	if (rsm.F) fclose(rsm.F);
+	rsm.F = NULL;
+	rsm.pos = rsm.adv = 0;
+
+	do {
+		if (getvar_i(V[ARGIND])+1 >= getvar_i(V[ARGC])) {
+			if (files_happen)
+				return NULL;
+			fname = "-";
+			F = stdin;
+		} else {
+			ind = getvar_s(incvar(V[ARGIND]));
+			fname = getvar_s(findvar(iamarray(V[ARGV]), ind));
+			if (fname && *fname && !is_assignment(fname))
+				F = afopen(fname, "r");
+		}
+	} while (!F);
+
+	files_happen = TRUE;
+	setvar_s(V[FILENAME], fname);
+	rsm.F = F;
+	return &rsm;
+}
+
+int awk_main(int argc, char **argv)
+{
+	char *s, *s1;
+	int i, j, c, flen;
+	var *v;
+	static var tv;
+	char **envp;
+	static int from_file = FALSE;
+	rstream *rsm;
+	FILE *F, *stdfiles[3];
+	static char * stdnames = "/dev/stdin\0/dev/stdout\0/dev/stderr";
+
+	/* allocate global buffer */
+	buf = xmalloc(MAXVARFMT+1);
+
+	vhash = hash_init();
+	ahash = hash_init();
+	fdhash = hash_init();
+	fnhash = hash_init();
+
+	/* initialize variables */
+	for (i=0;  *vNames;  i++) {
+		V[i] = v = newvar(nextword(&vNames));
+		if (*vValues != '\377')
+			setvar_s(v, nextword(&vValues));
+		else
+			setvar_i(v, 0);
+
+		if (*vNames == '*') {
+			v->type |= VF_SPECIAL;
+			vNames++;
+		}
+	}
+
+	handle_special(V[FS]);
+	handle_special(V[RS]);
+
+	stdfiles[0] = stdin;
+	stdfiles[1] = stdout;
+	stdfiles[2] = stderr;
+	for (i=0; i<3; i++) {
+		rsm = newfile(nextword(&stdnames));
+		rsm->F = stdfiles[i];
+	}
+
+	for (envp=environ; *envp; envp++) {
+		s = bb_xstrdup(*envp);
+		s1 = strchr(s, '=');
+		if (!s1) {
+			goto keep_going;
+		}
+		*(s1++) = '\0';
+		setvar_u(findvar(iamarray(V[ENVIRON]), s), s1);
+keep_going:
+		free(s);
+	}
+
+	while((c = getopt(argc, argv, "F:v:f:W:")) != EOF) {
+		switch (c) {
+			case 'F':
+				setvar_s(V[FS], optarg);
+				break;
+			case 'v':
+				if (! is_assignment(optarg))
+					bb_show_usage();
+				break;
+			case 'f':
+				from_file = TRUE;
+				F = afopen(programname = optarg, "r");
+				s = NULL;
+				/* one byte is reserved for some trick in next_token */
+				if (fseek(F, 0, SEEK_END) == 0) {
+					flen = ftell(F);
+					s = (char *)xmalloc(flen+4);
+					fseek(F, 0, SEEK_SET);
+					i = 1 + fread(s+1, 1, flen, F);
+				} else {
+					for (i=j=1; j>0; i+=j) {
+						s = (char *)xrealloc(s, i+4096);
+						j = fread(s+i, 1, 4094, F);
+					}
+				}
+				s[i] = '\0';
+				fclose(F);
+				parse_program(s+1);
+				free(s);
+				break;
+			case 'W':
+				bb_error_msg("Warning: unrecognized option '-W %s' ignored\n", optarg);
+				break;
+
+			default:
+				bb_show_usage();
+		}
+	}
+
+	if (!from_file) {
+		if (argc == optind)
+			bb_show_usage();
+		programname="cmd. line";
+		parse_program(argv[optind++]);
+
+	}
+
+	/* fill in ARGV array */
+	setvar_i(V[ARGC], argc - optind + 1);
+	setari_u(V[ARGV], 0, "awk");
+	for(i=optind; i < argc; i++)
+		setari_u(V[ARGV], i+1-optind, argv[i]);
+
+	evaluate(beginseq.first, &tv);
+	if (! mainseq.first && ! endseq.first)
+		awk_exit(EXIT_SUCCESS);
+
+	/* input file could already be opened in BEGIN block */
+	if (! iF) iF = next_input_file();
+
+	/* passing through input files */
+	while (iF) {
+
+		nextfile = FALSE;
+		setvar_i(V[FNR], 0);
+
+		while ((c = awk_getline(iF, V[F0])) > 0) {
+
+			nextrec = FALSE;
+			incvar(V[NR]);
+			incvar(V[FNR]);
+			evaluate(mainseq.first, &tv);
+
+			if (nextfile)
+				break;
+		}
+
+		if (c < 0)
+			runtime_error(strerror(errno));
+
+		iF = next_input_file();
+
+	}
+
+	awk_exit(EXIT_SUCCESS);
+
+	return 0;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/ed.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/ed.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/ed.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1362 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (c) 2002 by David I. Bell
+ * Permission is granted to use, distribute, or modify this source,
+ * provided that this copyright notice remains intact.
+ *
+ * The "ed" built-in command (much simplified)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+#include <sys/param.h>
+#include "busybox.h"
+
+#define	USERSIZE	1024	/* max line length typed in by user */
+#define	INITBUF_SIZE	1024	/* initial buffer size */
+typedef struct LINE {
+	struct LINE *next;
+	struct LINE *prev;
+	int len;
+	char data[1];
+} LINE;
+
+static LINE lines, *curLine;
+static int curNum, lastNum, marks[26], dirty;
+static char *bufBase, *bufPtr, *fileName, searchString[USERSIZE];
+static int bufUsed, bufSize;
+
+static void doCommands(void);
+static void subCommand(const char *cmd, int num1, int num2);
+static int getNum(const char **retcp, int *retHaveNum, int *retNum);
+static int setCurNum(int num);
+static int initEdit(void);
+static void termEdit(void);
+static void addLines(int num);
+static int insertLine(int num, const char *data, int len);
+static int deleteLines(int num1, int num2);
+static int printLines(int num1, int num2, int expandFlag);
+static int writeLines(const char *file, int num1, int num2);
+static int readLines(const char *file, int num);
+static int searchLines(const char *str, int num1, int num2);
+static LINE *findLine(int num);
+
+static int findString(const LINE *lp, const char * str, int len, int offset);
+
+int ed_main(int argc, char **argv)
+{
+	if (!initEdit())
+		return EXIT_FAILURE;
+
+	if (argc > 1) {
+		fileName = strdup(argv[1]);
+
+		if (fileName == NULL) {
+			bb_error_msg("No memory");
+			termEdit();
+			return EXIT_SUCCESS;
+		}
+
+		if (!readLines(fileName, 1)) {
+			termEdit();
+			return EXIT_SUCCESS;
+		}
+
+		if (lastNum)
+			setCurNum(1);
+
+		dirty = FALSE;
+	}
+
+	doCommands();
+
+	termEdit();
+	return EXIT_SUCCESS;
+}
+
+/*
+ * Read commands until we are told to stop.
+ */
+static void doCommands(void)
+{
+	const char *cp;
+	char *endbuf, *newname, buf[USERSIZE];
+	int len, num1, num2, have1, have2;
+
+	while (TRUE)
+	{
+		printf(": ");
+		fflush(stdout);
+
+		if (fgets(buf, sizeof(buf), stdin) == NULL)
+			return;
+
+		len = strlen(buf);
+
+		if (len == 0)
+			return;
+
+		endbuf = &buf[len - 1];
+
+		if (*endbuf != '\n')
+		{
+			bb_error_msg("Command line too long");
+
+			do
+			{
+				len = fgetc(stdin);
+			}
+			while ((len != EOF) && (len != '\n'));
+
+			continue;
+		}
+
+		while ((endbuf > buf) && isblank(endbuf[-1]))
+			endbuf--;
+
+		*endbuf = '\0';
+
+		cp = buf;
+
+		while (isblank(*cp))
+			cp++;
+
+		have1 = FALSE;
+		have2 = FALSE;
+
+		if ((curNum == 0) && (lastNum > 0))
+		{
+			curNum = 1;
+			curLine = lines.next;
+		}
+
+		if (!getNum(&cp, &have1, &num1))
+			continue;
+
+		while (isblank(*cp))
+			cp++;
+
+		if (*cp == ',')
+		{
+			cp++;
+
+			if (!getNum(&cp, &have2, &num2))
+				continue;
+
+			if (!have1)
+				num1 = 1;
+
+			if (!have2)
+				num2 = lastNum;
+
+			have1 = TRUE;
+			have2 = TRUE;
+		}
+
+		if (!have1)
+			num1 = curNum;
+
+		if (!have2)
+			num2 = num1;
+
+		switch (*cp++)
+		{
+			case 'a':
+				addLines(num1 + 1);
+				break;
+
+			case 'c':
+				deleteLines(num1, num2);
+				addLines(num1);
+				break;
+
+			case 'd':
+				deleteLines(num1, num2);
+				break;
+
+			case 'f':
+				if (*cp && !isblank(*cp))
+				{
+					bb_error_msg("Bad file command");
+					break;
+				}
+
+				while (isblank(*cp))
+					cp++;
+
+				if (*cp == '\0')
+				{
+					if (fileName)
+						printf("\"%s\"\n", fileName);
+					else
+						printf("No file name\n");
+
+					break;
+				}
+
+				newname = strdup(cp);
+
+				if (newname == NULL)
+				{
+					bb_error_msg("No memory for file name");
+					break;
+				}
+
+				if (fileName)
+					free(fileName);
+
+				fileName = newname;
+				break;
+
+			case 'i':
+				addLines(num1);
+				break;
+
+			case 'k':
+				while (isblank(*cp))
+					cp++;
+
+				if ((*cp < 'a') || (*cp > 'a') || cp[1])
+				{
+					bb_error_msg("Bad mark name");
+					break;
+				}
+
+				marks[*cp - 'a'] = num2;
+				break;
+
+			case 'l':
+				printLines(num1, num2, TRUE);
+				break;
+
+			case 'p':
+				printLines(num1, num2, FALSE);
+				break;
+
+			case 'q':
+				while (isblank(*cp))
+					cp++;
+
+				if (have1 || *cp)
+				{
+					bb_error_msg("Bad quit command");
+					break;
+				}
+
+				if (!dirty)
+					return;
+
+				printf("Really quit? ");
+				fflush(stdout);
+
+				buf[0] = '\0';
+				fgets(buf, sizeof(buf), stdin);
+				cp = buf;
+
+				while (isblank(*cp))
+					cp++;
+
+				if ((*cp == 'y') || (*cp == 'Y'))
+					return;
+
+				break;
+
+			case 'r':
+				if (*cp && !isblank(*cp))
+				{
+					bb_error_msg("Bad read command");
+					break;
+				}
+
+				while (isblank(*cp))
+					cp++;
+
+				if (*cp == '\0')
+				{
+					bb_error_msg("No file name");
+					break;
+				}
+
+				if (!have1)
+					num1 = lastNum;
+
+				if (readLines(cp, num1 + 1))
+					break;
+
+				if (fileName == NULL)
+					fileName = strdup(cp);
+
+				break;
+
+			case 's':
+				subCommand(cp, num1, num2);
+				break;
+
+			case 'w':
+				if (*cp && !isblank(*cp))
+				{
+					bb_error_msg("Bad write command");
+					break;
+				}
+
+				while (isblank(*cp))
+					cp++;
+
+				if (!have1) {
+					num1 = 1;
+					num2 = lastNum;
+				}
+
+				if (*cp == '\0')
+					cp = fileName;
+
+				if (cp == NULL)
+				{
+					bb_error_msg("No file name specified");
+					break;
+				}
+
+				writeLines(cp, num1, num2);
+				break;
+
+			case 'z':
+				switch (*cp)
+				{
+				case '-':
+					printLines(curNum-21, curNum, FALSE);
+					break;
+				case '.':
+					printLines(curNum-11, curNum+10, FALSE);
+					break;
+				default:
+					printLines(curNum, curNum+21, FALSE);
+					break;
+				}
+				break;
+
+			case '.':
+				if (have1)
+				{
+					bb_error_msg("No arguments allowed");
+					break;
+				}
+
+				printLines(curNum, curNum, FALSE);
+				break;
+
+			case '-':
+				if (setCurNum(curNum - 1))
+					printLines(curNum, curNum, FALSE);
+
+				break;
+
+			case '=':
+				printf("%d\n", num1);
+				break;
+
+			case '\0':
+				if (have1)
+				{
+					printLines(num2, num2, FALSE);
+					break;
+				}
+
+				if (setCurNum(curNum + 1))
+					printLines(curNum, curNum, FALSE);
+
+				break;
+
+			default:
+				bb_error_msg("Unimplemented command");
+				break;
+		}
+	}
+}
+
+
+/*
+ * Do the substitute command.
+ * The current line is set to the last substitution done.
+ */
+static void subCommand(const char * cmd, int num1, int num2)
+{
+	char *cp, *oldStr, *newStr, buf[USERSIZE];
+	int	delim, oldLen, newLen, deltaLen, offset;
+	LINE *lp, *nlp;
+	int globalFlag, printFlag, didSub, needPrint;
+
+	if ((num1 < 1) || (num2 > lastNum) || (num1 > num2))
+	{
+		bb_error_msg("Bad line range for substitute");
+
+		return;
+	}
+
+	globalFlag = FALSE;
+	printFlag = FALSE;
+	didSub = FALSE;
+	needPrint = FALSE;
+
+	/*
+	 * Copy the command so we can modify it.
+	 */
+	strcpy(buf, cmd);
+	cp = buf;
+
+	if (isblank(*cp) || (*cp == '\0'))
+	{
+		bb_error_msg("Bad delimiter for substitute");
+
+		return;
+	}
+
+	delim = *cp++;
+	oldStr = cp;
+
+	cp = strchr(cp, delim);
+
+	if (cp == NULL)
+	{
+		bb_error_msg("Missing 2nd delimiter for substitute");
+
+		return;
+	}
+
+	*cp++ = '\0';
+
+	newStr = cp;
+	cp = strchr(cp, delim);
+
+	if (cp)
+		*cp++ = '\0';
+	else
+		cp = "";
+
+	while (*cp) switch (*cp++)
+	{
+		case 'g':
+			globalFlag = TRUE;
+			break;
+
+		case 'p':
+			printFlag = TRUE;
+			break;
+
+		default:
+			bb_error_msg("Unknown option for substitute");
+
+			return;
+	}
+
+	if (*oldStr == '\0')
+	{
+		if (searchString[0] == '\0')
+		{
+			bb_error_msg("No previous search string");
+
+			return;
+		}
+
+		oldStr = searchString;
+	}
+
+	if (oldStr != searchString)
+		strcpy(searchString, oldStr);
+
+	lp = findLine(num1);
+
+	if (lp == NULL)
+		return;
+
+	oldLen = strlen(oldStr);
+	newLen = strlen(newStr);
+	deltaLen = newLen - oldLen;
+	offset = 0;
+	nlp = NULL;
+
+	while (num1 <= num2)
+	{
+		offset = findString(lp, oldStr, oldLen, offset);
+
+		if (offset < 0)
+		{
+			if (needPrint)
+			{
+				printLines(num1, num1, FALSE);
+				needPrint = FALSE;
+			}
+
+			offset = 0;
+			lp = lp->next;
+			num1++;
+
+			continue;
+		}
+
+		needPrint = printFlag;
+		didSub = TRUE;
+		dirty = TRUE;
+
+		/*
+		 * If the replacement string is the same size or shorter
+		 * than the old string, then the substitution is easy.
+		 */
+		if (deltaLen <= 0)
+		{
+			memcpy(&lp->data[offset], newStr, newLen);
+
+			if (deltaLen)
+			{
+				memcpy(&lp->data[offset + newLen],
+					&lp->data[offset + oldLen],
+					lp->len - offset - oldLen);
+
+				lp->len += deltaLen;
+			}
+
+			offset += newLen;
+
+			if (globalFlag)
+				continue;
+
+			if (needPrint)
+			{
+				printLines(num1, num1, FALSE);
+				needPrint = FALSE;
+			}
+
+			lp = lp->next;
+			num1++;
+
+			continue;
+		}
+
+		/*
+		 * The new string is larger, so allocate a new line
+		 * structure and use that.  Link it in in place of
+		 * the old line structure.
+		 */
+		nlp = (LINE *) malloc(sizeof(LINE) + lp->len + deltaLen);
+
+		if (nlp == NULL)
+		{
+			bb_error_msg("Cannot get memory for line");
+
+			return;
+		}
+
+		nlp->len = lp->len + deltaLen;
+
+		memcpy(nlp->data, lp->data, offset);
+
+		memcpy(&nlp->data[offset], newStr, newLen);
+
+		memcpy(&nlp->data[offset + newLen],
+			&lp->data[offset + oldLen],
+			lp->len - offset - oldLen);
+
+		nlp->next = lp->next;
+		nlp->prev = lp->prev;
+		nlp->prev->next = nlp;
+		nlp->next->prev = nlp;
+
+		if (curLine == lp)
+			curLine = nlp;
+
+		free(lp);
+		lp = nlp;
+
+		offset += newLen;
+
+		if (globalFlag)
+			continue;
+
+		if (needPrint)
+		{
+			printLines(num1, num1, FALSE);
+			needPrint = FALSE;
+		}
+
+		lp = lp->next;
+		num1++;
+	}
+
+	if (!didSub)
+		bb_error_msg("No substitutions found for \"%s\"", oldStr);
+}
+
+
+/*
+ * Search a line for the specified string starting at the specified
+ * offset in the line.  Returns the offset of the found string, or -1.
+ */
+static int findString( const LINE * lp, const char * str, int len, int offset)
+{
+	int left;
+	const char *cp, *ncp;
+
+	cp = &lp->data[offset];
+	left = lp->len - offset;
+
+	while (left >= len)
+	{
+		ncp = memchr(cp, *str, left);
+
+		if (ncp == NULL)
+			return -1;
+
+		left -= (ncp - cp);
+
+		if (left < len)
+			return -1;
+
+		cp = ncp;
+
+		if (memcmp(cp, str, len) == 0)
+			return (cp - lp->data);
+
+		cp++;
+		left--;
+	}
+
+	return -1;
+}
+
+
+/*
+ * Add lines which are typed in by the user.
+ * The lines are inserted just before the specified line number.
+ * The lines are terminated by a line containing a single dot (ugly!),
+ * or by an end of file.
+ */
+static void addLines(int num)
+{
+	int	len;
+	char	buf[USERSIZE + 1];
+
+	while (fgets(buf, sizeof(buf), stdin))
+	{
+		if ((buf[0] == '.') && (buf[1] == '\n') && (buf[2] == '\0'))
+			return;
+
+		len = strlen(buf);
+
+		if (len == 0)
+			return;
+
+		if (buf[len - 1] != '\n')
+		{
+			bb_error_msg("Line too long");
+
+			do
+			{
+				len = fgetc(stdin);
+			}
+			while ((len != EOF) && (len != '\n'));
+
+			return;
+		}
+
+		if (!insertLine(num++, buf, len))
+			return;
+	}
+}
+
+
+/*
+ * Parse a line number argument if it is present.  This is a sum
+ * or difference of numbers, '.', '$', 'x, or a search string.
+ * Returns TRUE if successful (whether or not there was a number).
+ * Returns FALSE if there was a parsing error, with a message output.
+ * Whether there was a number is returned indirectly, as is the number.
+ * The character pointer which stopped the scan is also returned.
+ */
+static int getNum(const char **retcp, int *retHaveNum, int *retNum)
+{
+	const char *cp;
+	char *endStr, str[USERSIZE];
+	int haveNum, value, num, sign;
+
+	cp = *retcp;
+	haveNum = FALSE;
+	value = 0;
+	sign = 1;
+
+	while (TRUE)
+	{
+		while (isblank(*cp))
+			cp++;
+
+		switch (*cp)
+		{
+			case '.':
+				haveNum = TRUE;
+				num = curNum;
+				cp++;
+				break;
+
+			case '$':
+				haveNum = TRUE;
+				num = lastNum;
+				cp++;
+				break;
+
+			case '\'':
+				cp++;
+
+				if ((*cp < 'a') || (*cp > 'z'))
+				{
+					bb_error_msg("Bad mark name");
+
+					return FALSE;
+				}
+
+				haveNum = TRUE;
+				num = marks[*cp++ - 'a'];
+				break;
+
+			case '/':
+				strcpy(str, ++cp);
+				endStr = strchr(str, '/');
+
+				if (endStr)
+				{
+					*endStr++ = '\0';
+					cp += (endStr - str);
+				}
+				else
+					cp = "";
+
+				num = searchLines(str, curNum, lastNum);
+
+				if (num == 0)
+					return FALSE;
+
+				haveNum = TRUE;
+				break;
+
+			default:
+				if (!isdigit(*cp))
+				{
+					*retcp = cp;
+					*retHaveNum = haveNum;
+					*retNum = value;
+
+					return TRUE;
+				}
+
+				num = 0;
+
+				while (isdigit(*cp))
+					num = num * 10 + *cp++ - '0';
+
+				haveNum = TRUE;
+				break;
+		}
+
+		value += num * sign;
+
+		while (isblank(*cp))
+			cp++;
+
+		switch (*cp)
+		{
+			case '-':
+				sign = -1;
+				cp++;
+				break;
+
+			case '+':
+				sign = 1;
+				cp++;
+				break;
+
+			default:
+				*retcp = cp;
+				*retHaveNum = haveNum;
+				*retNum = value;
+
+				return TRUE;
+		}
+	}
+}
+
+
+/*
+ * Initialize everything for editing.
+ */
+static int initEdit(void)
+{
+	int	i;
+
+	bufSize = INITBUF_SIZE;
+	bufBase = malloc(bufSize);
+
+	if (bufBase == NULL)
+	{
+		bb_error_msg("No memory for buffer");
+
+		return FALSE;
+	}
+
+	bufPtr = bufBase;
+	bufUsed = 0;
+
+	lines.next = &lines;
+	lines.prev = &lines;
+
+	curLine = NULL;
+	curNum = 0;
+	lastNum = 0;
+	dirty = FALSE;
+	fileName = NULL;
+	searchString[0] = '\0';
+
+	for (i = 0; i < 26; i++)
+		marks[i] = 0;
+
+	return TRUE;
+}
+
+
+/*
+ * Finish editing.
+ */
+static void termEdit(void)
+{
+	if (bufBase)
+		free(bufBase);
+
+	bufBase = NULL;
+	bufPtr = NULL;
+	bufSize = 0;
+	bufUsed = 0;
+
+	if (fileName)
+		free(fileName);
+
+	fileName = NULL;
+
+	searchString[0] = '\0';
+
+	if (lastNum)
+		deleteLines(1, lastNum);
+
+	lastNum = 0;
+	curNum = 0;
+	curLine = NULL;
+}
+
+
+/*
+ * Read lines from a file at the specified line number.
+ * Returns TRUE if the file was successfully read.
+ */
+static int readLines(const char * file, int num)
+{
+	int	fd, cc;
+	int len, lineCount, charCount;
+	char *cp;
+
+	if ((num < 1) || (num > lastNum + 1))
+	{
+		bb_error_msg("Bad line for read");
+
+		return FALSE;
+	}
+
+	fd = open(file, 0);
+
+	if (fd < 0)
+	{
+		perror(file);
+
+		return FALSE;
+	}
+
+	bufPtr = bufBase;
+	bufUsed = 0;
+	lineCount = 0;
+	charCount = 0;
+	cc = 0;
+
+	printf("\"%s\", ", file);
+	fflush(stdout);
+
+	do
+	{
+		cp = memchr(bufPtr, '\n', bufUsed);
+
+		if (cp)
+		{
+			len = (cp - bufPtr) + 1;
+
+			if (!insertLine(num, bufPtr, len))
+			{
+				close(fd);
+
+				return FALSE;
+			}
+
+			bufPtr += len;
+			bufUsed -= len;
+			charCount += len;
+			lineCount++;
+			num++;
+
+			continue;
+		}
+
+		if (bufPtr != bufBase)
+		{
+			memcpy(bufBase, bufPtr, bufUsed);
+			bufPtr = bufBase + bufUsed;
+		}
+
+		if (bufUsed >= bufSize)
+		{
+			len = (bufSize * 3) / 2;
+			cp = realloc(bufBase, len);
+
+			if (cp == NULL)
+			{
+				bb_error_msg("No memory for buffer");
+				close(fd);
+
+				return FALSE;
+			}
+
+			bufBase = cp;
+			bufPtr = bufBase + bufUsed;
+			bufSize = len;
+		}
+
+		cc = read(fd, bufPtr, bufSize - bufUsed);
+		bufUsed += cc;
+		bufPtr = bufBase;
+
+	}
+	while (cc > 0);
+
+	if (cc < 0)
+	{
+		perror(file);
+		close(fd);
+
+		return FALSE;
+	}
+
+	if (bufUsed)
+	{
+		if (!insertLine(num, bufPtr, bufUsed))
+		{
+			close(fd);
+
+			return -1;
+		}
+
+		lineCount++;
+		charCount += bufUsed;
+	}
+
+	close(fd);
+
+	printf("%d lines%s, %d chars\n", lineCount,
+		(bufUsed ? " (incomplete)" : ""), charCount);
+
+	return TRUE;
+}
+
+
+/*
+ * Write the specified lines out to the specified file.
+ * Returns TRUE if successful, or FALSE on an error with a message output.
+ */
+static int writeLines(const char * file, int num1, int num2)
+{
+	LINE *lp;
+	int	fd, lineCount, charCount;
+
+	if ((num1 < 1) || (num2 > lastNum) || (num1 > num2))
+	{
+		bb_error_msg("Bad line range for write");
+
+		return FALSE;
+	}
+
+	lineCount = 0;
+	charCount = 0;
+
+	fd = creat(file, 0666);
+
+	if (fd < 0) {
+		perror(file);
+
+		return FALSE;
+	}
+
+	printf("\"%s\", ", file);
+	fflush(stdout);
+
+	lp = findLine(num1);
+
+	if (lp == NULL)
+	{
+		close(fd);
+
+		return FALSE;
+	}
+
+	while (num1++ <= num2)
+	{
+		if (write(fd, lp->data, lp->len) != lp->len)
+		{
+			perror(file);
+			close(fd);
+
+			return FALSE;
+		}
+
+		charCount += lp->len;
+		lineCount++;
+		lp = lp->next;
+	}
+
+	if (close(fd) < 0)
+	{
+		perror(file);
+
+		return FALSE;
+	}
+
+	printf("%d lines, %d chars\n", lineCount, charCount);
+
+	return TRUE;
+}
+
+
+/*
+ * Print lines in a specified range.
+ * The last line printed becomes the current line.
+ * If expandFlag is TRUE, then the line is printed specially to
+ * show magic characters.
+ */
+static int printLines(int num1, int num2, int expandFlag)
+{
+	const LINE *lp;
+	const char *cp;
+	int ch, count;
+
+	if ((num1 < 1) || (num2 > lastNum) || (num1 > num2))
+	{
+		bb_error_msg("Bad line range for print");
+
+		return FALSE;
+	}
+
+	lp = findLine(num1);
+
+	if (lp == NULL)
+		return FALSE;
+
+	while (num1 <= num2)
+	{
+		if (!expandFlag)
+		{
+			write(1, lp->data, lp->len);
+			setCurNum(num1++);
+			lp = lp->next;
+
+			continue;
+		}
+
+		/*
+		 * Show control characters and characters with the
+		 * high bit set specially.
+		 */
+		cp = lp->data;
+		count = lp->len;
+
+		if ((count > 0) && (cp[count - 1] == '\n'))
+			count--;
+
+		while (count-- > 0)
+		{
+			ch = *cp++;
+
+			if (ch & 0x80)
+			{
+				fputs("M-", stdout);
+				ch &= 0x7f;
+			}
+
+			if (ch < ' ')
+			{
+				fputc('^', stdout);
+				ch += '@';
+			}
+
+			if (ch == 0x7f)
+			{
+				fputc('^', stdout);
+				ch = '?';
+			}
+
+			fputc(ch, stdout);
+		}
+
+		fputs("$\n", stdout);
+
+		setCurNum(num1++);
+		lp = lp->next;
+	}
+
+	return TRUE;
+}
+
+
+/*
+ * Insert a new line with the specified text.
+ * The line is inserted so as to become the specified line,
+ * thus pushing any existing and further lines down one.
+ * The inserted line is also set to become the current line.
+ * Returns TRUE if successful.
+ */
+static int insertLine(int num, const char * data, int len)
+{
+	LINE *newLp, *lp;
+
+	if ((num < 1) || (num > lastNum + 1))
+	{
+		bb_error_msg("Inserting at bad line number");
+
+		return FALSE;
+	}
+
+	newLp = (LINE *) malloc(sizeof(LINE) + len - 1);
+
+	if (newLp == NULL)
+	{
+		bb_error_msg("Failed to allocate memory for line");
+
+		return FALSE;
+	}
+
+	memcpy(newLp->data, data, len);
+	newLp->len = len;
+
+	if (num > lastNum)
+		lp = &lines;
+	else
+	{
+		lp = findLine(num);
+
+		if (lp == NULL)
+		{
+			free((char *) newLp);
+
+			return FALSE;
+		}
+	}
+
+	newLp->next = lp;
+	newLp->prev = lp->prev;
+	lp->prev->next = newLp;
+	lp->prev = newLp;
+
+	lastNum++;
+	dirty = TRUE;
+
+	return setCurNum(num);
+}
+
+
+/*
+ * Delete lines from the given range.
+ */
+static int deleteLines(int num1, int num2)
+{
+	LINE *lp, *nlp, *plp;
+	int count;
+
+	if ((num1 < 1) || (num2 > lastNum) || (num1 > num2))
+	{
+		bb_error_msg("Bad line numbers for delete");
+
+		return FALSE;
+	}
+
+	lp = findLine(num1);
+
+	if (lp == NULL)
+		return FALSE;
+
+	if ((curNum >= num1) && (curNum <= num2))
+	{
+		if (num2 < lastNum)
+			setCurNum(num2 + 1);
+		else if (num1 > 1)
+			setCurNum(num1 - 1);
+		else
+			curNum = 0;
+	}
+
+	count = num2 - num1 + 1;
+
+	if (curNum > num2)
+		curNum -= count;
+
+	lastNum -= count;
+
+	while (count-- > 0)
+	{
+		nlp = lp->next;
+		plp = lp->prev;
+		plp->next = nlp;
+		nlp->prev = plp;
+		lp->next = NULL;
+		lp->prev = NULL;
+		lp->len = 0;
+		free(lp);
+		lp = nlp;
+	}
+
+	dirty = TRUE;
+
+	return TRUE;
+}
+
+
+/*
+ * Search for a line which contains the specified string.
+ * If the string is NULL, then the previously searched for string
+ * is used.  The currently searched for string is saved for future use.
+ * Returns the line number which matches, or 0 if there was no match
+ * with an error printed.
+ */
+static int searchLines(const char *str, int num1, int num2)
+{
+	const LINE *lp;
+	int len;
+
+	if ((num1 < 1) || (num2 > lastNum) || (num1 > num2))
+	{
+		bb_error_msg("Bad line numbers for search");
+
+		return 0;
+	}
+
+	if (*str == '\0')
+	{
+		if (searchString[0] == '\0')
+		{
+			bb_error_msg("No previous search string");
+
+			return 0;
+		}
+
+		str = searchString;
+	}
+
+	if (str != searchString)
+		strcpy(searchString, str);
+
+	len = strlen(str);
+
+	lp = findLine(num1);
+
+	if (lp == NULL)
+		return 0;
+
+	while (num1 <= num2)
+	{
+		if (findString(lp, str, len, 0) >= 0)
+			return num1;
+
+		num1++;
+		lp = lp->next;
+	}
+
+	bb_error_msg("Cannot find string \"%s\"", str);
+
+	return 0;
+}
+
+
+/*
+ * Return a pointer to the specified line number.
+ */
+static LINE *findLine(int num)
+{
+	LINE *lp;
+	int lnum;
+
+	if ((num < 1) || (num > lastNum))
+	{
+		bb_error_msg("Line number %d does not exist", num);
+
+		return NULL;
+	}
+
+	if (curNum <= 0)
+	{
+		curNum = 1;
+		curLine = lines.next;
+	}
+
+	if (num == curNum)
+		return curLine;
+
+	lp = curLine;
+	lnum = curNum;
+
+	if (num < (curNum / 2))
+	{
+		lp = lines.next;
+		lnum = 1;
+	}
+	else if (num > ((curNum + lastNum) / 2))
+	{
+		lp = lines.prev;
+		lnum = lastNum;
+	}
+
+	while (lnum < num)
+	{
+		lp = lp->next;
+		lnum++;
+	}
+
+	while (lnum > num)
+	{
+		lp = lp->prev;
+		lnum--;
+	}
+
+	return lp;
+}
+
+
+/*
+ * Set the current line number.
+ * Returns TRUE if successful.
+ */
+static int setCurNum(int num)
+{
+	LINE *lp;
+
+	lp = findLine(num);
+
+	if (lp == NULL)
+		return FALSE;
+
+	curNum = num;
+	curLine = lp;
+
+	return TRUE;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/patch.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/patch.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/patch.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,273 @@
+/* vi: set sw=4 ts=4: */
+/*
+ *  busybox patch applet to handle the unified diff format.
+ *  Copyright (C) 2003 Glenn McGrath <bug1 at iinet.net.au>
+ *
+ *  Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ *  This applet is written to work with patches generated by GNU diff,
+ *  where there is equivalent functionality busybox patch shall behave
+ *  as per GNU patch.
+ *
+ *  There is a SUSv3 specification for patch, however it looks to be
+ *  incomplete, it doesnt even mention unified diff format.
+ *  http://www.opengroup.org/onlinepubs/007904975/utilities/patch.html
+ *
+ *  Issues
+ *   - Non-interactive
+ *   - Patches must apply cleanly or the hunk will fail.
+ *   - Reject file isnt saved
+ *   -
+ */
+
+#include <getopt.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+static unsigned int copy_lines(FILE *src_stream, FILE *dest_stream, const unsigned int lines_count)
+{
+	unsigned int i = 0;
+
+	while (src_stream && (i < lines_count)) {
+		char *line;
+		line = bb_get_line_from_file(src_stream);
+		if (line == NULL) {
+			break;
+		}
+		if (fputs(line, dest_stream) == EOF) {
+			bb_perror_msg_and_die("Error writing to new file");
+		}
+		free(line);
+
+		i++;
+	}
+	return(i);
+}
+
+/* If patch_level is -1 it will remove all directory names
+ * char *line must be greater than 4 chars
+ * returns NULL if the file doesnt exist or error
+ * returns malloc'ed filename
+ */
+
+static char *extract_filename(char *line, int patch_level)
+{
+	char *temp, *filename_start_ptr = line + 4;
+	int i;
+
+	/* Terminate string at end of source filename */
+	temp = strchr(filename_start_ptr, '\t');
+	if (temp) *temp = 0;
+
+	/* skip over (patch_level) number of leading directories */
+	for (i = 0; i < patch_level; i++) {
+		if(!(temp = strchr(filename_start_ptr, '/'))) break;
+		filename_start_ptr = temp + 1;
+	}
+
+	return(bb_xstrdup(filename_start_ptr));
+}
+
+static int file_doesnt_exist(const char *filename)
+{
+	struct stat statbuf;
+	return(stat(filename, &statbuf));
+}
+
+int patch_main(int argc, char **argv)
+{
+	int patch_level = -1;
+	char *patch_line;
+	int ret;
+	FILE *patch_file = NULL;
+
+	{
+		char *p, *i;
+		ret = bb_getopt_ulflags(argc, argv, "p:i:", &p, &i);
+		if (ret & 1)
+			patch_level = bb_xgetlarg(p, 10, -1, USHRT_MAX);
+		if (ret & 2) {
+			patch_file = bb_xfopen(i, "r");
+		} else {
+			patch_file = stdin;
+		}
+		ret = 0;
+	}
+
+	patch_line = bb_get_line_from_file(patch_file);
+	while (patch_line) {
+		FILE *src_stream;
+		FILE *dst_stream;
+		char *original_filename;
+		char *new_filename;
+		char *backup_filename;
+		unsigned int src_cur_line = 1;
+		unsigned int dest_cur_line = 0;
+		unsigned int dest_beg_line;
+		unsigned int bad_hunk_count = 0;
+		unsigned int hunk_count = 0;
+		char copy_trailing_lines_flag = 0;
+
+		/* Skip everything upto the "---" marker
+		 * No need to parse the lines "Only in <dir>", and "diff <args>"
+		 */
+		while (patch_line && strncmp(patch_line, "--- ", 4) != 0) {
+			free(patch_line);
+			patch_line = bb_get_line_from_file(patch_file);
+		}
+
+		/* Extract the filename used before the patch was generated */
+		original_filename = extract_filename(patch_line, patch_level);
+		free(patch_line);
+
+		patch_line = bb_get_line_from_file(patch_file);
+		if (strncmp(patch_line, "+++ ", 4) != 0) {
+			ret = 2;
+			bb_error_msg("Invalid patch");
+			continue;
+		}
+		new_filename = extract_filename(patch_line, patch_level);
+		free(patch_line);
+
+		if (file_doesnt_exist(new_filename)) {
+			char *line_ptr;
+			/* Create leading directories */
+			line_ptr = strrchr(new_filename, '/');
+			if (line_ptr) {
+				*line_ptr = '\0';
+				bb_make_directory(new_filename, -1, FILEUTILS_RECUR);
+				*line_ptr = '/';
+			}
+			dst_stream = bb_xfopen(new_filename, "w+");
+			backup_filename = NULL;
+		} else {
+			backup_filename = xmalloc(strlen(new_filename) + 6);
+			strcpy(backup_filename, new_filename);
+			strcat(backup_filename, ".orig");
+			if (rename(new_filename, backup_filename) == -1) {
+				bb_perror_msg_and_die("Couldnt create file %s",
+						backup_filename);
+			}
+			dst_stream = bb_xfopen(new_filename, "w");
+		}
+
+		if ((backup_filename == NULL) || file_doesnt_exist(original_filename)) {
+			src_stream = NULL;
+		} else {
+			if (strcmp(original_filename, new_filename) == 0) {
+				src_stream = bb_xfopen(backup_filename, "r");
+			} else {
+				src_stream = bb_xfopen(original_filename, "r");
+			}
+		}
+
+		printf("patching file %s\n", new_filename);
+
+		/* Handle each hunk */
+		patch_line = bb_get_line_from_file(patch_file);
+		while (patch_line) {
+			unsigned int count;
+			unsigned int src_beg_line;
+			unsigned int unused;
+			unsigned int hunk_offset_start = 0;
+			int hunk_error = 0;
+
+			/* This bit should be improved */
+			if ((sscanf(patch_line, "@@ -%d,%d +%d,%d @@", &src_beg_line, &unused, &dest_beg_line, &unused) != 4) &&
+				(sscanf(patch_line, "@@ -%d,%d +%d @@", &src_beg_line, &unused, &dest_beg_line) != 3) &&
+				(sscanf(patch_line, "@@ -%d +%d,%d @@", &src_beg_line, &dest_beg_line, &unused) != 3)) {
+				/* No more hunks for this file */
+				break;
+			}
+			free(patch_line);
+			hunk_count++;
+
+			if (src_beg_line && dest_beg_line) {
+				/* Copy unmodified lines upto start of hunk */
+				/* src_beg_line will be 0 if its a new file */
+				count = src_beg_line - src_cur_line;
+				if (copy_lines(src_stream, dst_stream, count) != count) {
+					bb_error_msg_and_die("Bad src file");
+				}
+				src_cur_line += count;
+				dest_cur_line += count;
+				copy_trailing_lines_flag = 1;
+			}
+			hunk_offset_start = src_cur_line;
+
+			while ((patch_line = bb_get_line_from_file(patch_file)) != NULL) {
+				if ((*patch_line == '-') || (*patch_line == ' ')) {
+					char *src_line = NULL;
+					if (src_stream) {
+						src_line = bb_get_line_from_file(src_stream);
+						if (!src_line) {
+							hunk_error++;
+							break;
+						} else {
+							src_cur_line++;
+						}
+						if (strcmp(src_line, patch_line + 1) != 0) {
+							bb_error_msg("Hunk #%d FAILED at %d.", hunk_count, hunk_offset_start);
+							hunk_error++;
+							free(patch_line);
+							break;
+						}
+						free(src_line);
+					}
+					if (*patch_line == ' ') {
+						fputs(patch_line + 1, dst_stream);
+						dest_cur_line++;
+					}
+				} else if (*patch_line == '+') {
+					fputs(patch_line + 1, dst_stream);
+					dest_cur_line++;
+				} else {
+					break;
+				}
+				free(patch_line);
+			}
+			if (hunk_error) {
+				bad_hunk_count++;
+			}
+		}
+
+		/* Cleanup last patched file */
+		if (copy_trailing_lines_flag) {
+			copy_lines(src_stream, dst_stream, -1);
+		}
+		if (src_stream) {
+			fclose(src_stream);
+		}
+		if (dst_stream) {
+			fclose(dst_stream);
+		}
+		if (bad_hunk_count) {
+			if (!ret) {
+				ret = 1;
+			}
+			bb_error_msg("%d out of %d hunk FAILED", bad_hunk_count, hunk_count);
+		} else {
+			/* It worked, we can remove the backup */
+			if (backup_filename) {
+				unlink(backup_filename);
+			}
+			if ((dest_cur_line == 0) || (dest_beg_line == 0)) {
+				/* The new patched file is empty, remove it */
+				if (unlink(new_filename) == -1) {
+					bb_perror_msg_and_die("Couldnt remove file %s", new_filename);
+				}
+				if (unlink(original_filename) == -1) {
+					bb_perror_msg_and_die("Couldnt remove original file %s", new_filename);
+				}
+			}
+		}
+	}
+
+	/* 0 = SUCCESS
+	 * 1 = Some hunks failed
+	 * 2 = More serious problems
+	 */
+	return(ret);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/sed.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/sed.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/sed.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1216 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * sed.c - very minimalist version of sed
+ *
+ * Copyright (C) 1999,2000,2001 by Lineo, inc. and Mark Whitley
+ * Copyright (C) 1999,2000,2001 by Mark Whitley <markw at codepoet.org>
+ * Copyright (C) 2002  Matt Kraai
+ * Copyright (C) 2003 by Glenn McGrath <bug1 at iinet.net.au>
+ * Copyright (C) 2003,2004 by Rob Landley <rob at landley.net>
+ *
+ * MAINTAINER: Rob Landley <rob at landley.net>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* Code overview.
+
+  Files are laid out to avoid unnecessary function declarations.  So for
+  example, every function add_cmd calls occurs before add_cmd in this file.
+
+  add_cmd() is called on each line of sed command text (from a file or from
+  the command line).  It calls get_address() and parse_cmd_args().  The
+  resulting sed_cmd_t structures are appended to a linked list
+  (bbg.sed_cmd_head/bbg.sed_cmd_tail).
+
+  add_input_file() adds a FILE * to the list of input files.  We need to
+  know all input sources ahead of time to find the last line for the $ match.
+
+  process_files() does actual sedding, reading data lines from each input FILE *
+  (which could be stdin) and applying the sed command list (sed_cmd_head) to
+  each of the resulting lines.
+
+  sed_main() is where external code calls into this, with a command line.
+*/
+
+
+/*
+	Supported features and commands in this version of sed:
+
+	 - comments ('#')
+	 - address matching: num|/matchstr/[,num|/matchstr/|$]command
+	 - commands: (p)rint, (d)elete, (s)ubstitue (with g & I flags)
+	 - edit commands: (a)ppend, (i)nsert, (c)hange
+	 - file commands: (r)ead
+	 - backreferences in substitution expressions (\0, \1, \2...\9)
+	 - grouped commands: {cmd1;cmd2}
+	 - transliteration (y/source-chars/dest-chars/)
+	 - pattern space hold space storing / swapping (g, h, x)
+	 - labels / branching (: label, b, t, T)
+
+	 (Note: Specifying an address (range) to match is *optional*; commands
+	 default to the whole pattern space if no specific address match was
+	 requested.)
+
+	Todo:
+	 - Create a wrapper around regex to make libc's regex conform with sed
+
+	Reference http://www.opengroup.org/onlinepubs/007904975/utilities/sed.html
+*/
+
+#include <stdio.h>
+#include <unistd.h>		/* for getopt() */
+#include <errno.h>
+#include <ctype.h>		/* for isspace() */
+#include <stdlib.h>
+#include <string.h>
+#include "busybox.h"
+#include "xregex.h"
+
+/* Each sed command turns into one of these structures. */
+typedef struct sed_cmd_s {
+    /* Ordered by alignment requirements: currently 36 bytes on x86 */
+
+    /* address storage */
+    regex_t *beg_match;	/* sed -e '/match/cmd' */
+    regex_t *end_match;	/* sed -e '/match/,/end_match/cmd' */
+    regex_t *sub_match;	/* For 's/sub_match/string/' */
+    int beg_line;		/* 'sed 1p'   0 == apply commands to all lines */
+    int end_line;		/* 'sed 1,3p' 0 == one line only. -1 = last line ($) */
+
+    FILE *file;			/* File (sw) command writes to, -1 for none. */
+    char *string;		/* Data string for (saicytb) commands. */
+
+    unsigned short which_match;		/* (s) Which match to replace (0 for all) */
+
+    /* Bitfields (gcc won't group them if we don't) */
+    unsigned int invert:1;			/* the '!' after the address */
+    unsigned int in_match:1;		/* Next line also included in match? */
+    unsigned int no_newline:1;		/* Last line written by (sw) had no '\n' */
+    unsigned int sub_p:1;			/* (s) print option */
+
+    /* GENERAL FIELDS */
+    char cmd;				/* The command char: abcdDgGhHilnNpPqrstwxy:={} */
+    struct sed_cmd_s *next;	/* Next command (linked list, NULL terminated) */
+} sed_cmd_t;
+
+static const char bad_format_in_subst[] =
+	"bad format in substitution expression";
+static const char *const semicolon_whitespace = "; \n\r\t\v";
+
+struct sed_globals
+{
+	/* options */
+	int be_quiet, in_place, regex_type;
+	FILE *nonstdout;
+	char *outname, *hold_space;
+
+	/* List of input files */
+	int input_file_count,current_input_file;
+	FILE **input_file_list;
+
+	regmatch_t regmatch[10];
+	regex_t *previous_regex_ptr;
+	
+	/* linked list of sed commands */
+	sed_cmd_t sed_cmd_head, *sed_cmd_tail;
+
+	/* Linked list of append lines */
+	llist_t *append_head;
+
+	char *add_cmd_line;
+
+	struct pipeline {
+		char *buf;	/* Space to hold string */
+		int idx;	/* Space used */
+		int len;	/* Space allocated */
+	} pipeline;
+} bbg;
+
+
+void sed_free_and_close_stuff(void);
+#if ENABLE_FEATURE_CLEAN_UP
+void sed_free_and_close_stuff(void)
+{
+	sed_cmd_t *sed_cmd = bbg.sed_cmd_head.next;
+
+	llist_free(bbg.append_head, free);
+
+	while (sed_cmd) {
+		sed_cmd_t *sed_cmd_next = sed_cmd->next;
+
+		if(sed_cmd->file)
+			bb_xprint_and_close_file(sed_cmd->file);
+
+		if (sed_cmd->beg_match) {
+			regfree(sed_cmd->beg_match);
+			free(sed_cmd->beg_match);
+		}
+		if (sed_cmd->end_match) {
+			regfree(sed_cmd->end_match);
+			free(sed_cmd->end_match);
+		}
+		if (sed_cmd->sub_match) {
+			regfree(sed_cmd->sub_match);
+			free(sed_cmd->sub_match);
+		}
+		free(sed_cmd->string);
+		free(sed_cmd);
+		sed_cmd = sed_cmd_next;
+	}
+
+	if(bbg.hold_space) free(bbg.hold_space);
+
+    while(bbg.current_input_file<bbg.input_file_count)
+		fclose(bbg.input_file_list[bbg.current_input_file++]);
+}
+#endif
+
+/* If something bad happens during -i operation, delete temp file */
+
+static void cleanup_outname(void)
+{
+  if(bbg.outname) unlink(bbg.outname);
+}
+
+/* strdup, replacing "\n" with '\n', and "\delimiter" with 'delimiter' */
+
+static void parse_escapes(char *dest, const char *string, int len, char from, char to)
+{
+	int i=0;
+
+	while(i<len) {
+		if(string[i] == '\\') {
+			if(!to || string[i+1] == from) {
+				*(dest++) = to ? to : string[i+1];
+				i+=2;
+				continue;
+			} else *(dest++)=string[i++];
+		}
+		*(dest++) = string[i++];
+	}
+	*dest=0;
+}
+
+static char *copy_parsing_escapes(const char *string, int len)
+{
+	char *dest=xmalloc(len+1);
+
+	parse_escapes(dest,string,len,'n','\n');
+	return dest;
+}
+
+
+/*
+ * index_of_next_unescaped_regexp_delim - walks left to right through a string
+ * beginning at a specified index and returns the index of the next regular
+ * expression delimiter (typically a forward * slash ('/')) not preceded by
+ * a backslash ('\').
+ */
+static int index_of_next_unescaped_regexp_delim(const char delimiter,
+	const char *str)
+{
+	int bracket = -1;
+	int escaped = 0;
+	int idx = 0;
+	char ch;
+
+	for (; (ch = str[idx]); idx++) {
+		if (bracket != -1) {
+			if (ch == ']' && !(bracket == idx - 1 || (bracket == idx - 2
+					&& str[idx - 1] == '^')))
+				bracket = -1;
+		} else if (escaped)
+			escaped = 0;
+		else if (ch == '\\')
+			escaped = 1;
+		else if (ch == '[')
+			bracket = idx;
+		else if (ch == delimiter)
+			return idx;
+	}
+
+	/* if we make it to here, we've hit the end of the string */
+	return -1;
+}
+
+/*
+ *  Returns the index of the third delimiter
+ */
+static int parse_regex_delim(const char *cmdstr, char **match, char **replace)
+{
+	const char *cmdstr_ptr = cmdstr;
+	char delimiter;
+	int idx = 0;
+
+	/* verify that the 's' or 'y' is followed by something.  That something
+	 * (typically a 'slash') is now our regexp delimiter... */
+	if (*cmdstr == '\0') bb_error_msg_and_die(bad_format_in_subst);
+	delimiter = *(cmdstr_ptr++);
+
+	/* save the match string */
+	idx = index_of_next_unescaped_regexp_delim(delimiter, cmdstr_ptr);
+	if (idx == -1) {
+		bb_error_msg_and_die(bad_format_in_subst);
+	}
+	*match = copy_parsing_escapes(cmdstr_ptr, idx);
+
+	/* save the replacement string */
+	cmdstr_ptr += idx + 1;
+	idx = index_of_next_unescaped_regexp_delim(delimiter, cmdstr_ptr);
+	if (idx == -1) {
+		bb_error_msg_and_die(bad_format_in_subst);
+	}
+	*replace = copy_parsing_escapes(cmdstr_ptr, idx);
+
+	return ((cmdstr_ptr - cmdstr) + idx);
+}
+
+/*
+ * returns the index in the string just past where the address ends.
+ */
+static int get_address(char *my_str, int *linenum, regex_t ** regex)
+{
+	char *pos = my_str;
+
+	if (isdigit(*my_str)) {
+		*linenum = strtol(my_str, &pos, 10);
+		/* endstr shouldnt ever equal NULL */
+	} else if (*my_str == '$') {
+		*linenum = -1;
+		pos++;
+	} else if (*my_str == '/' || *my_str == '\\') {
+		int next;
+		char delimiter;
+		char *temp;
+
+		if (*my_str == '\\') delimiter = *(++pos);
+		else delimiter = '/';
+		next = index_of_next_unescaped_regexp_delim(delimiter, ++pos);
+		if (next == -1)
+			bb_error_msg_and_die("unterminated match expression");
+
+		temp=copy_parsing_escapes(pos,next);
+		*regex = (regex_t *) xmalloc(sizeof(regex_t));
+		xregcomp(*regex, temp, bbg.regex_type|REG_NEWLINE);
+		free(temp);
+		/* Move position to next character after last delimiter */
+		pos+=(next+1);
+	}
+	return pos - my_str;
+}
+
+/* Grab a filename.  Whitespace at start is skipped, then goes to EOL. */
+static int parse_file_cmd(sed_cmd_t *sed_cmd, const char *filecmdstr, char **retval)
+{
+	int start = 0, idx, hack=0;
+
+	/* Skip whitespace, then grab filename to end of line */
+	while (isspace(filecmdstr[start])) start++;
+	idx=start;
+	while(filecmdstr[idx] && filecmdstr[idx]!='\n') idx++;
+	/* If lines glued together, put backslash back. */
+	if(filecmdstr[idx]=='\n') hack=1;
+	if(idx==start) bb_error_msg_and_die("Empty filename");
+	*retval = bb_xstrndup(filecmdstr+start, idx-start+hack+1);
+	if(hack) *(idx+*retval)='\\';
+
+	return idx;
+}
+
+static int parse_subst_cmd(sed_cmd_t *const sed_cmd, char *substr)
+{
+	int cflags = bbg.regex_type;
+	char *match;
+	int idx = 0;
+
+	/*
+	 * A substitution command should look something like this:
+	 *    s/match/replace/ #gIpw
+	 *    ||     |        |||
+	 *    mandatory       optional
+	 */
+	idx = parse_regex_delim(substr, &match, &sed_cmd->string);
+
+	/* determine the number of back references in the match string */
+	/* Note: we compute this here rather than in the do_subst_command()
+	 * function to save processor time, at the expense of a little more memory
+	 * (4 bits) per sed_cmd */
+
+	/* process the flags */
+
+	sed_cmd->which_match=1;
+	while (substr[++idx]) {
+		/* Parse match number */
+		if(isdigit(substr[idx])) {
+			if(match[0]!='^') {
+				/* Match 0 treated as all, multiple matches we take the last one. */
+				char *pos=substr+idx;
+				sed_cmd->which_match=(unsigned short)strtol(substr+idx,&pos,10);
+				idx=pos-substr;
+			}
+			continue;
+		}
+		/* Skip spaces */
+		if(isspace(substr[idx])) continue;
+
+		switch (substr[idx]) {
+			/* Replace all occurrences */
+			case 'g':
+				if (match[0] != '^') sed_cmd->which_match = 0;
+				break;
+			/* Print pattern space */
+			case 'p':
+				sed_cmd->sub_p = 1;
+				break;
+			/* Write to file */
+			case 'w':
+			{
+				char *temp;
+				idx+=parse_file_cmd(sed_cmd,substr+idx,&temp);
+
+				break;
+			}
+			/* Ignore case (gnu exension) */
+			case 'I':
+				cflags |= REG_ICASE;
+				break;
+			/* Comment */
+			case '#':
+				while(substr[++idx]);
+				/* Fall through */
+			/* End of command */
+			case ';':
+			case '}':
+				goto out;
+			default:
+				bb_error_msg_and_die("bad option in substitution expression");
+		}
+	}
+out:
+	/* compile the match string into a regex */
+	if (*match != '\0') {
+		/* If match is empty, we use last regex used at runtime */
+		sed_cmd->sub_match = (regex_t *) xmalloc(sizeof(regex_t));
+		xregcomp(sed_cmd->sub_match, match, cflags);
+	}
+	free(match);
+
+	return idx;
+}
+
+/*
+ *  Process the commands arguments
+ */
+static char *parse_cmd_args(sed_cmd_t *sed_cmd, char *cmdstr)
+{
+	/* handle (s)ubstitution command */
+	if (sed_cmd->cmd == 's') cmdstr += parse_subst_cmd(sed_cmd, cmdstr);
+	/* handle edit cmds: (a)ppend, (i)nsert, and (c)hange */
+	else if (strchr("aic", sed_cmd->cmd)) {
+		if ((sed_cmd->end_line || sed_cmd->end_match) && sed_cmd->cmd != 'c')
+			bb_error_msg_and_die
+				("only a beginning address can be specified for edit commands");
+		for(;;) {
+			if(*cmdstr=='\n' || *cmdstr=='\\') {
+				cmdstr++;
+				break;
+			} else if(isspace(*cmdstr)) cmdstr++;
+			else break;
+		}
+		sed_cmd->string = bb_xstrdup(cmdstr);
+		parse_escapes(sed_cmd->string,sed_cmd->string,strlen(cmdstr),0,0);
+		cmdstr += strlen(cmdstr);
+	/* handle file cmds: (r)ead */
+	} else if(strchr("rw", sed_cmd->cmd)) {
+		if (sed_cmd->end_line || sed_cmd->end_match)
+			bb_error_msg_and_die("Command only uses one address");
+		cmdstr += parse_file_cmd(sed_cmd, cmdstr, &sed_cmd->string);
+		if(sed_cmd->cmd=='w')
+			sed_cmd->file=bb_xfopen(sed_cmd->string,"w");
+	/* handle branch commands */
+	} else if (strchr(":btT", sed_cmd->cmd)) {
+		int length;
+
+		while(isspace(*cmdstr)) cmdstr++;
+		length = strcspn(cmdstr, semicolon_whitespace);
+		if (length) {
+			sed_cmd->string = bb_xstrndup(cmdstr, length);
+			cmdstr += length;
+		}
+	}
+	/* translation command */
+	else if (sed_cmd->cmd == 'y') {
+		char *match, *replace;
+		int i=cmdstr[0];
+
+		cmdstr+=parse_regex_delim(cmdstr, &match, &replace)+1;
+		/* \n already parsed, but \delimiter needs unescaping. */
+		parse_escapes(match,match,strlen(match),i,i);
+		parse_escapes(replace,replace,strlen(replace),i,i);
+
+		sed_cmd->string = xzalloc((strlen(match) + 1) * 2);
+		for (i = 0; match[i] && replace[i]; i++) {
+			sed_cmd->string[i * 2] = match[i];
+			sed_cmd->string[(i * 2) + 1] = replace[i];
+		}
+		free(match);
+		free(replace);
+	}
+	/* if it wasnt a single-letter command that takes no arguments
+	 * then it must be an invalid command.
+	 */
+	else if (strchr("dDgGhHlnNpPqx={}", sed_cmd->cmd) == 0) {
+		bb_error_msg_and_die("Unsupported command %c", sed_cmd->cmd);
+	}
+
+	/* give back whatever's left over */
+	return (cmdstr);
+}
+
+
+/* Parse address+command sets, skipping comment lines. */
+
+static void add_cmd(char *cmdstr)
+{
+	sed_cmd_t *sed_cmd;
+	int temp;
+
+	/* Append this line to any unfinished line from last time. */
+	if (bbg.add_cmd_line) {
+		cmdstr = bb_xasprintf("%s\n%s", bbg.add_cmd_line, cmdstr);
+		free(bbg.add_cmd_line);
+		bbg.add_cmd_line = cmdstr;
+	}
+
+	/* If this line ends with backslash, request next line. */
+	temp=strlen(cmdstr);
+	if(temp && cmdstr[temp-1]=='\\') {
+		if (!bbg.add_cmd_line) bbg.add_cmd_line = bb_xstrdup(cmdstr);
+		bbg.add_cmd_line[temp-1] = 0;
+		return;
+	}
+
+	/* Loop parsing all commands in this line. */
+	while(*cmdstr) {
+		/* Skip leading whitespace and semicolons */
+		cmdstr += strspn(cmdstr, semicolon_whitespace);
+
+		/* If no more commands, exit. */
+		if(!*cmdstr) break;
+
+		/* if this is a comment, jump past it and keep going */
+		if (*cmdstr == '#') {
+			/* "#n" is the same as using -n on the command line */
+			if (cmdstr[1] == 'n') bbg.be_quiet++;
+			if(!(cmdstr=strpbrk(cmdstr, "\n\r"))) break;
+			continue;
+		}
+
+		/* parse the command
+		 * format is: [addr][,addr][!]cmd
+		 *            |----||-----||-|
+		 *            part1 part2  part3
+		 */
+
+		sed_cmd = xzalloc(sizeof(sed_cmd_t));
+
+		/* first part (if present) is an address: either a '$', a number or a /regex/ */
+		cmdstr += get_address(cmdstr, &sed_cmd->beg_line, &sed_cmd->beg_match);
+
+		/* second part (if present) will begin with a comma */
+		if (*cmdstr == ',') {
+			int idx;
+
+			cmdstr++;
+			idx = get_address(cmdstr, &sed_cmd->end_line, &sed_cmd->end_match);
+			if (!idx) bb_error_msg_and_die("no address after comma\n");
+			cmdstr += idx;
+		}
+
+		/* skip whitespace before the command */
+		while (isspace(*cmdstr)) cmdstr++;
+
+		/* Check for inversion flag */
+		if (*cmdstr == '!') {
+			sed_cmd->invert = 1;
+			cmdstr++;
+
+			/* skip whitespace before the command */
+			while (isspace(*cmdstr)) cmdstr++;
+		}
+
+		/* last part (mandatory) will be a command */
+		if (!*cmdstr) bb_error_msg_and_die("missing command");
+		sed_cmd->cmd = *(cmdstr++);
+		cmdstr = parse_cmd_args(sed_cmd, cmdstr);
+
+		/* Add the command to the command array */
+		bbg.sed_cmd_tail->next = sed_cmd;
+		bbg.sed_cmd_tail = bbg.sed_cmd_tail->next;
+	}
+
+	/* If we glued multiple lines together, free the memory. */
+	free(bbg.add_cmd_line);
+	bbg.add_cmd_line = NULL;
+}
+
+/* Append to a string, reallocating memory as necessary. */
+
+#define PIPE_GROW 64
+
+static void pipe_putc(char c)
+{
+	if(bbg.pipeline.idx==bbg.pipeline.len) {
+		bbg.pipeline.buf = xrealloc(bbg.pipeline.buf,
+								bbg.pipeline.len + PIPE_GROW);
+		bbg.pipeline.len+=PIPE_GROW;
+	}
+	bbg.pipeline.buf[bbg.pipeline.idx++] = c;
+}
+
+static void do_subst_w_backrefs(const char *line, const char *replace)
+{
+	int i,j;
+
+	/* go through the replacement string */
+	for (i = 0; replace[i]; i++) {
+		/* if we find a backreference (\1, \2, etc.) print the backref'ed * text */
+		if (replace[i] == '\\' && replace[i+1]>='0' && replace[i+1]<='9') {
+			int backref=replace[++i]-'0';
+
+			/* print out the text held in bbg.regmatch[backref] */
+			if(bbg.regmatch[backref].rm_so != -1)
+				for (j = bbg.regmatch[backref].rm_so;
+					j < bbg.regmatch[backref].rm_eo; j++) pipe_putc(line[j]);
+		}
+
+		/* if we find a backslash escaped character, print the character */
+		else if (replace[i] == '\\') pipe_putc(replace[++i]);
+
+		/* if we find an unescaped '&' print out the whole matched text. */
+		else if (replace[i] == '&')
+			for (j = bbg.regmatch[0].rm_so; j < bbg.regmatch[0].rm_eo; j++)
+				pipe_putc(line[j]);
+		/* Otherwise just output the character. */
+		else pipe_putc(replace[i]);
+	}
+}
+
+static int do_subst_command(sed_cmd_t *sed_cmd, char **line)
+{
+	char *oldline = *line;
+	int altered = 0;
+	int match_count=0;
+	regex_t *current_regex;
+
+	/* Handle empty regex. */
+	if (sed_cmd->sub_match == NULL) {
+		current_regex = bbg.previous_regex_ptr;
+		if(!current_regex)
+			bb_error_msg_and_die("No previous regexp.");
+	} else bbg.previous_regex_ptr = current_regex = sed_cmd->sub_match;
+
+	/* Find the first match */
+	if(REG_NOMATCH==regexec(current_regex, oldline, 10, bbg.regmatch, 0))
+		return 0;
+
+	/* Initialize temporary output buffer. */
+	bbg.pipeline.buf=xmalloc(PIPE_GROW);
+	bbg.pipeline.len=PIPE_GROW;
+	bbg.pipeline.idx=0;
+
+	/* Now loop through, substituting for matches */
+	do {
+		int i;
+
+		/* Work around bug in glibc regexec, demonstrated by:
+		   echo " a.b" | busybox sed 's [^ .]* x g'
+		   The match_count check is so not to break
+		   echo "hi" | busybox sed 's/^/!/g' */
+		if(!bbg.regmatch[0].rm_so && !bbg.regmatch[0].rm_eo && match_count) {
+			pipe_putc(*(oldline++));
+			continue;
+		}
+
+		match_count++;
+
+		/* If we aren't interested in this match, output old line to
+		   end of match and continue */
+		if(sed_cmd->which_match && sed_cmd->which_match!=match_count) {
+			for(i=0;i<bbg.regmatch[0].rm_eo;i++)
+				pipe_putc(oldline[i]);
+			continue;
+		}
+
+		/* print everything before the match */
+		for (i = 0; i < bbg.regmatch[0].rm_so; i++) pipe_putc(oldline[i]);
+
+		/* then print the substitution string */
+		do_subst_w_backrefs(oldline, sed_cmd->string);
+
+		/* advance past the match */
+		oldline += bbg.regmatch[0].rm_eo;
+		/* flag that something has changed */
+		altered++;
+
+		/* if we're not doing this globally, get out now */
+		if (sed_cmd->which_match) break;
+	} while (*oldline && (regexec(current_regex, oldline, 10, bbg.regmatch, 0) != REG_NOMATCH));
+
+	/* Copy rest of string into output pipeline */
+
+	while(*oldline) pipe_putc(*(oldline++));
+	pipe_putc(0);
+
+	free(*line);
+	*line = bbg.pipeline.buf;
+	return altered;
+}
+
+/* Set command pointer to point to this label.  (Does not handle null label.) */
+static sed_cmd_t *branch_to(const char *label)
+{
+	sed_cmd_t *sed_cmd;
+
+	for (sed_cmd = bbg.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) {
+		if ((sed_cmd->cmd == ':') && (sed_cmd->string) && (strcmp(sed_cmd->string, label) == 0)) {
+			return (sed_cmd);
+		}
+	}
+	bb_error_msg_and_die("Can't find label for jump to `%s'", label);
+}
+
+static void append(char *s)
+{
+	llist_add_to_end(&bbg.append_head, bb_xstrdup(s));
+}
+
+static void flush_append(void)
+{
+	char *data;
+
+	/* Output appended lines. */
+	while((data = (char *)llist_pop(&bbg.append_head))) {
+		fprintf(bbg.nonstdout,"%s\n",data);
+		free(data);
+	}
+}
+
+static void add_input_file(FILE *file)
+{
+	bbg.input_file_list=xrealloc(bbg.input_file_list,
+			(bbg.input_file_count + 1) * sizeof(FILE *));
+	bbg.input_file_list[bbg.input_file_count++] = file;
+}
+
+/* Get next line of input from bbg.input_file_list, flushing append buffer and
+ * noting if we ran out of files without a newline on the last line we read.
+ */
+static char *get_next_line(int *no_newline)
+{
+	char *temp=NULL;
+	int len;
+
+	flush_append();
+	while (bbg.current_input_file<bbg.input_file_count) {
+		temp = bb_get_chunk_from_file(bbg.input_file_list[bbg.current_input_file],&len);
+		if (temp) {
+			*no_newline = !(len && temp[len-1]=='\n');
+			if (!*no_newline) temp[len-1] = 0;
+			break;
+		// Close this file and advance to next one
+		} else fclose(bbg.input_file_list[bbg.current_input_file++]);
+	}
+
+	return temp;
+}
+
+/* Output line of text.  missing_newline means the last line output did not
+   end with a newline.  no_newline means this line does not end with a
+   newline. */
+
+static int puts_maybe_newline(char *s, FILE *file, int missing_newline, int no_newline)
+{
+	if(missing_newline) fputc('\n',file);
+	fputs(s,file);
+	if(!no_newline) fputc('\n',file);
+
+    if(ferror(file)) {
+		bb_default_error_retval = 4;  /* It's what gnu sed exits with... */
+		bb_error_msg_and_die(bb_msg_write_error);
+	}
+
+	return no_newline;
+}
+
+#define sed_puts(s,n) missing_newline=puts_maybe_newline(s,bbg.nonstdout,missing_newline,n)
+
+/* Process all the lines in all the files */
+
+static void process_files(void)
+{
+	char *pattern_space, *next_line;
+	int linenum = 0, missing_newline=0;
+	int no_newline,next_no_newline=0;
+
+	/* Prime the pump */
+	next_line = get_next_line(&next_no_newline);
+
+	/* go through every line in each file */
+	for(;;) {
+		sed_cmd_t *sed_cmd;
+		int substituted=0;
+
+		/* Advance to next line.  Stop if out of lines. */
+		if(!(pattern_space=next_line)) break;
+		no_newline=next_no_newline;
+
+		/* Read one line in advance so we can act on the last line,
+		 * the '$' address */
+		next_line = get_next_line(&next_no_newline);
+		linenum++;
+restart:
+		/* for every line, go through all the commands */
+		for (sed_cmd = bbg.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next)
+		{
+			int old_matched, matched;
+
+			old_matched = sed_cmd->in_match;
+
+			/* Determine if this command matches this line: */
+
+			/* Are we continuing a previous multi-line match? */
+
+			sed_cmd->in_match = sed_cmd->in_match
+
+			/* Or is no range necessary? */
+				|| (!sed_cmd->beg_line && !sed_cmd->end_line
+					&& !sed_cmd->beg_match && !sed_cmd->end_match)
+
+			/* Or did we match the start of a numerical range? */
+				|| (sed_cmd->beg_line > 0 && (sed_cmd->beg_line == linenum))
+
+			/* Or does this line match our begin address regex? */
+			        || (sed_cmd->beg_match &&
+				    !regexec(sed_cmd->beg_match, pattern_space, 0, NULL, 0))
+
+			/* Or did we match last line of input? */
+				|| (sed_cmd->beg_line == -1 && next_line == NULL);
+
+			/* Snapshot the value */
+
+			matched = sed_cmd->in_match;
+
+			/* Is this line the end of the current match? */
+
+			if(matched) {
+				sed_cmd->in_match = !(
+					/* has the ending line come, or is this a single address command? */
+					(sed_cmd->end_line ?
+						sed_cmd->end_line==-1 ?
+							!next_line
+							: sed_cmd->end_line<=linenum
+						: !sed_cmd->end_match)
+					/* or does this line matches our last address regex */
+					|| (sed_cmd->end_match && old_matched && (regexec(sed_cmd->end_match, pattern_space, 0, NULL, 0) == 0))
+				);
+			}
+
+			/* Skip blocks of commands we didn't match. */
+			if (sed_cmd->cmd == '{') {
+				if(sed_cmd->invert ? matched : !matched)
+					while(sed_cmd && sed_cmd->cmd!='}') sed_cmd=sed_cmd->next;
+				if(!sed_cmd) bb_error_msg_and_die("Unterminated {");
+				continue;
+			}
+
+			/* Okay, so did this line match? */
+			if (sed_cmd->invert ? !matched : matched) {
+				/* Update last used regex in case a blank substitute BRE is found */
+				if (sed_cmd->beg_match) {
+					bbg.previous_regex_ptr = sed_cmd->beg_match;
+				}
+
+				/* actual sedding */
+				switch (sed_cmd->cmd) {
+
+					/* Print line number */
+					case '=':
+						fprintf(bbg.nonstdout,"%d\n", linenum);
+						break;
+
+					/* Write the current pattern space up to the first newline */
+					case 'P':
+					{
+						char *tmp = strchr(pattern_space, '\n');
+
+						if (tmp) {
+							*tmp = '\0';
+							sed_puts(pattern_space,1);
+							*tmp = '\n';
+							break;
+						}
+						/* Fall Through */
+					}
+
+					/* Write the current pattern space to output */
+					case 'p':
+						sed_puts(pattern_space,no_newline);
+						break;
+					/* Delete up through first newline */
+					case 'D':
+					{
+						char *tmp = strchr(pattern_space,'\n');
+
+						if(tmp) {
+							tmp=bb_xstrdup(tmp+1);
+							free(pattern_space);
+							pattern_space=tmp;
+							goto restart;
+						}
+					}
+					/* discard this line. */
+					case 'd':
+						goto discard_line;
+
+					/* Substitute with regex */
+					case 's':
+						if(do_subst_command(sed_cmd, &pattern_space)) {
+							substituted|=1;
+
+							/* handle p option */
+							if(sed_cmd->sub_p)
+								sed_puts(pattern_space,no_newline);
+							/* handle w option */
+							if(sed_cmd->file)
+								sed_cmd->no_newline=puts_maybe_newline(pattern_space, sed_cmd->file, sed_cmd->no_newline, no_newline);
+
+						}
+						break;
+
+					/* Append line to linked list to be printed later */
+					case 'a':
+					{
+						append(sed_cmd->string);
+						break;
+					}
+
+					/* Insert text before this line */
+					case 'i':
+						sed_puts(sed_cmd->string,1);
+						break;
+
+					/* Cut and paste text (replace) */
+					case 'c':
+						/* Only triggers on last line of a matching range. */
+						if (!sed_cmd->in_match) sed_puts(sed_cmd->string,0);
+						goto discard_line;
+
+					/* Read file, append contents to output */
+					case 'r':
+					{
+						FILE *rfile;
+
+						rfile = fopen(sed_cmd->string, "r");
+						if (rfile) {
+							char *line;
+
+							while ((line = bb_get_chomped_line_from_file(rfile))
+									!= NULL)
+								append(line);
+							bb_xprint_and_close_file(rfile);
+						}
+
+						break;
+					}
+
+					/* Write pattern space to file. */
+					case 'w':
+						sed_cmd->no_newline=puts_maybe_newline(pattern_space,sed_cmd->file, sed_cmd->no_newline,no_newline);
+						break;
+
+					/* Read next line from input */
+					case 'n':
+						if (!bbg.be_quiet)
+							sed_puts(pattern_space,no_newline);
+						if (next_line) {
+							free(pattern_space);
+							pattern_space = next_line;
+							no_newline=next_no_newline;
+							next_line = get_next_line(&next_no_newline);
+							linenum++;
+							break;
+						}
+						/* fall through */
+
+					/* Quit.  End of script, end of input. */
+					case 'q':
+						/* Exit the outer while loop */
+						free(next_line);
+						next_line = NULL;
+						goto discard_commands;
+
+					/* Append the next line to the current line */
+					case 'N':
+					{
+						/* If no next line, jump to end of script and exit. */
+						if (next_line == NULL) {
+							/* Jump to end of script and exit */
+							free(next_line);
+							next_line = NULL;
+							goto discard_line;
+						/* append next_line, read new next_line. */
+						} else {
+							int len=strlen(pattern_space);
+
+							pattern_space = realloc(pattern_space, len + strlen(next_line) + 2);
+							pattern_space[len]='\n';
+							strcpy(pattern_space+len+1, next_line);
+							no_newline=next_no_newline;
+							next_line = get_next_line(&next_no_newline);
+							linenum++;
+						}
+						break;
+					}
+
+					/* Test/branch if substitution occurred */
+					case 't':
+						if(!substituted) break;
+						substituted=0;
+						/* Fall through */
+					/* Test/branch if substitution didn't occur */
+					case 'T':
+						if (substituted) break;
+						/* Fall through */
+					/* Branch to label */
+					case 'b':
+						if (!sed_cmd->string) goto discard_commands;
+						else sed_cmd = branch_to(sed_cmd->string);
+						break;
+					/* Transliterate characters */
+					case 'y':
+					{
+						int i;
+
+						for (i = 0; pattern_space[i]; i++) {
+							int j;
+
+							for (j = 0; sed_cmd->string[j]; j += 2) {
+								if (pattern_space[i] == sed_cmd->string[j]) {
+									pattern_space[i] = sed_cmd->string[j + 1];
+									break;
+								}
+							}
+						}
+
+						break;
+					}
+					case 'g':	/* Replace pattern space with hold space */
+						free(pattern_space);
+						pattern_space = bb_xstrdup(bbg.hold_space ? bbg.hold_space : "");
+						break;
+					case 'G':	/* Append newline and hold space to pattern space */
+					{
+						int pattern_space_size = 2;
+						int hold_space_size = 0;
+
+						if (pattern_space)
+							pattern_space_size += strlen(pattern_space);
+						if (bbg.hold_space)
+							hold_space_size = strlen(bbg.hold_space);
+						pattern_space = xrealloc(pattern_space,
+								pattern_space_size + hold_space_size);
+						if (pattern_space_size == 2) pattern_space[0]=0;
+						strcat(pattern_space, "\n");
+						if (bbg.hold_space)
+							strcat(pattern_space, bbg.hold_space);
+						no_newline=0;
+
+						break;
+					}
+					case 'h':	/* Replace hold space with pattern space */
+						free(bbg.hold_space);
+						bbg.hold_space = bb_xstrdup(pattern_space);
+						break;
+					case 'H':	/* Append newline and pattern space to hold space */
+					{
+						int hold_space_size = 2;
+						int pattern_space_size = 0;
+
+						if (bbg.hold_space)
+							hold_space_size += strlen(bbg.hold_space);
+						if (pattern_space)
+							pattern_space_size = strlen(pattern_space);
+						bbg.hold_space = xrealloc(bbg.hold_space,
+											hold_space_size + pattern_space_size);
+
+						if (hold_space_size == 2) *bbg.hold_space=0;
+						strcat(bbg.hold_space, "\n");
+						if (pattern_space) strcat(bbg.hold_space, pattern_space);
+
+						break;
+					}
+					case 'x': /* Exchange hold and pattern space */
+					{
+						char *tmp = pattern_space;
+						pattern_space = bbg.hold_space ? : xzalloc(1);
+						no_newline=0;
+						bbg.hold_space = tmp;
+						break;
+					}
+				}
+			}
+		}
+
+		/*
+		 * exit point from sedding...
+		 */
+discard_commands:
+		/* we will print the line unless we were told to be quiet ('-n')
+		   or if the line was suppressed (ala 'd'elete) */
+		if (!bbg.be_quiet) sed_puts(pattern_space,no_newline);
+
+		/* Delete and such jump here. */
+discard_line:
+		flush_append();
+		free(pattern_space);
+	}
+}
+
+/* It is possible to have a command line argument with embedded
+   newlines.  This counts as multiple command lines. */
+
+static void add_cmd_block(char *cmdstr)
+{
+	int go=1;
+	char *temp=bb_xstrdup(cmdstr),*temp2=temp;
+
+	while(go) {
+		int len=strcspn(temp2,"\n");
+		if(!temp2[len]) go=0;
+		else temp2[len]=0;
+		add_cmd(temp2);
+		temp2+=len+1;
+	}
+	free(temp);
+}
+
+int sed_main(int argc, char **argv)
+{
+	int status = EXIT_SUCCESS, opt, getpat = 1;
+
+	bbg.sed_cmd_tail=&bbg.sed_cmd_head;
+
+	/* destroy command strings on exit */
+	if (ENABLE_FEATURE_CLEAN_UP) atexit(sed_free_and_close_stuff);
+
+	/* Lie to autoconf when it starts asking stupid questions. */
+	if(argc==2 && !strcmp(argv[1],"--version")) {
+		printf("This is not GNU sed version 4.0\n");
+		exit(0);
+	}
+
+	/* do normal option parsing */
+	while ((opt = getopt(argc, argv, "irne:f:")) > 0) {
+		switch (opt) {
+		case 'i':
+			bbg.in_place++;
+			atexit(cleanup_outname);
+			break;
+		case 'r':
+			bbg.regex_type|=REG_EXTENDED;
+			break;
+		case 'n':
+			bbg.be_quiet++;
+			break;
+		case 'e':
+			add_cmd_block(optarg);
+			getpat=0;
+			break;
+		case 'f':
+		{
+			FILE *cmdfile;
+			char *line;
+
+			cmdfile = bb_xfopen(optarg, "r");
+
+			while ((line = bb_get_chomped_line_from_file(cmdfile)) != NULL) {
+				add_cmd(line);
+				getpat=0;
+				free(line);
+			}
+			bb_xprint_and_close_file(cmdfile);
+
+			break;
+		}
+		default:
+			bb_show_usage();
+		}
+	}
+
+	/* if we didn't get a pattern from -e or -f, use argv[optind] */
+	if(getpat) {
+		if (argv[optind] == NULL)
+			bb_show_usage();
+		else
+			add_cmd_block(argv[optind++]);
+	}
+	/* Flush any unfinished commands. */
+	add_cmd("");
+
+	/* By default, we write to stdout */
+	bbg.nonstdout=stdout;
+
+	/* argv[(optind)..(argc-1)] should be names of file to process. If no
+	 * files were specified or '-' was specified, take input from stdin.
+	 * Otherwise, we process all the files specified. */
+	if (argv[optind] == NULL) {
+		if(bbg.in_place) bb_error_msg_and_die(bb_msg_requires_arg, "-i");
+		add_input_file(stdin);
+		process_files();
+	} else {
+		int i;
+		FILE *file;
+
+		for (i = optind; i < argc; i++) {
+			if(!strcmp(argv[i], "-") && !bbg.in_place) {
+				add_input_file(stdin);
+				process_files();
+			} else {
+				file = bb_wfopen(argv[i], "r");
+				if (file) {
+					if(bbg.in_place) {
+						struct stat statbuf;
+						int nonstdoutfd;
+
+						bbg.outname=bb_xstrndup(argv[i],strlen(argv[i])+6);
+						strcat(bbg.outname,"XXXXXX");
+						if(-1==(nonstdoutfd=mkstemp(bbg.outname)))
+							bb_error_msg_and_die("no temp file");
+						bbg.nonstdout=fdopen(nonstdoutfd,"w");
+
+						/* Set permissions of output file */
+
+						fstat(fileno(file),&statbuf);
+						fchmod(nonstdoutfd,statbuf.st_mode);
+						add_input_file(file);
+						process_files();
+						fclose(bbg.nonstdout);
+
+						bbg.nonstdout=stdout;
+						unlink(argv[i]);
+						rename(bbg.outname,argv[i]);
+						free(bbg.outname);
+						bbg.outname=0;
+					} else add_input_file(file);
+				} else {
+					status = EXIT_FAILURE;
+				}
+			}
+		}
+		if(bbg.input_file_count>bbg.current_input_file) process_files();
+	}
+
+	return status;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/vi.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/vi.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/editors/vi.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3944 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * tiny vi.c: A small 'vi' clone
+ * Copyright (C) 2000, 2001 Sterling Huxley <sterling at europa.com>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+/*
+ * Things To Do:
+ *	EXINIT
+ *	$HOME/.exrc  and  ./.exrc
+ *	add magic to search	/foo.*bar
+ *	add :help command
+ *	:map macros
+ *	how about mode lines:   vi: set sw=8 ts=8:
+ *	if mark[] values were line numbers rather than pointers
+ *	   it would be easier to change the mark when add/delete lines
+ *	More intelligence in refresh()
+ *	":r !cmd"  and  "!cmd"  to filter text through an external command
+ *	A true "undo" facility
+ *	An "ex" line oriented mode- maybe using "cmdedit"
+ */
+
+
+#include "busybox.h"
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <regex.h>
+#include <ctype.h>
+#include <errno.h>
+#define vi_Version BB_VER " " BB_BT
+
+#ifdef CONFIG_LOCALE_SUPPORT
+#define Isprint(c) isprint((c))
+#else
+#define Isprint(c) ( (c) >= ' ' && (c) != 127 && (c) != ((unsigned char)'\233') )
+#endif
+
+#define MAX_SCR_COLS		BUFSIZ
+
+// Misc. non-Ascii keys that report an escape sequence
+#define VI_K_UP			128	// cursor key Up
+#define VI_K_DOWN		129	// cursor key Down
+#define VI_K_RIGHT		130	// Cursor Key Right
+#define VI_K_LEFT		131	// cursor key Left
+#define VI_K_HOME		132	// Cursor Key Home
+#define VI_K_END		133	// Cursor Key End
+#define VI_K_INSERT		134	// Cursor Key Insert
+#define VI_K_PAGEUP		135	// Cursor Key Page Up
+#define VI_K_PAGEDOWN		136	// Cursor Key Page Down
+#define VI_K_FUN1		137	// Function Key F1
+#define VI_K_FUN2		138	// Function Key F2
+#define VI_K_FUN3		139	// Function Key F3
+#define VI_K_FUN4		140	// Function Key F4
+#define VI_K_FUN5		141	// Function Key F5
+#define VI_K_FUN6		142	// Function Key F6
+#define VI_K_FUN7		143	// Function Key F7
+#define VI_K_FUN8		144	// Function Key F8
+#define VI_K_FUN9		145	// Function Key F9
+#define VI_K_FUN10		146	// Function Key F10
+#define VI_K_FUN11		147	// Function Key F11
+#define VI_K_FUN12		148	// Function Key F12
+
+/* vt102 typical ESC sequence */
+/* terminal standout start/normal ESC sequence */
+static const char SOs[] = "\033[7m";
+static const char SOn[] = "\033[0m";
+/* terminal bell sequence */
+static const char bell[] = "\007";
+/* Clear-end-of-line and Clear-end-of-screen ESC sequence */
+static const char Ceol[] = "\033[0K";
+static const char Ceos [] = "\033[0J";
+/* Cursor motion arbitrary destination ESC sequence */
+static const char CMrc[] = "\033[%d;%dH";
+/* Cursor motion up and down ESC sequence */
+static const char CMup[] = "\033[A";
+static const char CMdown[] = "\n";
+
+
+enum {
+	YANKONLY = FALSE,
+	YANKDEL = TRUE,
+	FORWARD = 1,	// code depends on "1"  for array index
+	BACK = -1,	// code depends on "-1" for array index
+	LIMITED = 0,	// how much of text[] in char_search
+	FULL = 1,	// how much of text[] in char_search
+
+	S_BEFORE_WS = 1,	// used in skip_thing() for moving "dot"
+	S_TO_WS = 2,		// used in skip_thing() for moving "dot"
+	S_OVER_WS = 3,		// used in skip_thing() for moving "dot"
+	S_END_PUNCT = 4,	// used in skip_thing() for moving "dot"
+	S_END_ALNUM = 5 	// used in skip_thing() for moving "dot"
+};
+
+typedef unsigned char Byte;
+
+static int vi_setops;
+#define VI_AUTOINDENT 1
+#define VI_SHOWMATCH  2
+#define VI_IGNORECASE 4
+#define VI_ERR_METHOD 8
+#define autoindent (vi_setops & VI_AUTOINDENT)
+#define showmatch  (vi_setops & VI_SHOWMATCH )
+#define ignorecase (vi_setops & VI_IGNORECASE)
+/* indicate error with beep or flash */
+#define err_method (vi_setops & VI_ERR_METHOD)
+
+
+static int editing;		// >0 while we are editing a file
+static int cmd_mode;		// 0=command  1=insert 2=replace
+static int file_modified;	// buffer contents changed
+static int last_file_modified = -1;
+static int fn_start;		// index of first cmd line file name
+static int save_argc;		// how many file names on cmd line
+static int cmdcnt;		// repetition count
+static fd_set rfds;		// use select() for small sleeps
+static struct timeval tv;	// use select() for small sleeps
+static int rows, columns;	// the terminal screen is this size
+static int crow, ccol, offset;	// cursor is on Crow x Ccol with Horz Ofset
+static Byte *status_buffer;	// mesages to the user
+#define STATUS_BUFFER_LEN  200
+static int have_status_msg;     // is default edit status needed?
+static int last_status_cksum;   // hash of current status line
+static Byte *cfn;		// previous, current, and next file name
+static Byte *text, *end, *textend;	// pointers to the user data in memory
+static Byte *screen;		// pointer to the virtual screen buffer
+static int screensize;		//            and its size
+static Byte *screenbegin;	// index into text[], of top line on the screen
+static Byte *dot;		// where all the action takes place
+static int tabstop;
+static struct termios term_orig, term_vi;	// remember what the cooked mode was
+static Byte erase_char;         // the users erase character
+static Byte last_input_char;    // last char read from user
+static Byte last_forward_char;  // last char searched for with 'f'
+
+#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
+static int last_row;		// where the cursor was last moved to
+#endif							/* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
+#ifdef CONFIG_FEATURE_VI_USE_SIGNALS
+static jmp_buf restart;		// catch_sig()
+#endif							/* CONFIG_FEATURE_VI_USE_SIGNALS */
+#if defined(CONFIG_FEATURE_VI_USE_SIGNALS) || defined(CONFIG_FEATURE_VI_CRASHME)
+static int my_pid;
+#endif
+#ifdef CONFIG_FEATURE_VI_DOT_CMD
+static int adding2q;		// are we currently adding user input to q
+static Byte *last_modifying_cmd;	// last modifying cmd for "."
+static Byte *ioq, *ioq_start;	// pointer to string for get_one_char to "read"
+#endif							/* CONFIG_FEATURE_VI_DOT_CMD */
+#if	defined(CONFIG_FEATURE_VI_DOT_CMD) || defined(CONFIG_FEATURE_VI_YANKMARK)
+static Byte *modifying_cmds;	// cmds that modify text[]
+#endif							/* CONFIG_FEATURE_VI_DOT_CMD || CONFIG_FEATURE_VI_YANKMARK */
+#ifdef CONFIG_FEATURE_VI_READONLY
+static int vi_readonly, readonly;
+#endif							/* CONFIG_FEATURE_VI_READONLY */
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+static Byte *reg[28];		// named register a-z, "D", and "U" 0-25,26,27
+static int YDreg, Ureg;		// default delete register and orig line for "U"
+static Byte *mark[28];		// user marks points somewhere in text[]-  a-z and previous context ''
+static Byte *context_start, *context_end;
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+#ifdef CONFIG_FEATURE_VI_SEARCH
+static Byte *last_search_pattern;	// last pattern from a '/' or '?' search
+#endif							/* CONFIG_FEATURE_VI_SEARCH */
+
+
+static void edit_file(Byte *);	// edit one file
+static void do_cmd(Byte);	// execute a command
+static void sync_cursor(Byte *, int *, int *);	// synchronize the screen cursor to dot
+static Byte *begin_line(Byte *);	// return pointer to cur line B-o-l
+static Byte *end_line(Byte *);	// return pointer to cur line E-o-l
+static Byte *prev_line(Byte *);	// return pointer to prev line B-o-l
+static Byte *next_line(Byte *);	// return pointer to next line B-o-l
+static Byte *end_screen(void);	// get pointer to last char on screen
+static int count_lines(Byte *, Byte *);	// count line from start to stop
+static Byte *find_line(int);	// find begining of line #li
+static Byte *move_to_col(Byte *, int);	// move "p" to column l
+static int isblnk(Byte);	// is the char a blank or tab
+static void dot_left(void);	// move dot left- dont leave line
+static void dot_right(void);	// move dot right- dont leave line
+static void dot_begin(void);	// move dot to B-o-l
+static void dot_end(void);	// move dot to E-o-l
+static void dot_next(void);	// move dot to next line B-o-l
+static void dot_prev(void);	// move dot to prev line B-o-l
+static void dot_scroll(int, int);	// move the screen up or down
+static void dot_skip_over_ws(void);	// move dot pat WS
+static void dot_delete(void);	// delete the char at 'dot'
+static Byte *bound_dot(Byte *);	// make sure  text[0] <= P < "end"
+static Byte *new_screen(int, int);	// malloc virtual screen memory
+static Byte *new_text(int);	// malloc memory for text[] buffer
+static Byte *char_insert(Byte *, Byte);	// insert the char c at 'p'
+static Byte *stupid_insert(Byte *, Byte);	// stupidly insert the char c at 'p'
+static Byte find_range(Byte **, Byte **, Byte);	// return pointers for an object
+static int st_test(Byte *, int, int, Byte *);	// helper for skip_thing()
+static Byte *skip_thing(Byte *, int, int, int);	// skip some object
+static Byte *find_pair(Byte *, Byte);	// find matching pair ()  []  {}
+static Byte *text_hole_delete(Byte *, Byte *);	// at "p", delete a 'size' byte hole
+static Byte *text_hole_make(Byte *, int);	// at "p", make a 'size' byte hole
+static Byte *yank_delete(Byte *, Byte *, int, int);	// yank text[] into register then delete
+static void show_help(void);	// display some help info
+static void rawmode(void);	// set "raw" mode on tty
+static void cookmode(void);	// return to "cooked" mode on tty
+static int mysleep(int);	// sleep for 'h' 1/100 seconds
+static Byte readit(void);	// read (maybe cursor) key from stdin
+static Byte get_one_char(void);	// read 1 char from stdin
+static int file_size(const Byte *);   // what is the byte size of "fn"
+static int file_insert(Byte *, Byte *, int);
+static int file_write(Byte *, Byte *, Byte *);
+static void place_cursor(int, int, int);
+static void screen_erase(void);
+static void clear_to_eol(void);
+static void clear_to_eos(void);
+static void standout_start(void);	// send "start reverse video" sequence
+static void standout_end(void);	// send "end reverse video" sequence
+static void flash(int);		// flash the terminal screen
+static void show_status_line(void);	// put a message on the bottom line
+static void psb(const char *, ...);     // Print Status Buf
+static void psbs(const char *, ...);    // Print Status Buf in standout mode
+static void ni(Byte *);		// display messages
+static int format_edit_status(void);	// format file status on status line
+static void redraw(int);	// force a full screen refresh
+static void format_line(Byte*, Byte*, int);
+static void refresh(int);	// update the terminal from screen[]
+
+static void Indicate_Error(void);       // use flash or beep to indicate error
+#define indicate_error(c) Indicate_Error()
+static void Hit_Return(void);
+
+#ifdef CONFIG_FEATURE_VI_SEARCH
+static Byte *char_search(Byte *, Byte *, int, int);	// search for pattern starting at p
+static int mycmp(Byte *, Byte *, int);	// string cmp based in "ignorecase"
+#endif							/* CONFIG_FEATURE_VI_SEARCH */
+#ifdef CONFIG_FEATURE_VI_COLON
+static Byte *get_one_address(Byte *, int *);	// get colon addr, if present
+static Byte *get_address(Byte *, int *, int *);	// get two colon addrs, if present
+static void colon(Byte *);	// execute the "colon" mode cmds
+#endif							/* CONFIG_FEATURE_VI_COLON */
+#ifdef CONFIG_FEATURE_VI_USE_SIGNALS
+static void winch_sig(int);	// catch window size changes
+static void suspend_sig(int);	// catch ctrl-Z
+static void catch_sig(int);     // catch ctrl-C and alarm time-outs
+#endif							/* CONFIG_FEATURE_VI_USE_SIGNALS */
+#ifdef CONFIG_FEATURE_VI_DOT_CMD
+static void start_new_cmd_q(Byte);	// new queue for command
+static void end_cmd_q(void);	// stop saving input chars
+#else							/* CONFIG_FEATURE_VI_DOT_CMD */
+#define end_cmd_q()
+#endif							/* CONFIG_FEATURE_VI_DOT_CMD */
+#ifdef CONFIG_FEATURE_VI_SETOPTS
+static void showmatching(Byte *);	// show the matching pair ()  []  {}
+#endif							/* CONFIG_FEATURE_VI_SETOPTS */
+#if defined(CONFIG_FEATURE_VI_YANKMARK) || (defined(CONFIG_FEATURE_VI_COLON) && defined(CONFIG_FEATURE_VI_SEARCH)) || defined(CONFIG_FEATURE_VI_CRASHME)
+static Byte *string_insert(Byte *, Byte *);	// insert the string at 'p'
+#endif							/* CONFIG_FEATURE_VI_YANKMARK || CONFIG_FEATURE_VI_SEARCH || CONFIG_FEATURE_VI_CRASHME */
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+static Byte *text_yank(Byte *, Byte *, int);	// save copy of "p" into a register
+static Byte what_reg(void);		// what is letter of current YDreg
+static void check_context(Byte);	// remember context for '' command
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+#ifdef CONFIG_FEATURE_VI_CRASHME
+static void crash_dummy();
+static void crash_test();
+static int crashme = 0;
+#endif							/* CONFIG_FEATURE_VI_CRASHME */
+
+
+static void write1(const char *out)
+{
+	fputs(out, stdout);
+}
+
+int vi_main(int argc, char **argv)
+{
+	int c;
+	RESERVE_CONFIG_BUFFER(STATUS_BUFFER, STATUS_BUFFER_LEN);
+
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+	int i;
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+#if defined(CONFIG_FEATURE_VI_USE_SIGNALS) || defined(CONFIG_FEATURE_VI_CRASHME)
+	my_pid = getpid();
+#endif
+#ifdef CONFIG_FEATURE_VI_CRASHME
+	(void) srand((long) my_pid);
+#endif							/* CONFIG_FEATURE_VI_CRASHME */
+
+	status_buffer = (Byte *)STATUS_BUFFER;
+	last_status_cksum = 0;
+
+#ifdef CONFIG_FEATURE_VI_READONLY
+	vi_readonly = readonly = FALSE;
+	if (strncmp(argv[0], "view", 4) == 0) {
+		readonly = TRUE;
+		vi_readonly = TRUE;
+	}
+#endif							/* CONFIG_FEATURE_VI_READONLY */
+	vi_setops = VI_AUTOINDENT | VI_SHOWMATCH | VI_IGNORECASE | VI_ERR_METHOD;
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+	for (i = 0; i < 28; i++) {
+		reg[i] = 0;
+	}					// init the yank regs
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+#if defined(CONFIG_FEATURE_VI_DOT_CMD) || defined(CONFIG_FEATURE_VI_YANKMARK)
+	modifying_cmds = (Byte *) "aAcCdDiIJoOpPrRsxX<>~";	// cmds modifying text[]
+#endif							/* CONFIG_FEATURE_VI_DOT_CMD */
+
+	//  1-  process $HOME/.exrc file
+	//  2-  process EXINIT variable from environment
+	//  3-  process command line args
+	while ((c = getopt(argc, argv, "hCR")) != -1) {
+		switch (c) {
+#ifdef CONFIG_FEATURE_VI_CRASHME
+		case 'C':
+			crashme = 1;
+			break;
+#endif							/* CONFIG_FEATURE_VI_CRASHME */
+#ifdef CONFIG_FEATURE_VI_READONLY
+		case 'R':		// Read-only flag
+			readonly = TRUE;
+			vi_readonly = TRUE;
+			break;
+#endif							/* CONFIG_FEATURE_VI_READONLY */
+			//case 'r':	// recover flag-  ignore- we don't use tmp file
+			//case 'x':	// encryption flag- ignore
+			//case 'c':	// execute command first
+			//case 'h':	// help -- just use default
+		default:
+			show_help();
+			return 1;
+		}
+	}
+
+	// The argv array can be used by the ":next"  and ":rewind" commands
+	// save optind.
+	fn_start = optind;	// remember first file name for :next and :rew
+	save_argc = argc;
+
+	//----- This is the main file handling loop --------------
+	if (optind >= argc) {
+		editing = 1;	// 0= exit,  1= one file,  2= multiple files
+		edit_file(0);
+	} else {
+		for (; optind < argc; optind++) {
+			editing = 1;	// 0=exit, 1=one file, 2+ =many files
+			free(cfn);
+			cfn = (Byte *) bb_xstrdup(argv[optind]);
+			edit_file(cfn);
+		}
+	}
+	//-----------------------------------------------------------
+
+	return (0);
+}
+
+static void edit_file(Byte * fn)
+{
+	Byte c;
+	int cnt, size, ch;
+
+#ifdef CONFIG_FEATURE_VI_USE_SIGNALS
+	int sig;
+#endif							/* CONFIG_FEATURE_VI_USE_SIGNALS */
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+	static Byte *cur_line;
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+
+	rawmode();
+	rows = 24;
+	columns = 80;
+	ch= -1;
+	if (ENABLE_FEATURE_VI_WIN_RESIZE)
+		get_terminal_width_height(0, &columns, &rows);
+	new_screen(rows, columns);	// get memory for virtual screen
+
+	cnt = file_size(fn);	// file size
+	size = 2 * cnt;		// 200% of file size
+	new_text(size);		// get a text[] buffer
+	screenbegin = dot = end = text;
+	if (fn != 0) {
+		ch= file_insert(fn, text, cnt);
+	}
+	if (ch < 1) {
+		(void) char_insert(text, '\n');	// start empty buf with dummy line
+	}
+	file_modified = 0;
+	last_file_modified = -1;
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+	YDreg = 26;			// default Yank/Delete reg
+	Ureg = 27;			// hold orig line for "U" cmd
+	for (cnt = 0; cnt < 28; cnt++) {
+		mark[cnt] = 0;
+	}					// init the marks
+	mark[26] = mark[27] = text;	// init "previous context"
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+
+	last_forward_char = last_input_char = '\0';
+	crow = 0;
+	ccol = 0;
+
+#ifdef CONFIG_FEATURE_VI_USE_SIGNALS
+	catch_sig(0);
+	signal(SIGWINCH, winch_sig);
+	signal(SIGTSTP, suspend_sig);
+	sig = setjmp(restart);
+	if (sig != 0) {
+		screenbegin = dot = text;
+	}
+#endif							/* CONFIG_FEATURE_VI_USE_SIGNALS */
+
+	editing = 1;
+	cmd_mode = 0;		// 0=command  1=insert  2='R'eplace
+	cmdcnt = 0;
+	tabstop = 8;
+	offset = 0;			// no horizontal offset
+	c = '\0';
+#ifdef CONFIG_FEATURE_VI_DOT_CMD
+	free(last_modifying_cmd);
+	free(ioq_start);
+	ioq = ioq_start = last_modifying_cmd = 0;
+	adding2q = 0;
+#endif							/* CONFIG_FEATURE_VI_DOT_CMD */
+	redraw(FALSE);			// dont force every col re-draw
+	show_status_line();
+
+	//------This is the main Vi cmd handling loop -----------------------
+	while (editing > 0) {
+#ifdef CONFIG_FEATURE_VI_CRASHME
+		if (crashme > 0) {
+			if ((end - text) > 1) {
+				crash_dummy();	// generate a random command
+			} else {
+				crashme = 0;
+				dot =
+					string_insert(text, (Byte *) "\n\n#####  Ran out of text to work on.  #####\n\n");	// insert the string
+				refresh(FALSE);
+			}
+		}
+#endif							/* CONFIG_FEATURE_VI_CRASHME */
+		last_input_char = c = get_one_char();	// get a cmd from user
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+		// save a copy of the current line- for the 'U" command
+		if (begin_line(dot) != cur_line) {
+			cur_line = begin_line(dot);
+			text_yank(begin_line(dot), end_line(dot), Ureg);
+		}
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+#ifdef CONFIG_FEATURE_VI_DOT_CMD
+		// These are commands that change text[].
+		// Remember the input for the "." command
+		if (!adding2q && ioq_start == 0
+			&& strchr((char *) modifying_cmds, c) != NULL) {
+			start_new_cmd_q(c);
+		}
+#endif							/* CONFIG_FEATURE_VI_DOT_CMD */
+		do_cmd(c);		// execute the user command
+		//
+		// poll to see if there is input already waiting. if we are
+		// not able to display output fast enough to keep up, skip
+		// the display update until we catch up with input.
+		if (mysleep(0) == 0) {
+			// no input pending- so update output
+			refresh(FALSE);
+			show_status_line();
+		}
+#ifdef CONFIG_FEATURE_VI_CRASHME
+		if (crashme > 0)
+			crash_test();	// test editor variables
+#endif							/* CONFIG_FEATURE_VI_CRASHME */
+	}
+	//-------------------------------------------------------------------
+
+	place_cursor(rows, 0, FALSE);	// go to bottom of screen
+	clear_to_eol();		// Erase to end of line
+	cookmode();
+}
+
+//----- The Colon commands -------------------------------------
+#ifdef CONFIG_FEATURE_VI_COLON
+static Byte *get_one_address(Byte * p, int *addr)	// get colon addr, if present
+{
+	int st;
+	Byte *q;
+
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+	Byte c;
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+#ifdef CONFIG_FEATURE_VI_SEARCH
+	Byte *pat, buf[BUFSIZ];
+#endif							/* CONFIG_FEATURE_VI_SEARCH */
+
+	*addr = -1;			// assume no addr
+	if (*p == '.') {	// the current line
+		p++;
+		q = begin_line(dot);
+		*addr = count_lines(text, q);
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+	} else if (*p == '\'') {	// is this a mark addr
+		p++;
+		c = tolower(*p);
+		p++;
+		if (c >= 'a' && c <= 'z') {
+			// we have a mark
+			c = c - 'a';
+			q = mark[(int) c];
+			if (q != NULL) {	// is mark valid
+				*addr = count_lines(text, q);	// count lines
+			}
+		}
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+#ifdef CONFIG_FEATURE_VI_SEARCH
+	} else if (*p == '/') {	// a search pattern
+		q = buf;
+		for (p++; *p; p++) {
+			if (*p == '/')
+				break;
+			*q++ = *p;
+			*q = '\0';
+		}
+		pat = (Byte *) bb_xstrdup((char *) buf);	// save copy of pattern
+		if (*p == '/')
+			p++;
+		q = char_search(dot, pat, FORWARD, FULL);
+		if (q != NULL) {
+			*addr = count_lines(text, q);
+		}
+		free(pat);
+#endif							/* CONFIG_FEATURE_VI_SEARCH */
+	} else if (*p == '$') {	// the last line in file
+		p++;
+		q = begin_line(end - 1);
+		*addr = count_lines(text, q);
+	} else if (isdigit(*p)) {	// specific line number
+		sscanf((char *) p, "%d%n", addr, &st);
+		p += st;
+	} else {			// I don't reconise this
+		// unrecognised address- assume -1
+		*addr = -1;
+	}
+	return (p);
+}
+
+static Byte *get_address(Byte *p, int *b, int *e)	// get two colon addrs, if present
+{
+	//----- get the address' i.e., 1,3   'a,'b  -----
+	// get FIRST addr, if present
+	while (isblnk(*p))
+		p++;				// skip over leading spaces
+	if (*p == '%') {			// alias for 1,$
+		p++;
+		*b = 1;
+		*e = count_lines(text, end-1);
+		goto ga0;
+	}
+	p = get_one_address(p, b);
+	while (isblnk(*p))
+		p++;
+	if (*p == ',') {			// is there a address separator
+		p++;
+		while (isblnk(*p))
+			p++;
+		// get SECOND addr, if present
+		p = get_one_address(p, e);
+	}
+ga0:
+	while (isblnk(*p))
+		p++;				// skip over trailing spaces
+	return (p);
+}
+
+#ifdef CONFIG_FEATURE_VI_SETOPTS
+static void setops(const Byte *args, const char *opname, int flg_no,
+			const char *short_opname, int opt)
+{
+	const char *a = (char *) args + flg_no;
+	int l = strlen(opname) - 1; /* opname have + ' ' */
+
+	if (strncasecmp(a, opname, l) == 0 ||
+			strncasecmp(a, short_opname, 2) == 0) {
+		if(flg_no)
+			vi_setops &= ~opt;
+		 else
+			vi_setops |= opt;
+	}
+}
+#endif
+
+static void colon(Byte * buf)
+{
+	Byte c, *orig_buf, *buf1, *q, *r;
+	Byte *fn, cmd[BUFSIZ], args[BUFSIZ];
+	int i, l, li, ch, st, b, e;
+	int useforce = FALSE, forced = FALSE;
+	struct stat st_buf;
+
+	// :3154	// if (-e line 3154) goto it  else stay put
+	// :4,33w! foo	// write a portion of buffer to file "foo"
+	// :w		// write all of buffer to current file
+	// :q		// quit
+	// :q!		// quit- dont care about modified file
+	// :'a,'z!sort -u   // filter block through sort
+	// :'f		// goto mark "f"
+	// :'fl		// list literal the mark "f" line
+	// :.r bar	// read file "bar" into buffer before dot
+	// :/123/,/abc/d    // delete lines from "123" line to "abc" line
+	// :/xyz/	// goto the "xyz" line
+	// :s/find/replace/ // substitute pattern "find" with "replace"
+	// :!<cmd>	// run <cmd> then return
+	//
+
+	if (strlen((char *) buf) <= 0)
+		goto vc1;
+	if (*buf == ':')
+		buf++;			// move past the ':'
+
+	li = st = ch = i = 0;
+	b = e = -1;
+	q = text;			// assume 1,$ for the range
+	r = end - 1;
+	li = count_lines(text, end - 1);
+	fn = cfn;			// default to current file
+	memset(cmd, '\0', BUFSIZ);	// clear cmd[]
+	memset(args, '\0', BUFSIZ);	// clear args[]
+
+	// look for optional address(es)  :.  :1  :1,9   :'q,'a   :%
+	buf = get_address(buf, &b, &e);
+
+	// remember orig command line
+	orig_buf = buf;
+
+	// get the COMMAND into cmd[]
+	buf1 = cmd;
+	while (*buf != '\0') {
+		if (isspace(*buf))
+			break;
+		*buf1++ = *buf++;
+	}
+	// get any ARGuments
+	while (isblnk(*buf))
+		buf++;
+	strcpy((char *) args, (char *) buf);
+	buf1 = (Byte*)last_char_is((char *)cmd, '!');
+	if (buf1) {
+		useforce = TRUE;
+		*buf1 = '\0';   // get rid of !
+	}
+	if (b >= 0) {
+		// if there is only one addr, then the addr
+		// is the line number of the single line the
+		// user wants. So, reset the end
+		// pointer to point at end of the "b" line
+		q = find_line(b);	// what line is #b
+		r = end_line(q);
+		li = 1;
+	}
+	if (e >= 0) {
+		// we were given two addrs.  change the
+		// end pointer to the addr given by user.
+		r = find_line(e);	// what line is #e
+		r = end_line(r);
+		li = e - b + 1;
+	}
+	// ------------ now look for the command ------------
+	i = strlen((char *) cmd);
+	if (i == 0) {		// :123CR goto line #123
+		if (b >= 0) {
+			dot = find_line(b);	// what line is #b
+			dot_skip_over_ws();
+		}
+	} else if (strncmp((char *) cmd, "!", 1) == 0) {	// run a cmd
+		// :!ls   run the <cmd>
+		(void) alarm(0);		// wait for input- no alarms
+		place_cursor(rows - 1, 0, FALSE);	// go to Status line
+		clear_to_eol();			// clear the line
+		cookmode();
+		system((char*)(orig_buf+1));		// run the cmd
+		rawmode();
+		Hit_Return();			// let user see results
+		(void) alarm(3);		// done waiting for input
+	} else if (strncmp((char *) cmd, "=", i) == 0) {	// where is the address
+		if (b < 0) {	// no addr given- use defaults
+			b = e = count_lines(text, dot);
+		}
+		psb("%d", b);
+	} else if (strncasecmp((char *) cmd, "delete", i) == 0) {	// delete lines
+		if (b < 0) {	// no addr given- use defaults
+			q = begin_line(dot);	// assume .,. for the range
+			r = end_line(dot);
+		}
+		dot = yank_delete(q, r, 1, YANKDEL);	// save, then delete lines
+		dot_skip_over_ws();
+	} else if (strncasecmp((char *) cmd, "edit", i) == 0) {	// Edit a file
+		int sr;
+		sr= 0;
+		// don't edit, if the current file has been modified
+		if (file_modified && ! useforce) {
+			psbs("No write since last change (:edit! overrides)");
+			goto vc1;
+		}
+		if (strlen((char*)args) > 0) {
+			// the user supplied a file name
+			fn= args;
+		} else if (cfn != 0 && strlen((char*)cfn) > 0) {
+			// no user supplied name- use the current filename
+			fn= cfn;
+			goto vc5;
+		} else {
+			// no user file name, no current name- punt
+			psbs("No current filename");
+			goto vc1;
+		}
+
+		// see if file exists- if not, its just a new file request
+		if ((sr=stat((char*)fn, &st_buf)) < 0) {
+			// This is just a request for a new file creation.
+			// The file_insert below will fail but we get
+			// an empty buffer with a file name.  Then the "write"
+			// command can do the create.
+		} else {
+			if ((st_buf.st_mode & (S_IFREG)) == 0) {
+				// This is not a regular file
+				psbs("\"%s\" is not a regular file", fn);
+				goto vc1;
+			}
+			if ((st_buf.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)) == 0) {
+				// dont have any read permissions
+				psbs("\"%s\" is not readable", fn);
+				goto vc1;
+			}
+		}
+
+		// There is a read-able regular file
+		// make this the current file
+		q = (Byte *) bb_xstrdup((char *) fn);	// save the cfn
+		free(cfn);		// free the old name
+		cfn = q;			// remember new cfn
+
+	  vc5:
+		// delete all the contents of text[]
+		new_text(2 * file_size(fn));
+		screenbegin = dot = end = text;
+
+		// insert new file
+		ch = file_insert(fn, text, file_size(fn));
+
+		if (ch < 1) {
+			// start empty buf with dummy line
+			(void) char_insert(text, '\n');
+			ch= 1;
+		}
+		file_modified = 0;
+		last_file_modified = -1;
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+		if (Ureg >= 0 && Ureg < 28 && reg[Ureg] != 0) {
+			free(reg[Ureg]);	//   free orig line reg- for 'U'
+			reg[Ureg]= 0;
+		}
+		if (YDreg >= 0 && YDreg < 28 && reg[YDreg] != 0) {
+			free(reg[YDreg]);	//   free default yank/delete register
+			reg[YDreg]= 0;
+		}
+		for (li = 0; li < 28; li++) {
+			mark[li] = 0;
+		}				// init the marks
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+		// how many lines in text[]?
+		li = count_lines(text, end - 1);
+		psb("\"%s\"%s"
+#ifdef CONFIG_FEATURE_VI_READONLY
+			"%s"
+#endif							/* CONFIG_FEATURE_VI_READONLY */
+			" %dL, %dC", cfn,
+			(sr < 0 ? " [New file]" : ""),
+#ifdef CONFIG_FEATURE_VI_READONLY
+			((vi_readonly || readonly) ? " [Read only]" : ""),
+#endif							/* CONFIG_FEATURE_VI_READONLY */
+			li, ch);
+	} else if (strncasecmp((char *) cmd, "file", i) == 0) {	// what File is this
+		if (b != -1 || e != -1) {
+			ni((Byte *) "No address allowed on this command");
+			goto vc1;
+		}
+		if (strlen((char *) args) > 0) {
+			// user wants a new filename
+			free(cfn);
+			cfn = (Byte *) bb_xstrdup((char *) args);
+		} else {
+			// user wants file status info
+			last_status_cksum = 0;	// force status update
+		}
+	} else if (strncasecmp((char *) cmd, "features", i) == 0) {	// what features are available
+		// print out values of all features
+		place_cursor(rows - 1, 0, FALSE);	// go to Status line, bottom of screen
+		clear_to_eol();	// clear the line
+		cookmode();
+		show_help();
+		rawmode();
+		Hit_Return();
+	} else if (strncasecmp((char *) cmd, "list", i) == 0) {	// literal print line
+		if (b < 0) {	// no addr given- use defaults
+			q = begin_line(dot);	// assume .,. for the range
+			r = end_line(dot);
+		}
+		place_cursor(rows - 1, 0, FALSE);	// go to Status line, bottom of screen
+		clear_to_eol();	// clear the line
+		puts("\r");
+		for (; q <= r; q++) {
+			int c_is_no_print;
+
+			c = *q;
+			c_is_no_print = c > 127 && !Isprint(c);
+			if (c_is_no_print) {
+				c = '.';
+				standout_start();
+				}
+			if (c == '\n') {
+				write1("$\r");
+			} else if (c < ' ' || c == 127) {
+				putchar('^');
+				if(c == 127)
+					c = '?';
+				 else
+				c += '@';
+			}
+			putchar(c);
+			if (c_is_no_print)
+				standout_end();
+		}
+#ifdef CONFIG_FEATURE_VI_SET
+	  vc2:
+#endif							/* CONFIG_FEATURE_VI_SET */
+		Hit_Return();
+	} else if ((strncasecmp((char *) cmd, "quit", i) == 0) ||	// Quit
+			   (strncasecmp((char *) cmd, "next", i) == 0)) {	// edit next file
+		if (useforce) {
+			// force end of argv list
+			if (*cmd == 'q') {
+				optind = save_argc;
+			}
+			editing = 0;
+			goto vc1;
+		}
+		// don't exit if the file been modified
+		if (file_modified) {
+			psbs("No write since last change (:%s! overrides)",
+				 (*cmd == 'q' ? "quit" : "next"));
+			goto vc1;
+		}
+		// are there other file to edit
+		if (*cmd == 'q' && optind < save_argc - 1) {
+			psbs("%d more file to edit", (save_argc - optind - 1));
+			goto vc1;
+		}
+		if (*cmd == 'n' && optind >= save_argc - 1) {
+			psbs("No more files to edit");
+			goto vc1;
+		}
+		editing = 0;
+	} else if (strncasecmp((char *) cmd, "read", i) == 0) {	// read file into text[]
+		fn = args;
+		if (strlen((char *) fn) <= 0) {
+			psbs("No filename given");
+			goto vc1;
+		}
+		if (b < 0) {	// no addr given- use defaults
+			q = begin_line(dot);	// assume "dot"
+		}
+		// read after current line- unless user said ":0r foo"
+		if (b != 0)
+			q = next_line(q);
+#ifdef CONFIG_FEATURE_VI_READONLY
+		l= readonly;			// remember current files' status
+#endif
+		ch = file_insert(fn, q, file_size(fn));
+#ifdef CONFIG_FEATURE_VI_READONLY
+		readonly= l;
+#endif
+		if (ch < 0)
+			goto vc1;	// nothing was inserted
+		// how many lines in text[]?
+		li = count_lines(q, q + ch - 1);
+		psb("\"%s\""
+#ifdef CONFIG_FEATURE_VI_READONLY
+			"%s"
+#endif							/* CONFIG_FEATURE_VI_READONLY */
+			" %dL, %dC", fn,
+#ifdef CONFIG_FEATURE_VI_READONLY
+			((vi_readonly || readonly) ? " [Read only]" : ""),
+#endif							/* CONFIG_FEATURE_VI_READONLY */
+			li, ch);
+		if (ch > 0) {
+			// if the insert is before "dot" then we need to update
+			if (q <= dot)
+				dot += ch;
+			file_modified++;
+		}
+	} else if (strncasecmp((char *) cmd, "rewind", i) == 0) {	// rewind cmd line args
+		if (file_modified && ! useforce) {
+			psbs("No write since last change (:rewind! overrides)");
+		} else {
+			// reset the filenames to edit
+			optind = fn_start - 1;
+			editing = 0;
+		}
+#ifdef CONFIG_FEATURE_VI_SET
+	} else if (strncasecmp((char *) cmd, "set", i) == 0) {	// set or clear features
+		i = 0;			// offset into args
+		if (strlen((char *) args) == 0) {
+			// print out values of all options
+			place_cursor(rows - 1, 0, FALSE);	// go to Status line, bottom of screen
+			clear_to_eol();	// clear the line
+			printf("----------------------------------------\r\n");
+#ifdef CONFIG_FEATURE_VI_SETOPTS
+			if (!autoindent)
+				printf("no");
+			printf("autoindent ");
+			if (!err_method)
+				printf("no");
+			printf("flash ");
+			if (!ignorecase)
+				printf("no");
+			printf("ignorecase ");
+			if (!showmatch)
+				printf("no");
+			printf("showmatch ");
+			printf("tabstop=%d ", tabstop);
+#endif							/* CONFIG_FEATURE_VI_SETOPTS */
+			printf("\r\n");
+			goto vc2;
+		}
+		if (strncasecmp((char *) args, "no", 2) == 0)
+			i = 2;		// ":set noautoindent"
+#ifdef CONFIG_FEATURE_VI_SETOPTS
+		setops(args, "autoindent ", i, "ai", VI_AUTOINDENT);
+		setops(args, "flash ", i, "fl", VI_ERR_METHOD);
+		setops(args, "ignorecase ", i, "ic", VI_IGNORECASE);
+		setops(args, "showmatch ", i, "ic", VI_SHOWMATCH);
+		if (strncasecmp((char *) args + i, "tabstop=%d ", 7) == 0) {
+			sscanf(strchr((char *) args + i, '='), "=%d", &ch);
+			if (ch > 0 && ch < columns - 1)
+				tabstop = ch;
+		}
+#endif							/* CONFIG_FEATURE_VI_SETOPTS */
+#endif							/* CONFIG_FEATURE_VI_SET */
+#ifdef CONFIG_FEATURE_VI_SEARCH
+	} else if (strncasecmp((char *) cmd, "s", 1) == 0) {	// substitute a pattern with a replacement pattern
+		Byte *ls, *F, *R;
+		int gflag;
+
+		// F points to the "find" pattern
+		// R points to the "replace" pattern
+		// replace the cmd line delimiters "/" with NULLs
+		gflag = 0;		// global replace flag
+		c = orig_buf[1];	// what is the delimiter
+		F = orig_buf + 2;	// start of "find"
+		R = (Byte *) strchr((char *) F, c);	// middle delimiter
+		if (!R) goto colon_s_fail;
+		*R++ = '\0';	// terminate "find"
+		buf1 = (Byte *) strchr((char *) R, c);
+		if (!buf1) goto colon_s_fail;
+		*buf1++ = '\0';	// terminate "replace"
+		if (*buf1 == 'g') {	// :s/foo/bar/g
+			buf1++;
+			gflag++;	// turn on gflag
+		}
+		q = begin_line(q);
+		if (b < 0) {	// maybe :s/foo/bar/
+			q = begin_line(dot);	// start with cur line
+			b = count_lines(text, q);	// cur line number
+		}
+		if (e < 0)
+			e = b;		// maybe :.s/foo/bar/
+		for (i = b; i <= e; i++) {	// so, :20,23 s \0 find \0 replace \0
+			ls = q;		// orig line start
+		  vc4:
+			buf1 = char_search(q, F, FORWARD, LIMITED);	// search cur line only for "find"
+			if (buf1 != NULL) {
+				// we found the "find" pattern- delete it
+				(void) text_hole_delete(buf1, buf1 + strlen((char *) F) - 1);
+				// inset the "replace" patern
+				(void) string_insert(buf1, R);	// insert the string
+				// check for "global"  :s/foo/bar/g
+				if (gflag == 1) {
+					if ((buf1 + strlen((char *) R)) < end_line(ls)) {
+						q = buf1 + strlen((char *) R);
+						goto vc4;	// don't let q move past cur line
+					}
+				}
+			}
+			q = next_line(ls);
+		}
+#endif							/* CONFIG_FEATURE_VI_SEARCH */
+	} else if (strncasecmp((char *) cmd, "version", i) == 0) {	// show software version
+		psb("%s", vi_Version);
+	} else if (strncasecmp((char *) cmd, "write", i) == 0		// write text to file
+			|| strncasecmp((char *) cmd, "wq", i) == 0
+			|| strncasecmp((char *) cmd, "wn", i) == 0
+			|| strncasecmp((char *) cmd, "x", i) == 0) {
+		// is there a file name to write to?
+		if (strlen((char *) args) > 0) {
+			fn = args;
+		}
+#ifdef CONFIG_FEATURE_VI_READONLY
+		if ((vi_readonly || readonly) && ! useforce) {
+			psbs("\"%s\" File is read only", fn);
+			goto vc3;
+		}
+#endif							/* CONFIG_FEATURE_VI_READONLY */
+		// how many lines in text[]?
+		li = count_lines(q, r);
+		ch = r - q + 1;
+		// see if file exists- if not, its just a new file request
+		if (useforce) {
+			// if "fn" is not write-able, chmod u+w
+			// sprintf(syscmd, "chmod u+w %s", fn);
+			// system(syscmd);
+			forced = TRUE;
+		}
+		l = file_write(fn, q, r);
+		if (useforce && forced) {
+			// chmod u-w
+			// sprintf(syscmd, "chmod u-w %s", fn);
+			// system(syscmd);
+			forced = FALSE;
+		}
+		if (l < 0) {
+			if (l == -1)
+				psbs("Write error: %s", strerror(errno));
+		} else {
+			psb("\"%s\" %dL, %dC", fn, li, l);
+			if (q == text && r == end - 1 && l == ch) {
+				file_modified = 0;
+				last_file_modified = -1;
+			}
+			if ((cmd[0] == 'x' || cmd[1] == 'q' || cmd[1] == 'n' ||
+			     cmd[0] == 'X' || cmd[1] == 'Q' || cmd[1] == 'N')
+			     && l == ch) {
+				editing = 0;
+			}
+		}
+#ifdef CONFIG_FEATURE_VI_READONLY
+	  vc3:;
+#endif							/* CONFIG_FEATURE_VI_READONLY */
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+	} else if (strncasecmp((char *) cmd, "yank", i) == 0) {	// yank lines
+		if (b < 0) {	// no addr given- use defaults
+			q = begin_line(dot);	// assume .,. for the range
+			r = end_line(dot);
+		}
+		text_yank(q, r, YDreg);
+		li = count_lines(q, r);
+		psb("Yank %d lines (%d chars) into [%c]",
+			li, strlen((char *) reg[YDreg]), what_reg());
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+	} else {
+		// cmd unknown
+		ni((Byte *) cmd);
+	}
+  vc1:
+	dot = bound_dot(dot);	// make sure "dot" is valid
+	return;
+#ifdef CONFIG_FEATURE_VI_SEARCH
+colon_s_fail:
+	psb(":s expression missing delimiters");
+#endif
+}
+
+#endif							/* CONFIG_FEATURE_VI_COLON */
+
+static void Hit_Return(void)
+{
+	char c;
+
+	standout_start();	// start reverse video
+	write1("[Hit return to continue]");
+	standout_end();		// end reverse video
+	while ((c = get_one_char()) != '\n' && c != '\r')	/*do nothing */
+		;
+	redraw(TRUE);		// force redraw all
+}
+
+//----- Synchronize the cursor to Dot --------------------------
+static void sync_cursor(Byte * d, int *row, int *col)
+{
+	Byte *beg_cur;				// begin and end of "d" line
+	Byte *beg_scr, *end_scr;	// begin and end of screen
+	Byte *tp;
+	int cnt, ro, co;
+
+	beg_cur = begin_line(d);	// first char of cur line
+
+	beg_scr = end_scr = screenbegin;	// first char of screen
+	end_scr = end_screen();	// last char of screen
+
+	if (beg_cur < screenbegin) {
+		// "d" is before  top line on screen
+		// how many lines do we have to move
+		cnt = count_lines(beg_cur, screenbegin);
+	  sc1:
+		screenbegin = beg_cur;
+		if (cnt > (rows - 1) / 2) {
+			// we moved too many lines. put "dot" in middle of screen
+			for (cnt = 0; cnt < (rows - 1) / 2; cnt++) {
+				screenbegin = prev_line(screenbegin);
+			}
+		}
+	} else if (beg_cur > end_scr) {
+		// "d" is after bottom line on screen
+		// how many lines do we have to move
+		cnt = count_lines(end_scr, beg_cur);
+		if (cnt > (rows - 1) / 2)
+			goto sc1;	// too many lines
+		for (ro = 0; ro < cnt - 1; ro++) {
+			// move screen begin the same amount
+			screenbegin = next_line(screenbegin);
+			// now, move the end of screen
+			end_scr = next_line(end_scr);
+			end_scr = end_line(end_scr);
+		}
+	}
+	// "d" is on screen- find out which row
+	tp = screenbegin;
+	for (ro = 0; ro < rows - 1; ro++) {	// drive "ro" to correct row
+		if (tp == beg_cur)
+			break;
+		tp = next_line(tp);
+	}
+
+	// find out what col "d" is on
+	co = 0;
+	do {				// drive "co" to correct column
+		if (*tp == '\n' || *tp == '\0')
+			break;
+		if (*tp == '\t') {
+			//         7       - (co %    8  )
+			co += ((tabstop - 1) - (co % tabstop));
+		} else if (*tp < ' ' || *tp == 127) {
+			co++;		// display as ^X, use 2 columns
+		}
+	} while (tp++ < d && ++co);
+
+	// "co" is the column where "dot" is.
+	// The screen has "columns" columns.
+	// The currently displayed columns are  0+offset -- columns+ofset
+	// |-------------------------------------------------------------|
+	//               ^ ^                                ^
+	//        offset | |------- columns ----------------|
+	//
+	// If "co" is already in this range then we do not have to adjust offset
+	//      but, we do have to subtract the "offset" bias from "co".
+	// If "co" is outside this range then we have to change "offset".
+	// If the first char of a line is a tab the cursor will try to stay
+	//  in column 7, but we have to set offset to 0.
+
+	if (co < 0 + offset) {
+		offset = co;
+	}
+	if (co >= columns + offset) {
+		offset = co - columns + 1;
+	}
+	// if the first char of the line is a tab, and "dot" is sitting on it
+	//  force offset to 0.
+	if (d == beg_cur && *d == '\t') {
+		offset = 0;
+	}
+	co -= offset;
+
+	*row = ro;
+	*col = co;
+}
+
+//----- Text Movement Routines ---------------------------------
+static Byte *begin_line(Byte * p) // return pointer to first char cur line
+{
+	while (p > text && p[-1] != '\n')
+		p--;			// go to cur line B-o-l
+	return (p);
+}
+
+static Byte *end_line(Byte * p) // return pointer to NL of cur line line
+{
+	while (p < end - 1 && *p != '\n')
+		p++;			// go to cur line E-o-l
+	return (p);
+}
+
+static inline Byte *dollar_line(Byte * p) // return pointer to just before NL line
+{
+	while (p < end - 1 && *p != '\n')
+		p++;			// go to cur line E-o-l
+	// Try to stay off of the Newline
+	if (*p == '\n' && (p - begin_line(p)) > 0)
+		p--;
+	return (p);
+}
+
+static Byte *prev_line(Byte * p) // return pointer first char prev line
+{
+	p = begin_line(p);	// goto begining of cur line
+	if (p[-1] == '\n' && p > text)
+		p--;			// step to prev line
+	p = begin_line(p);	// goto begining of prev line
+	return (p);
+}
+
+static Byte *next_line(Byte * p) // return pointer first char next line
+{
+	p = end_line(p);
+	if (*p == '\n' && p < end - 1)
+		p++;			// step to next line
+	return (p);
+}
+
+//----- Text Information Routines ------------------------------
+static Byte *end_screen(void)
+{
+	Byte *q;
+	int cnt;
+
+	// find new bottom line
+	q = screenbegin;
+	for (cnt = 0; cnt < rows - 2; cnt++)
+		q = next_line(q);
+	q = end_line(q);
+	return (q);
+}
+
+static int count_lines(Byte * start, Byte * stop) // count line from start to stop
+{
+	Byte *q;
+	int cnt;
+
+	if (stop < start) {	// start and stop are backwards- reverse them
+		q = start;
+		start = stop;
+		stop = q;
+	}
+	cnt = 0;
+	stop = end_line(stop);	// get to end of this line
+	for (q = start; q <= stop && q <= end - 1; q++) {
+		if (*q == '\n')
+			cnt++;
+	}
+	return (cnt);
+}
+
+static Byte *find_line(int li)	// find begining of line #li
+{
+	Byte *q;
+
+	for (q = text; li > 1; li--) {
+		q = next_line(q);
+	}
+	return (q);
+}
+
+//----- Dot Movement Routines ----------------------------------
+static void dot_left(void)
+{
+	if (dot > text && dot[-1] != '\n')
+		dot--;
+}
+
+static void dot_right(void)
+{
+	if (dot < end - 1 && *dot != '\n')
+		dot++;
+}
+
+static void dot_begin(void)
+{
+	dot = begin_line(dot);	// return pointer to first char cur line
+}
+
+static void dot_end(void)
+{
+	dot = end_line(dot);	// return pointer to last char cur line
+}
+
+static Byte *move_to_col(Byte * p, int l)
+{
+	int co;
+
+	p = begin_line(p);
+	co = 0;
+	do {
+		if (*p == '\n' || *p == '\0')
+			break;
+		if (*p == '\t') {
+			//         7       - (co %    8  )
+			co += ((tabstop - 1) - (co % tabstop));
+		} else if (*p < ' ' || *p == 127) {
+			co++;		// display as ^X, use 2 columns
+		}
+	} while (++co <= l && p++ < end);
+	return (p);
+}
+
+static void dot_next(void)
+{
+	dot = next_line(dot);
+}
+
+static void dot_prev(void)
+{
+	dot = prev_line(dot);
+}
+
+static void dot_scroll(int cnt, int dir)
+{
+	Byte *q;
+
+	for (; cnt > 0; cnt--) {
+		if (dir < 0) {
+			// scroll Backwards
+			// ctrl-Y  scroll up one line
+			screenbegin = prev_line(screenbegin);
+		} else {
+			// scroll Forwards
+			// ctrl-E  scroll down one line
+			screenbegin = next_line(screenbegin);
+		}
+	}
+	// make sure "dot" stays on the screen so we dont scroll off
+	if (dot < screenbegin)
+		dot = screenbegin;
+	q = end_screen();	// find new bottom line
+	if (dot > q)
+		dot = begin_line(q);	// is dot is below bottom line?
+	dot_skip_over_ws();
+}
+
+static void dot_skip_over_ws(void)
+{
+	// skip WS
+	while (isspace(*dot) && *dot != '\n' && dot < end - 1)
+		dot++;
+}
+
+static void dot_delete(void)	// delete the char at 'dot'
+{
+	(void) text_hole_delete(dot, dot);
+}
+
+static Byte *bound_dot(Byte * p) // make sure  text[0] <= P < "end"
+{
+	if (p >= end && end > text) {
+		p = end - 1;
+		indicate_error('1');
+	}
+	if (p < text) {
+		p = text;
+		indicate_error('2');
+	}
+	return (p);
+}
+
+//----- Helper Utility Routines --------------------------------
+
+//----------------------------------------------------------------
+//----- Char Routines --------------------------------------------
+/* Chars that are part of a word-
+ *    0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+ * Chars that are Not part of a word (stoppers)
+ *    !"#$%&'()*+,-./:;<=>?@[\]^`{|}~
+ * Chars that are WhiteSpace
+ *    TAB NEWLINE VT FF RETURN SPACE
+ * DO NOT COUNT NEWLINE AS WHITESPACE
+ */
+
+static Byte *new_screen(int ro, int co)
+{
+	int li;
+
+	free(screen);
+	screensize = ro * co + 8;
+	screen = (Byte *) xmalloc(screensize);
+	// initialize the new screen. assume this will be a empty file.
+	screen_erase();
+	//   non-existent text[] lines start with a tilde (~).
+	for (li = 1; li < ro - 1; li++) {
+		screen[(li * co) + 0] = '~';
+	}
+	return (screen);
+}
+
+static Byte *new_text(int size)
+{
+	if (size < 10240)
+		size = 10240;	// have a minimum size for new files
+	free(text);
+	text = (Byte *) xmalloc(size + 8);
+	memset(text, '\0', size);	// clear new text[]
+	//text += 4;		// leave some room for "oops"
+	textend = text + size - 1;
+	//textend -= 4;		// leave some root for "oops"
+	return (text);
+}
+
+#ifdef CONFIG_FEATURE_VI_SEARCH
+static int mycmp(Byte * s1, Byte * s2, int len)
+{
+	int i;
+
+	i = strncmp((char *) s1, (char *) s2, len);
+#ifdef CONFIG_FEATURE_VI_SETOPTS
+	if (ignorecase) {
+		i = strncasecmp((char *) s1, (char *) s2, len);
+	}
+#endif							/* CONFIG_FEATURE_VI_SETOPTS */
+	return (i);
+}
+
+static Byte *char_search(Byte * p, Byte * pat, int dir, int range)	// search for pattern starting at p
+{
+#ifndef REGEX_SEARCH
+	Byte *start, *stop;
+	int len;
+
+	len = strlen((char *) pat);
+	if (dir == FORWARD) {
+		stop = end - 1;	// assume range is p - end-1
+		if (range == LIMITED)
+			stop = next_line(p);	// range is to next line
+		for (start = p; start < stop; start++) {
+			if (mycmp(start, pat, len) == 0) {
+				return (start);
+			}
+		}
+	} else if (dir == BACK) {
+		stop = text;	// assume range is text - p
+		if (range == LIMITED)
+			stop = prev_line(p);	// range is to prev line
+		for (start = p - len; start >= stop; start--) {
+			if (mycmp(start, pat, len) == 0) {
+				return (start);
+			}
+		}
+	}
+	// pattern not found
+	return (NULL);
+#else							/*REGEX_SEARCH */
+	char *q;
+	struct re_pattern_buffer preg;
+	int i;
+	int size, range;
+
+	re_syntax_options = RE_SYNTAX_POSIX_EXTENDED;
+	preg.translate = 0;
+	preg.fastmap = 0;
+	preg.buffer = 0;
+	preg.allocated = 0;
+
+	// assume a LIMITED forward search
+	q = next_line(p);
+	q = end_line(q);
+	q = end - 1;
+	if (dir == BACK) {
+		q = prev_line(p);
+		q = text;
+	}
+	// count the number of chars to search over, forward or backward
+	size = q - p;
+	if (size < 0)
+		size = p - q;
+	// RANGE could be negative if we are searching backwards
+	range = q - p;
+
+	q = (char *) re_compile_pattern(pat, strlen((char *) pat), &preg);
+	if (q != 0) {
+		// The pattern was not compiled
+		psbs("bad search pattern: \"%s\": %s", pat, q);
+		i = 0;			// return p if pattern not compiled
+		goto cs1;
+	}
+
+	q = p;
+	if (range < 0) {
+		q = p - size;
+		if (q < text)
+			q = text;
+	}
+	// search for the compiled pattern, preg, in p[]
+	// range < 0-  search backward
+	// range > 0-  search forward
+	// 0 < start < size
+	// re_search() < 0  not found or error
+	// re_search() > 0  index of found pattern
+	//            struct pattern    char     int    int    int     struct reg
+	// re_search (*pattern_buffer,  *string, size,  start, range,  *regs)
+	i = re_search(&preg, q, size, 0, range, 0);
+	if (i == -1) {
+		p = 0;
+		i = 0;			// return NULL if pattern not found
+	}
+  cs1:
+	if (dir == FORWARD) {
+		p = p + i;
+	} else {
+		p = p - i;
+	}
+	return (p);
+#endif							/*REGEX_SEARCH */
+}
+#endif							/* CONFIG_FEATURE_VI_SEARCH */
+
+static Byte *char_insert(Byte * p, Byte c) // insert the char c at 'p'
+{
+	if (c == 22) {		// Is this an ctrl-V?
+		p = stupid_insert(p, '^');	// use ^ to indicate literal next
+		p--;			// backup onto ^
+		refresh(FALSE);	// show the ^
+		c = get_one_char();
+		*p = c;
+		p++;
+		file_modified++;	// has the file been modified
+	} else if (c == 27) {	// Is this an ESC?
+		cmd_mode = 0;
+		cmdcnt = 0;
+		end_cmd_q();	// stop adding to q
+		last_status_cksum = 0;	// force status update
+		if ((p[-1] != '\n') && (dot>text)) {
+			p--;
+		}
+	} else if (c == erase_char || c == 8 || c == 127) { // Is this a BS
+		//     123456789
+		if ((p[-1] != '\n') && (dot>text)) {
+			p--;
+			p = text_hole_delete(p, p);	// shrink buffer 1 char
+		}
+	} else {
+		// insert a char into text[]
+		Byte *sp;		// "save p"
+
+		if (c == 13)
+			c = '\n';	// translate \r to \n
+		sp = p;			// remember addr of insert
+		p = stupid_insert(p, c);	// insert the char
+#ifdef CONFIG_FEATURE_VI_SETOPTS
+		if (showmatch && strchr(")]}", *sp) != NULL) {
+			showmatching(sp);
+		}
+		if (autoindent && c == '\n') {	// auto indent the new line
+			Byte *q;
+
+			q = prev_line(p);	// use prev line as templet
+			for (; isblnk(*q); q++) {
+				p = stupid_insert(p, *q);	// insert the char
+			}
+		}
+#endif							/* CONFIG_FEATURE_VI_SETOPTS */
+	}
+	return (p);
+}
+
+static Byte *stupid_insert(Byte * p, Byte c) // stupidly insert the char c at 'p'
+{
+	p = text_hole_make(p, 1);
+	if (p != 0) {
+		*p = c;
+		file_modified++;	// has the file been modified
+		p++;
+	}
+	return (p);
+}
+
+static Byte find_range(Byte ** start, Byte ** stop, Byte c)
+{
+	Byte *save_dot, *p, *q;
+	int cnt;
+
+	save_dot = dot;
+	p = q = dot;
+
+	if (strchr("cdy><", c)) {
+		// these cmds operate on whole lines
+		p = q = begin_line(p);
+		for (cnt = 1; cnt < cmdcnt; cnt++) {
+			q = next_line(q);
+		}
+		q = end_line(q);
+	} else if (strchr("^%$0bBeEft", c)) {
+		// These cmds operate on char positions
+		do_cmd(c);		// execute movement cmd
+		q = dot;
+	} else if (strchr("wW", c)) {
+		do_cmd(c);		// execute movement cmd
+		// if we are at the next word's first char
+		// step back one char
+		// but check the possibilities when it is true
+		if (dot > text && ((isspace(dot[-1]) && !isspace(dot[0]))
+				|| (ispunct(dot[-1]) && !ispunct(dot[0]))
+				|| (isalnum(dot[-1]) && !isalnum(dot[0]))))
+			dot--;		// move back off of next word
+		if (dot > text && *dot == '\n')
+			dot--;		// stay off NL
+		q = dot;
+	} else if (strchr("H-k{", c)) {
+		// these operate on multi-lines backwards
+		q = end_line(dot);	// find NL
+		do_cmd(c);		// execute movement cmd
+		dot_begin();
+		p = dot;
+	} else if (strchr("L+j}\r\n", c)) {
+		// these operate on multi-lines forwards
+		p = begin_line(dot);
+		do_cmd(c);		// execute movement cmd
+		dot_end();		// find NL
+		q = dot;
+	} else {
+		c = 27;			// error- return an ESC char
+		//break;
+	}
+	*start = p;
+	*stop = q;
+	if (q < p) {
+		*start = q;
+		*stop = p;
+	}
+	dot = save_dot;
+	return (c);
+}
+
+static int st_test(Byte * p, int type, int dir, Byte * tested)
+{
+	Byte c, c0, ci;
+	int test, inc;
+
+	inc = dir;
+	c = c0 = p[0];
+	ci = p[inc];
+	test = 0;
+
+	if (type == S_BEFORE_WS) {
+		c = ci;
+		test = ((!isspace(c)) || c == '\n');
+	}
+	if (type == S_TO_WS) {
+		c = c0;
+		test = ((!isspace(c)) || c == '\n');
+	}
+	if (type == S_OVER_WS) {
+		c = c0;
+		test = ((isspace(c)));
+	}
+	if (type == S_END_PUNCT) {
+		c = ci;
+		test = ((ispunct(c)));
+	}
+	if (type == S_END_ALNUM) {
+		c = ci;
+		test = ((isalnum(c)) || c == '_');
+	}
+	*tested = c;
+	return (test);
+}
+
+static Byte *skip_thing(Byte * p, int linecnt, int dir, int type)
+{
+	Byte c;
+
+	while (st_test(p, type, dir, &c)) {
+		// make sure we limit search to correct number of lines
+		if (c == '\n' && --linecnt < 1)
+			break;
+		if (dir >= 0 && p >= end - 1)
+			break;
+		if (dir < 0 && p <= text)
+			break;
+		p += dir;		// move to next char
+	}
+	return (p);
+}
+
+// find matching char of pair  ()  []  {}
+static Byte *find_pair(Byte * p, Byte c)
+{
+	Byte match, *q;
+	int dir, level;
+
+	match = ')';
+	level = 1;
+	dir = 1;			// assume forward
+	switch (c) {
+	case '(':
+		match = ')';
+		break;
+	case '[':
+		match = ']';
+		break;
+	case '{':
+		match = '}';
+		break;
+	case ')':
+		match = '(';
+		dir = -1;
+		break;
+	case ']':
+		match = '[';
+		dir = -1;
+		break;
+	case '}':
+		match = '{';
+		dir = -1;
+		break;
+	}
+	for (q = p + dir; text <= q && q < end; q += dir) {
+		// look for match, count levels of pairs  (( ))
+		if (*q == c)
+			level++;	// increase pair levels
+		if (*q == match)
+			level--;	// reduce pair level
+		if (level == 0)
+			break;		// found matching pair
+	}
+	if (level != 0)
+		q = NULL;		// indicate no match
+	return (q);
+}
+
+#ifdef CONFIG_FEATURE_VI_SETOPTS
+// show the matching char of a pair,  ()  []  {}
+static void showmatching(Byte * p)
+{
+	Byte *q, *save_dot;
+
+	// we found half of a pair
+	q = find_pair(p, *p);	// get loc of matching char
+	if (q == NULL) {
+		indicate_error('3');	// no matching char
+	} else {
+		// "q" now points to matching pair
+		save_dot = dot;	// remember where we are
+		dot = q;		// go to new loc
+		refresh(FALSE);	// let the user see it
+		(void) mysleep(40);	// give user some time
+		dot = save_dot;	// go back to old loc
+		refresh(FALSE);
+	}
+}
+#endif							/* CONFIG_FEATURE_VI_SETOPTS */
+
+//  open a hole in text[]
+static Byte *text_hole_make(Byte * p, int size)	// at "p", make a 'size' byte hole
+{
+	Byte *src, *dest;
+	int cnt;
+
+	if (size <= 0)
+		goto thm0;
+	src = p;
+	dest = p + size;
+	cnt = end - src;	// the rest of buffer
+	if (memmove(dest, src, cnt) != dest) {
+		psbs("can't create room for new characters");
+	}
+	memset(p, ' ', size);	// clear new hole
+	end = end + size;	// adjust the new END
+	file_modified++;	// has the file been modified
+  thm0:
+	return (p);
+}
+
+//  close a hole in text[]
+static Byte *text_hole_delete(Byte * p, Byte * q) // delete "p" thru "q", inclusive
+{
+	Byte *src, *dest;
+	int cnt, hole_size;
+
+	// move forwards, from beginning
+	// assume p <= q
+	src = q + 1;
+	dest = p;
+	if (q < p) {		// they are backward- swap them
+		src = p + 1;
+		dest = q;
+	}
+	hole_size = q - p + 1;
+	cnt = end - src;
+	if (src < text || src > end)
+		goto thd0;
+	if (dest < text || dest >= end)
+		goto thd0;
+	if (src >= end)
+		goto thd_atend;	// just delete the end of the buffer
+	if (memmove(dest, src, cnt) != dest) {
+		psbs("can't delete the character");
+	}
+  thd_atend:
+	end = end - hole_size;	// adjust the new END
+	if (dest >= end)
+		dest = end - 1;	// make sure dest in below end-1
+	if (end <= text)
+		dest = end = text;	// keep pointers valid
+	file_modified++;	// has the file been modified
+  thd0:
+	return (dest);
+}
+
+// copy text into register, then delete text.
+// if dist <= 0, do not include, or go past, a NewLine
+//
+static Byte *yank_delete(Byte * start, Byte * stop, int dist, int yf)
+{
+	Byte *p;
+
+	// make sure start <= stop
+	if (start > stop) {
+		// they are backwards, reverse them
+		p = start;
+		start = stop;
+		stop = p;
+	}
+	if (dist <= 0) {
+		// we can not cross NL boundaries
+		p = start;
+		if (*p == '\n')
+			return (p);
+		// dont go past a NewLine
+		for (; p + 1 <= stop; p++) {
+			if (p[1] == '\n') {
+				stop = p;	// "stop" just before NewLine
+				break;
+			}
+		}
+	}
+	p = start;
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+	text_yank(start, stop, YDreg);
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+	if (yf == YANKDEL) {
+		p = text_hole_delete(start, stop);
+	}					// delete lines
+	return (p);
+}
+
+static void show_help(void)
+{
+	puts("These features are available:"
+#ifdef CONFIG_FEATURE_VI_SEARCH
+	"\n\tPattern searches with / and ?"
+#endif							/* CONFIG_FEATURE_VI_SEARCH */
+#ifdef CONFIG_FEATURE_VI_DOT_CMD
+	"\n\tLast command repeat with \'.\'"
+#endif							/* CONFIG_FEATURE_VI_DOT_CMD */
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+	"\n\tLine marking with  'x"
+	"\n\tNamed buffers with  \"x"
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+#ifdef CONFIG_FEATURE_VI_READONLY
+	"\n\tReadonly if vi is called as \"view\""
+	"\n\tReadonly with -R command line arg"
+#endif							/* CONFIG_FEATURE_VI_READONLY */
+#ifdef CONFIG_FEATURE_VI_SET
+	"\n\tSome colon mode commands with \':\'"
+#endif							/* CONFIG_FEATURE_VI_SET */
+#ifdef CONFIG_FEATURE_VI_SETOPTS
+	"\n\tSettable options with \":set\""
+#endif							/* CONFIG_FEATURE_VI_SETOPTS */
+#ifdef CONFIG_FEATURE_VI_USE_SIGNALS
+	"\n\tSignal catching- ^C"
+	"\n\tJob suspend and resume with ^Z"
+#endif							/* CONFIG_FEATURE_VI_USE_SIGNALS */
+#ifdef CONFIG_FEATURE_VI_WIN_RESIZE
+	"\n\tAdapt to window re-sizes"
+#endif							/* CONFIG_FEATURE_VI_WIN_RESIZE */
+	);
+}
+
+static inline void print_literal(Byte * buf, Byte * s) // copy s to buf, convert unprintable
+{
+	Byte c, b[2];
+
+	b[1] = '\0';
+	strcpy((char *) buf, "");	// init buf
+	if (strlen((char *) s) <= 0)
+		s = (Byte *) "(NULL)";
+	for (; *s > '\0'; s++) {
+		int c_is_no_print;
+
+		c = *s;
+		c_is_no_print = c > 127 && !Isprint(c);
+		if (c_is_no_print) {
+			strcat((char *) buf, SOn);
+			c = '.';
+		}
+		if (c < ' ' || c == 127) {
+			strcat((char *) buf, "^");
+			if(c == 127)
+				c = '?';
+			 else
+			c += '@';
+		}
+		b[0] = c;
+		strcat((char *) buf, (char *) b);
+		if (c_is_no_print)
+			strcat((char *) buf, SOs);
+		if (*s == '\n') {
+			strcat((char *) buf, "$");
+		}
+	}
+}
+
+#ifdef CONFIG_FEATURE_VI_DOT_CMD
+static void start_new_cmd_q(Byte c)
+{
+	// release old cmd
+	free(last_modifying_cmd);
+	// get buffer for new cmd
+	last_modifying_cmd = (Byte *) xmalloc(BUFSIZ);
+	memset(last_modifying_cmd, '\0', BUFSIZ);	// clear new cmd queue
+	// if there is a current cmd count put it in the buffer first
+	if (cmdcnt > 0)
+		sprintf((char *) last_modifying_cmd, "%d%c", cmdcnt, c);
+	else // just save char c onto queue
+		last_modifying_cmd[0] = c;
+	adding2q = 1;
+}
+
+static void end_cmd_q(void)
+{
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+	YDreg = 26;			// go back to default Yank/Delete reg
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+	adding2q = 0;
+	return;
+}
+#endif							/* CONFIG_FEATURE_VI_DOT_CMD */
+
+#if defined(CONFIG_FEATURE_VI_YANKMARK) || (defined(CONFIG_FEATURE_VI_COLON) && defined(CONFIG_FEATURE_VI_SEARCH)) || defined(CONFIG_FEATURE_VI_CRASHME)
+static Byte *string_insert(Byte * p, Byte * s) // insert the string at 'p'
+{
+	int cnt, i;
+
+	i = strlen((char *) s);
+	p = text_hole_make(p, i);
+	strncpy((char *) p, (char *) s, i);
+	for (cnt = 0; *s != '\0'; s++) {
+		if (*s == '\n')
+			cnt++;
+	}
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+	psb("Put %d lines (%d chars) from [%c]", cnt, i, what_reg());
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+	return (p);
+}
+#endif							/* CONFIG_FEATURE_VI_YANKMARK || CONFIG_FEATURE_VI_COLON || CONFIG_FEATURE_VI_CRASHME */
+
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+static Byte *text_yank(Byte * p, Byte * q, int dest)	// copy text into a register
+{
+	Byte *t;
+	int cnt;
+
+	if (q < p) {		// they are backwards- reverse them
+		t = q;
+		q = p;
+		p = t;
+	}
+	cnt = q - p + 1;
+	t = reg[dest];
+	free(t);		//  if already a yank register, free it
+	t = (Byte *) xmalloc(cnt + 1);	// get a new register
+	memset(t, '\0', cnt + 1);	// clear new text[]
+	strncpy((char *) t, (char *) p, cnt);	// copy text[] into bufer
+	reg[dest] = t;
+	return (p);
+}
+
+static Byte what_reg(void)
+{
+	Byte c;
+	int i;
+
+	i = 0;
+	c = 'D';			// default to D-reg
+	if (0 <= YDreg && YDreg <= 25)
+		c = 'a' + (Byte) YDreg;
+	if (YDreg == 26)
+		c = 'D';
+	if (YDreg == 27)
+		c = 'U';
+	return (c);
+}
+
+static void check_context(Byte cmd)
+{
+	// A context is defined to be "modifying text"
+	// Any modifying command establishes a new context.
+
+	if (dot < context_start || dot > context_end) {
+		if (strchr((char *) modifying_cmds, cmd) != NULL) {
+			// we are trying to modify text[]- make this the current context
+			mark[27] = mark[26];	// move cur to prev
+			mark[26] = dot;	// move local to cur
+			context_start = prev_line(prev_line(dot));
+			context_end = next_line(next_line(dot));
+			//loiter= start_loiter= now;
+		}
+	}
+	return;
+}
+
+static inline Byte *swap_context(Byte * p) // goto new context for '' command make this the current context
+{
+	Byte *tmp;
+
+	// the current context is in mark[26]
+	// the previous context is in mark[27]
+	// only swap context if other context is valid
+	if (text <= mark[27] && mark[27] <= end - 1) {
+		tmp = mark[27];
+		mark[27] = mark[26];
+		mark[26] = tmp;
+		p = mark[26];	// where we are going- previous context
+		context_start = prev_line(prev_line(prev_line(p)));
+		context_end = next_line(next_line(next_line(p)));
+	}
+	return (p);
+}
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+
+static int isblnk(Byte c) // is the char a blank or tab
+{
+	return (c == ' ' || c == '\t');
+}
+
+//----- Set terminal attributes --------------------------------
+static void rawmode(void)
+{
+	tcgetattr(0, &term_orig);
+	term_vi = term_orig;
+	term_vi.c_lflag &= (~ICANON & ~ECHO);	// leave ISIG ON- allow intr's
+	term_vi.c_iflag &= (~IXON & ~ICRNL);
+	term_vi.c_oflag &= (~ONLCR);
+	term_vi.c_cc[VMIN] = 1;
+	term_vi.c_cc[VTIME] = 0;
+	erase_char = term_vi.c_cc[VERASE];
+	tcsetattr(0, TCSANOW, &term_vi);
+}
+
+static void cookmode(void)
+{
+	fflush(stdout);
+	tcsetattr(0, TCSANOW, &term_orig);
+}
+
+//----- Come here when we get a window resize signal ---------
+#ifdef CONFIG_FEATURE_VI_USE_SIGNALS
+static void winch_sig(int sig ATTRIBUTE_UNUSED)
+{
+	signal(SIGWINCH, winch_sig);
+	if (ENABLE_FEATURE_VI_WIN_RESIZE)
+	   get_terminal_width_height(0, &columns, &rows);
+	new_screen(rows, columns);	// get memory for virtual screen
+	redraw(TRUE);		// re-draw the screen
+}
+
+//----- Come here when we get a continue signal -------------------
+static void cont_sig(int sig ATTRIBUTE_UNUSED)
+{
+	rawmode();			// terminal to "raw"
+	last_status_cksum = 0;	// force status update
+	redraw(TRUE);		// re-draw the screen
+
+	signal(SIGTSTP, suspend_sig);
+	signal(SIGCONT, SIG_DFL);
+	kill(my_pid, SIGCONT);
+}
+
+//----- Come here when we get a Suspend signal -------------------
+static void suspend_sig(int sig ATTRIBUTE_UNUSED)
+{
+	place_cursor(rows - 1, 0, FALSE);	// go to bottom of screen
+	clear_to_eol();		// Erase to end of line
+	cookmode();			// terminal to "cooked"
+
+	signal(SIGCONT, cont_sig);
+	signal(SIGTSTP, SIG_DFL);
+	kill(my_pid, SIGTSTP);
+}
+
+//----- Come here when we get a signal ---------------------------
+static void catch_sig(int sig)
+{
+	signal(SIGINT, catch_sig);
+	if(sig)
+		longjmp(restart, sig);
+}
+#endif							/* CONFIG_FEATURE_VI_USE_SIGNALS */
+
+static int mysleep(int hund)	// sleep for 'h' 1/100 seconds
+{
+	// Don't hang- Wait 5/100 seconds-  1 Sec= 1000000
+	fflush(stdout);
+	FD_ZERO(&rfds);
+	FD_SET(0, &rfds);
+	tv.tv_sec = 0;
+	tv.tv_usec = hund * 10000;
+	select(1, &rfds, NULL, NULL, &tv);
+	return (FD_ISSET(0, &rfds));
+}
+
+#define readbuffer bb_common_bufsiz1
+
+static int readed_for_parse;
+
+//----- IO Routines --------------------------------------------
+static Byte readit(void)	// read (maybe cursor) key from stdin
+{
+	Byte c;
+	int n;
+	struct esc_cmds {
+		const char *seq;
+		Byte val;
+	};
+
+	static const struct esc_cmds esccmds[] = {
+		{"OA", (Byte) VI_K_UP},       // cursor key Up
+		{"OB", (Byte) VI_K_DOWN},     // cursor key Down
+		{"OC", (Byte) VI_K_RIGHT},    // Cursor Key Right
+		{"OD", (Byte) VI_K_LEFT},     // cursor key Left
+		{"OH", (Byte) VI_K_HOME},     // Cursor Key Home
+		{"OF", (Byte) VI_K_END},      // Cursor Key End
+		{"[A", (Byte) VI_K_UP},       // cursor key Up
+		{"[B", (Byte) VI_K_DOWN},     // cursor key Down
+		{"[C", (Byte) VI_K_RIGHT},    // Cursor Key Right
+		{"[D", (Byte) VI_K_LEFT},     // cursor key Left
+		{"[H", (Byte) VI_K_HOME},     // Cursor Key Home
+		{"[F", (Byte) VI_K_END},      // Cursor Key End
+		{"[1~", (Byte) VI_K_HOME},     // Cursor Key Home
+		{"[2~", (Byte) VI_K_INSERT},  // Cursor Key Insert
+		{"[4~", (Byte) VI_K_END},      // Cursor Key End
+		{"[5~", (Byte) VI_K_PAGEUP},  // Cursor Key Page Up
+		{"[6~", (Byte) VI_K_PAGEDOWN},        // Cursor Key Page Down
+		{"OP", (Byte) VI_K_FUN1},     // Function Key F1
+		{"OQ", (Byte) VI_K_FUN2},     // Function Key F2
+		{"OR", (Byte) VI_K_FUN3},     // Function Key F3
+		{"OS", (Byte) VI_K_FUN4},     // Function Key F4
+		{"[15~", (Byte) VI_K_FUN5},   // Function Key F5
+		{"[17~", (Byte) VI_K_FUN6},   // Function Key F6
+		{"[18~", (Byte) VI_K_FUN7},   // Function Key F7
+		{"[19~", (Byte) VI_K_FUN8},   // Function Key F8
+		{"[20~", (Byte) VI_K_FUN9},   // Function Key F9
+		{"[21~", (Byte) VI_K_FUN10},  // Function Key F10
+		{"[23~", (Byte) VI_K_FUN11},  // Function Key F11
+		{"[24~", (Byte) VI_K_FUN12},  // Function Key F12
+		{"[11~", (Byte) VI_K_FUN1},   // Function Key F1
+		{"[12~", (Byte) VI_K_FUN2},   // Function Key F2
+		{"[13~", (Byte) VI_K_FUN3},   // Function Key F3
+		{"[14~", (Byte) VI_K_FUN4},   // Function Key F4
+	};
+
+#define ESCCMDS_COUNT (sizeof(esccmds)/sizeof(struct esc_cmds))
+
+	(void) alarm(0);	// turn alarm OFF while we wait for input
+	fflush(stdout);
+	n = readed_for_parse;
+	// get input from User- are there already input chars in Q?
+	if (n <= 0) {
+	  ri0:
+		// the Q is empty, wait for a typed char
+		n = read(0, readbuffer, BUFSIZ - 1);
+		if (n < 0) {
+			if (errno == EINTR)
+				goto ri0;	// interrupted sys call
+			if (errno == EBADF)
+				editing = 0;
+			if (errno == EFAULT)
+				editing = 0;
+			if (errno == EINVAL)
+				editing = 0;
+			if (errno == EIO)
+				editing = 0;
+			errno = 0;
+		}
+		if(n <= 0)
+			return 0;       // error
+		if (readbuffer[0] == 27) {
+	// This is an ESC char. Is this Esc sequence?
+	// Could be bare Esc key. See if there are any
+	// more chars to read after the ESC. This would
+	// be a Function or Cursor Key sequence.
+	FD_ZERO(&rfds);
+	FD_SET(0, &rfds);
+	tv.tv_sec = 0;
+	tv.tv_usec = 50000;	// Wait 5/100 seconds- 1 Sec=1000000
+
+	// keep reading while there are input chars and room in buffer
+			while (select(1, &rfds, NULL, NULL, &tv) > 0 && n <= (BUFSIZ - 5)) {
+		// read the rest of the ESC string
+				int r = read(0, (void *) (readbuffer + n), BUFSIZ - n);
+				if (r > 0) {
+					n += r;
+				}
+			}
+		}
+		readed_for_parse = n;
+	}
+	c = readbuffer[0];
+	if(c == 27 && n > 1) {
+	// Maybe cursor or function key?
+		const struct esc_cmds *eindex;
+
+		for (eindex = esccmds; eindex < &esccmds[ESCCMDS_COUNT]; eindex++) {
+			int cnt = strlen(eindex->seq);
+
+			if(n <= cnt)
+				continue;
+			if(strncmp(eindex->seq, (char *) readbuffer + 1, cnt))
+				continue;
+			// is a Cursor key- put derived value back into Q
+			c = eindex->val;
+			// for squeeze out the ESC sequence
+			n = cnt + 1;
+			break;
+		}
+		if(eindex == &esccmds[ESCCMDS_COUNT]) {
+			/* defined ESC sequence not found, set only one ESC */
+			n = 1;
+	}
+	} else {
+		n = 1;
+	}
+	// remove key sequence from Q
+	readed_for_parse -= n;
+	memmove(readbuffer, readbuffer + n, BUFSIZ - n);
+	(void) alarm(3);	// we are done waiting for input, turn alarm ON
+	return (c);
+}
+
+//----- IO Routines --------------------------------------------
+static Byte get_one_char(void)
+{
+	static Byte c;
+
+#ifdef CONFIG_FEATURE_VI_DOT_CMD
+	// ! adding2q  && ioq == 0  read()
+	// ! adding2q  && ioq != 0  *ioq
+	// adding2q         *last_modifying_cmd= read()
+	if (!adding2q) {
+		// we are not adding to the q.
+		// but, we may be reading from a q
+		if (ioq == 0) {
+			// there is no current q, read from STDIN
+			c = readit();	// get the users input
+		} else {
+			// there is a queue to get chars from first
+			c = *ioq++;
+			if (c == '\0') {
+				// the end of the q, read from STDIN
+				free(ioq_start);
+				ioq_start = ioq = 0;
+				c = readit();	// get the users input
+			}
+		}
+	} else {
+		// adding STDIN chars to q
+		c = readit();	// get the users input
+		if (last_modifying_cmd != 0) {
+			int len = strlen((char *) last_modifying_cmd);
+			if (len + 1 >= BUFSIZ) {
+				psbs("last_modifying_cmd overrun");
+			} else {
+				// add new char to q
+				last_modifying_cmd[len] = c;
+			}
+		}
+	}
+#else							/* CONFIG_FEATURE_VI_DOT_CMD */
+	c = readit();		// get the users input
+#endif							/* CONFIG_FEATURE_VI_DOT_CMD */
+	return (c);			// return the char, where ever it came from
+}
+
+static Byte *get_input_line(Byte * prompt) // get input line- use "status line"
+{
+	Byte buf[BUFSIZ];
+	Byte c;
+	int i;
+	static Byte *obufp = NULL;
+
+	strcpy((char *) buf, (char *) prompt);
+	last_status_cksum = 0;	// force status update
+	place_cursor(rows - 1, 0, FALSE);	// go to Status line, bottom of screen
+	clear_to_eol();		// clear the line
+	write1((char *) prompt);      // write out the :, /, or ? prompt
+
+	for (i = strlen((char *) buf); i < BUFSIZ;) {
+		c = get_one_char();	// read user input
+		if (c == '\n' || c == '\r' || c == 27)
+			break;		// is this end of input
+		if (c == erase_char || c == 8 || c == 127) {
+			// user wants to erase prev char
+			i--;		// backup to prev char
+			buf[i] = '\0';	// erase the char
+			buf[i + 1] = '\0';	// null terminate buffer
+			write1("\b \b");     // erase char on screen
+			if (i <= 0) {	// user backs up before b-o-l, exit
+				break;
+			}
+		} else {
+			buf[i] = c;	// save char in buffer
+			buf[i + 1] = '\0';	// make sure buffer is null terminated
+			putchar(c);   // echo the char back to user
+			i++;
+		}
+	}
+	refresh(FALSE);
+	free(obufp);
+	obufp = (Byte *) bb_xstrdup((char *) buf);
+	return (obufp);
+}
+
+static int file_size(const Byte * fn) // what is the byte size of "fn"
+{
+	struct stat st_buf;
+	int cnt, sr;
+
+	if (fn == 0 || strlen((char *)fn) <= 0)
+		return (-1);
+	cnt = -1;
+	sr = stat((char *) fn, &st_buf);	// see if file exists
+	if (sr >= 0) {
+		cnt = (int) st_buf.st_size;
+	}
+	return (cnt);
+}
+
+static int file_insert(Byte * fn, Byte * p, int size)
+{
+	int fd, cnt;
+
+	cnt = -1;
+#ifdef CONFIG_FEATURE_VI_READONLY
+	readonly = FALSE;
+#endif							/* CONFIG_FEATURE_VI_READONLY */
+	if (fn == 0 || strlen((char*) fn) <= 0) {
+		psbs("No filename given");
+		goto fi0;
+	}
+	if (size == 0) {
+		// OK- this is just a no-op
+		cnt = 0;
+		goto fi0;
+	}
+	if (size < 0) {
+		psbs("Trying to insert a negative number (%d) of characters", size);
+		goto fi0;
+	}
+	if (p < text || p > end) {
+		psbs("Trying to insert file outside of memory");
+		goto fi0;
+	}
+
+	// see if we can open the file
+#ifdef CONFIG_FEATURE_VI_READONLY
+	if (vi_readonly) goto fi1;		// do not try write-mode
+#endif
+	fd = open((char *) fn, O_RDWR);			// assume read & write
+	if (fd < 0) {
+		// could not open for writing- maybe file is read only
+#ifdef CONFIG_FEATURE_VI_READONLY
+  fi1:
+#endif
+		fd = open((char *) fn, O_RDONLY);	// try read-only
+		if (fd < 0) {
+			psbs("\"%s\" %s", fn, "could not open file");
+			goto fi0;
+		}
+#ifdef CONFIG_FEATURE_VI_READONLY
+		// got the file- read-only
+		readonly = TRUE;
+#endif							/* CONFIG_FEATURE_VI_READONLY */
+	}
+	p = text_hole_make(p, size);
+	cnt = read(fd, p, size);
+	close(fd);
+	if (cnt < 0) {
+		cnt = -1;
+		p = text_hole_delete(p, p + size - 1);	// un-do buffer insert
+		psbs("could not read file \"%s\"", fn);
+	} else if (cnt < size) {
+		// There was a partial read, shrink unused space text[]
+		p = text_hole_delete(p + cnt, p + (size - cnt) - 1);	// un-do buffer insert
+		psbs("could not read all of file \"%s\"", fn);
+	}
+	if (cnt >= size)
+		file_modified++;
+  fi0:
+	return (cnt);
+}
+
+static int file_write(Byte * fn, Byte * first, Byte * last)
+{
+	int fd, cnt, charcnt;
+
+	if (fn == 0) {
+		psbs("No current filename");
+		return (-2);
+	}
+	charcnt = 0;
+	// FIXIT- use the correct umask()
+	fd = open((char *) fn, (O_WRONLY | O_CREAT | O_TRUNC), 0664);
+	if (fd < 0)
+		return (-1);
+	cnt = last - first + 1;
+	charcnt = write(fd, first, cnt);
+	if (charcnt == cnt) {
+		// good write
+		//file_modified= FALSE; // the file has not been modified
+	} else {
+		charcnt = 0;
+	}
+	close(fd);
+	return (charcnt);
+}
+
+//----- Terminal Drawing ---------------------------------------
+// The terminal is made up of 'rows' line of 'columns' columns.
+// classically this would be 24 x 80.
+//  screen coordinates
+//  0,0     ...     0,79
+//  1,0     ...     1,79
+//  .       ...     .
+//  .       ...     .
+//  22,0    ...     22,79
+//  23,0    ...     23,79   status line
+//
+
+//----- Move the cursor to row x col (count from 0, not 1) -------
+static void place_cursor(int row, int col, int opti)
+{
+	char cm1[BUFSIZ];
+	char *cm;
+#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
+	char cm2[BUFSIZ];
+	Byte *screenp;
+	// char cm3[BUFSIZ];
+	int Rrow= last_row;
+#endif							/* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
+
+	memset(cm1, '\0', BUFSIZ - 1);  // clear the buffer
+
+	if (row < 0) row = 0;
+	if (row >= rows) row = rows - 1;
+	if (col < 0) col = 0;
+	if (col >= columns) col = columns - 1;
+
+	//----- 1.  Try the standard terminal ESC sequence
+	sprintf((char *) cm1, CMrc, row + 1, col + 1);
+	cm= cm1;
+	if (! opti) goto pc0;
+
+#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
+	//----- find the minimum # of chars to move cursor -------------
+	//----- 2.  Try moving with discreet chars (Newline, [back]space, ...)
+	memset(cm2, '\0', BUFSIZ - 1);  // clear the buffer
+
+	// move to the correct row
+	while (row < Rrow) {
+		// the cursor has to move up
+		strcat(cm2, CMup);
+		Rrow--;
+	}
+	while (row > Rrow) {
+		// the cursor has to move down
+		strcat(cm2, CMdown);
+		Rrow++;
+	}
+
+	// now move to the correct column
+	strcat(cm2, "\r");			// start at col 0
+	// just send out orignal source char to get to correct place
+	screenp = &screen[row * columns];	// start of screen line
+	strncat(cm2, (char* )screenp, col);
+
+	//----- 3.  Try some other way of moving cursor
+	//---------------------------------------------
+
+	// pick the shortest cursor motion to send out
+	cm= cm1;
+	if (strlen(cm2) < strlen(cm)) {
+		cm= cm2;
+	}  /* else if (strlen(cm3) < strlen(cm)) {
+		cm= cm3;
+	} */
+#endif							/* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
+  pc0:
+	write1(cm);                 // move the cursor
+}
+
+//----- Erase from cursor to end of line -----------------------
+static void clear_to_eol(void)
+{
+	write1(Ceol);   // Erase from cursor to end of line
+}
+
+//----- Erase from cursor to end of screen -----------------------
+static void clear_to_eos(void)
+{
+	write1(Ceos);   // Erase from cursor to end of screen
+}
+
+//----- Start standout mode ------------------------------------
+static void standout_start(void) // send "start reverse video" sequence
+{
+	write1(SOs);     // Start reverse video mode
+}
+
+//----- End standout mode --------------------------------------
+static void standout_end(void) // send "end reverse video" sequence
+{
+	write1(SOn);     // End reverse video mode
+}
+
+//----- Flash the screen  --------------------------------------
+static void flash(int h)
+{
+	standout_start();	// send "start reverse video" sequence
+	redraw(TRUE);
+	(void) mysleep(h);
+	standout_end();		// send "end reverse video" sequence
+	redraw(TRUE);
+}
+
+static void Indicate_Error(void)
+{
+#ifdef CONFIG_FEATURE_VI_CRASHME
+	if (crashme > 0)
+		return;			// generate a random command
+#endif							/* CONFIG_FEATURE_VI_CRASHME */
+	if (!err_method) {
+		write1(bell);   // send out a bell character
+	} else {
+		flash(10);
+	}
+}
+
+//----- Screen[] Routines --------------------------------------
+//----- Erase the Screen[] memory ------------------------------
+static void screen_erase(void)
+{
+	memset(screen, ' ', screensize);	// clear new screen
+}
+
+static int bufsum(unsigned char *buf, int count)
+{
+	int sum = 0;
+	unsigned char *e = buf + count;
+	while (buf < e)
+		sum += *buf++;
+	return sum;
+}
+
+//----- Draw the status line at bottom of the screen -------------
+static void show_status_line(void)
+{
+	int cnt = 0, cksum = 0;
+
+	// either we already have an error or status message, or we
+	// create one.
+	if (!have_status_msg) {
+		cnt = format_edit_status();
+		cksum = bufsum(status_buffer, cnt);
+	}
+	if (have_status_msg || ((cnt > 0 && last_status_cksum != cksum))) {
+		last_status_cksum= cksum;		// remember if we have seen this line
+		place_cursor(rows - 1, 0, FALSE);	// put cursor on status line
+		write1((char*)status_buffer);
+		clear_to_eol();
+		if (have_status_msg) {
+			if (((int)strlen((char*)status_buffer) - (have_status_msg - 1)) >
+					(columns - 1) ) {
+				have_status_msg = 0;
+				Hit_Return();
+			}
+			have_status_msg = 0;
+		}
+		place_cursor(crow, ccol, FALSE);	// put cursor back in correct place
+	}
+	fflush(stdout);
+}
+
+//----- format the status buffer, the bottom line of screen ------
+// format status buffer, with STANDOUT mode
+static void psbs(const char *format, ...)
+{
+	va_list args;
+
+	va_start(args, format);
+	strcpy((char *) status_buffer, SOs);	// Terminal standout mode on
+	vsprintf((char *) status_buffer + strlen((char *) status_buffer), format, args);
+	strcat((char *) status_buffer, SOn);	// Terminal standout mode off
+	va_end(args);
+
+	have_status_msg = 1 + sizeof(SOs) + sizeof(SOn) - 2;
+
+	return;
+}
+
+// format status buffer
+static void psb(const char *format, ...)
+{
+	va_list args;
+
+	va_start(args, format);
+	vsprintf((char *) status_buffer, format, args);
+	va_end(args);
+
+	have_status_msg = 1;
+
+	return;
+}
+
+static void ni(Byte * s) // display messages
+{
+	Byte buf[BUFSIZ];
+
+	print_literal(buf, s);
+	psbs("\'%s\' is not implemented", buf);
+}
+
+static int format_edit_status(void)	// show file status on status line
+{
+	int cur, percent, ret, trunc_at;
+	static int tot;
+
+	// file_modified is now a counter rather than a flag.  this
+	// helps reduce the amount of line counting we need to do.
+	// (this will cause a mis-reporting of modified status
+	// once every MAXINT editing operations.)
+
+	// it would be nice to do a similar optimization here -- if
+	// we haven't done a motion that could have changed which line
+	// we're on, then we shouldn't have to do this count_lines()
+	cur = count_lines(text, dot);
+
+	// reduce counting -- the total lines can't have
+	// changed if we haven't done any edits.
+	if (file_modified != last_file_modified) {
+		tot = cur + count_lines(dot, end - 1) - 1;
+		last_file_modified = file_modified;
+	}
+
+	//    current line         percent
+	//   -------------    ~~ ----------
+	//    total lines            100
+	if (tot > 0) {
+		percent = (100 * cur) / tot;
+	} else {
+		cur = tot = 0;
+		percent = 100;
+	}
+
+	trunc_at = columns < STATUS_BUFFER_LEN-1 ?
+		columns : STATUS_BUFFER_LEN-1;
+
+	ret = snprintf((char *) status_buffer, trunc_at+1,
+#ifdef CONFIG_FEATURE_VI_READONLY
+		"%c %s%s%s %d/%d %d%%",
+#else
+		"%c %s%s %d/%d %d%%",
+#endif
+		(cmd_mode ? (cmd_mode == 2 ? 'R':'I'):'-'),
+		(cfn != 0 ? (char *) cfn : "No file"),
+#ifdef CONFIG_FEATURE_VI_READONLY
+		((vi_readonly || readonly) ? " [Read-only]" : ""),
+#endif
+		(file_modified ? " [modified]" : ""),
+		cur, tot, percent);
+
+	if (ret >= 0 && ret < trunc_at)
+		return ret;  /* it all fit */
+
+	return trunc_at;  /* had to truncate */
+}
+
+//----- Force refresh of all Lines -----------------------------
+static void redraw(int full_screen)
+{
+	place_cursor(0, 0, FALSE);	// put cursor in correct place
+	clear_to_eos();		// tel terminal to erase display
+	screen_erase();		// erase the internal screen buffer
+	last_status_cksum = 0;	// force status update
+	refresh(full_screen);	// this will redraw the entire display
+	show_status_line();
+}
+
+//----- Format a text[] line into a buffer ---------------------
+static void format_line(Byte *dest, Byte *src, int li)
+{
+	int co;
+	Byte c;
+
+	for (co= 0; co < MAX_SCR_COLS; co++) {
+		c= ' ';		// assume blank
+		if (li > 0 && co == 0) {
+			c = '~';        // not first line, assume Tilde
+		}
+		// are there chars in text[] and have we gone past the end
+		if (text < end && src < end) {
+			c = *src++;
+		}
+		if (c == '\n')
+			break;
+		if (c > 127 && !Isprint(c)) {
+			c = '.';
+		}
+		if (c < ' ' || c == 127) {
+			if (c == '\t') {
+				c = ' ';
+				//       co %    8     !=     7
+				for (; (co % tabstop) != (tabstop - 1); co++) {
+					dest[co] = c;
+				}
+			} else {
+				dest[co++] = '^';
+				if(c == 127)
+					c = '?';
+				 else
+					c += '@';       // make it visible
+			}
+		}
+		// the co++ is done here so that the column will
+		// not be overwritten when we blank-out the rest of line
+		dest[co] = c;
+		if (src >= end)
+			break;
+	}
+}
+
+//----- Refresh the changed screen lines -----------------------
+// Copy the source line from text[] into the buffer and note
+// if the current screenline is different from the new buffer.
+// If they differ then that line needs redrawing on the terminal.
+//
+static void refresh(int full_screen)
+{
+	static int old_offset;
+	int li, changed;
+	Byte buf[MAX_SCR_COLS];
+	Byte *tp, *sp;		// pointer into text[] and screen[]
+#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
+	int last_li= -2;				// last line that changed- for optimizing cursor movement
+#endif							/* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
+
+	if (ENABLE_FEATURE_VI_WIN_RESIZE)
+		get_terminal_width_height(0, &columns, &rows);
+	sync_cursor(dot, &crow, &ccol);	// where cursor will be (on "dot")
+	tp = screenbegin;	// index into text[] of top line
+
+	// compare text[] to screen[] and mark screen[] lines that need updating
+	for (li = 0; li < rows - 1; li++) {
+		int cs, ce;				// column start & end
+		memset(buf, ' ', MAX_SCR_COLS);		// blank-out the buffer
+		buf[MAX_SCR_COLS-1] = 0;		// NULL terminate the buffer
+		// format current text line into buf
+		format_line(buf, tp, li);
+
+		// skip to the end of the current text[] line
+		while (tp < end && *tp++ != '\n') /*no-op*/ ;
+
+		// see if there are any changes between vitual screen and buf
+		changed = FALSE;	// assume no change
+		cs= 0;
+		ce= columns-1;
+		sp = &screen[li * columns];	// start of screen line
+		if (full_screen) {
+			// force re-draw of every single column from 0 - columns-1
+			goto re0;
+		}
+		// compare newly formatted buffer with virtual screen
+		// look forward for first difference between buf and screen
+		for ( ; cs <= ce; cs++) {
+			if (buf[cs + offset] != sp[cs]) {
+				changed = TRUE;	// mark for redraw
+				break;
+			}
+		}
+
+		// look backward for last difference between buf and screen
+		for ( ; ce >= cs; ce--) {
+			if (buf[ce + offset] != sp[ce]) {
+				changed = TRUE;	// mark for redraw
+				break;
+			}
+		}
+		// now, cs is index of first diff, and ce is index of last diff
+
+		// if horz offset has changed, force a redraw
+		if (offset != old_offset) {
+  re0:
+			changed = TRUE;
+		}
+
+		// make a sanity check of columns indexes
+		if (cs < 0) cs= 0;
+		if (ce > columns-1) ce= columns-1;
+		if (cs > ce) {  cs= 0;  ce= columns-1;  }
+		// is there a change between vitual screen and buf
+		if (changed) {
+			//  copy changed part of buffer to virtual screen
+			memmove(sp+cs, buf+(cs+offset), ce-cs+1);
+
+			// move cursor to column of first change
+			if (offset != old_offset) {
+				// opti_cur_move is still too stupid
+				// to handle offsets correctly
+				place_cursor(li, cs, FALSE);
+			} else {
+#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
+				// if this just the next line
+				//  try to optimize cursor movement
+				//  otherwise, use standard ESC sequence
+				place_cursor(li, cs, li == (last_li+1) ? TRUE : FALSE);
+				last_li= li;
+#else							/* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
+				place_cursor(li, cs, FALSE);	// use standard ESC sequence
+#endif							/* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
+			}
+
+			// write line out to terminal
+			{
+				int nic = ce-cs+1;
+				char *out = (char*)sp+cs;
+
+				while(nic-- > 0) {
+					putchar(*out);
+					out++;
+				}
+			}
+#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
+			last_row = li;
+#endif							/* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
+		}
+	}
+
+#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
+	place_cursor(crow, ccol, (crow == last_row) ? TRUE : FALSE);
+	last_row = crow;
+#else
+	place_cursor(crow, ccol, FALSE);
+#endif							/* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
+
+	if (offset != old_offset)
+		old_offset = offset;
+}
+
+//---------------------------------------------------------------------
+//----- the Ascii Chart -----------------------------------------------
+//
+//  00 nul   01 soh   02 stx   03 etx   04 eot   05 enq   06 ack   07 bel
+//  08 bs    09 ht    0a nl    0b vt    0c np    0d cr    0e so    0f si
+//  10 dle   11 dc1   12 dc2   13 dc3   14 dc4   15 nak   16 syn   17 etb
+//  18 can   19 em    1a sub   1b esc   1c fs    1d gs    1e rs    1f us
+//  20 sp    21 !     22 "     23 #     24 $     25 %     26 &     27 '
+//  28 (     29 )     2a *     2b +     2c ,     2d -     2e .     2f /
+//  30 0     31 1     32 2     33 3     34 4     35 5     36 6     37 7
+//  38 8     39 9     3a :     3b ;     3c <     3d =     3e >     3f ?
+//  40 @     41 A     42 B     43 C     44 D     45 E     46 F     47 G
+//  48 H     49 I     4a J     4b K     4c L     4d M     4e N     4f O
+//  50 P     51 Q     52 R     53 S     54 T     55 U     56 V     57 W
+//  58 X     59 Y     5a Z     5b [     5c \     5d ]     5e ^     5f _
+//  60 `     61 a     62 b     63 c     64 d     65 e     66 f     67 g
+//  68 h     69 i     6a j     6b k     6c l     6d m     6e n     6f o
+//  70 p     71 q     72 r     73 s     74 t     75 u     76 v     77 w
+//  78 x     79 y     7a z     7b {     7c |     7d }     7e ~     7f del
+//---------------------------------------------------------------------
+
+//----- Execute a Vi Command -----------------------------------
+static void do_cmd(Byte c)
+{
+	Byte c1, *p, *q, *msg, buf[9], *save_dot;
+	int cnt, i, j, dir, yf;
+
+	c1 = c;				// quiet the compiler
+	cnt = yf = dir = 0;	// quiet the compiler
+	p = q = save_dot = msg = buf;	// quiet the compiler
+	memset(buf, '\0', 9);	// clear buf
+
+	show_status_line();
+
+	/* if this is a cursor key, skip these checks */
+	switch (c) {
+		case VI_K_UP:
+		case VI_K_DOWN:
+		case VI_K_LEFT:
+		case VI_K_RIGHT:
+		case VI_K_HOME:
+		case VI_K_END:
+		case VI_K_PAGEUP:
+		case VI_K_PAGEDOWN:
+			goto key_cmd_mode;
+	}
+
+	if (cmd_mode == 2) {
+		//  flip-flop Insert/Replace mode
+		if (c == VI_K_INSERT) goto dc_i;
+		// we are 'R'eplacing the current *dot with new char
+		if (*dot == '\n') {
+			// don't Replace past E-o-l
+			cmd_mode = 1;	// convert to insert
+		} else {
+			if (1 <= c || Isprint(c)) {
+				if (c != 27)
+					dot = yank_delete(dot, dot, 0, YANKDEL);	// delete char
+				dot = char_insert(dot, c);	// insert new char
+			}
+			goto dc1;
+		}
+	}
+	if (cmd_mode == 1) {
+		//  hitting "Insert" twice means "R" replace mode
+		if (c == VI_K_INSERT) goto dc5;
+		// insert the char c at "dot"
+		if (1 <= c || Isprint(c)) {
+			dot = char_insert(dot, c);
+		}
+		goto dc1;
+	}
+
+key_cmd_mode:
+	switch (c) {
+		//case 0x01:	// soh
+		//case 0x09:	// ht
+		//case 0x0b:	// vt
+		//case 0x0e:	// so
+		//case 0x0f:	// si
+		//case 0x10:	// dle
+		//case 0x11:	// dc1
+		//case 0x13:	// dc3
+#ifdef CONFIG_FEATURE_VI_CRASHME
+	case 0x14:			// dc4  ctrl-T
+		crashme = (crashme == 0) ? 1 : 0;
+		break;
+#endif							/* CONFIG_FEATURE_VI_CRASHME */
+		//case 0x16:	// syn
+		//case 0x17:	// etb
+		//case 0x18:	// can
+		//case 0x1c:	// fs
+		//case 0x1d:	// gs
+		//case 0x1e:	// rs
+		//case 0x1f:	// us
+		//case '!':	// !-
+		//case '#':	// #-
+		//case '&':	// &-
+		//case '(':	// (-
+		//case ')':	// )-
+		//case '*':	// *-
+		//case ',':	// ,-
+		//case '=':	// =-
+		//case '@':	// @-
+		//case 'F':	// F-
+		//case 'K':	// K-
+		//case 'Q':	// Q-
+		//case 'S':	// S-
+		//case 'T':	// T-
+		//case 'V':	// V-
+		//case '[':	// [-
+		//case '\\':	// \-
+		//case ']':	// ]-
+		//case '_':	// _-
+		//case '`':	// `-
+		//case 'g':	// g-
+		//case 'u':	// u- FIXME- there is no undo
+		//case 'v':	// v-
+	default:			// unrecognised command
+		buf[0] = c;
+		buf[1] = '\0';
+		if (c < ' ') {
+			buf[0] = '^';
+			buf[1] = c + '@';
+			buf[2] = '\0';
+		}
+		ni((Byte *) buf);
+		end_cmd_q();	// stop adding to q
+	case 0x00:			// nul- ignore
+		break;
+	case 2:			// ctrl-B  scroll up   full screen
+	case VI_K_PAGEUP:	// Cursor Key Page Up
+		dot_scroll(rows - 2, -1);
+		break;
+#ifdef CONFIG_FEATURE_VI_USE_SIGNALS
+	case 0x03:			// ctrl-C   interrupt
+		longjmp(restart, 1);
+		break;
+	case 26:			// ctrl-Z suspend
+		suspend_sig(SIGTSTP);
+		break;
+#endif							/* CONFIG_FEATURE_VI_USE_SIGNALS */
+	case 4:			// ctrl-D  scroll down half screen
+		dot_scroll((rows - 2) / 2, 1);
+		break;
+	case 5:			// ctrl-E  scroll down one line
+		dot_scroll(1, 1);
+		break;
+	case 6:			// ctrl-F  scroll down full screen
+	case VI_K_PAGEDOWN:	// Cursor Key Page Down
+		dot_scroll(rows - 2, 1);
+		break;
+	case 7:			// ctrl-G  show current status
+		last_status_cksum = 0;	// force status update
+		break;
+	case 'h':			// h- move left
+	case VI_K_LEFT:	// cursor key Left
+	case 8:		// ctrl-H- move left    (This may be ERASE char)
+	case 127:	// DEL- move left   (This may be ERASE char)
+		if (cmdcnt-- > 1) {
+			do_cmd(c);
+		}				// repeat cnt
+		dot_left();
+		break;
+	case 10:			// Newline ^J
+	case 'j':			// j- goto next line, same col
+	case VI_K_DOWN:	// cursor key Down
+		if (cmdcnt-- > 1) {
+			do_cmd(c);
+		}				// repeat cnt
+		dot_next();		// go to next B-o-l
+		dot = move_to_col(dot, ccol + offset);	// try stay in same col
+		break;
+	case 12:			// ctrl-L  force redraw whole screen
+	case 18:			// ctrl-R  force redraw
+		place_cursor(0, 0, FALSE);	// put cursor in correct place
+		clear_to_eos();	// tel terminal to erase display
+		(void) mysleep(10);
+		screen_erase();	// erase the internal screen buffer
+		last_status_cksum = 0;	// force status update
+		refresh(TRUE);	// this will redraw the entire display
+		break;
+	case 13:			// Carriage Return ^M
+	case '+':			// +- goto next line
+		if (cmdcnt-- > 1) {
+			do_cmd(c);
+		}				// repeat cnt
+		dot_next();
+		dot_skip_over_ws();
+		break;
+	case 21:			// ctrl-U  scroll up   half screen
+		dot_scroll((rows - 2) / 2, -1);
+		break;
+	case 25:			// ctrl-Y  scroll up one line
+		dot_scroll(1, -1);
+		break;
+	case 27:			// esc
+		if (cmd_mode == 0)
+			indicate_error(c);
+		cmd_mode = 0;	// stop insrting
+		end_cmd_q();
+		last_status_cksum = 0;	// force status update
+		break;
+	case ' ':			// move right
+	case 'l':			// move right
+	case VI_K_RIGHT:	// Cursor Key Right
+		if (cmdcnt-- > 1) {
+			do_cmd(c);
+		}				// repeat cnt
+		dot_right();
+		break;
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+	case '"':			// "- name a register to use for Delete/Yank
+		c1 = get_one_char();
+		c1 = tolower(c1);
+		if (islower(c1)) {
+			YDreg = c1 - 'a';
+		} else {
+			indicate_error(c);
+		}
+		break;
+	case '\'':			// '- goto a specific mark
+		c1 = get_one_char();
+		c1 = tolower(c1);
+		if (islower(c1)) {
+			c1 = c1 - 'a';
+			// get the b-o-l
+			q = mark[(int) c1];
+			if (text <= q && q < end) {
+				dot = q;
+				dot_begin();	// go to B-o-l
+				dot_skip_over_ws();
+			}
+		} else if (c1 == '\'') {	// goto previous context
+			dot = swap_context(dot);	// swap current and previous context
+			dot_begin();	// go to B-o-l
+			dot_skip_over_ws();
+		} else {
+			indicate_error(c);
+		}
+		break;
+	case 'm':			// m- Mark a line
+		// this is really stupid.  If there are any inserts or deletes
+		// between text[0] and dot then this mark will not point to the
+		// correct location! It could be off by many lines!
+		// Well..., at least its quick and dirty.
+		c1 = get_one_char();
+		c1 = tolower(c1);
+		if (islower(c1)) {
+			c1 = c1 - 'a';
+			// remember the line
+			mark[(int) c1] = dot;
+		} else {
+			indicate_error(c);
+		}
+		break;
+	case 'P':			// P- Put register before
+	case 'p':			// p- put register after
+		p = reg[YDreg];
+		if (p == 0) {
+			psbs("Nothing in register %c", what_reg());
+			break;
+		}
+		// are we putting whole lines or strings
+		if (strchr((char *) p, '\n') != NULL) {
+			if (c == 'P') {
+				dot_begin();	// putting lines- Put above
+			}
+			if (c == 'p') {
+				// are we putting after very last line?
+				if (end_line(dot) == (end - 1)) {
+					dot = end;	// force dot to end of text[]
+				} else {
+					dot_next();	// next line, then put before
+				}
+			}
+		} else {
+			if (c == 'p')
+				dot_right();	// move to right, can move to NL
+		}
+		dot = string_insert(dot, p);	// insert the string
+		end_cmd_q();	// stop adding to q
+		break;
+	case 'U':			// U- Undo; replace current line with original version
+		if (reg[Ureg] != 0) {
+			p = begin_line(dot);
+			q = end_line(dot);
+			p = text_hole_delete(p, q);	// delete cur line
+			p = string_insert(p, reg[Ureg]);	// insert orig line
+			dot = p;
+			dot_skip_over_ws();
+		}
+		break;
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+	case '$':			// $- goto end of line
+	case VI_K_END:		// Cursor Key End
+		if (cmdcnt-- > 1) {
+			do_cmd(c);
+		}				// repeat cnt
+		dot = end_line(dot);
+		break;
+	case '%':			// %- find matching char of pair () [] {}
+		for (q = dot; q < end && *q != '\n'; q++) {
+			if (strchr("()[]{}", *q) != NULL) {
+				// we found half of a pair
+				p = find_pair(q, *q);
+				if (p == NULL) {
+					indicate_error(c);
+				} else {
+					dot = p;
+				}
+				break;
+			}
+		}
+		if (*q == '\n')
+			indicate_error(c);
+		break;
+	case 'f':			// f- forward to a user specified char
+		last_forward_char = get_one_char();	// get the search char
+		//
+		// dont separate these two commands. 'f' depends on ';'
+		//
+		//**** fall thru to ... ';'
+	case ';':			// ;- look at rest of line for last forward char
+		if (cmdcnt-- > 1) {
+			do_cmd(';');
+		}				// repeat cnt
+		if (last_forward_char == 0) break;
+		q = dot + 1;
+		while (q < end - 1 && *q != '\n' && *q != last_forward_char) {
+			q++;
+		}
+		if (*q == last_forward_char)
+			dot = q;
+		break;
+	case '-':			// -- goto prev line
+		if (cmdcnt-- > 1) {
+			do_cmd(c);
+		}				// repeat cnt
+		dot_prev();
+		dot_skip_over_ws();
+		break;
+#ifdef CONFIG_FEATURE_VI_DOT_CMD
+	case '.':			// .- repeat the last modifying command
+		// Stuff the last_modifying_cmd back into stdin
+		// and let it be re-executed.
+		if (last_modifying_cmd != 0) {
+			ioq = ioq_start = (Byte *) bb_xstrdup((char *) last_modifying_cmd);
+		}
+		break;
+#endif							/* CONFIG_FEATURE_VI_DOT_CMD */
+#ifdef CONFIG_FEATURE_VI_SEARCH
+	case '?':			// /- search for a pattern
+	case '/':			// /- search for a pattern
+		buf[0] = c;
+		buf[1] = '\0';
+		q = get_input_line(buf);	// get input line- use "status line"
+		if (strlen((char *) q) == 1)
+			goto dc3;	// if no pat re-use old pat
+		if (strlen((char *) q) > 1) {	// new pat- save it and find
+			// there is a new pat
+			free(last_search_pattern);
+			last_search_pattern = (Byte *) bb_xstrdup((char *) q);
+			goto dc3;	// now find the pattern
+		}
+		// user changed mind and erased the "/"-  do nothing
+		break;
+	case 'N':			// N- backward search for last pattern
+		if (cmdcnt-- > 1) {
+			do_cmd(c);
+		}				// repeat cnt
+		dir = BACK;		// assume BACKWARD search
+		p = dot - 1;
+		if (last_search_pattern[0] == '?') {
+			dir = FORWARD;
+			p = dot + 1;
+		}
+		goto dc4;		// now search for pattern
+		break;
+	case 'n':			// n- repeat search for last pattern
+		// search rest of text[] starting at next char
+		// if search fails return orignal "p" not the "p+1" address
+		if (cmdcnt-- > 1) {
+			do_cmd(c);
+		}				// repeat cnt
+	  dc3:
+		if (last_search_pattern == 0) {
+			msg = (Byte *) "No previous regular expression";
+			goto dc2;
+		}
+		if (last_search_pattern[0] == '/') {
+			dir = FORWARD;	// assume FORWARD search
+			p = dot + 1;
+		}
+		if (last_search_pattern[0] == '?') {
+			dir = BACK;
+			p = dot - 1;
+		}
+	  dc4:
+		q = char_search(p, last_search_pattern + 1, dir, FULL);
+		if (q != NULL) {
+			dot = q;	// good search, update "dot"
+			msg = (Byte *) "";
+			goto dc2;
+		}
+		// no pattern found between "dot" and "end"- continue at top
+		p = text;
+		if (dir == BACK) {
+			p = end - 1;
+		}
+		q = char_search(p, last_search_pattern + 1, dir, FULL);
+		if (q != NULL) {	// found something
+			dot = q;	// found new pattern- goto it
+			msg = (Byte *) "search hit BOTTOM, continuing at TOP";
+			if (dir == BACK) {
+				msg = (Byte *) "search hit TOP, continuing at BOTTOM";
+			}
+		} else {
+			msg = (Byte *) "Pattern not found";
+		}
+	  dc2:
+		if (*msg) psbs("%s", msg);
+		break;
+	case '{':			// {- move backward paragraph
+		q = char_search(dot, (Byte *) "\n\n", BACK, FULL);
+		if (q != NULL) {	// found blank line
+			dot = next_line(q);	// move to next blank line
+		}
+		break;
+	case '}':			// }- move forward paragraph
+		q = char_search(dot, (Byte *) "\n\n", FORWARD, FULL);
+		if (q != NULL) {	// found blank line
+			dot = next_line(q);	// move to next blank line
+		}
+		break;
+#endif							/* CONFIG_FEATURE_VI_SEARCH */
+	case '0':			// 0- goto begining of line
+	case '1':			// 1-
+	case '2':			// 2-
+	case '3':			// 3-
+	case '4':			// 4-
+	case '5':			// 5-
+	case '6':			// 6-
+	case '7':			// 7-
+	case '8':			// 8-
+	case '9':			// 9-
+		if (c == '0' && cmdcnt < 1) {
+			dot_begin();	// this was a standalone zero
+		} else {
+			cmdcnt = cmdcnt * 10 + (c - '0');	// this 0 is part of a number
+		}
+		break;
+	case ':':			// :- the colon mode commands
+		p = get_input_line((Byte *) ":");	// get input line- use "status line"
+#ifdef CONFIG_FEATURE_VI_COLON
+		colon(p);		// execute the command
+#else							/* CONFIG_FEATURE_VI_COLON */
+		if (*p == ':')
+			p++;				// move past the ':'
+		cnt = strlen((char *) p);
+		if (cnt <= 0)
+			break;
+		if (strncasecmp((char *) p, "quit", cnt) == 0 ||
+			strncasecmp((char *) p, "q!", cnt) == 0) {	// delete lines
+			if (file_modified && p[1] != '!') {
+				psbs("No write since last change (:quit! overrides)");
+			} else {
+				editing = 0;
+			}
+		} else if (strncasecmp((char *) p, "write", cnt) == 0
+				|| strncasecmp((char *) p, "wq", cnt) == 0
+				|| strncasecmp((char *) p, "wn", cnt) == 0
+				|| strncasecmp((char *) p, "x", cnt) == 0) {
+			cnt = file_write(cfn, text, end - 1);
+			if (cnt < 0) {
+				if (cnt == -1)
+					psbs("Write error: %s", strerror(errno));
+			} else {
+				file_modified = 0;
+				last_file_modified = -1;
+				psb("\"%s\" %dL, %dC", cfn, count_lines(text, end - 1), cnt);
+				if (p[0] == 'x' || p[1] == 'q' || p[1] == 'n' ||
+				    p[0] == 'X' || p[1] == 'Q' || p[1] == 'N') {
+					editing = 0;
+				}
+			}
+		} else if (strncasecmp((char *) p, "file", cnt) == 0 ) {
+			last_status_cksum = 0;	// force status update
+		} else if (sscanf((char *) p, "%d", &j) > 0) {
+			dot = find_line(j);		// go to line # j
+			dot_skip_over_ws();
+		} else {		// unrecognised cmd
+			ni((Byte *) p);
+		}
+#endif							/* CONFIG_FEATURE_VI_COLON */
+		break;
+	case '<':			// <- Left  shift something
+	case '>':			// >- Right shift something
+		cnt = count_lines(text, dot);	// remember what line we are on
+		c1 = get_one_char();	// get the type of thing to delete
+		find_range(&p, &q, c1);
+		(void) yank_delete(p, q, 1, YANKONLY);	// save copy before change
+		p = begin_line(p);
+		q = end_line(q);
+		i = count_lines(p, q);	// # of lines we are shifting
+		for ( ; i > 0; i--, p = next_line(p)) {
+			if (c == '<') {
+				// shift left- remove tab or 8 spaces
+				if (*p == '\t') {
+					// shrink buffer 1 char
+					(void) text_hole_delete(p, p);
+				} else if (*p == ' ') {
+					// we should be calculating columns, not just SPACE
+					for (j = 0; *p == ' ' && j < tabstop; j++) {
+						(void) text_hole_delete(p, p);
+					}
+				}
+			} else if (c == '>') {
+				// shift right -- add tab or 8 spaces
+				(void) char_insert(p, '\t');
+			}
+		}
+		dot = find_line(cnt);	// what line were we on
+		dot_skip_over_ws();
+		end_cmd_q();	// stop adding to q
+		break;
+	case 'A':			// A- append at e-o-l
+		dot_end();		// go to e-o-l
+		//**** fall thru to ... 'a'
+	case 'a':			// a- append after current char
+		if (*dot != '\n')
+			dot++;
+		goto dc_i;
+		break;
+	case 'B':			// B- back a blank-delimited Word
+	case 'E':			// E- end of a blank-delimited word
+	case 'W':			// W- forward a blank-delimited word
+		if (cmdcnt-- > 1) {
+			do_cmd(c);
+		}				// repeat cnt
+		dir = FORWARD;
+		if (c == 'B')
+			dir = BACK;
+		if (c == 'W' || isspace(dot[dir])) {
+			dot = skip_thing(dot, 1, dir, S_TO_WS);
+			dot = skip_thing(dot, 2, dir, S_OVER_WS);
+		}
+		if (c != 'W')
+			dot = skip_thing(dot, 1, dir, S_BEFORE_WS);
+		break;
+	case 'C':			// C- Change to e-o-l
+	case 'D':			// D- delete to e-o-l
+		save_dot = dot;
+		dot = dollar_line(dot);	// move to before NL
+		// copy text into a register and delete
+		dot = yank_delete(save_dot, dot, 0, YANKDEL);	// delete to e-o-l
+		if (c == 'C')
+			goto dc_i;	// start inserting
+#ifdef CONFIG_FEATURE_VI_DOT_CMD
+		if (c == 'D')
+			end_cmd_q();	// stop adding to q
+#endif							/* CONFIG_FEATURE_VI_DOT_CMD */
+		break;
+	case 'G':		// G- goto to a line number (default= E-O-F)
+		dot = end - 1;				// assume E-O-F
+		if (cmdcnt > 0) {
+			dot = find_line(cmdcnt);	// what line is #cmdcnt
+		}
+		dot_skip_over_ws();
+		break;
+	case 'H':			// H- goto top line on screen
+		dot = screenbegin;
+		if (cmdcnt > (rows - 1)) {
+			cmdcnt = (rows - 1);
+		}
+		if (cmdcnt-- > 1) {
+			do_cmd('+');
+		}				// repeat cnt
+		dot_skip_over_ws();
+		break;
+	case 'I':			// I- insert before first non-blank
+		dot_begin();	// 0
+		dot_skip_over_ws();
+		//**** fall thru to ... 'i'
+	case 'i':			// i- insert before current char
+	case VI_K_INSERT:	// Cursor Key Insert
+	  dc_i:
+		cmd_mode = 1;	// start insrting
+		break;
+	case 'J':			// J- join current and next lines together
+		if (cmdcnt-- > 2) {
+			do_cmd(c);
+		}				// repeat cnt
+		dot_end();		// move to NL
+		if (dot < end - 1) {	// make sure not last char in text[]
+			*dot++ = ' ';	// replace NL with space
+			file_modified++;
+			while (isblnk(*dot)) {	// delete leading WS
+				dot_delete();
+			}
+		}
+		end_cmd_q();	// stop adding to q
+		break;
+	case 'L':			// L- goto bottom line on screen
+		dot = end_screen();
+		if (cmdcnt > (rows - 1)) {
+			cmdcnt = (rows - 1);
+		}
+		if (cmdcnt-- > 1) {
+			do_cmd('-');
+		}				// repeat cnt
+		dot_begin();
+		dot_skip_over_ws();
+		break;
+	case 'M':			// M- goto middle line on screen
+		dot = screenbegin;
+		for (cnt = 0; cnt < (rows-1) / 2; cnt++)
+			dot = next_line(dot);
+		break;
+	case 'O':			// O- open a empty line above
+		//    0i\n ESC -i
+		p = begin_line(dot);
+		if (p[-1] == '\n') {
+			dot_prev();
+	case 'o':			// o- open a empty line below; Yes, I know it is in the middle of the "if (..."
+			dot_end();
+			dot = char_insert(dot, '\n');
+		} else {
+			dot_begin();	// 0
+			dot = char_insert(dot, '\n');	// i\n ESC
+			dot_prev();	// -
+		}
+		goto dc_i;
+		break;
+	case 'R':			// R- continuous Replace char
+	  dc5:
+		cmd_mode = 2;
+		break;
+	case 'X':			// X- delete char before dot
+	case 'x':			// x- delete the current char
+	case 's':			// s- substitute the current char
+		if (cmdcnt-- > 1) {
+			do_cmd(c);
+		}				// repeat cnt
+		dir = 0;
+		if (c == 'X')
+			dir = -1;
+		if (dot[dir] != '\n') {
+			if (c == 'X')
+				dot--;	// delete prev char
+			dot = yank_delete(dot, dot, 0, YANKDEL);	// delete char
+		}
+		if (c == 's')
+			goto dc_i;	// start insrting
+		end_cmd_q();	// stop adding to q
+		break;
+	case 'Z':			// Z- if modified, {write}; exit
+		// ZZ means to save file (if necessary), then exit
+		c1 = get_one_char();
+		if (c1 != 'Z') {
+			indicate_error(c);
+			break;
+		}
+		if (file_modified) {
+#ifdef CONFIG_FEATURE_VI_READONLY
+			if (vi_readonly || readonly) {
+			    psbs("\"%s\" File is read only", cfn);
+			    break;
+			}
+#endif		/* CONFIG_FEATURE_VI_READONLY */
+			cnt = file_write(cfn, text, end - 1);
+			if (cnt < 0) {
+				if (cnt == -1)
+					psbs("Write error: %s", strerror(errno));
+			} else if (cnt == (end - 1 - text + 1)) {
+				editing = 0;
+			}
+		} else {
+			editing = 0;
+		}
+		break;
+	case '^':			// ^- move to first non-blank on line
+		dot_begin();
+		dot_skip_over_ws();
+		break;
+	case 'b':			// b- back a word
+	case 'e':			// e- end of word
+		if (cmdcnt-- > 1) {
+			do_cmd(c);
+		}				// repeat cnt
+		dir = FORWARD;
+		if (c == 'b')
+			dir = BACK;
+		if ((dot + dir) < text || (dot + dir) > end - 1)
+			break;
+		dot += dir;
+		if (isspace(*dot)) {
+			dot = skip_thing(dot, (c == 'e') ? 2 : 1, dir, S_OVER_WS);
+		}
+		if (isalnum(*dot) || *dot == '_') {
+			dot = skip_thing(dot, 1, dir, S_END_ALNUM);
+		} else if (ispunct(*dot)) {
+			dot = skip_thing(dot, 1, dir, S_END_PUNCT);
+		}
+		break;
+	case 'c':			// c- change something
+	case 'd':			// d- delete something
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+	case 'y':			// y- yank   something
+	case 'Y':			// Y- Yank a line
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+		yf = YANKDEL;	// assume either "c" or "d"
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+		if (c == 'y' || c == 'Y')
+			yf = YANKONLY;
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+		c1 = 'y';
+		if (c != 'Y')
+			c1 = get_one_char();	// get the type of thing to delete
+		find_range(&p, &q, c1);
+		if (c1 == 27) {	// ESC- user changed mind and wants out
+			c = c1 = 27;	// Escape- do nothing
+		} else if (strchr("wW", c1)) {
+			if (c == 'c') {
+				// don't include trailing WS as part of word
+				while (isblnk(*q)) {
+					if (q <= text || q[-1] == '\n')
+						break;
+					q--;
+				}
+			}
+			dot = yank_delete(p, q, 0, yf);	// delete word
+		} else if (strchr("^0bBeEft$", c1)) {
+			// single line copy text into a register and delete
+			dot = yank_delete(p, q, 0, yf);	// delete word
+		} else if (strchr("cdykjHL%+-{}\r\n", c1)) {
+			// multiple line copy text into a register and delete
+			dot = yank_delete(p, q, 1, yf);	// delete lines
+			if (c == 'c') {
+				dot = char_insert(dot, '\n');
+				// on the last line of file don't move to prev line
+				if (dot != (end-1)) {
+					dot_prev();
+				}
+			} else if (c == 'd') {
+				dot_begin();
+				dot_skip_over_ws();
+			}
+		} else {
+			// could not recognize object
+			c = c1 = 27;	// error-
+			indicate_error(c);
+		}
+		if (c1 != 27) {
+			// if CHANGING, not deleting, start inserting after the delete
+			if (c == 'c') {
+				strcpy((char *) buf, "Change");
+				goto dc_i;	// start inserting
+			}
+			if (c == 'd') {
+				strcpy((char *) buf, "Delete");
+			}
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+			if (c == 'y' || c == 'Y') {
+				strcpy((char *) buf, "Yank");
+			}
+			p = reg[YDreg];
+			q = p + strlen((char *) p);
+			for (cnt = 0; p <= q; p++) {
+				if (*p == '\n')
+					cnt++;
+			}
+			psb("%s %d lines (%d chars) using [%c]",
+				buf, cnt, strlen((char *) reg[YDreg]), what_reg());
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+			end_cmd_q();	// stop adding to q
+		}
+		break;
+	case 'k':			// k- goto prev line, same col
+	case VI_K_UP:		// cursor key Up
+		if (cmdcnt-- > 1) {
+			do_cmd(c);
+		}				// repeat cnt
+		dot_prev();
+		dot = move_to_col(dot, ccol + offset);	// try stay in same col
+		break;
+	case 'r':			// r- replace the current char with user input
+		c1 = get_one_char();	// get the replacement char
+		if (*dot != '\n') {
+			*dot = c1;
+			file_modified++;	// has the file been modified
+		}
+		end_cmd_q();	// stop adding to q
+		break;
+	case 't':			// t- move to char prior to next x
+		last_forward_char = get_one_char();
+		do_cmd(';');
+		if (*dot == last_forward_char)
+			dot_left();
+		last_forward_char= 0;
+		break;
+	case 'w':			// w- forward a word
+		if (cmdcnt-- > 1) {
+			do_cmd(c);
+		}				// repeat cnt
+		if (isalnum(*dot) || *dot == '_') {	// we are on ALNUM
+			dot = skip_thing(dot, 1, FORWARD, S_END_ALNUM);
+		} else if (ispunct(*dot)) {	// we are on PUNCT
+			dot = skip_thing(dot, 1, FORWARD, S_END_PUNCT);
+		}
+		if (dot < end - 1)
+			dot++;		// move over word
+		if (isspace(*dot)) {
+			dot = skip_thing(dot, 2, FORWARD, S_OVER_WS);
+		}
+		break;
+	case 'z':			// z-
+		c1 = get_one_char();	// get the replacement char
+		cnt = 0;
+		if (c1 == '.')
+			cnt = (rows - 2) / 2;	// put dot at center
+		if (c1 == '-')
+			cnt = rows - 2;	// put dot at bottom
+		screenbegin = begin_line(dot);	// start dot at top
+		dot_scroll(cnt, -1);
+		break;
+	case '|':			// |- move to column "cmdcnt"
+		dot = move_to_col(dot, cmdcnt - 1);	// try to move to column
+		break;
+	case '~':			// ~- flip the case of letters   a-z -> A-Z
+		if (cmdcnt-- > 1) {
+			do_cmd(c);
+		}				// repeat cnt
+		if (islower(*dot)) {
+			*dot = toupper(*dot);
+			file_modified++;	// has the file been modified
+		} else if (isupper(*dot)) {
+			*dot = tolower(*dot);
+			file_modified++;	// has the file been modified
+		}
+		dot_right();
+		end_cmd_q();	// stop adding to q
+		break;
+		//----- The Cursor and Function Keys -----------------------------
+	case VI_K_HOME:	// Cursor Key Home
+		dot_begin();
+		break;
+		// The Fn keys could point to do_macro which could translate them
+	case VI_K_FUN1:	// Function Key F1
+	case VI_K_FUN2:	// Function Key F2
+	case VI_K_FUN3:	// Function Key F3
+	case VI_K_FUN4:	// Function Key F4
+	case VI_K_FUN5:	// Function Key F5
+	case VI_K_FUN6:	// Function Key F6
+	case VI_K_FUN7:	// Function Key F7
+	case VI_K_FUN8:	// Function Key F8
+	case VI_K_FUN9:	// Function Key F9
+	case VI_K_FUN10:	// Function Key F10
+	case VI_K_FUN11:	// Function Key F11
+	case VI_K_FUN12:	// Function Key F12
+		break;
+	}
+
+  dc1:
+	// if text[] just became empty, add back an empty line
+	if (end == text) {
+		(void) char_insert(text, '\n');	// start empty buf with dummy line
+		dot = text;
+	}
+	// it is OK for dot to exactly equal to end, otherwise check dot validity
+	if (dot != end) {
+		dot = bound_dot(dot);	// make sure "dot" is valid
+	}
+#ifdef CONFIG_FEATURE_VI_YANKMARK
+	check_context(c);	// update the current context
+#endif							/* CONFIG_FEATURE_VI_YANKMARK */
+
+	if (!isdigit(c))
+		cmdcnt = 0;		// cmd was not a number, reset cmdcnt
+	cnt = dot - begin_line(dot);
+	// Try to stay off of the Newline
+	if (*dot == '\n' && cnt > 0 && cmd_mode == 0)
+		dot--;
+}
+
+#ifdef CONFIG_FEATURE_VI_CRASHME
+static int totalcmds = 0;
+static int Mp = 85;             // Movement command Probability
+static int Np = 90;             // Non-movement command Probability
+static int Dp = 96;             // Delete command Probability
+static int Ip = 97;             // Insert command Probability
+static int Yp = 98;             // Yank command Probability
+static int Pp = 99;             // Put command Probability
+static int M = 0, N = 0, I = 0, D = 0, Y = 0, P = 0, U = 0;
+char chars[20] = "\t012345 abcdABCD-=.$";
+char *words[20] = { "this", "is", "a", "test",
+	"broadcast", "the", "emergency", "of",
+	"system", "quick", "brown", "fox",
+	"jumped", "over", "lazy", "dogs",
+	"back", "January", "Febuary", "March"
+};
+char *lines[20] = {
+	"You should have received a copy of the GNU General Public License\n",
+	"char c, cm, *cmd, *cmd1;\n",
+	"generate a command by percentages\n",
+	"Numbers may be typed as a prefix to some commands.\n",
+	"Quit, discarding changes!\n",
+	"Forced write, if permission originally not valid.\n",
+	"In general, any ex or ed command (such as substitute or delete).\n",
+	"I have tickets available for the Blazers vs LA Clippers for Monday, Janurary 1 at 1:00pm.\n",
+	"Please get w/ me and I will go over it with you.\n",
+	"The following is a list of scheduled, committed changes.\n",
+	"1.   Launch Norton Antivirus (Start, Programs, Norton Antivirus)\n",
+	"Reminder....Town Meeting in Central Perk cafe today at 3:00pm.\n",
+	"Any question about transactions please contact Sterling Huxley.\n",
+	"I will try to get back to you by Friday, December 31.\n",
+	"This Change will be implemented on Friday.\n",
+	"Let me know if you have problems accessing this;\n",
+	"Sterling Huxley recently added you to the access list.\n",
+	"Would you like to go to lunch?\n",
+	"The last command will be automatically run.\n",
+	"This is too much english for a computer geek.\n",
+};
+char *multilines[20] = {
+	"You should have received a copy of the GNU General Public License\n",
+	"char c, cm, *cmd, *cmd1;\n",
+	"generate a command by percentages\n",
+	"Numbers may be typed as a prefix to some commands.\n",
+	"Quit, discarding changes!\n",
+	"Forced write, if permission originally not valid.\n",
+	"In general, any ex or ed command (such as substitute or delete).\n",
+	"I have tickets available for the Blazers vs LA Clippers for Monday, Janurary 1 at 1:00pm.\n",
+	"Please get w/ me and I will go over it with you.\n",
+	"The following is a list of scheduled, committed changes.\n",
+	"1.   Launch Norton Antivirus (Start, Programs, Norton Antivirus)\n",
+	"Reminder....Town Meeting in Central Perk cafe today at 3:00pm.\n",
+	"Any question about transactions please contact Sterling Huxley.\n",
+	"I will try to get back to you by Friday, December 31.\n",
+	"This Change will be implemented on Friday.\n",
+	"Let me know if you have problems accessing this;\n",
+	"Sterling Huxley recently added you to the access list.\n",
+	"Would you like to go to lunch?\n",
+	"The last command will be automatically run.\n",
+	"This is too much english for a computer geek.\n",
+};
+
+// create a random command to execute
+static void crash_dummy()
+{
+	static int sleeptime;   // how long to pause between commands
+	char c, cm, *cmd, *cmd1;
+	int i, cnt, thing, rbi, startrbi, percent;
+
+	// "dot" movement commands
+	cmd1 = " \n\r\002\004\005\006\025\0310^$-+wWeEbBhjklHL";
+
+	// is there already a command running?
+	if (readed_for_parse > 0)
+		goto cd1;
+  cd0:
+	startrbi = rbi = 0;
+	sleeptime = 0;          // how long to pause between commands
+	memset(readbuffer, '\0', BUFSIZ);   // clear the read buffer
+	// generate a command by percentages
+	percent = (int) lrand48() % 100;        // get a number from 0-99
+	if (percent < Mp) {     //  Movement commands
+		// available commands
+		cmd = cmd1;
+		M++;
+	} else if (percent < Np) {      //  non-movement commands
+		cmd = "mz<>\'\"";       // available commands
+		N++;
+	} else if (percent < Dp) {      //  Delete commands
+		cmd = "dx";             // available commands
+		D++;
+	} else if (percent < Ip) {      //  Inset commands
+		cmd = "iIaAsrJ";        // available commands
+		I++;
+	} else if (percent < Yp) {      //  Yank commands
+		cmd = "yY";             // available commands
+		Y++;
+	} else if (percent < Pp) {      //  Put commands
+		cmd = "pP";             // available commands
+		P++;
+	} else {
+		// We do not know how to handle this command, try again
+		U++;
+		goto cd0;
+	}
+	// randomly pick one of the available cmds from "cmd[]"
+	i = (int) lrand48() % strlen(cmd);
+	cm = cmd[i];
+	if (strchr(":\024", cm))
+		goto cd0;               // dont allow colon or ctrl-T commands
+	readbuffer[rbi++] = cm; // put cmd into input buffer
+
+	// now we have the command-
+	// there are 1, 2, and multi char commands
+	// find out which and generate the rest of command as necessary
+	if (strchr("dmryz<>\'\"", cm)) {        // 2-char commands
+		cmd1 = " \n\r0$^-+wWeEbBhjklHL";
+		if (cm == 'm' || cm == '\'' || cm == '\"') {    // pick a reg[]
+			cmd1 = "abcdefghijklmnopqrstuvwxyz";
+		}
+		thing = (int) lrand48() % strlen(cmd1); // pick a movement command
+		c = cmd1[thing];
+		readbuffer[rbi++] = c;  // add movement to input buffer
+	}
+	if (strchr("iIaAsc", cm)) {     // multi-char commands
+		if (cm == 'c') {
+			// change some thing
+			thing = (int) lrand48() % strlen(cmd1); // pick a movement command
+			c = cmd1[thing];
+			readbuffer[rbi++] = c;  // add movement to input buffer
+		}
+		thing = (int) lrand48() % 4;    // what thing to insert
+		cnt = (int) lrand48() % 10;     // how many to insert
+		for (i = 0; i < cnt; i++) {
+			if (thing == 0) {       // insert chars
+				readbuffer[rbi++] = chars[((int) lrand48() % strlen(chars))];
+			} else if (thing == 1) {        // insert words
+				strcat((char *) readbuffer, words[(int) lrand48() % 20]);
+				strcat((char *) readbuffer, " ");
+				sleeptime = 0;  // how fast to type
+			} else if (thing == 2) {        // insert lines
+				strcat((char *) readbuffer, lines[(int) lrand48() % 20]);
+				sleeptime = 0;  // how fast to type
+			} else {        // insert multi-lines
+				strcat((char *) readbuffer, multilines[(int) lrand48() % 20]);
+				sleeptime = 0;  // how fast to type
+			}
+		}
+		strcat((char *) readbuffer, "\033");
+	}
+	readed_for_parse = strlen(readbuffer);
+  cd1:
+	totalcmds++;
+	if (sleeptime > 0)
+		(void) mysleep(sleeptime);      // sleep 1/100 sec
+}
+
+// test to see if there are any errors
+static void crash_test()
+{
+	static time_t oldtim;
+	time_t tim;
+	char d[2], msg[BUFSIZ];
+
+	msg[0] = '\0';
+	if (end < text) {
+		strcat((char *) msg, "end<text ");
+	}
+	if (end > textend) {
+		strcat((char *) msg, "end>textend ");
+	}
+	if (dot < text) {
+		strcat((char *) msg, "dot<text ");
+	}
+	if (dot > end) {
+		strcat((char *) msg, "dot>end ");
+	}
+	if (screenbegin < text) {
+		strcat((char *) msg, "screenbegin<text ");
+	}
+	if (screenbegin > end - 1) {
+		strcat((char *) msg, "screenbegin>end-1 ");
+	}
+
+	if (strlen(msg) > 0) {
+		alarm(0);
+		printf("\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s",
+			totalcmds, last_input_char, msg, SOs, SOn);
+		fflush(stdout);
+		while (read(0, d, 1) > 0) {
+			if (d[0] == '\n' || d[0] == '\r')
+				break;
+		}
+		alarm(3);
+	}
+	tim = (time_t) time((time_t *) 0);
+	if (tim >= (oldtim + 3)) {
+		sprintf((char *) status_buffer,
+				"Tot=%d: M=%d N=%d I=%d D=%d Y=%d P=%d U=%d size=%d",
+				totalcmds, M, N, I, D, Y, P, U, end - text + 1);
+		oldtim = tim;
+	}
+	return;
+}
+#endif					          /* CONFIG_FEATURE_VI_CRASHME */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/bootfloppy.txt
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/bootfloppy.txt	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/bootfloppy.txt	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,180 @@
+Building a Busybox Boot Floppy
+==============================
+
+This document describes how to buid a boot floppy using the following
+components:
+
+ - Linux Kernel (http://www.kernel.org)
+ - uClibc: C library (http://www.uclibc.org/)
+ - Busybox: Unix utilities (http://busybox.net/)
+ - Syslinux: bootloader (http://syslinux.zytor.com)
+
+It is based heavily on a paper presented by Erik Andersen at the 2001 Embedded
+Systems Conference.
+
+
+
+Building The Software Components
+--------------------------------
+
+Detailed instructions on how to build Busybox, uClibc, or a working Linux
+kernel are beyond the scope of this document. The following guidelines will
+help though:
+
+	- Stock Busybox from CVS or a tarball will work with no modifications to
+	  any files. Just extract and go.
+	- Ditto uClibc.
+	- Your Linux kernel must include support for initrd or else the floppy
+	  won't be able to mount it's root file system.
+
+If you require further information on building Busybox uClibc or Linux, please
+refer to the web pages and documentation for those individual programs.
+
+
+
+Making a Root File System
+-------------------------
+
+The following steps will create a root file system.
+
+ - Create an empty file that you can format as a filesystem:
+
+	dd if=/dev/zero of=rootfs bs=1k count=4000
+
+ - Set up the rootfs file we just created to be used as a loop device (may not
+   be necessary)
+
+	losetup /dev/loop0 rootfs
+
+ - Format the rootfs file with a filesystem:
+
+	mkfs.ext2 -F -i 2000 rootfs
+
+ - Mount the file on a mountpoint so we can place files in it:
+
+	mkdir loop
+	mount -o loop rootfs loop/
+
+	(you will probably need to be root to do this)
+
+ - Copy on the C library, the dynamic linking library, and other necessary
+   libraries. For this example, we copy the following files from the uClibc
+   tree:
+
+	mkdir loop/lib
+	(chdir to uClibc directory)
+	cp -a libc.so* uClibc*.so \
+		ld.so-1/d-link/ld-linux-uclibc.so* \
+		ld.so-1/libdl/libdl.so* \
+		crypt/libcrypt.so* \
+		(path to)loop/lib
+
+ - Install the Busybox binary and accompanying symlinks:
+
+	(chdir to busybox directory)
+	make PREFIX=(path to)loop/ install
+
+ - Make device files in /dev:
+
+ 	This can be done by running the 'mkdevs.sh' script. If you want the gory
+	details, you can read the script.
+
+ - Make necessary files in /etc:
+
+	For this, just cp -a the etc/ directory onto rootfs. Again, if you want
+	all the details, you can just look at the files in the dir.
+
+ - Unmount the rootfs from the mountpoint:
+
+	umount loop
+
+ - Compress it:
+
+	gzip -9 rootfs
+
+
+Making a SYSLINUX boot floppy
+-----------------------------
+
+The following steps will create the boot floppy.
+
+Note: You will need to have the mtools package installed beforehand.
+
+ - Insert a floppy in the drive and format it with an MSDOS filesystem:
+
+	mformat a:
+
+	(if the system doesn't know what device 'a:' is, look at /etc/mtools.conf)
+
+ - Run syslinux on the floppy:
+
+	syslinux -s /dev/fd0
+
+	(the -s stands for "safe, slow, and stupid" and should work better with
+	buggy BIOSes; it can be omitted)
+
+ - Put on a syslinux.cfg file:
+
+	mcopy syslinux.cfg a:
+
+	(more on syslinux.cfg below)
+
+ - Copy the root file system you made onto the MSDOS formatted floppy
+
+	mcopy rootfs.gz a:
+
+ - Build a linux kernel and copy it onto the disk with the filename 'linux'
+
+	mcopy bzImage a:linux
+
+
+Sample syslinux.cfg
+~~~~~~~~~~~~~~~~~~~
+
+The following simple syslinux.cfg file should work. You can tweak it if you
+like.
+
+----begin-syslinux.cfg---------------
+DEFAULT linux
+APPEND initrd=rootfs.gz root=/dev/ram0
+TIMEOUT 10
+PROMPT 1
+----end-syslinux.cfg---------------
+
+Some changes you could make to syslinux.cfg:
+
+ - This value is the number seconds it will wait before booting. You can set
+   the timeout to 0 (or omit) to boot instantly, or you can set it as high as
+   10 to wait awhile.
+
+ - PROMPT can be set to 0 to disable the 'boot:' prompt.
+
+ - you can add this line to display the contents of a file as a welcome
+   message:
+
+	DISPLAY display.txt
+
+
+
+Additional Resources
+--------------------
+
+Other useful information on making a Linux bootfloppy is available at the
+following URLs:
+
+http://www.linuxdoc.org/HOWTO/Bootdisk-HOWTO/index.html
+http://www.linux-embedded.com/howto/Embedded-Linux-Howto.html
+http://linux-embedded.org/howto/LFS-HOWTO.html
+http://linux-embedded.org/pmhowto.html
+http://recycle.lbl.gov/~ldoolitt/embedded/ (Larry Doolittle's stuff)
+
+
+
+Possible TODOs
+--------------
+
+The following features that we might want to add later:
+
+ - support for additional filesystems besides ext2, i.e. minix
+ - different libc, static vs dynamic loading
+ - maybe using an alternate bootloader

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/display.txt
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/display.txt	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/display.txt	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+
+This boot floppy is made with Busybox, uClibc, and the Linux kernel.
+Hit RETURN to boot or enter boot parameters at the prompt below.
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/fstab
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/fstab	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/fstab	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+proc		/proc	proc	defaults    0	0
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/init.d/rcS
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/init.d/rcS	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/init.d/rcS	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+#! /bin/sh
+
+/bin/mount -a


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/init.d/rcS
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/inittab
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/inittab	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/inittab	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,5 @@
+::sysinit:/etc/init.d/rcS
+::respawn:-/bin/sh
+tty2::askfirst:-/bin/sh
+::ctrlaltdel:/bin/umount -a -r
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/profile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/profile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/etc/profile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,8 @@
+# /etc/profile: system-wide .profile file for the Bourne shells
+
+echo
+echo -n "Processing /etc/profile... "
+# no-op
+echo "Done"
+echo
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/mkdevs.sh
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/mkdevs.sh	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/mkdevs.sh	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,62 @@
+#!/bin/sh
+#
+# makedev.sh - creates device files for a busybox boot floppy image
+
+
+# we do our work in the dev/ directory
+if [ -z "$1" ]; then
+	echo "usage: `basename $0` path/to/dev/dir"
+	exit 1
+fi
+
+cd $1
+
+
+# miscellaneous one-of-a-kind stuff
+mknod console c 5 1
+mknod full c 1 7
+mknod kmem c 1 2
+mknod mem c 1 1
+mknod null c 1 3
+mknod port c 1 4
+mknod random c 1 8
+mknod urandom c 1 9
+mknod zero c 1 5
+ln -s /proc/kcore core
+
+# IDE HD devs
+# note: not going to bother creating all concievable partitions; you can do
+# that yourself as you need 'em.
+mknod hda b 3 0
+mknod hdb b 3 64
+mknod hdc b 22 0
+mknod hdd b 22 64
+
+# loop devs
+for i in `seq 0 7`; do
+	mknod loop$i b 7 $i
+done
+
+# ram devs
+for i in `seq 0 9`; do
+	mknod ram$i b 1 $i
+done
+ln -s ram1 ram
+
+# ttys
+mknod tty c 5 0
+for i in `seq 0 9`; do
+	mknod tty$i c 4 $i
+done
+
+# virtual console screen devs
+for i in `seq 0 9`; do
+	mknod vcs$i b 7 $i
+done
+ln -s vcs0 vcs
+
+# virtual console screen w/ attributes devs
+for i in `seq 0 9`; do
+	mknod vcsa$i b 7 $i
+done
+ln -s vcsa0 vcsa


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/mkdevs.sh
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/mkrootfs.sh
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/mkrootfs.sh	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/mkrootfs.sh	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,105 @@
+#!/bin/bash
+#
+# mkrootfs.sh - creates a root file system
+#
+
+# TODO: need to add checks here to verify that busybox, uClibc and bzImage
+# exist
+
+
+# command-line settable variables
+BUSYBOX_DIR=..
+UCLIBC_DIR=../../uClibc
+TARGET_DIR=./loop
+FSSIZE=4000
+CLEANUP=1
+MKFS='mkfs.ext2 -F'
+
+# don't-touch variables
+BASE_DIR=`pwd`
+
+
+while getopts 'b:u:s:t:Cm' opt
+do
+	case $opt in
+		b) BUSYBOX_DIR=$OPTARG ;;
+		u) UCLIBC_DIR=$OPTARG ;;
+		t) TARGET_DIR=$OPTARG ;;
+		s) FSSIZE=$OPTARG ;;
+		C) CLEANUP=0 ;;
+		m) MKFS='mkfs.minix' ;;
+		*)
+			echo "usage: `basename $0` [-bu]"
+			echo "  -b DIR  path to busybox direcory (default ..)"
+			echo "  -u DIR  path to uClibc direcory (default ../../uClibc)"
+			echo "  -t DIR  path to target direcory (default ./loop)"
+			echo "  -s SIZE size of root filesystem in Kbytes (default 4000)"
+			echo "  -C      don't perform cleanup (umount target dir, gzip rootfs, etc.)"
+			echo "          (this allows you to 'chroot loop/ /bin/sh' to test it)"
+			echo "  -m      use minix filesystem (default is ext2)"
+			exit 1
+			;;
+	esac
+done
+
+
+
+
+# clean up from any previous work
+mount | grep -q loop
+[ $? -eq 0 ] && umount $TARGET_DIR
+[ -d $TARGET_DIR ] && rm -rf $TARGET_DIR/
+[ -f rootfs ] && rm -f rootfs
+[ -f rootfs.gz ] && rm -f rootfs.gz
+
+
+# prepare root file system and mount as loopback
+dd if=/dev/zero of=rootfs bs=1k count=$FSSIZE
+$MKFS -i 2000 rootfs
+mkdir $TARGET_DIR
+mount -o loop,exec rootfs $TARGET_DIR # must be root
+
+
+# install uClibc
+mkdir -p $TARGET_DIR/lib
+cd $UCLIBC_DIR
+make INSTALL_DIR=
+cp -a libc.so* $BASE_DIR/$TARGET_DIR/lib
+cp -a uClibc*.so $BASE_DIR/$TARGET_DIR/lib
+cp -a ld.so-1/d-link/ld-linux-uclibc.so* $BASE_DIR/$TARGET_DIR/lib
+cp -a ld.so-1/libdl/libdl.so* $BASE_DIR/$TARGET_DIR/lib
+cp -a crypt/libcrypt.so* $BASE_DIR/$TARGET_DIR/lib
+cd $BASE_DIR
+
+
+# install busybox and components
+cd $BUSYBOX_DIR
+make distclean
+make CC=$BASE_DIR/$UCLIBC_DIR/extra/gcc-uClibc/i386-uclibc-gcc
+make PREFIX=$BASE_DIR/$TARGET_DIR install
+cd $BASE_DIR
+
+
+# make files in /dev
+mkdir $TARGET_DIR/dev
+./mkdevs.sh $TARGET_DIR/dev
+
+
+# make files in /etc
+cp -a etc $TARGET_DIR
+ln -s /proc/mounts $TARGET_DIR/etc/mtab
+
+
+# other miscellaneous setup
+mkdir $TARGET_DIR/initrd
+mkdir $TARGET_DIR/proc
+
+
+# Done. Maybe do cleanup.
+if [ $CLEANUP -eq 1 ]
+then
+	umount $TARGET_DIR
+	rmdir $TARGET_DIR
+	gzip -9 rootfs
+fi
+


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/mkrootfs.sh
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/mksyslinux.sh
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/mksyslinux.sh	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/mksyslinux.sh	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,48 @@
+#!/bin/bash
+#
+# Formats a floppy to use Syslinux
+
+dummy=""
+
+
+# need to have mtools installed
+if [ -z `which mformat` -o -z `which mcopy` ]; then
+	echo "You must have the mtools package installed to run this script"
+	exit 1
+fi
+
+
+# need an arg for the location of the kernel
+if [ -z "$1" ]; then
+	echo "usage: `basename $0` path/to/linux/kernel"
+	exit 1
+fi
+
+
+# need to have a root file system built
+if [ ! -f rootfs.gz ]; then
+	echo "You need to have a rootfs built first."
+	echo "Hit RETURN to make one now or Control-C to quit."
+	read dummy
+	./mkrootfs.sh
+fi
+
+
+# prepare the floppy
+echo "Please insert a blank floppy in the drive and press RETURN to format"
+echo "(WARNING: All data will be erased! Hit Control-C to abort)"
+read dummy
+
+echo "Formatting the floppy..."
+mformat a:
+echo "Making it bootable with Syslinux..."
+syslinux -s /dev/fd0
+echo "Copying Syslinux configuration files..."
+mcopy syslinux.cfg display.txt a:
+echo "Copying root filesystem file..."
+mcopy rootfs.gz a:
+# XXX: maybe check for "no space on device" errors here
+echo "Copying linux kernel..."
+mcopy $1 a:linux
+# XXX: maybe check for "no space on device" errors here too
+echo "Finished: boot floppy created"


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/mksyslinux.sh
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/quickstart.txt
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/quickstart.txt	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/quickstart.txt	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,15 @@
+Quickstart on making the Busybox boot-floppy:
+
+  1) Download Busybox and uClibc from CVS or tarballs. Make sure they share a
+     common parent directory. (i.e. busybox/ and uclibc/ are both right off of
+	 /tmp, or wherever.)
+
+  2) Build a Linux kernel. Make sure you include support for initrd.
+
+  3) Put a floppy in the drive. Make sure it is a floppy you don't care about
+     because the contents will be overwritten.
+
+  4) As root, type ./mksyslinux.sh path/to/linux/kernel from this directory.
+     Wait patiently while the magic happens.
+
+  5) Boot up on the floppy.

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/syslinux.cfg
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/syslinux.cfg	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/bootfloppy/syslinux.cfg	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,7 @@
+display display.txt
+default linux
+timeout 10
+prompt 1
+label linux
+	kernel linux
+	append initrd=rootfs.gz root=/dev/ram0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/busybox.spec
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/busybox.spec	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/busybox.spec	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,44 @@
+%define name	busybox
+%define epoch   0
+%define version	0.61.pre
+%define release	%(date -I | sed -e 's/-/_/g')
+%define serial  1
+
+Name:	 %{name}
+#Epoch:   %{epoch}
+Version: %{version}
+Release: %{release}
+Serial:	 %{serial}
+Copyright: GPL
+Group: System/Utilities
+Summary: BusyBox is a tiny suite of Unix utilities in a multi-call binary.
+URL:	 http://busybox.net/
+Source:	 ftp://busybox.net/busybox/%{name}-%{version}.tar.gz
+Buildroot: /var/tmp/%{name}-%{version}
+Packager : Erik Andersen <andersen at codepoet.org>
+
+%Description
+BusyBox combines tiny versions of many common UNIX utilities into a single
+small executable. It provides minimalist replacements for most of the utilities
+you usually find in fileutils, shellutils, findutils, textutils, grep, gzip,
+tar, etc.  BusyBox provides a fairly complete POSIX environment for any small
+or emdedded system.  The utilities in BusyBox generally have fewer options then
+their full featured GNU cousins; however, the options that are provided behave
+very much like their GNU counterparts.
+
+%Prep
+%setup -q -n %{name}-%{version}
+
+%Build
+make
+
+%Install
+rm -rf $RPM_BUILD_ROOT
+make PREFIX=$RPM_BUILD_ROOT install
+
+%Clean
+rm -rf $RPM_BUILD_ROOT
+
+%Files
+%defattr(-,root,root)
+/

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/depmod.pl
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/depmod.pl	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/depmod.pl	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,289 @@
+#!/usr/bin/perl -w
+# vi: set ts=4:
+# Copyright (c) 2001 David Schleef <ds at schleef.org>
+# Copyright (c) 2001 Erik Andersen <andersen at codepoet.org>
+# Copyright (c) 2001 Stuart Hughes <seh at zee2.com>
+# Copyright (c) 2002 Steven J. Hill <shill at broadcom.com>
+# Copyright (c) 2006 Freescale Semiconductor, Inc <stuarth at freescale.com>
+#
+# History:
+# March 2006: Stuart Hughes <stuarth at freescale.com>.
+#             Significant updates, including implementing the '-F' option
+#             and adding support for 2.6 kernels.
+
+# This program is free software; you can redistribute it and/or modify it
+# under the same terms as Perl itself.
+use Getopt::Long;
+use File::Find;
+use strict;
+
+# Set up some default values
+my $kdir="";
+my $basedir="";
+my $kernel="";
+my $kernelsyms="";
+my $stdout=0;
+my $verbose=0;
+my $help=0;
+my $nm = $ENV{'NM'} || "nm";
+
+# more globals
+my (@liblist) = ();
+my $exp = {};
+my $dep = {};
+my $mod = {};
+
+my $usage = <<TXT;
+$0 -b basedir { -k <vmlinux> | -F <System.map> } [options]... 
+  Where:
+   -h --help         : Show this help screen
+   -b --basedir      : Modules base directory (e.g /lib/modules/<2.x.y>)
+   -k --kernel       : Kernel binary for the target (e.g. vmlinux)
+   -F --kernelsyms   : Kernel symbol file (e.g. System.map)
+   -n --stdout       : Write to stdout instead of <basedir>/modules.dep
+   -v --verbose      : Print out lots of debugging stuff
+TXT
+
+# get command-line options
+GetOptions(
+	"help|h"         => \$help,
+	"basedir|b=s"    => \$basedir,
+	"kernel|k=s"     => \$kernel,
+	"kernelsyms|F=s" => \$kernelsyms,
+	"stdout|n"       => \$stdout,
+	"verbose|v"      => \$verbose,
+);
+
+die $usage if $help;
+die $usage unless $basedir && ( $kernel || $kernelsyms );
+die "can't use both -k and -F\n\n$usage" if $kernel && $kernelsyms;
+
+# Strip any trailing or multiple slashes from basedir
+$basedir =~ s-(/)\1+-/-g;
+
+# The base directory should contain /lib/modules somewhere
+if($basedir !~ m-/lib/modules-) {
+    warn "WARNING: base directory does not match ..../lib/modules\n";
+}
+
+# if no kernel version is contained in the basedir, try to find one
+if($basedir !~ m-/lib/modules/\d\.\d-) {
+    opendir(BD, $basedir) or die "can't open basedir $basedir : $!\n";
+    foreach ( readdir(BD) ) {
+        next if /^\.\.?$/;
+        next unless -d "$basedir/$_";
+        warn "dir = $_\n" if $verbose;
+        if( /^\d\.\d/ ) {
+            $kdir = $_;
+            warn("Guessed module directory as $basedir/$kdir\n");
+            last;
+        }
+    }
+    closedir(BD);
+    die "Cannot find a kernel version under $basedir\n" unless $kdir;
+    $basedir = "$basedir/$kdir";
+}
+
+# Find the list of .o or .ko files living under $basedir
+warn "**** Locating all modules\n" if $verbose;
+find sub {
+    my $file;
+	if ( -f $_  && ! -d $_ ) {
+		$file = $File::Find::name;
+		if ( $file =~ /\.k?o$/ ) {
+			push(@liblist, $file);
+			warn "$file\n" if $verbose;
+		}
+	}
+}, $basedir;
+warn "**** Finished locating modules\n" if $verbose;
+
+foreach my $obj ( @liblist ){
+    # turn the input file name into a target tag name
+    my ($tgtname) = $obj =~ m-(/lib/modules/.*)$-;
+
+    warn "\nMODULE = $tgtname\n" if $verbose;
+
+    # get a list of symbols
+	my @output=`$nm $obj`;
+
+    build_ref_tables($tgtname, \@output, $exp, $dep);
+}
+
+
+# vmlinux is a special name that is only used to resolve symbols
+my $tgtname = 'vmlinux';
+my @output = $kernelsyms ? `cat $kernelsyms` : `$nm $kernel`;
+warn "\nMODULE = $tgtname\n" if $verbose;
+build_ref_tables($tgtname, \@output, $exp, $dep);
+
+# resolve the dependencies for each module
+# reduce dependencies: remove unresolvable and resolved from vmlinux/System.map
+# remove duplicates
+foreach my $module (keys %$dep) {
+    warn "reducing module: $module\n" if $verbose;
+    $mod->{$module} = {};
+    foreach (@{$dep->{$module}}) {
+        if( $exp->{$_} ) {
+            warn "resolved symbol $_ in file $exp->{$_}\n" if $verbose;
+            next if $exp->{$_} =~ /vmlinux/;
+            $mod->{$module}{$exp->{$_}} = 1;
+        } else {
+            warn "unresolved symbol $_ in file $module\n";
+        }
+    }
+}
+
+# figure out where the output should go
+if ($stdout == 0) {
+    open(STDOUT, ">$basedir/modules.dep")
+                             or die "cannot open $basedir/modules.dep: $!";
+}
+my $kseries = $basedir =~ m,/2\.6\.[^/]*, ? '2.6' : '2.4';
+
+foreach my $module ( keys %$mod ) {
+    if($kseries eq '2.4') {
+	    print "$module:\t";
+	    my @sorted = sort bydep keys %{$mod->{$module}};
+	    print join(" \\\n\t", at sorted);
+	    print "\n\n";
+    } else {
+	    print "$module: ";
+	    my @sorted = sort bydep keys %{$mod->{$module}};
+	    print join(" ", at sorted);
+	    print "\n";
+    }
+}
+
+
+sub build_ref_tables
+{
+    my ($name, $sym_ar, $exp, $dep) = @_;
+
+	my $ksymtab = grep m/ __ksymtab/, @$sym_ar;
+
+    # gather the exported symbols
+	if($ksymtab){
+        # explicitly exported
+        foreach ( @$sym_ar ) {
+            / __ksymtab_(.*)$/ and do {
+                warn "sym = $1\n" if $verbose;
+                $exp->{$1} = $name;
+            };
+        }
+	} else {
+        # exporting all symbols
+        foreach ( @$sym_ar ) {
+            / [ABCDGRST] (.*)$/ and do {
+                warn "syma = $1\n" if $verbose;
+                $exp->{$1} = $name;
+            };
+        }
+	}
+
+    # this takes makes sure modules with no dependencies get listed
+    push @{$dep->{$name}}, 'printk' unless $name eq 'vmlinux';
+
+    # gather the unresolved symbols
+    foreach ( @$sym_ar ) {
+        !/ __this_module/ && / U (.*)$/ and do {
+            warn "und = $1\n" if $verbose;
+            push @{$dep->{$name}}, $1;
+        };
+    }
+}
+
+sub bydep
+{
+    foreach my $f ( keys %{$mod->{$b}} ) {
+        if($f eq $a) {
+            return 1;
+        }
+    }
+    return -1;
+}
+
+
+
+__END__
+
+=head1 NAME
+
+depmod.pl - a cross platform script to generate kernel module
+dependency lists (modules.conf) which can then be used by modprobe
+on the target platform. 
+
+It supports Linux 2.4 and 2.6 styles of modules.conf (auto-detected)
+
+=head1 SYNOPSIS
+
+depmod.pl [OPTION]... [basedir]...
+
+Example:
+
+	depmod.pl -F linux/System.map -b target/lib/modules/2.6.11
+
+=head1 DESCRIPTION
+
+The purpose of this script is to automagically generate a list of of kernel
+module dependencies.  This script produces dependency lists that should be
+identical to the depmod program from the modutils package.  Unlike the depmod
+binary, however, depmod.pl is designed to be run on your host system, not
+on your target system.
+
+This script was written by David Schleef <ds at schleef.org> to be used in
+conjunction with the BusyBox modprobe applet.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-h --help>
+
+This displays the help message.
+
+=item B<-b --basedir>
+
+The base directory uner which the target's modules will be found.  This
+defaults to the /lib/modules directory. 
+
+If you don't specify the kernel version, this script will search for
+one under the specified based directory and use the first thing that
+looks like a kernel version.
+
+=item B<-k --kernel>
+
+Kernel binary for the target (vmlinux).  You must either supply a kernel binary
+or a kernel symbol file (using the -F option).
+
+=item B<-F --kernelsyms>
+
+Kernel symbol file for the target (System.map).
+
+=item B<-n --stdout>
+
+Write to stdout instead of modules.dep
+kernel binary for the target (using the -k option).
+
+=item B<--verbose>
+
+Verbose (debug) output
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+ Copyright (c) 2001 David Schleef <ds at schleef.org>
+ Copyright (c) 2001 Erik Andersen <andersen at codepoet.org>
+ Copyright (c) 2001 Stuart Hughes <seh at zee2.com>
+ Copyright (c) 2002 Steven J. Hill <shill at broadcom.com>
+ Copyright (c) 2006 Freescale Semiconductor, Inc <stuarth at freescale.com>
+
+This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+=head1 AUTHOR
+
+David Schleef <ds at schleef.org>
+
+=cut


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/depmod.pl
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/devfsd.conf
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/devfsd.conf	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/devfsd.conf	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,133 @@
+# Sample /etc/devfsd.conf configuration file.
+# Richard Gooch  <rgooch at atnf.csiro.au>		17-FEB-2002
+#
+# adapted for busybox devfsd implementation by Tito <farmatito at tiscali.it>
+#
+# Enable full compatibility mode for old device names. You may comment these
+# out if you don't use the old device names. Make sure you know what you're
+# doing!
+REGISTER	.*		MKOLDCOMPAT
+UNREGISTER	.*		RMOLDCOMPAT
+
+# You may comment out the above and uncomment the following if you've
+# configured your system to use the original "new" devfs names or the really
+# new names
+#REGISTER	^vc/		MKOLDCOMPAT
+#UNREGISTER	^vc/		RMOLDCOMPAT
+#REGISTER	^pty/		MKOLDCOMPAT
+#UNREGISTER	^pty/		RMOLDCOMPAT
+#REGISTER	^misc/		MKOLDCOMPAT
+#UNREGISTER	^misc/		RMOLDCOMPAT
+
+# You may comment these out if you don't use the original "new" names
+REGISTER	.*		MKNEWCOMPAT
+UNREGISTER	.*		RMNEWCOMPAT
+
+# Enable module autoloading. You may comment this out if you don't use
+# autoloading
+# Supported by busybox when CONFIG_DEVFSD_MODLOAD is set.
+# This actually doesn't work with busybox  modutils but needs
+# the real modutils' modprobe
+LOOKUP		.*		MODLOAD
+
+# Uncomment the following if you want to set the group to "tty" for the
+# pseudo-tty devices. This is necessary so that mesg(1) can later be used to
+# enable/disable talk requests and wall(1) messages.
+REGISTER	^pty/s.*	PERMISSIONS	-1.tty	0600
+#REGISTER	^pts/.*		PERMISSIONS	-1.tty	0600
+
+# Restoring /dev/log on startup would trigger the minilogd/initlog deadlock
+# (minilogd falsely assuming syslogd has been started).
+REGISTER	^log$		IGNORE
+CREATE		^log$		IGNORE
+CHANGE		^log$		IGNORE
+DELETE		^log$		IGNORE
+
+#
+# Uncomment this if you want permissions to be saved and restored
+# Do not do this for pseudo-terminal devices
+REGISTER	^pt[sy]		IGNORE
+CREATE		^pt[sy]		IGNORE
+CHANGE		^pt[sy]		IGNORE
+DELETE		^pt[sy]		IGNORE
+REGISTER	.*		COPY	/lib/dev-state/$devname $devpath
+CREATE		.*		COPY	$devpath /lib/dev-state/$devname
+CHANGE		.*		COPY	$devpath /lib/dev-state/$devname
+#DELETE		.*		CFUNCTION GLOBAL unlink /lib/dev-state/$devname
+# Busybox
+DELETE		.*		EXECUTE /bin/rm -f		/lib/dev-state/$devname
+
+RESTORE		/lib/dev-state
+
+#
+# Uncomment this if you want the old /dev/cdrom symlink
+#REGISTER	^cdroms/cdrom0$	CFUNCTION GLOBAL mksymlink $devname cdrom
+#UNREGISTER	^cdroms/cdrom0$	CFUNCTION GLOBAL unlink cdrom
+# busybox
+REGISTER	^cdroms/cdrom0$	EXECUTE /bin/ln -sf $devname cdrom
+UNREGISTER	^cdroms/cdrom0$	EXECUTE /bin/rm -f cdrom
+
+#REGISTER	^v4l/video0$	CFUNCTION GLOBAL mksymlink v4l/video0 video
+#UNREGISTER	^v4l/video0$	CFUNCTION GLOBAL unlink video
+#REGISTER	^radio0$	CFUNCTION GLOBAL mksymlink radio0 radio
+#UNREGISTER	^radio0$	CFUNCTION GLOBAL unlink radio
+# Busybox
+REGISTER	^v4l/video0$	EXECUTE /bin/ln -sf v4l/video0 video
+UNREGISTER	^v4l/video0$	EXECUTE /bin/rm -f video
+REGISTER	^radio0$		EXECUTE /bin/ln -sf  radio0 radio
+UNREGISTER	^radio0$		EXECUTE /bin/rm -f radio
+
+# ALSA stuff
+#LOOKUP 		snd 		MODLOAD ACTION snd
+
+# Uncomment this to let PAM manage devfs
+# Not supported by busybox
+#REGISTER	.*		CFUNCTION /lib/security/pam_console_apply_devfsd.so pam_console_apply_single $devpath
+
+# Uncomment this to manage USB mouse
+# Not supported by busybox
+#REGISTER	^input/mouse0$	CFUNCTION GLOBAL mksymlink $devname usbmouse
+#UNREGISTER	^input/mouse0$	CFUNCTION GLOBAL unlink usbmouse
+# Busybox
+#REGISTER	^input/mouse0$	EXECUTE /bin/ln -sf $devname usbmouse
+#UNREGISTER	^input/mouse0$	EXECUTE /bin/rm -f usbmouse
+# Not supported by busybox
+#REGISTER	^input/mice$	CFUNCTION GLOBAL mksymlink $devname usbmouse
+#UNREGISTER	^input/mice$	CFUNCTION GLOBAL unlink usbmouse
+# Busybox
+REGISTER	^input/mice$	EXECUTE /bin/ln -sf $devname usbmouse
+UNREGISTER	^input/mice$	EXECUTE /bin/rm -f usbmouse
+
+# If you have removable media and want to force media revalidation when looking
+# up new or old compatibility names, uncomment the following lines
+# SCSI NEWCOMPAT  /dev/sd/* names
+LOOKUP		^(sd/c[0-9]+b[0-9]+t[0-9]+u[0-9]+)p[0-9]+$	EXECUTE /bin/dd if=$mntpnt/\1 of=/dev/null count=1
+# SCSI OLDCOMPAT  /dev/sd?? names
+LOOKUP		^(sd[a-z]+)[0-9]+$	EXECUTE /bin/dd if=$mntpnt/\1 of=/dev/null count=1
+# IDE NEWCOMPAT   /dev/ide/hd/* names
+LOOKUP		^(ide/hd/c[0-9]+b[0-9]+t[0-9]+u[0-9]+)p[0-9]+$	EXECUTE /bin/dd if=$mntpnt/\1 of=/dev/null count=1
+# IDE OLDCOMPAT   /dev/hd?? names
+LOOKUP		^(hd[a-z])[0-9]+$	EXECUTE /bin/dd if=$mntpnt/\1 of=/dev/null count=1
+# IDE-SCSI NEWCOMPAT  /dev/sd/* names
+#LOOKUP		^(sd/c[0-9]+b[0-9]+t[0-9]+u[0-9]+)p[0-9]+$	EXECUTE /bin/dd if=$mntpnt/\1 of=/dev/null count=1
+#SCSI OLDCOMPAT  /dev/scd? names
+LOOKUP		^(scd+)[0-9]+$	EXECUTE /bin/dd if=$mntpnt/\1 of=/dev/null count=1
+
+
+REGISTER ^dvb/card[0-9]+/[^/]+$ PERMISSIONS root.video 0660
+# Not supported by busybox
+#REGISTER	^dvb/card([0-9]+)/([^/0-9]*)[0-9]+$	CFUNCTION GLOBAL mksymlink /dev/$devname ost/\2\1
+#UNREGISTER	^dvb/card([0-9]+)/([^/0-9]*)[0-9]+$	CFUNCTION GLOBAL unlink ost/\2\1
+# Busybox
+REGISTER	^dvb/card([0-9]+)/([^/0-9]*)[0-9]+$	EXECUTE /bin/ln -sf /dev/$devname ost/\2\1
+UNREGISTER	^dvb/card([0-9]+)/([^/0-9]*)[0-9]+$	EXECUTE /bin/rm -f ost/\2\1
+
+# Include package-generated files from /etc/devfs/conf.d
+# Supported by busybox
+# INCLUDE   /etc/devfs/conf.d/
+INCLUDE   /etc/devfs/busybox/
+# Busybox: just for testing
+#INCLUDE			/etc/devfs/nothing/
+#INCLUDE			/etc/devfs/nothing/nothing
+#OPTIONAL_INCLUDE	/etc/devfs/nothing/
+#OPTIONAL_INCLUDE	/etc/devfs/nothing/nothing

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/dnsd.conf
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/dnsd.conf	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/dnsd.conf	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+thebox 192.168.1.5

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/inetd.conf
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/inetd.conf	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/inetd.conf	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,73 @@
+# /etc/inetd.conf:  see inetd(8) for further informations.
+#
+# Internet server configuration database
+#
+#
+# If you want to disable an entry so it isn't touched during
+# package updates just comment it out with a single '#' character.
+#
+# If you make changes to this file, either reboot your machine or
+# send the inetd process a HUP signal:
+# Do a "ps x" as root and look up the pid of inetd. Then do a
+#     kill -HUP <pid of inetd>
+# inetd will re-read this file whenever it gets that signal.
+# <service_name> <sock_type> <proto> <flags> <user> <server_path> <args>
+#
+#:INTERNAL: Internal services
+# It is generally considered safer to keep these off.
+echo     stream  tcp	nowait	root	internal
+echo     dgram   udp	wait	root	internal
+#discard  stream  tcp	nowait	root	internal
+#discard  dgram   udp	wait	root	internal
+daytime  stream  tcp	nowait	root	internal
+daytime  dgram   udp	wait	root	internal
+#chargen  stream  tcp	nowait	root	internal
+#chargen  dgram   udp	wait	root	internal
+time     stream  tcp	nowait	root	internal
+time     dgram   udp	wait	root	internal
+
+# These are standard services.
+#
+#ftp	stream	tcp	nowait	root	/usr/sbin/tcpd	in.ftpd
+#telnet	stream	tcp	nowait	root	/sbin/telnetd	/sbin/telnetd
+#nntp	stream	tcp	nowait	root	tcpd	in.nntpd
+#smtp  stream  tcp     nowait  root    tcpd    sendmail -v
+#
+# Shell, login, exec and talk are BSD protocols.
+#
+# If you run an ntalk daemon (such as netkit-ntalk) on the old talk
+# port, that is, "talk" as opposed to "ntalk", it won't work and may
+# cause certain broken talk clients to malfunction.
+#
+# The talkd from netkit-ntalk 0.12 and higher, however, can speak the
+# old talk protocol and can be used safely.
+#
+#shell	stream	tcp	nowait	root	/usr/sbin/tcpd	in.rshd -L
+#login	stream	tcp	nowait	root	/usr/sbin/tcpd	in.rlogind -L
+#exec	stream	tcp	nowait	root	/usr/sbin/tcpd	in.rexecd
+#talk	dgram	udp	wait	root	/usr/sbin/tcpd	in.talkd
+#ntalk	dgram	udp	wait	root	/usr/sbin/tcpd	in.talkd
+#
+# Pop et al
+# Leave these off unless you're using them.
+#pop2	stream	tcp	nowait	root	/usr/sbin/tcpd	in.pop2d
+#pop3	stream	tcp	nowait	root	/usr/sbin/tcpd	in.pop3d
+#
+# The Internet UUCP service.
+# uucp	stream	tcp	nowait	uucp	/usr/sbin/tcpd	/usr/lib/uucp/uucico	-l
+#
+# Tftp service is provided primarily for booting.  Most sites
+# run this only on machines acting as "boot servers." If you don't
+# need it, don't use it.
+#
+#tftp	dgram	udp	wait	nobody	/usr/sbin/tcpd	in.tftpd
+#bootps	dgram	udp	wait	root	/usr/sbin/in.bootpd	in.bootpd
+#
+# Finger, systat and netstat give out user information which may be
+# valuable to potential "system crackers."  Many sites choose to disable
+# some or all of these services to improve security.
+#
+#finger	stream	tcp	nowait	nobody	/usr/sbin/tcpd	in.fingerd -w
+#systat	stream	tcp	nowait	nobody	/usr/sbin/tcpd	/bin/ps	-auwwx
+#netstat	stream	tcp	nowait	root	/bin/netstat	/bin/netstat	-a
+#ident	stream	tcp	nowait	root	/usr/sbin/in.identd	in.identd

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/inittab
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/inittab	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/inittab	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,90 @@
+# /etc/inittab init(8) configuration for BusyBox
+#
+# Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+#
+#
+# Note, BusyBox init doesn't support runlevels.  The runlevels field is
+# completely ignored by BusyBox init. If you want runlevels, use sysvinit.
+#
+#
+# Format for each entry: <id>:<runlevels>:<action>:<process>
+#
+# <id>: WARNING: This field has a non-traditional meaning for BusyBox init!
+#
+#	The id field is used by BusyBox init to specify the controlling tty for
+#	the specified process to run on.  The contents of this field are
+#	appended to "/dev/" and used as-is.  There is no need for this field to
+#	be unique, although if it isn't you may have strange results.  If this
+#	field is left blank, it is completely ignored.  Also note that if
+#	BusyBox detects that a serial console is in use, then all entries
+#	containing non-empty id fields will be ignored.  BusyBox init does
+#	nothing with utmp.  We don't need no stinkin' utmp.
+#
+# <runlevels>: The runlevels field is completely ignored.
+#
+# <action>: Valid actions include: sysinit, respawn, askfirst, wait, once,
+#                                  restart, ctrlaltdel, and shutdown.
+#
+#       Note: askfirst acts just like respawn, but before running the specified
+#       process it displays the line "Please press Enter to activate this
+#       console." and then waits for the user to press enter before starting
+#       the specified process.
+#
+#       Note: unrecognised actions (like initdefault) will cause init to emit
+#       an error message, and then go along with its business.
+#
+# <process>: Specifies the process to be executed and it's command line.
+#
+# Note: BusyBox init works just fine without an inittab. If no inittab is
+# found, it has the following default behavior:
+#         ::sysinit:/etc/init.d/rcS
+#         ::askfirst:/bin/sh
+#         ::ctrlaltdel:/sbin/reboot
+#         ::shutdown:/sbin/swapoff -a
+#         ::shutdown:/bin/umount -a -r
+#         ::restart:/sbin/init
+#
+# if it detects that /dev/console is _not_ a serial console, it will
+# also run:
+#         tty2::askfirst:/bin/sh
+#         tty3::askfirst:/bin/sh
+#         tty4::askfirst:/bin/sh
+#
+# Boot-time system configuration/initialization script.
+# This is run first except when booting in single-user mode.
+#
+::sysinit:/etc/init.d/rcS
+
+# /bin/sh invocations on selected ttys
+#
+# Note below that we prefix the shell commands with a "-" to indicate to the
+# shell that it is supposed to be a login shell.  Normally this is handled by
+# login, but since we are bypassing login in this case, BusyBox lets you do
+# this yourself...
+#
+# Start an "askfirst" shell on the console (whatever that may be)
+::askfirst:-/bin/sh
+# Start an "askfirst" shell on /dev/tty2-4
+tty2::askfirst:-/bin/sh
+tty3::askfirst:-/bin/sh
+tty4::askfirst:-/bin/sh
+
+# /sbin/getty invocations for selected ttys
+tty4::respawn:/sbin/getty 38400 tty5
+tty5::respawn:/sbin/getty 38400 tty6
+
+# Example of how to put a getty on a serial line (for a terminal)
+#::respawn:/sbin/getty -L ttyS0 9600 vt100
+#::respawn:/sbin/getty -L ttyS1 9600 vt100
+#
+# Example how to put a getty on a modem line.
+#::respawn:/sbin/getty 57600 ttyS2
+
+# Stuff to do when restarting the init process
+::restart:/sbin/init
+
+# Stuff to do before rebooting
+::ctrlaltdel:/sbin/reboot
+::shutdown:/bin/umount -a -r
+::shutdown:/sbin/swapoff -a
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/mk2knr.pl
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/mk2knr.pl	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/mk2knr.pl	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,84 @@
+#!/usr/bin/perl -w
+#
+# @(#) mk2knr.pl - generates a perl script that converts lexemes to K&R-style
+#
+# How to use this script:
+#  - In the busybox directory type 'examples/mk2knr.pl files-to-convert'
+#  - Review the 'convertme.pl' script generated and remove / edit any of the
+#    substitutions in there (please especially check for false positives)
+#  - Type './convertme.pl same-files-as-before'
+#  - Compile and see if it works
+#
+# BUGS: This script does not ignore strings inside comments or strings inside
+# quotes (it probably should).
+
+# set this to something else if you want
+$convertme = 'convertme.pl';
+
+# internal-use variables (don't touch)
+$convert = 0;
+%converted = ();
+
+# if no files were specified, print usage
+die "usage: $0 file.c | file.h\n" if scalar(@ARGV) == 0;
+
+# prepare the "convert me" file
+open(CM, ">$convertme") or die "convertme.pl $!";
+print CM "#!/usr/bin/perl -p -i\n\n";
+
+# process each file passed on the cmd line
+while (<>) {
+
+	# if the line says "getopt" in it anywhere, we don't want to muck with it
+	# because option lists tend to include strings like "cxtzvOf:" which get
+	# matched by the "check for mixed case" regexps below
+	next if /getopt/;
+
+	# tokenize the string into just the variables
+	while (/([a-zA-Z_][a-zA-Z0-9_]*)/g) {
+		$var = $1;
+
+		# ignore the word "BusyBox"
+		next if ($var =~ /BusyBox/);
+
+		# this checks for javaStyle or szHungarianNotation
+		$convert++ if ($var =~ /^[a-z]+[A-Z][a-z]+/);
+
+		# this checks for PascalStyle
+		$convert++ if ($var =~ /^[A-Z][a-z]+[A-Z][a-z]+/);
+
+		# if we want to add more checks, we can add 'em here, but the above
+		# checks catch "just enough" and not too much, so prolly not.
+
+		if ($convert) {
+			$convert = 0;
+
+			# skip ahead if we've already dealt with this one
+			next if ($converted{$var});
+
+			# record that we've dealt with this var
+			$converted{$var} = 1;
+
+			print CM "s/\\b$var\\b/"; # more to come in just a minute
+
+			# change the first letter to lower-case
+			$var = lcfirst($var);
+
+			# put underscores before all remaining upper-case letters
+			$var =~ s/([A-Z])/_$1/g;
+
+			# now change the remaining characters to lower-case
+			$var = lc($var);
+
+			print CM "$var/g;\n";
+		}
+	}
+}
+
+# tidy up and make the $convertme script executable
+close(CM);
+chmod 0755, $convertme;
+
+# print a helpful help message
+print "Done. Scheduled name changes are in $convertme.\n";
+print "Please review/modify it and then type ./$convertme to do the search & replace.\n";


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/mk2knr.pl
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.bound
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.bound	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.bound	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,31 @@
+#!/bin/sh
+# Sample udhcpc renew script
+
+RESOLV_CONF="/etc/udhcpc/resolv.conf"
+
+[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
+[ -n "$subnet" ] && NETMASK="netmask $subnet"
+
+/sbin/ifconfig $interface $ip $BROADCAST $NETMASK
+
+if [ -n "$router" ]
+then
+	echo "deleting routers"
+	while /sbin/route del default gw 0.0.0.0 dev $interface
+	do :
+	done
+
+	metric=0
+	for i in $router
+	do
+		/sbin/route add default gw $i dev $interface metric $((metric++))
+	done
+fi
+
+echo -n > $RESOLV_CONF
+[ -n "$domain" ] && echo domain $domain >> $RESOLV_CONF
+for i in $dns
+do
+	echo adding dns $i
+	echo nameserver $i >> $RESOLV_CONF
+done
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.bound
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.deconfig
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.deconfig	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.deconfig	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+#!/bin/sh
+# Sample udhcpc deconfig script
+
+/sbin/ifconfig $interface 0.0.0.0


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.deconfig
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.nak
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.nak	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.nak	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+#!/bin/sh
+# Sample udhcpc nak script
+
+echo Received a NAK: $message


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.nak
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.renew
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.renew	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.renew	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,31 @@
+#!/bin/sh
+# Sample udhcpc bound script
+
+RESOLV_CONF="/etc/udhcpc/resolv.conf"
+
+[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
+[ -n "$subnet" ] && NETMASK="netmask $subnet"
+
+/sbin/ifconfig $interface $ip $BROADCAST $NETMASK
+
+if [ -n "$router" ]
+then
+	echo "deleting routers"
+	while /sbin/route del default gw 0.0.0.0 dev $interface
+	do :
+	done
+
+	metric=0
+	for i in $router
+	do
+		/sbin/route add default gw $i dev $interface metric $((metric++))
+	done
+fi
+
+echo -n > $RESOLV_CONF
+[ -n "$domain" ] && echo domain $domain >> $RESOLV_CONF
+for i in $dns
+do
+	echo adding dns $i
+	echo nameserver $i >> $RESOLV_CONF
+done
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.renew
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.script
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.script	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/sample.script	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,7 @@
+#!/bin/sh
+# Currently, we only dispatch according to command.  However, a more
+# elaborate system might dispatch by command and interface or do some
+# common initialization first, especially if more dhcp event notifications
+# are added.
+
+exec /usr/share/udhcpc/sample.$1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/simple.script
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/simple.script	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/simple.script	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+# udhcpc script edited by Tim Riker <Tim at Rikers.org>
+
+[ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1
+
+RESOLV_CONF="/etc/resolv.conf"
+[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
+[ -n "$subnet" ] && NETMASK="netmask $subnet"
+
+case "$1" in
+	deconfig)
+		/sbin/ifconfig $interface 0.0.0.0
+		;;
+
+	renew|bound)
+		/sbin/ifconfig $interface $ip $BROADCAST $NETMASK
+
+		if [ -n "$router" ] ; then
+			echo "deleting routers"
+			while route del default gw 0.0.0.0 dev $interface ; do
+				:
+			done
+
+			metric=0
+			for i in $router ; do
+				route add default gw $i dev $interface metric $((metric++))
+			done
+		fi
+
+		echo -n > $RESOLV_CONF
+		[ -n "$domain" ] && echo search $domain >> $RESOLV_CONF
+		for i in $dns ; do
+			echo adding dns $i
+			echo nameserver $i >> $RESOLV_CONF
+		done
+		;;
+esac
+
+exit 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/udhcpd.conf
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/udhcpd.conf	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/udhcp/udhcpd.conf	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,123 @@
+# Sample udhcpd configuration file (/etc/udhcpd.conf)
+
+# The start and end of the IP lease block
+
+start 		192.168.0.20	#default: 192.168.0.20
+end		192.168.0.254	#default: 192.168.0.254
+
+
+# The interface that udhcpd will use
+
+interface	eth0		#default: eth0
+
+
+# The maximim number of leases (includes addressesd reserved
+# by OFFER's, DECLINE's, and ARP conficts
+
+#max_leases	254		#default: 254
+
+
+# If remaining is true (default), udhcpd will store the time
+# remaining for each lease in the udhcpd leases file. This is
+# for embedded systems that cannot keep time between reboots.
+# If you set remaining to no, the absolute time that the lease
+# expires at will be stored in the dhcpd.leases file.
+
+#remaining	yes		#default: yes
+
+
+# The time period at which udhcpd will write out a dhcpd.leases
+# file. If this is 0, udhcpd will never automatically write a
+# lease file. (specified in seconds)
+
+#auto_time	7200		#default: 7200 (2 hours)
+
+
+# The amount of time that an IP will be reserved (leased) for if a
+# DHCP decline message is received (seconds).
+
+#decline_time	3600		#default: 3600 (1 hour)
+
+
+# The amount of time that an IP will be reserved (leased) for if an
+# ARP conflct occurs. (seconds
+
+#conflict_time	3600		#default: 3600 (1 hour)
+
+
+# How long an offered address is reserved (leased) in seconds
+
+#offer_time	60		#default: 60 (1 minute)
+
+# If a lease to be given is below this value, the full lease time is
+# instead used (seconds).
+
+#min_lease	60		#defult: 60
+
+
+# The location of the leases file
+
+#lease_file	/var/lib/misc/udhcpd.leases	#defualt: /var/lib/misc/udhcpd.leases
+
+# The location of the pid file
+#pidfile	/var/run/udhcpd.pid	#default: /var/run/udhcpd.pid
+
+# Everytime udhcpd writes a leases file, the below script will be called.
+# Useful for writing the lease file to flash every few hours.
+
+#notify_file				#default: (no script)
+
+#notify_file	dumpleases 	# <--- usefull for debugging
+
+# The following are bootp specific options, setable by udhcpd.
+
+#siaddr		192.168.0.22		#default: 0.0.0.0
+
+#sname		zorak			#default: (none)
+
+#boot_file	/var/nfs_root		#default: (none)
+
+# The remainer of options are DHCP options and can be specifed with the
+# keyword 'opt' or 'option'. If an option can take multiple items, such
+# as the dns option, they can be listed on the same line, or multiple
+# lines. The only option with a default is 'lease'.
+
+#Examles
+opt	dns	192.168.10.2 192.168.10.10
+option	subnet	255.255.255.0
+opt	router	192.168.10.2
+opt	wins	192.168.10.10
+option	dns	129.219.13.81	# appened to above DNS servers for a total of 3
+option	domain	local
+option	lease	864000		# 10 days of seconds
+
+
+# Currently supported options, for more info, see options.c
+#opt subnet
+#opt timezone
+#opt router
+#opt timesvr
+#opt namesvr
+#opt dns
+#opt logsvr
+#opt cookiesvr
+#opt lprsvr
+#opt bootsize
+#opt domain
+#opt swapsvr
+#opt rootpath
+#opt ipttl
+#opt mtu
+#opt broadcast
+#opt wins
+#opt lease
+#opt ntpsrv
+#opt tftp
+#opt bootfile
+
+
+# Static leases map
+#static_lease 00:60:08:11:CE:4E 192.168.0.54
+#static_lease 00:60:08:11:CE:3E 192.168.0.44
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/undeb
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/undeb	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/undeb	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+# This should work with the GNU version of tar and gzip!
+# This should work with the bash or ash shell!
+# Requires the programs (ar, tar, gzip, and the pager more or less).
+#
+usage() {
+echo "Usage: undeb -c package.deb            <Print control file info>"
+echo "       undeb -l package.deb            <List contents of deb package>"
+echo "       undeb -x package.deb /foo/boo   <Extract deb package to this directory,"
+echo "                                        put . for current directory>"
+exit
+}
+
+deb=$2
+
+exist() {
+if [ "$deb" = "" ]; then
+usage
+elif [ ! -s "$deb" ]; then
+echo "Can't find $deb!"
+exit
+fi
+}
+
+if [ "$1" = "" ]; then
+usage
+elif [ "$1" = "-l" ]; then
+exist
+type more >/dev/null 2>&1 && pager=more
+type less >/dev/null 2>&1 && pager=less
+[ "$pager" = "" ] && echo "No pager found!" && exit
+(ar -p $deb control.tar.gz | tar -xzO *control ; echo -e "\nPress enter to scroll, q to Quit!\n" ; ar -p $deb data.tar.gz | tar -tzv) | $pager
+exit
+elif [ "$1" = "-c" ]; then
+exist
+ar -p $deb control.tar.gz | tar -xzO *control
+exit
+elif [ "$1" = "-x" ]; then
+exist
+if [ "$3" = "" ]; then
+usage
+elif [ ! -d "$3" ]; then
+echo "No such directory $3!"
+exit
+fi
+ar -p $deb data.tar.gz | tar -xzvpf - -C $3 || exit
+echo
+echo "Extracted $deb to $3!"
+exit
+else
+usage
+fi

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/unrpm
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/unrpm	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/unrpm	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,48 @@
+#!/bin/sh
+#
+# This should work with the GNU version of cpio and gzip!
+# This should work with the bash or ash shell!
+# Requires the programs (cpio, gzip, and the pager more or less).
+#
+usage() {
+echo "Usage: unrpm -l package.rpm            <List contents of rpm package>"
+echo "       unrpm -x package.rpm /foo/boo   <Extract rpm package to this directory,"
+echo "                                        put . for current directory>"
+exit
+}
+
+rpm=$2
+
+exist() {
+if [ "$rpm" = "" ]; then
+usage
+elif [ ! -s "$rpm" ]; then
+echo "Can't find $rpm!"
+exit
+fi
+}
+
+if [ "$1" = "" ]; then
+usage
+elif [ "$1" = "-l" ]; then
+exist
+type more >/dev/null 2>&1 && pager=more
+type less >/dev/null 2>&1 && pager=less
+[ "$pager" = "" ] && echo "No pager found!" && exit
+(echo -e "\nPress enter to scroll, q to Quit!\n" ; rpm2cpio $rpm | cpio -tv --quiet) | $pager
+exit
+elif [ "$1" = "-x" ]; then
+exist
+if [ "$3" = "" ]; then
+usage
+elif [ ! -d "$3" ]; then
+echo "No such directory $3!"
+exit
+fi
+rpm2cpio $rpm | (umask 0 ; cd $3 ; cpio -idmuv) || exit
+echo
+echo "Extracted $rpm to $3!"
+exit
+else
+usage
+fi

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/zcip.script
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/zcip.script	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/examples/zcip.script	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# only for use as a "zcip" callback script
+if [ "x$interface" = x ]
+then
+	exit 1
+fi
+
+# zcip should start on boot/resume and various media changes
+case "$1" in
+init)
+	# for now, zcip requires the link to be already up,
+	# and it drops links when they go down.  that isn't
+	# the most robust model...
+	exit 0
+	;;
+config)
+	if [ "x$ip" = x ]
+	then
+		exit 1
+	fi
+	# remember $ip for $interface, to use on restart
+	if [ "x$IP" != x -a -w "$IP.$interface" ]
+	then
+		echo $ip > "$IP.$interface"
+	fi
+	exec ip address add dev $interface \
+		scope link local "$ip/16" broadcast +
+	;;
+deconfig)
+	if [ x$ip = x ]
+	then
+		exit 1
+	fi
+	exec ip address del dev $interface local $ip
+	;;
+esac
+exit 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,159 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Finding Utilities"
+
+config CONFIG_FIND
+	bool "find"
+	default n
+	help
+	  find is used to search your system to find specified files.
+
+config CONFIG_FEATURE_FIND_PRINT0
+	bool "Enable -print0 option"
+	default y
+	depends on CONFIG_FIND
+	help
+	  Causes output names to be separated by a null character
+	  rather than a newline.  This allows names that contain
+	  newlines and other whitespace to be more easily
+	  interpreted by other programs.
+
+config CONFIG_FEATURE_FIND_MTIME
+	bool "Enable modified time matching (-mtime) option"
+	default y
+	depends on CONFIG_FIND
+	help
+	  Allow searching based on the modification time of
+	  files, in days.
+
+config CONFIG_FEATURE_FIND_MMIN
+	bool "Enable modified time matching (-min) option"
+	default y
+	depends on CONFIG_FIND
+	help
+	  Allow searching based on the modification time of
+	  files, in minutes.
+
+config CONFIG_FEATURE_FIND_PERM
+	bool "Enable permissions matching (-perm) option"
+	default y
+	depends on CONFIG_FIND
+	help
+	  Enable searching based on file permissions.
+
+config CONFIG_FEATURE_FIND_TYPE
+	bool "Enable filetype matching (-type) option"
+	default y
+	depends on CONFIG_FIND
+	help
+	  Enable searching based on file type (file,
+	  directory, socket, device, etc.).
+
+config CONFIG_FEATURE_FIND_XDEV
+	bool "Enable stay in filesystem (-xdev) option"
+	default y
+	depends on CONFIG_FIND
+	help
+	  This option will allow find to restrict searches to a single
+	  filesystem.
+
+config CONFIG_FEATURE_FIND_NEWER
+	bool "Enable -newer option for comparing file mtimes"
+	default y
+	depends on CONFIG_FIND
+	help
+	  Support the 'find -newer' option for finding any files which have
+	  a modified time that is more recent than the specified FILE.
+
+config CONFIG_FEATURE_FIND_INUM
+	bool "Enable inode number matching (-inum) option"
+	default y
+	depends on CONFIG_FIND
+	help
+	  Support the 'find -inum' option for searching by inode number.
+
+config CONFIG_FEATURE_FIND_EXEC
+	bool "Enable (-exec) option allowing execution of commands"
+	default y
+	depends on CONFIG_FIND
+	help
+	  Support the 'find -exec' option for executing commands based upon
+	  the files matched.
+
+config CONFIG_GREP
+	bool "grep"
+	default n
+	help
+	  grep is used to search files for a specified pattern.
+
+config CONFIG_FEATURE_GREP_EGREP_ALIAS
+	bool "Support extended regular expressions (egrep & grep -E)"
+	default y
+	depends on CONFIG_GREP
+	help
+	  Enabled support for extended regular expressions.  Extended
+	  regular expressions allow for alternation (foo|bar), grouping,
+	  and various repetition operators.
+
+config CONFIG_FEATURE_GREP_FGREP_ALIAS
+	bool "Alias fgrep to grep -F"
+	default y
+	depends on CONFIG_GREP
+	help
+	  fgrep sees the search pattern as a normal string rather than
+	  regular expressions.
+	  grep -F is always builtin, this just creates the fgrep alias.
+
+config CONFIG_FEATURE_GREP_CONTEXT
+	bool "Enable before and after context flags (-A, -B and -C)"
+	default y
+	depends on CONFIG_GREP
+	help
+	  Print the specified number of leading (-B) and/or trailing (-A)
+	  context surrounding our matching lines.
+	  Print the specified number of context lines (-C).
+
+config CONFIG_XARGS
+	bool "xargs"
+	default n
+	help
+	  xargs is used to execute a specified command on
+	  every item from standard input.
+
+config CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION
+	bool "Enable prompt and confirmation option -p"
+	default n
+	depends on CONFIG_XARGS
+	help
+	  Support prompt the user about whether to run each command
+	  line and read a line from the terminal.
+
+config CONFIG_FEATURE_XARGS_SUPPORT_QUOTES
+	bool "Enable support single and double quotes and backslash"
+	default n
+	depends on CONFIG_XARGS
+	help
+	  Default xargs unsupport single and double quotes
+	  and backslash for can use aruments with spaces.
+
+config CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT
+	bool "Enable support options -x"
+	default n
+	depends on CONFIG_XARGS
+	help
+	  Enable support exit if the size (see the -s or -n option)
+	  is exceeded.
+
+config CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM
+	bool "Enable options -0"
+	default n
+	depends on CONFIG_XARGS
+	help
+	  Enable input filenames are terminated by a null character
+	  instead of by whitespace, and the quotes and backslash
+	  are not special.
+
+endmenu

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/findutils
+FINDUTILS_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include $(srcdir)/Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,31 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+FINDUTILS_AR:=findutils.a
+ifndef $(FINDUTILS_DIR)
+FINDUTILS_DIR:=$(top_builddir)/findutils/
+endif
+srcdir=$(top_srcdir)/findutils
+
+FINDUTILS-y:=
+FINDUTILS-$(CONFIG_FIND)	+= find.o
+FINDUTILS-$(CONFIG_GREP)	+= grep.o
+FINDUTILS-$(CONFIG_XARGS)	+= xargs.o
+
+ifneq ($(strip $(FINDUTILS-y)),)
+libraries-y+=$(FINDUTILS_DIR)$(FINDUTILS_AR)
+endif
+
+FINDUTILS_SRC-y:=$(patsubst %.o,$(srcdir)/%.c,$(FINDUTILS-y))
+FINDUTILS_SRC-a:=$(wildcard $(srcdir)/*.c)
+APPLET_SRC-y+=$(FINDUTILS_SRC-y)
+APPLET_SRC-a+=$(FINDUTILS_SRC-a)
+
+$(FINDUTILS_DIR)$(FINDUTILS_AR): $(patsubst %,$(FINDUTILS_DIR)%, $(FINDUTILS-y))
+	$(do_ar)
+
+$(FINDUTILS_DIR)%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/find.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/find.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/find.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,337 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini find implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Reworked by David Douthitt <n9ubh at callsign.net> and
+ *  Matt Kraai <kraai at alumni.carnegiemellon.edu>.
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fnmatch.h>
+#include <time.h>
+#include <ctype.h>
+
+static char *pattern;
+#ifdef CONFIG_FEATURE_FIND_PRINT0
+static char printsep = '\n';
+#endif
+
+#ifdef CONFIG_FEATURE_FIND_TYPE
+static int type_mask = 0;
+#endif
+
+#ifdef CONFIG_FEATURE_FIND_PERM
+static char perm_char = 0;
+static int perm_mask = 0;
+#endif
+
+#ifdef CONFIG_FEATURE_FIND_MTIME
+static char mtime_char;
+static int mtime_days;
+#endif
+
+#ifdef CONFIG_FEATURE_FIND_MMIN
+static char mmin_char;
+static int mmin_mins;
+#endif
+
+#ifdef CONFIG_FEATURE_FIND_XDEV
+static dev_t *xdev_dev;
+static int xdev_count = 0;
+#endif
+
+#ifdef CONFIG_FEATURE_FIND_NEWER
+static time_t newer_mtime;
+#endif
+
+#ifdef CONFIG_FEATURE_FIND_INUM
+static ino_t inode_num;
+#endif
+
+#ifdef CONFIG_FEATURE_FIND_EXEC
+static char **exec_str;
+static int num_matches;
+static int exec_opt;
+#endif
+
+static int fileAction(const char *fileName, struct stat *statbuf, void* junk)
+{
+#ifdef CONFIG_FEATURE_FIND_XDEV
+	if (S_ISDIR(statbuf->st_mode) && xdev_count) {
+		int i;
+		for (i=0; i<xdev_count; i++) {
+			if (xdev_dev[i] != statbuf->st_dev)
+				return SKIP;
+		}
+	}
+#endif
+	if (pattern != NULL) {
+		const char *tmp = strrchr(fileName, '/');
+
+		if (tmp == NULL)
+			tmp = fileName;
+		else
+			tmp++;
+		if (!(fnmatch(pattern, tmp, FNM_PERIOD) == 0))
+			goto no_match;
+	}
+#ifdef CONFIG_FEATURE_FIND_TYPE
+	if (type_mask != 0) {
+		if (!((statbuf->st_mode & S_IFMT) == type_mask))
+			goto no_match;
+	}
+#endif
+#ifdef CONFIG_FEATURE_FIND_PERM
+	if (perm_mask != 0) {
+		if (!((isdigit(perm_char) && (statbuf->st_mode & 07777) == perm_mask) ||
+			 (perm_char == '-' && (statbuf->st_mode & perm_mask) == perm_mask) ||
+			 (perm_char == '+' && (statbuf->st_mode & perm_mask) != 0)))
+			goto no_match;
+	}
+#endif
+#ifdef CONFIG_FEATURE_FIND_MTIME
+	if (mtime_char != 0) {
+		time_t file_age = time(NULL) - statbuf->st_mtime;
+		time_t mtime_secs = mtime_days * 24 * 60 * 60;
+		if (!((isdigit(mtime_char) && file_age >= mtime_secs &&
+						file_age < mtime_secs + 24 * 60 * 60) ||
+				(mtime_char == '+' && file_age >= mtime_secs + 24 * 60 * 60) ||
+				(mtime_char == '-' && file_age < mtime_secs)))
+			goto no_match;
+	}
+#endif
+#ifdef CONFIG_FEATURE_FIND_MMIN
+	if (mmin_char != 0) {
+		time_t file_age = time(NULL) - statbuf->st_mtime;
+		time_t mmin_secs = mmin_mins * 60;
+		if (!((isdigit(mmin_char) && file_age >= mmin_secs &&
+						file_age < mmin_secs + 60) ||
+				(mmin_char == '+' && file_age >= mmin_secs + 60) ||
+				(mmin_char == '-' && file_age < mmin_secs)))
+			goto no_match;
+	}
+#endif
+#ifdef CONFIG_FEATURE_FIND_NEWER
+	if (newer_mtime != 0) {
+		time_t file_age = newer_mtime - statbuf->st_mtime;
+		if (file_age >= 0)
+			goto no_match;
+	}
+#endif
+#ifdef CONFIG_FEATURE_FIND_INUM
+	if (inode_num != 0) {
+		if (!(statbuf->st_ino == inode_num))
+			goto no_match;
+	}
+#endif
+#ifdef CONFIG_FEATURE_FIND_EXEC
+	if (exec_opt) {
+		int i;
+		char *cmd_string = "";
+		for (i = 0; i < num_matches; i++)
+			cmd_string = bb_xasprintf("%s%s%s", cmd_string, exec_str[i], fileName);
+		cmd_string = bb_xasprintf("%s%s", cmd_string, exec_str[num_matches]);
+		system(cmd_string);
+		goto no_match;
+	}
+#endif
+
+#ifdef CONFIG_FEATURE_FIND_PRINT0
+	printf("%s%c", fileName, printsep);
+#else
+	puts(fileName);
+#endif
+no_match:
+	return (TRUE);
+}
+
+#ifdef CONFIG_FEATURE_FIND_TYPE
+static int find_type(char *type)
+{
+	int mask = 0;
+
+	switch (type[0]) {
+		case 'b':
+			mask = S_IFBLK;
+			break;
+		case 'c':
+			mask = S_IFCHR;
+			break;
+		case 'd':
+			mask = S_IFDIR;
+			break;
+		case 'p':
+			mask = S_IFIFO;
+			break;
+		case 'f':
+			mask = S_IFREG;
+			break;
+		case 'l':
+			mask = S_IFLNK;
+			break;
+		case 's':
+			mask = S_IFSOCK;
+			break;
+	}
+
+	if (mask == 0 || type[1] != '\0')
+		bb_error_msg_and_die(bb_msg_invalid_arg, type, "-type");
+
+	return mask;
+}
+#endif
+
+int find_main(int argc, char **argv)
+{
+	int dereference = FALSE;
+	int i, firstopt, status = EXIT_SUCCESS;
+
+	for (firstopt = 1; firstopt < argc; firstopt++) {
+		if (argv[firstopt][0] == '-')
+			break;
+	}
+
+	/* Parse any options */
+	for (i = firstopt; i < argc; i++) {
+		if (strcmp(argv[i], "-follow") == 0)
+			dereference = TRUE;
+		else if (strcmp(argv[i], "-print") == 0) {
+			;
+			}
+#ifdef CONFIG_FEATURE_FIND_PRINT0
+		else if (strcmp(argv[i], "-print0") == 0)
+			printsep = '\0';
+#endif
+		else if (strcmp(argv[i], "-name") == 0) {
+			if (++i == argc)
+				bb_error_msg_and_die(bb_msg_requires_arg, "-name");
+			pattern = argv[i];
+#ifdef CONFIG_FEATURE_FIND_TYPE
+		} else if (strcmp(argv[i], "-type") == 0) {
+			if (++i == argc)
+				bb_error_msg_and_die(bb_msg_requires_arg, "-type");
+			type_mask = find_type(argv[i]);
+#endif
+#ifdef CONFIG_FEATURE_FIND_PERM
+		} else if (strcmp(argv[i], "-perm") == 0) {
+			char *end;
+			if (++i == argc)
+				bb_error_msg_and_die(bb_msg_requires_arg, "-perm");
+			perm_mask = strtol(argv[i], &end, 8);
+			if ((end[0] != '\0') || (perm_mask > 07777))
+				bb_error_msg_and_die(bb_msg_invalid_arg, argv[i], "-perm");
+			if ((perm_char = argv[i][0]) == '-')
+				perm_mask = -perm_mask;
+#endif
+#ifdef CONFIG_FEATURE_FIND_MTIME
+		} else if (strcmp(argv[i], "-mtime") == 0) {
+			char *end;
+			if (++i == argc)
+				bb_error_msg_and_die(bb_msg_requires_arg, "-mtime");
+			mtime_days = strtol(argv[i], &end, 10);
+			if (end[0] != '\0')
+				bb_error_msg_and_die(bb_msg_invalid_arg, argv[i], "-mtime");
+			if ((mtime_char = argv[i][0]) == '-')
+				mtime_days = -mtime_days;
+#endif
+#ifdef CONFIG_FEATURE_FIND_MMIN
+		} else if (strcmp(argv[i], "-mmin") == 0) {
+			char *end;
+			if (++i == argc)
+				bb_error_msg_and_die(bb_msg_requires_arg, "-mmin");
+			mmin_mins = strtol(argv[i], &end, 10);
+			if (end[0] != '\0')
+				bb_error_msg_and_die(bb_msg_invalid_arg, argv[i], "-mmin");
+			if ((mmin_char = argv[i][0]) == '-')
+				mmin_mins = -mmin_mins;
+#endif
+#ifdef CONFIG_FEATURE_FIND_XDEV
+		} else if (strcmp(argv[i], "-xdev") == 0) {
+			struct stat stbuf;
+
+			xdev_count = ( firstopt - 1 ) ? ( firstopt - 1 ) : 1;
+			xdev_dev = xmalloc ( xdev_count * sizeof( dev_t ));
+
+			if ( firstopt == 1 ) {
+				xstat ( ".", &stbuf );
+				xdev_dev [0] = stbuf. st_dev;
+			}
+			else {
+
+				for (i = 1; i < firstopt; i++) {
+					xstat ( argv [i], &stbuf );
+					xdev_dev [i-1] = stbuf. st_dev;
+				}
+			}
+#endif
+#ifdef CONFIG_FEATURE_FIND_NEWER
+		} else if (strcmp(argv[i], "-newer") == 0) {
+			struct stat stat_newer;
+			if (++i == argc)
+				bb_error_msg_and_die(bb_msg_requires_arg, "-newer");
+			xstat (argv[i], &stat_newer);
+			newer_mtime = stat_newer.st_mtime;
+#endif
+#ifdef CONFIG_FEATURE_FIND_INUM
+		} else if (strcmp(argv[i], "-inum") == 0) {
+			char *end;
+			if (++i == argc)
+				bb_error_msg_and_die(bb_msg_requires_arg, "-inum");
+			inode_num = strtol(argv[i], &end, 10);
+			if (end[0] != '\0')
+				bb_error_msg_and_die(bb_msg_invalid_arg, argv[i], "-inum");
+#endif
+#ifdef CONFIG_FEATURE_FIND_EXEC
+		} else if (strcmp(argv[i], "-exec") == 0) {
+			int b_pos;
+			char *cmd_string = "";
+
+			while (i++) {
+				if (i == argc)
+					bb_error_msg_and_die(bb_msg_requires_arg, "-exec");
+				if (*argv[i] == ';')
+					break;
+				cmd_string = bb_xasprintf("%s %s", cmd_string, argv[i]);
+			}
+
+			if (*cmd_string == 0)
+				bb_error_msg_and_die(bb_msg_requires_arg, "-exec");
+			cmd_string++;
+			exec_str = xmalloc(sizeof(char *));
+
+			while ((b_pos = strstr(cmd_string, "{}") - cmd_string), (b_pos >= 0)) {
+				num_matches++;
+				exec_str = xrealloc(exec_str, (num_matches + 1) * sizeof(char *));
+				exec_str[num_matches - 1] = bb_xstrndup(cmd_string, b_pos);
+				cmd_string += b_pos + 2;
+			}
+			exec_str[num_matches] = bb_xstrdup(cmd_string);
+			exec_opt = 1;
+#endif
+		} else
+			bb_show_usage();
+	}
+
+	if (firstopt == 1) {
+		if (! recursive_action(".", TRUE, dereference, FALSE, fileAction,
+					fileAction, NULL))
+			status = EXIT_FAILURE;
+	} else {
+		for (i = 1; i < firstopt; i++) {
+			if (! recursive_action(argv[i], TRUE, dereference, FALSE, fileAction,
+						fileAction, NULL))
+				status = EXIT_FAILURE;
+		}
+	}
+
+	return status;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/grep.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/grep.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/grep.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,438 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini grep implementation for busybox using libc regex.
+ *
+ * Copyright (C) 1999,2000,2001 by Lineo, inc. and Mark Whitley
+ * Copyright (C) 1999,2000,2001 by Mark Whitley <markw at codepoet.org>
+ *
+ * Licensed under the GPL v2, see the file LICENSE in this tarball.
+ */
+/* BB_AUDIT SUSv3 defects - unsupported option -x.  */
+/* BB_AUDIT GNU defects - always acts as -a.  */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/grep.html */
+/*
+ * 2004,2006 (C) Vladimir Oleynik <dzo at simtreas.ru> -
+ * correction "-e pattern1 -e pattern2" logic and more optimizations.
+ * precompiled regex
+*/
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include <errno.h>
+#include "xregex.h"
+
+
+/* options */
+static unsigned long opt;
+#define GREP_OPTS "lnqvscFiHhe:f:L"
+#define GREP_OPT_l (1<<0)
+#define PRINT_FILES_WITH_MATCHES (opt & GREP_OPT_l)
+#define GREP_OPT_n (1<<1)
+#define PRINT_LINE_NUM (opt & GREP_OPT_n)
+#define GREP_OPT_q (1<<2)
+#define BE_QUIET (opt & GREP_OPT_q)
+#define GREP_OPT_v (1<<3)
+typedef char invert_search_t;
+static invert_search_t invert_search;
+#define GREP_OPT_s (1<<4)
+#define SUPPRESS_ERR_MSGS (opt & GREP_OPT_s)
+#define GREP_OPT_c (1<<5)
+#define PRINT_MATCH_COUNTS (opt & GREP_OPT_c)
+#define GREP_OPT_F (1<<6)
+#define FGREP_FLAG (opt & GREP_OPT_F)
+#define GREP_OPT_i (1<<7)
+#define GREP_OPT_H (1<<8)
+#define GREP_OPT_h (1<<9)
+#define GREP_OPT_e (1<<10)
+#define GREP_OPT_f (1<<11)
+#define GREP_OPT_L (1<<12)
+#define PRINT_FILES_WITHOUT_MATCHES ((opt & GREP_OPT_L) != 0)
+#if ENABLE_FEATURE_GREP_CONTEXT
+#define GREP_OPT_CONTEXT "A:B:C"
+#define GREP_OPT_A (1<<13)
+#define GREP_OPT_B (1<<14)
+#define GREP_OPT_C (1<<15)
+#define GREP_OPT_E (1<<16)
+#else
+#define GREP_OPT_CONTEXT ""
+#define GREP_OPT_A (0)
+#define GREP_OPT_B (0)
+#define GREP_OPT_C (0)
+#define GREP_OPT_E (1<<13)
+#endif
+#if ENABLE_FEATURE_GREP_EGREP_ALIAS
+# define OPT_EGREP "E"
+#else
+# define OPT_EGREP ""
+#endif
+
+static int reflags;
+static int print_filename;
+
+#if ENABLE_FEATURE_GREP_CONTEXT
+static int lines_before;
+static int lines_after;
+static char **before_buf;
+static int last_line_printed;
+#endif /* ENABLE_FEATURE_GREP_CONTEXT */
+
+/* globals used internally */
+static llist_t *pattern_head;   /* growable list of patterns to match */
+static char *cur_file;          /* the current file we are reading */
+
+typedef struct GREP_LIST_DATA {
+	char *pattern;
+	regex_t preg;
+#define PATTERN_MEM_A 1
+#define COMPILED 2
+	int flg_mem_alocated_compiled;
+} grep_list_data_t;
+
+static void print_line(const char *line, int linenum, char decoration)
+{
+#if ENABLE_FEATURE_GREP_CONTEXT
+	/* possibly print the little '--' separator */
+	if ((lines_before || lines_after) && last_line_printed &&
+			last_line_printed < linenum - 1) {
+		puts("--");
+	}
+	last_line_printed = linenum;
+#endif
+	if (print_filename > 0)
+		printf("%s%c", cur_file, decoration);
+	if (PRINT_LINE_NUM)
+		printf("%i%c", linenum, decoration);
+	puts(line);
+}
+
+
+static int grep_file(FILE *file)
+{
+	char *line;
+	invert_search_t ret;
+	int linenum = 0;
+	int nmatches = 0;
+#if ENABLE_FEATURE_GREP_CONTEXT
+	int print_n_lines_after = 0;
+	int curpos = 0; /* track where we are in the circular 'before' buffer */
+	int idx = 0; /* used for iteration through the circular buffer */
+#endif /* ENABLE_FEATURE_GREP_CONTEXT */
+
+	while ((line = bb_get_chomped_line_from_file(file)) != NULL) {
+		llist_t *pattern_ptr = pattern_head;
+		grep_list_data_t * gl;
+
+		linenum++;
+		ret = 0;
+		while (pattern_ptr) {
+			gl = (grep_list_data_t *)pattern_ptr->data;
+			if (FGREP_FLAG) {
+				ret = strstr(line, gl->pattern) != NULL;
+			} else {
+				/*
+				 * test for a postitive-assertion match (regexec returns success (0)
+				 * and the user did not specify invert search), or a negative-assertion
+				 * match (regexec returns failure (REG_NOMATCH) and the user specified
+				 * invert search)
+				 */
+				if(!(gl->flg_mem_alocated_compiled & COMPILED)) {
+					gl->flg_mem_alocated_compiled |= COMPILED;
+					xregcomp(&(gl->preg), gl->pattern, reflags);
+				}
+				ret |= regexec(&(gl->preg), line, 0, NULL, 0) == 0;
+			}
+			pattern_ptr = pattern_ptr->link;
+		} /* while (pattern_ptr) */
+
+		if ((ret ^ invert_search)) {
+
+			if (PRINT_FILES_WITH_MATCHES || BE_QUIET)
+				free(line);
+
+			/* if we found a match but were told to be quiet, stop here */
+			if (BE_QUIET || PRINT_FILES_WITHOUT_MATCHES)
+				return -1;
+
+				/* keep track of matches */
+				nmatches++;
+
+				/* if we're just printing filenames, we stop after the first match */
+				if (PRINT_FILES_WITH_MATCHES)
+					break;
+
+				/* print the matched line */
+				if (PRINT_MATCH_COUNTS == 0) {
+#if ENABLE_FEATURE_GREP_CONTEXT
+					int prevpos = (curpos == 0) ? lines_before - 1 : curpos - 1;
+
+					/* if we were told to print 'before' lines and there is at least
+					 * one line in the circular buffer, print them */
+					if (lines_before && before_buf[prevpos] != NULL) {
+						int first_buf_entry_line_num = linenum - lines_before;
+
+						/* advance to the first entry in the circular buffer, and
+						 * figure out the line number is of the first line in the
+						 * buffer */
+						idx = curpos;
+						while (before_buf[idx] == NULL) {
+							idx = (idx + 1) % lines_before;
+							first_buf_entry_line_num++;
+						}
+
+						/* now print each line in the buffer, clearing them as we go */
+						while (before_buf[idx] != NULL) {
+							print_line(before_buf[idx], first_buf_entry_line_num, '-');
+							free(before_buf[idx]);
+							before_buf[idx] = NULL;
+							idx = (idx + 1) % lines_before;
+							first_buf_entry_line_num++;
+						}
+					}
+
+					/* make a note that we need to print 'after' lines */
+					print_n_lines_after = lines_after;
+#endif
+					print_line(line, linenum, ':');
+				}
+			}
+#if ENABLE_FEATURE_GREP_CONTEXT
+			else { /* no match */
+				/* Add the line to the circular 'before' buffer */
+				if(lines_before) {
+					free(before_buf[curpos]);
+					before_buf[curpos] = bb_xstrdup(line);
+					curpos = (curpos + 1) % lines_before;
+				}
+			}
+
+			/* if we need to print some context lines after the last match, do so */
+			if (print_n_lines_after && (last_line_printed != linenum)) {
+				print_line(line, linenum, '-');
+				print_n_lines_after--;
+			}
+#endif /* ENABLE_FEATURE_GREP_CONTEXT */
+		free(line);
+	}
+
+
+	/* special-case file post-processing for options where we don't print line
+	 * matches, just filenames and possibly match counts */
+
+	/* grep -c: print [filename:]count, even if count is zero */
+	if (PRINT_MATCH_COUNTS) {
+		if (print_filename > 0)
+			printf("%s:", cur_file);
+		    printf("%d\n", nmatches);
+	}
+
+	/* grep -l: print just the filename, but only if we grepped the line in the file  */
+	if (PRINT_FILES_WITH_MATCHES && nmatches > 0) {
+		puts(cur_file);
+	}
+
+	/* grep -L: print just the filename, but only if we didn't grep the line in the file  */
+	if (PRINT_FILES_WITHOUT_MATCHES && nmatches == 0) {
+		puts(cur_file);
+	}
+
+	return nmatches;
+}
+
+#if ENABLE_FEATURE_CLEAN_UP
+#define new_grep_list_data(p, m) add_grep_list_data(p, m)
+static char * add_grep_list_data(char *pattern, int flg_used_mem)
+#else
+#define new_grep_list_data(p, m) add_grep_list_data(p)
+static char * add_grep_list_data(char *pattern)
+#endif
+{
+	grep_list_data_t *gl = xmalloc(sizeof(grep_list_data_t));
+	gl->pattern = pattern;
+#if ENABLE_FEATURE_CLEAN_UP
+	gl->flg_mem_alocated_compiled = flg_used_mem;
+#else
+	gl->flg_mem_alocated_compiled = 0;
+#endif
+	return (char *)gl;
+}
+
+
+static void load_regexes_from_file(llist_t *fopt)
+{
+	char *line;
+	FILE *f;
+
+	while(fopt) {
+		llist_t *cur = fopt;
+		char *ffile = cur->data;
+
+		fopt = cur->link;
+		free(cur);
+		f = bb_xfopen(ffile, "r");
+		while ((line = bb_get_chomped_line_from_file(f)) != NULL) {
+			llist_add_to(&pattern_head,
+				new_grep_list_data(line, PATTERN_MEM_A));
+		}
+	}
+}
+
+
+int grep_main(int argc, char **argv)
+{
+	FILE *file;
+	int matched;
+	llist_t *fopt = NULL;
+	int error_open_count = 0;
+
+	/* do normal option parsing */
+#if ENABLE_FEATURE_GREP_CONTEXT
+  {
+	char *junk;
+	char *slines_after;
+	char *slines_before;
+	char *Copt;
+
+	bb_opt_complementally = "H-h:e::f::C-AB";
+	opt = bb_getopt_ulflags(argc, argv,
+		GREP_OPTS GREP_OPT_CONTEXT OPT_EGREP,
+		&pattern_head, &fopt,
+		&slines_after, &slines_before, &Copt);
+
+	if(opt & GREP_OPT_C) {
+		/* C option unseted A and B options, but next -A or -B
+		   may be ovewrite own option */
+		if(!(opt & GREP_OPT_A))         /* not overwtited */
+			slines_after = Copt;
+		if(!(opt & GREP_OPT_B))         /* not overwtited */
+			slines_before = Copt;
+		opt |= GREP_OPT_A|GREP_OPT_B;   /* set for parse now */
+	}
+	if(opt & GREP_OPT_A) {
+		lines_after = strtoul(slines_after, &junk, 10);
+		if(*junk != '\0')
+			bb_error_msg_and_die(bb_msg_invalid_arg, slines_after, "-A");
+	}
+	if(opt & GREP_OPT_B) {
+		lines_before = strtoul(slines_before, &junk, 10);
+		if(*junk != '\0')
+			bb_error_msg_and_die(bb_msg_invalid_arg, slines_before, "-B");
+	}
+	/* sanity checks after parse may be invalid numbers ;-) */
+	if ((opt & (GREP_OPT_c|GREP_OPT_q|GREP_OPT_l|GREP_OPT_L))) {
+		opt &= ~GREP_OPT_n;
+		lines_before = 0;
+		lines_after = 0;
+	} else if(lines_before > 0)
+		before_buf = (char **)xcalloc(lines_before, sizeof(char *));
+  }
+#else
+	/* with auto sanity checks */
+	bb_opt_complementally = "H-h:e::f::c-n:q-n:l-n";
+	opt = bb_getopt_ulflags(argc, argv, GREP_OPTS OPT_EGREP,
+		&pattern_head, &fopt);
+#endif
+	invert_search = (opt & GREP_OPT_v) != 0;        /* 0 | 1 */
+
+	if(opt & GREP_OPT_H)
+		print_filename++;
+	if(opt & GREP_OPT_h)
+		print_filename--;
+	if (pattern_head != NULL) {
+		/* convert char *argv[] to grep_list_data_t */
+		llist_t *cur;
+
+		for(cur = pattern_head; cur; cur = cur->link)
+			cur->data = new_grep_list_data(cur->data, 0);
+	}
+	if(opt & GREP_OPT_f)
+		load_regexes_from_file(fopt);
+
+	if(ENABLE_FEATURE_GREP_FGREP_ALIAS && bb_applet_name[0] == 'f')
+		opt |= GREP_OPT_F;
+
+	if(ENABLE_FEATURE_GREP_EGREP_ALIAS &&
+			(bb_applet_name[0] == 'e' || (opt & GREP_OPT_E)))
+		reflags = REG_EXTENDED | REG_NOSUB;
+	else
+		reflags = REG_NOSUB;
+
+	if(opt & GREP_OPT_i)
+		reflags |= REG_ICASE;
+
+	argv += optind;
+	argc -= optind;
+
+	/* if we didn't get a pattern from a -e and no command file was specified,
+	 * argv[optind] should be the pattern. no pattern, no worky */
+	if (pattern_head == NULL) {
+		if (*argv == NULL)
+			bb_show_usage();
+		else {
+			char *pattern = new_grep_list_data(*argv++, 0);
+
+			llist_add_to(&pattern_head, pattern);
+			argc--;
+		}
+	}
+
+	/* argv[(optind)..(argc-1)] should be names of file to grep through. If
+	 * there is more than one file to grep, we will print the filenames */
+	if (argc > 1) {
+		print_filename++;
+
+	/* If no files were specified, or '-' was specified, take input from
+	 * stdin. Otherwise, we grep through all the files specified. */
+	} else if (argc == 0) {
+		argc++;
+	}
+	matched = 0;
+	while (argc--) {
+		cur_file = *argv++;
+		if(!cur_file || (*cur_file == '-' && !cur_file[1])) {
+			cur_file = "(standard input)";
+			file = stdin;
+		} else {
+			file = fopen(cur_file, "r");
+		}
+		if (file == NULL) {
+			if (!SUPPRESS_ERR_MSGS)
+				bb_perror_msg("%s", cur_file);
+			error_open_count++;
+		} else {
+			matched += grep_file(file);
+			if(matched < 0) {
+				/* we found a match but were told to be quiet, stop here and
+				* return success */
+				break;
+			}
+			fclose(file);
+		}
+	}
+
+	/* destroy all the elments in the pattern list */
+	if (ENABLE_FEATURE_CLEAN_UP) {
+		while (pattern_head) {
+			llist_t *pattern_head_ptr = pattern_head;
+			grep_list_data_t *gl =
+				(grep_list_data_t *)pattern_head_ptr->data;
+
+			pattern_head = pattern_head->link;
+			if((gl->flg_mem_alocated_compiled & PATTERN_MEM_A))
+				free(gl->pattern);
+			if((gl->flg_mem_alocated_compiled & COMPILED))
+				regfree(&(gl->preg));
+			free(pattern_head_ptr);
+		}
+	}
+	/* 0 = success, 1 = failed, 2 = error */
+	/* If the -q option is specified, the exit status shall be zero
+	 * if an input line is selected, even if an error was detected.  */
+	if(BE_QUIET && matched)
+		return 0;
+	if(error_open_count)
+		return 2;
+	return !matched; /* invert return value 0 = success, 1 = failed */
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/xargs.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/xargs.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/findutils/xargs.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,573 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini xargs implementation for busybox
+ * Options are supported: "-prtx -n max_arg -s max_chars -e[ouf_str]"
+ *
+ * (C) 2002,2003 by Vladimir Oleynik <dzo at simtreas.ru>
+ *
+ * Special thanks
+ * - Mark Whitley and Glenn McGrath for stimulus to rewrite :)
+ * - Mike Rendell <michael at cs.mun.ca>
+ * and David MacKenzie <djm at gnu.ai.mit.edu>.
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ * xargs is described in the Single Unix Specification v3 at
+ * http://www.opengroup.org/onlinepubs/007904975/utilities/xargs.html
+ *
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+/* COMPAT:  SYSV version defaults size (and has a max value of) to 470.
+   We try to make it as large as possible. */
+#if !defined(ARG_MAX) && defined(_SC_ARG_MAX)
+#define ARG_MAX sysconf (_SC_ARG_MAX)
+#endif
+#ifndef ARG_MAX
+#define ARG_MAX 470
+#endif
+
+
+#ifdef TEST
+# ifndef CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION
+#  define CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION
+# endif
+# ifndef CONFIG_FEATURE_XARGS_SUPPORT_QUOTES
+#  define CONFIG_FEATURE_XARGS_SUPPORT_QUOTES
+# endif
+# ifndef CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT
+#  define CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT
+# endif
+# ifndef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM
+#  define CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM
+# endif
+#endif
+
+/*
+   This function have special algorithm.
+   Don`t use fork and include to main!
+*/
+static int xargs_exec(char *const *args)
+{
+	pid_t p;
+	volatile int exec_errno = 0;    /* shared vfork stack */
+
+	if ((p = vfork()) >= 0) {
+		if (p == 0) {
+			/* vfork -- child */
+			execvp(args[0], args);
+			exec_errno = errno;     /* set error to shared stack */
+			_exit(1);
+		} else {
+			/* vfork -- parent */
+			int status;
+
+			while (wait(&status) == (pid_t) - 1)
+				if (errno != EINTR)
+					break;
+			if (exec_errno) {
+				errno = exec_errno;
+				bb_perror_msg("%s", args[0]);
+				return exec_errno == ENOENT ? 127 : 126;
+			} else {
+				if (WEXITSTATUS(status) == 255) {
+					bb_error_msg("%s: exited with status 255; aborting", args[0]);
+					return 124;
+				}
+				if (WIFSTOPPED(status)) {
+					bb_error_msg("%s: stopped by signal %d",
+						args[0], WSTOPSIG(status));
+					return 125;
+				}
+				if (WIFSIGNALED(status)) {
+					bb_error_msg("%s: terminated by signal %d",
+						args[0], WTERMSIG(status));
+					return 125;
+				}
+				if (WEXITSTATUS(status) != 0)
+					return 123;
+				return 0;
+			}
+		}
+	} else {
+		bb_perror_msg_and_die("vfork");
+	}
+}
+
+
+typedef struct xlist_s {
+	char *data;
+	size_t lenght;
+	struct xlist_s *link;
+} xlist_t;
+
+static int eof_stdin_detected;
+
+#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+#define ISSPACE(c) (ISBLANK (c) || (c) == '\n' || (c) == '\r' \
+		    || (c) == '\f' || (c) == '\v')
+
+#ifdef CONFIG_FEATURE_XARGS_SUPPORT_QUOTES
+static xlist_t *process_stdin(xlist_t * list_arg,
+	const char *eof_str, size_t mc, char *buf)
+{
+#define NORM      0
+#define QUOTE     1
+#define BACKSLASH 2
+#define SPACE     4
+
+	char *s = NULL;         /* start word */
+	char *p = NULL;         /* pointer to end word */
+	char q = 0;             /* quote char */
+	char state = NORM;
+	char eof_str_detected = 0;
+	size_t line_l = 0;      /* size loaded args line */
+	int c;                  /* current char */
+	xlist_t *cur;
+	xlist_t *prev;
+
+	for (prev = cur = list_arg; cur; cur = cur->link) {
+		line_l += cur->lenght;  /* previous allocated */
+		if (prev != cur)
+			prev = prev->link;
+	}
+
+	while (!eof_stdin_detected) {
+		c = getchar();
+		if (c == EOF) {
+			eof_stdin_detected++;
+			if (s)
+				goto unexpected_eof;
+			break;
+		}
+		if (eof_str_detected)
+			continue;
+		if (state == BACKSLASH) {
+			state = NORM;
+			goto set;
+		} else if (state == QUOTE) {
+			if (c == q) {
+				q = 0;
+				state = NORM;
+			} else {
+				goto set;
+			}
+		} else { /* if(state == NORM) */
+
+			if (ISSPACE(c)) {
+				if (s) {
+unexpected_eof:
+					state = SPACE;
+					c = 0;
+					goto set;
+				}
+			} else {
+				if (s == NULL)
+					s = p = buf;
+				if (c == '\\') {
+					state = BACKSLASH;
+				} else if (c == '\'' || c == '"') {
+					q = c;
+					state = QUOTE;
+				} else {
+set:
+					if ((size_t)(p - buf) >= mc)
+						bb_error_msg_and_die("argument line too long");
+					*p++ = c;
+				}
+			}
+		}
+		if (state == SPACE) {   /* word's delimiter or EOF detected */
+			if (q) {
+				bb_error_msg_and_die("unmatched %s quote",
+					q == '\'' ? "single" : "double");
+			}
+			/* word loaded */
+			if (eof_str) {
+				eof_str_detected = strcmp(s, eof_str) == 0;
+			}
+			if (!eof_str_detected) {
+				size_t lenght = (p - buf);
+
+				cur = xmalloc(sizeof(xlist_t) + lenght);
+				cur->data = memcpy(cur + 1, s, lenght);
+				cur->lenght = lenght;
+				cur->link = NULL;
+				if (prev == NULL) {
+					list_arg = cur;
+				} else {
+					prev->link = cur;
+				}
+				prev = cur;
+				line_l += lenght;
+				if (line_l > mc) {
+					/* stop memory usage :-) */
+					break;
+				}
+			}
+			s = NULL;
+			state = NORM;
+		}
+	}
+	return list_arg;
+}
+#else
+/* The variant does not support single quotes, double quotes or backslash */
+static xlist_t *process_stdin(xlist_t * list_arg,
+	const char *eof_str, size_t mc, char *buf)
+{
+
+	int c;                  /* current char */
+	int eof_str_detected = 0;
+	char *s = NULL;         /* start word */
+	char *p = NULL;         /* pointer to end word */
+	size_t line_l = 0;      /* size loaded args line */
+	xlist_t *cur;
+	xlist_t *prev;
+
+	for (prev = cur = list_arg; cur; cur = cur->link) {
+		line_l += cur->lenght;  /* previous allocated */
+		if (prev != cur)
+			prev = prev->link;
+	}
+
+	while (!eof_stdin_detected) {
+		c = getchar();
+		if (c == EOF) {
+			eof_stdin_detected++;
+		}
+		if (eof_str_detected)
+			continue;
+		if (c == EOF || ISSPACE(c)) {
+			if (s == NULL)
+				continue;
+			c = EOF;
+		}
+		if (s == NULL)
+			s = p = buf;
+		if ((p - buf) >= mc)
+			bb_error_msg_and_die("argument line too long");
+		*p++ = c == EOF ? 0 : c;
+		if (c == EOF) { /* word's delimiter or EOF detected */
+			/* word loaded */
+			if (eof_str) {
+				eof_str_detected = strcmp(s, eof_str) == 0;
+			}
+			if (!eof_str_detected) {
+				size_t lenght = (p - buf);
+
+				cur = xmalloc(sizeof(xlist_t) + lenght);
+				cur->data = memcpy(cur + 1, s, lenght);
+				cur->lenght = lenght;
+				cur->link = NULL;
+				if (prev == NULL) {
+					list_arg = cur;
+				} else {
+					prev->link = cur;
+				}
+				prev = cur;
+				line_l += lenght;
+				if (line_l > mc) {
+					/* stop memory usage :-) */
+					break;
+				}
+				s = NULL;
+			}
+		}
+	}
+	return list_arg;
+}
+#endif /* CONFIG_FEATURE_XARGS_SUPPORT_QUOTES */
+
+
+#ifdef CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION
+/* Prompt the user for a response, and
+   if the user responds affirmatively, return true;
+   otherwise, return false. Used "/dev/tty", not stdin. */
+static int xargs_ask_confirmation(void)
+{
+	static FILE *tty_stream;
+	int c, savec;
+
+	if (!tty_stream) {
+		tty_stream = bb_xfopen(CURRENT_TTY, "r");
+		/* pranoidal security by vodz */
+		fcntl(fileno(tty_stream), F_SETFD, FD_CLOEXEC);
+	}
+	fputs(" ?...", stderr);
+	fflush(stderr);
+	c = savec = getc(tty_stream);
+	while (c != EOF && c != '\n')
+		c = getc(tty_stream);
+	if (savec == 'y' || savec == 'Y')
+		return 1;
+	return 0;
+}
+
+# define OPT_INC_P 1
+#else
+# define OPT_INC_P 0
+# define xargs_ask_confirmation() 1
+#endif /* CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION */
+
+#ifdef CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT
+# define OPT_INC_X 1
+#else
+# define OPT_INC_X 0
+#endif
+
+#ifdef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM
+static xlist_t *process0_stdin(xlist_t * list_arg, const char *eof_str ATTRIBUTE_UNUSED,
+							   size_t mc, char *buf)
+{
+	int c;                  /* current char */
+	char *s = NULL;         /* start word */
+	char *p = NULL;         /* pointer to end word */
+	size_t line_l = 0;      /* size loaded args line */
+	xlist_t *cur;
+	xlist_t *prev;
+
+	for (prev = cur = list_arg; cur; cur = cur->link) {
+		line_l += cur->lenght;  /* previous allocated */
+		if (prev != cur)
+			prev = prev->link;
+	}
+
+	while (!eof_stdin_detected) {
+		c = getchar();
+		if (c == EOF) {
+			eof_stdin_detected++;
+			if (s == NULL)
+				break;
+			c = 0;
+		}
+		if (s == NULL)
+			s = p = buf;
+		if ((size_t)(p - buf) >= mc)
+			bb_error_msg_and_die("argument line too long");
+		*p++ = c;
+		if (c == 0) {   /* word's delimiter or EOF detected */
+			/* word loaded */
+			size_t lenght = (p - buf);
+
+			cur = xmalloc(sizeof(xlist_t) + lenght);
+			cur->data = memcpy(cur + 1, s, lenght);
+			cur->lenght = lenght;
+			cur->link = NULL;
+			if (prev == NULL) {
+				list_arg = cur;
+			} else {
+				prev->link = cur;
+			}
+			prev = cur;
+			line_l += lenght;
+			if (line_l > mc) {
+				/* stop memory usage :-) */
+				break;
+			}
+			s = NULL;
+		}
+	}
+	return list_arg;
+}
+
+# define READ_ARGS(l, e, nmc, mc) (*read_args)(l, e, nmc, mc)
+# define OPT_INC_0 1    /* future use */
+#else
+# define OPT_INC_0 0    /* future use */
+# define READ_ARGS(l, e, nmc, mc) process_stdin(l, e, nmc, mc)
+#endif /* CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM */
+
+
+#define OPT_VERBOSE     (1<<0)
+#define OPT_NO_EMPTY    (1<<1)
+#define OPT_UPTO_NUMBER (1<<2)
+#define OPT_UPTO_SIZE   (1<<3)
+#define OPT_EOF_STRING  (1<<4)
+#ifdef CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION
+#define OPT_INTERACTIVE (1<<5)
+#else
+#define OPT_INTERACTIVE (0)     /* require for algorithm &| */
+#endif
+#define OPT_TERMINATE   (1<<(5+OPT_INC_P))
+#define OPT_ZEROTERM    (1<<(5+OPT_INC_P+OPT_INC_X))
+/* next future
+#define OPT_NEXT_OTHER  (1<<(5+OPT_INC_P+OPT_INC_X+OPT_INC_0))
+*/
+
+int xargs_main(int argc, char **argv)
+{
+	char **args;
+	int i, a, n;
+	xlist_t *list = NULL;
+	xlist_t *cur;
+	int child_error = 0;
+	char *max_args, *max_chars;
+	int n_max_arg;
+	size_t n_chars = 0;
+	long orig_arg_max;
+	const char *eof_str = "_";
+	unsigned long opt;
+	size_t n_max_chars;
+
+#ifdef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM
+	xlist_t *(*read_args) (xlist_t *, const char *, size_t, char *) = process_stdin;
+#endif
+
+#ifdef CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION
+	bb_opt_complementally = "pt";
+#endif
+
+	opt = bb_getopt_ulflags(argc, argv, "+trn:s:e::"
+#ifdef CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION
+	"p"
+#endif
+#ifdef CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT
+	"x"
+#endif
+#ifdef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM
+	"0"
+#endif
+	,&max_args, &max_chars, &eof_str);
+
+	a = argc - optind;
+	argv += optind;
+	if (a == 0) {
+		/* default behavior is to echo all the filenames */
+		*argv = "echo";
+		a++;
+	}
+
+	orig_arg_max = ARG_MAX;
+	if (orig_arg_max == -1)
+		orig_arg_max = LONG_MAX;
+	orig_arg_max -= 2048;   /* POSIX.2 requires subtracting 2048.  */
+	if ((opt & OPT_UPTO_SIZE)) {
+		n_max_chars = bb_xgetularg10_bnd(max_chars, 1, orig_arg_max);
+		for (i = 0; i < a; i++) {
+			n_chars += strlen(*argv) + 1;
+		}
+		if (n_max_chars < n_chars) {
+			bb_error_msg_and_die("can not fit single argument within argument list size limit");
+		}
+		n_max_chars -= n_chars;
+	} else {
+		/* Sanity check for systems with huge ARG_MAX defines (e.g., Suns which
+		   have it at 1 meg).  Things will work fine with a large ARG_MAX but it
+		   will probably hurt the system more than it needs to; an array of this
+		   size is allocated.  */
+		if (orig_arg_max > 20 * 1024)
+			orig_arg_max = 20 * 1024;
+		n_max_chars = orig_arg_max;
+	}
+	max_chars = xmalloc(n_max_chars);
+
+	if ((opt & OPT_UPTO_NUMBER)) {
+		n_max_arg = bb_xgetularg10_bnd(max_args, 1, INT_MAX);
+	} else {
+		n_max_arg = n_max_chars;
+	}
+
+#ifdef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM
+	if (opt & OPT_ZEROTERM)
+		read_args = process0_stdin;
+#endif
+
+	while ((list = READ_ARGS(list, eof_str, n_max_chars, max_chars)) != NULL ||
+		(opt & OPT_NO_EMPTY) == 0)
+	{
+		opt |= OPT_NO_EMPTY;
+		n = 0;
+		n_chars = 0;
+#ifdef CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT
+		for (cur = list; cur;) {
+			n_chars += cur->lenght;
+			n++;
+			cur = cur->link;
+			if (n_chars > n_max_chars || (n == n_max_arg && cur)) {
+				if (opt & OPT_TERMINATE)
+					bb_error_msg_and_die("argument list too long");
+				break;
+			}
+		}
+#else
+		for (cur = list; cur; cur = cur->link) {
+			n_chars += cur->lenght;
+			n++;
+			if (n_chars > n_max_chars || n == n_max_arg) {
+				break;
+			}
+		}
+#endif /* CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT */
+
+		/* allocating pointers for execvp:
+		   a*arg, n*arg from stdin, NULL */
+		args = xcalloc(n + a + 1, sizeof(char *));
+
+		/* Store the command to be executed
+		   (taken from the command line) */
+		for (i = 0; i < a; i++)
+			args[i] = argv[i];
+		/* (taken from stdin) */
+		for (cur = list; n; cur = cur->link) {
+			args[i++] = cur->data;
+			n--;
+		}
+
+		if ((opt & (OPT_INTERACTIVE | OPT_VERBOSE))) {
+			for (i = 0; args[i]; i++) {
+				if (i)
+					fputc(' ', stderr);
+				fputs(args[i], stderr);
+			}
+			if ((opt & OPT_INTERACTIVE) == 0)
+				fputc('\n', stderr);
+		}
+		if ((opt & OPT_INTERACTIVE) == 0 || xargs_ask_confirmation() != 0) {
+			child_error = xargs_exec(args);
+		}
+
+		/* clean up */
+		for (i = a; args[i]; i++) {
+			cur = list;
+			list = list->link;
+			free(cur);
+		}
+		free(args);
+		if (child_error > 0 && child_error != 123) {
+			break;
+		}
+	}
+#ifdef CONFIG_FEATURE_CLEAN_UP
+	free(max_chars);
+#endif
+	return child_error;
+}
+
+
+#ifdef TEST
+
+const char *bb_applet_name = "debug stuff usage";
+
+void bb_show_usage(void)
+{
+	fprintf(stderr, "Usage: %s [-p] [-r] [-t] -[x] [-n max_arg] [-s max_chars]\n",
+		bb_applet_name);
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	return xargs_main(argc, argv);
+}
+#endif /* TEST */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/applets.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/applets.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/applets.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,310 @@
+/*
+ * applets.h - a listing of all busybox applets.
+ *
+ * If you write a new applet, you need to add an entry to this list to make
+ * busybox aware of it.
+ *
+ * It is CRUCIAL that this listing be kept in ascii order, otherwise the binary
+ * search lookup contributed by Gaute B Strokkenes stops working. If you value
+ * your kneecaps, you'll be sure to *make sure* that any changes made to this
+ * file result in the listing remaining in ascii order. You have been warned.
+ */
+
+#undef APPLET
+#undef APPLET_ODDNAME
+#undef APPLET_NOUSAGE
+
+
+#if defined(PROTOTYPES)
+# define APPLET(a,b,c) extern int a##_main(int argc, char **argv);
+# define APPLET_NOUSAGE(a,b,c,d) extern int b##_main(int argc, char **argv);
+# define APPLET_ODDNAME(a,b,c,d,e) extern int b##_main(int argc, char **argv);
+#elif defined(MAKE_USAGE)
+# ifdef CONFIG_FEATURE_VERBOSE_USAGE
+#  define APPLET(a,b,c) a##_trivial_usage "\n\n" a##_full_usage "\0"
+#  define APPLET_NOUSAGE(a,b,c,d) "\b\0"
+#  define APPLET_ODDNAME(a,b,c,d,e) e##_trivial_usage "\n\n" e##_full_usage "\0"
+# else
+#  define APPLET(a,b,c) a##_trivial_usage "\0"
+#  define APPLET_NOUSAGE(a,b,c,d) "\b\0"
+#  define APPLET_ODDNAME(a,b,c,d,e) e##_trivial_usage "\0"
+# endif
+#elif defined(MAKE_LINKS)
+# define APPLET(a,b,c) LINK b a
+# define APPLET_NOUSAGE(a,b,c,d) LINK c a
+# define APPLET_ODDNAME(a,b,c,d,e) LINK c a
+#else
+  const struct BB_applet applets[] = {
+# define APPLET(a,b,c) {#a,a##_main,b,c},
+# define APPLET_NOUSAGE(a,b,c,d) {#a,b##_main,c,d},
+# define APPLET_ODDNAME(a,b,c,d,e) {#a,b##_main,c,d},
+#endif
+
+#ifdef CONFIG_INSTALL_NO_USR
+# define _BB_DIR_USR_BIN _BB_DIR_BIN
+# define _BB_DIR_USR_SBIN _BB_DIR_SBIN
+#endif
+
+
+USE_TEST(APPLET_NOUSAGE([, test, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_TEST(APPLET_NOUSAGE([[, test, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_ADDGROUP(APPLET(addgroup, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_ADDUSER(APPLET(adduser, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_ADJTIMEX(APPLET(adjtimex, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_AR(APPLET(ar, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_ARPING(APPLET(arping, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_ASH(APPLET_NOUSAGE(ash, ash, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_AWK(APPLET(awk, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_BASENAME(APPLET(basename, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_BBCONFIG(APPLET(bbconfig, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_BUNZIP2(APPLET(bunzip2, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+/* Always enabled. */
+APPLET_NOUSAGE(busybox, busybox, _BB_DIR_BIN, _BB_SUID_MAYBE)
+USE_BUNZIP2(APPLET_ODDNAME(bzcat, bunzip2, _BB_DIR_USR_BIN, _BB_SUID_NEVER, bzcat))
+USE_CAL(APPLET(cal, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_CAT(APPLET(cat, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_CATV(APPLET(catv, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_CHATTR(APPLET(chattr, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_CHGRP(APPLET(chgrp, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_CHMOD(APPLET(chmod, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_CHOWN(APPLET(chown, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_CHROOT(APPLET(chroot, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
+USE_CHVT(APPLET(chvt, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_CKSUM(APPLET(cksum, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_CLEAR(APPLET(clear, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_CMP(APPLET(cmp, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_COMM(APPLET(comm, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_CP(APPLET(cp, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_CPIO(APPLET(cpio, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_CROND(APPLET(crond, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
+USE_CRONTAB(APPLET(crontab, _BB_DIR_USR_BIN, _BB_SUID_ALWAYS))
+USE_CUT(APPLET(cut, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_DATE(APPLET(date, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_DC(APPLET(dc, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_DD(APPLET(dd, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_DEALLOCVT(APPLET(deallocvt, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_DELGROUP(APPLET_ODDNAME(delgroup, deluser, _BB_DIR_BIN, _BB_SUID_NEVER, delgroup))
+USE_DELUSER(APPLET(deluser, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_DEVFSD(APPLET(devfsd, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_DF(APPLET(df, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_DIFF(APPLET(diff, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_DIRNAME(APPLET(dirname, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_DMESG(APPLET(dmesg, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_DNSD(APPLET(dnsd, _BB_DIR_USR_SBIN, _BB_SUID_ALWAYS))
+USE_DOS2UNIX(APPLET(dos2unix, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_DPKG(APPLET(dpkg, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_DPKG_DEB(APPLET_ODDNAME(dpkg-deb, dpkg_deb, _BB_DIR_USR_BIN, _BB_SUID_NEVER, dpkg_deb))
+USE_DU(APPLET(du, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_DUMPKMAP(APPLET(dumpkmap, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_APP_DUMPLEASES(APPLET(dumpleases, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_E2FSCK(APPLET(e2fsck, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_E2LABEL(APPLET_NOUSAGE(e2label, tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_ECHO(APPLET(echo, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_ED(APPLET(ed, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_FEATURE_GREP_EGREP_ALIAS(APPLET_NOUSAGE(egrep, grep, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_EJECT(APPLET(eject, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_ENV(APPLET(env, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_ETHER_WAKE(APPLET_ODDNAME(ether-wake, etherwake, _BB_DIR_USR_BIN, _BB_SUID_NEVER, ether_wake))
+USE_EXPR(APPLET(expr, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_FAKEIDENTD(APPLET(fakeidentd, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
+USE_FALSE(APPLET(false, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_FBSET(APPLET(fbset, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
+USE_FDFLUSH(APPLET_ODDNAME(fdflush, freeramdisk, _BB_DIR_BIN, _BB_SUID_NEVER, fdflush))
+USE_FDFORMAT(APPLET(fdformat, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_FDISK(APPLET(fdisk, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_FEATURE_GREP_FGREP_ALIAS(APPLET_NOUSAGE(fgrep, grep, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_FIND(APPLET(find, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_FINDFS(APPLET_NOUSAGE(findfs, tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_FOLD(APPLET(fold, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_FREE(APPLET(free, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_FREERAMDISK(APPLET(freeramdisk, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_FSCK(APPLET(fsck, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_E2FSCK(APPLET_NOUSAGE(fsck.ext2, e2fsck, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_E2FSCK(APPLET_NOUSAGE(fsck.ext3, e2fsck, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_FSCK_MINIX(APPLET_ODDNAME(fsck.minix, fsck_minix, _BB_DIR_SBIN, _BB_SUID_NEVER, fsck_minix))
+USE_FTPGET(APPLET_ODDNAME(ftpget, ftpgetput, _BB_DIR_USR_BIN, _BB_SUID_NEVER,ftpget))
+USE_FTPPUT(APPLET_ODDNAME(ftpput, ftpgetput, _BB_DIR_USR_BIN, _BB_SUID_NEVER,ftpput))
+USE_FUSER(APPLET(fuser, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_GETOPT(APPLET(getopt, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_GETTY(APPLET(getty, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_GREP(APPLET(grep, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_GUNZIP(APPLET(gunzip, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_GZIP(APPLET(gzip, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_HALT(APPLET(halt, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_HDPARM(APPLET(hdparm, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_HEAD(APPLET(head, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_HEXDUMP(APPLET(hexdump, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_HOSTID(APPLET(hostid, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_HOSTNAME(APPLET(hostname, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_HTTPD(APPLET(httpd, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
+USE_HUSH(APPLET_NOUSAGE(hush, hush, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_HWCLOCK(APPLET(hwclock, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_ID(APPLET(id, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_IFCONFIG(APPLET(ifconfig, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_IFUPDOWN(APPLET_ODDNAME(ifdown, ifupdown, _BB_DIR_SBIN, _BB_SUID_NEVER, ifdown))
+USE_IFUPDOWN(APPLET_ODDNAME(ifup, ifupdown, _BB_DIR_SBIN, _BB_SUID_NEVER, ifup))
+USE_INETD(APPLET(inetd, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
+USE_INIT(APPLET(init, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_INSMOD(APPLET(insmod, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_INSTALL(APPLET(install, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_IP(APPLET(ip, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_IPADDR(APPLET(ipaddr, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_IPCALC(APPLET(ipcalc, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_IPCRM(APPLET(ipcrm, _BB_DIR_USR_BIN, _BB_SUID_ALWAYS))
+USE_IPCS(APPLET(ipcs, _BB_DIR_USR_BIN, _BB_SUID_ALWAYS))
+USE_IPLINK(APPLET(iplink, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_IPROUTE(APPLET(iproute, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_IPTUNNEL(APPLET(iptunnel, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_KILL(APPLET(kill, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_KILLALL(APPLET_ODDNAME(killall, kill, _BB_DIR_USR_BIN, _BB_SUID_NEVER, killall))
+USE_KLOGD(APPLET(klogd, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_LASH(APPLET(lash, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_LAST(APPLET(last, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_LENGTH(APPLET(length, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_LESS(APPLET(less, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_SETARCH(APPLET_NOUSAGE(linux32, setarch, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_SETARCH(APPLET_NOUSAGE(linux64, setarch, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_FEATURE_INITRD(APPLET_NOUSAGE(linuxrc, init, _BB_DIR_ROOT, _BB_SUID_NEVER))
+USE_LN(APPLET(ln, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_LOADFONT(APPLET(loadfont, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_LOADKMAP(APPLET(loadkmap, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_LOGGER(APPLET(logger, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_LOGIN(APPLET(login, _BB_DIR_BIN, _BB_SUID_ALWAYS))
+USE_LOGNAME(APPLET(logname, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_LOGREAD(APPLET(logread, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_LOSETUP(APPLET(losetup, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_LS(APPLET(ls, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_LSATTR(APPLET(lsattr, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_LSMOD(APPLET(lsmod, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_UNLZMA(APPLET_ODDNAME(lzmacat, unlzma, _BB_DIR_USR_BIN, _BB_SUID_NEVER, lzmacat))
+USE_MAKEDEVS(APPLET(makedevs, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_MD5SUM(APPLET(md5sum, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_MDEV(APPLET(mdev, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_MESG(APPLET(mesg, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_MKDIR(APPLET(mkdir, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_MKE2FS(APPLET(mke2fs, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_MKFIFO(APPLET(mkfifo, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_MKE2FS(APPLET_NOUSAGE(mkfs.ext2, mke2fs, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_MKE2FS(APPLET_NOUSAGE(mkfs.ext3, mke2fs, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_MKFS_MINIX(APPLET_ODDNAME(mkfs.minix, mkfs_minix, _BB_DIR_SBIN, _BB_SUID_NEVER, mkfs_minix))
+USE_MKNOD(APPLET(mknod, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_MKSWAP(APPLET(mkswap, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_MKTEMP(APPLET(mktemp, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_MODPROBE(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_MORE(APPLET(more, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_MOUNT(APPLET(mount, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_MOUNTPOINT(APPLET(mountpoint, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_MSH(APPLET_NOUSAGE(msh, msh, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_MT(APPLET(mt, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_MV(APPLET(mv, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_NAMEIF(APPLET(nameif, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_NC(APPLET(nc, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_NETSTAT(APPLET(netstat, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_NICE(APPLET(nice, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_NOHUP(APPLET(nohup, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_NSLOOKUP(APPLET(nslookup, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_OD(APPLET(od, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_OPENVT(APPLET(openvt, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_PASSWD(APPLET(passwd, _BB_DIR_USR_BIN, _BB_SUID_ALWAYS))
+USE_PATCH(APPLET(patch, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_PIDOF(APPLET(pidof, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_PING(APPLET(ping, _BB_DIR_BIN, _BB_SUID_MAYBE))
+USE_PING6(APPLET(ping6, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_PIPE_PROGRESS(APPLET_NOUSAGE(pipe_progress, pipe_progress, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_PIVOT_ROOT(APPLET(pivot_root, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_HALT(APPLET_ODDNAME(poweroff, halt, _BB_DIR_SBIN, _BB_SUID_NEVER, poweroff))
+USE_PRINTENV(APPLET(printenv, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_PRINTF(APPLET(printf, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_PS(APPLET(ps, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_PWD(APPLET(pwd, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_RDATE(APPLET(rdate, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
+USE_READLINK(APPLET(readlink, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_READPROFILE(APPLET(readprofile, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
+USE_REALPATH(APPLET(realpath, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_HALT(APPLET_ODDNAME(reboot, halt, _BB_DIR_SBIN, _BB_SUID_NEVER, reboot))
+USE_RENICE(APPLET(renice, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_RESET(APPLET(reset, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_RM(APPLET(rm, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_RMDIR(APPLET(rmdir, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_RMMOD(APPLET(rmmod, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_ROUTE(APPLET(route, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_RPM(APPLET(rpm, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_RPM2CPIO(APPLET(rpm2cpio, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_RUN_PARTS(APPLET_ODDNAME(run-parts, run_parts, _BB_DIR_BIN, _BB_SUID_NEVER, run_parts))
+USE_RUNLEVEL(APPLET(runlevel, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_RX(APPLET(rx, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_SED(APPLET(sed, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_SEQ(APPLET(seq, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_SETARCH(APPLET(setarch, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_SETCONSOLE(APPLET(setconsole, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_SETKEYCODES(APPLET(setkeycodes, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_SETLOGCONS(APPLET(setlogcons, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
+USE_SETSID(APPLET(setsid, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_FEATURE_SH_IS_ASH(APPLET_NOUSAGE(sh, ash, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_FEATURE_SH_IS_HUSH(APPLET_NOUSAGE(sh, hush, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_FEATURE_SH_IS_LASH(APPLET_NOUSAGE(sh, lash, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_FEATURE_SH_IS_MSH(APPLET_NOUSAGE(sh, msh, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_SHA1SUM(APPLET(sha1sum, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_SLEEP(APPLET(sleep, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_SORT(APPLET(sort, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_START_STOP_DAEMON(APPLET_ODDNAME(start-stop-daemon, start_stop_daemon, _BB_DIR_SBIN, _BB_SUID_NEVER, start_stop_daemon))
+USE_STAT(APPLET(stat, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_STRINGS(APPLET(strings, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_STTY(APPLET(stty, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_SU(APPLET(su, _BB_DIR_BIN, _BB_SUID_ALWAYS))
+USE_SULOGIN(APPLET(sulogin, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_SUM(APPLET(sum, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_SWAPONOFF(APPLET_ODDNAME(swapoff, swap_on_off, _BB_DIR_SBIN, _BB_SUID_NEVER,swapoff))
+USE_SWAPONOFF(APPLET_ODDNAME(swapon, swap_on_off, _BB_DIR_SBIN, _BB_SUID_NEVER, swapon))
+USE_SWITCH_ROOT(APPLET(switch_root, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_SYNC(APPLET(sync, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_BB_SYSCTL(APPLET(sysctl, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_SYSLOGD(APPLET(syslogd, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_TAIL(APPLET(tail, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_TAR(APPLET(tar, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_TEE(APPLET(tee, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_TELNET(APPLET(telnet, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_TELNETD(APPLET(telnetd, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
+USE_TEST(APPLET(test, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_TFTP(APPLET(tftp, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_TIME(APPLET(time, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_TOP(APPLET(top, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_TOUCH(APPLET(touch, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_TR(APPLET(tr, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_TRACEROUTE(APPLET(traceroute, _BB_DIR_USR_BIN, _BB_SUID_MAYBE))
+USE_TRUE(APPLET(true, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_TTY(APPLET(tty, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_TUNE2FS(APPLET(tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_APP_UDHCPC(APPLET(udhcpc, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_APP_UDHCPD(APPLET(udhcpd, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
+USE_UMOUNT(APPLET(umount, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_UNAME(APPLET(uname, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_UNCOMPRESS(APPLET(uncompress, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_UNIQ(APPLET(uniq, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_UNIX2DOS(APPLET_ODDNAME(unix2dos, dos2unix, _BB_DIR_USR_BIN, _BB_SUID_NEVER, unix2dos))
+USE_UNLZMA(APPLET(unlzma, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_UNZIP(APPLET(unzip, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_UPTIME(APPLET(uptime, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_USLEEP(APPLET(usleep, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_UUDECODE(APPLET(uudecode, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_UUENCODE(APPLET(uuencode, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_VCONFIG(APPLET(vconfig, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_VI(APPLET(vi, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_VLOCK(APPLET(vlock, _BB_DIR_USR_BIN, _BB_SUID_ALWAYS))
+USE_WATCH(APPLET(watch, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_WATCHDOG(APPLET(watchdog, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_WC(APPLET(wc, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_WGET(APPLET(wget, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_WHICH(APPLET(which, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_WHO(APPLET(who, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_WHOAMI(APPLET(whoami, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_XARGS(APPLET(xargs, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_YES(APPLET(yes, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_GUNZIP(APPLET_ODDNAME(zcat, gunzip, _BB_DIR_BIN, _BB_SUID_NEVER, zcat))
+USE_ZCIP(APPLET(zcip, _BB_DIR_SBIN, _BB_SUID_NEVER))
+
+#if !defined(PROTOTYPES) && !defined(MAKE_USAGE)
+	{ 0,NULL,0,0 }
+};
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/bb_config.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/bb_config.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/bb_config.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2675 @@
+#ifndef BB_CONFIG_H
+#define BB_CONFIG_H
+/*
+ * Automatically generated header file: don't edit
+ */
+
+/* Version Number */
+#define BB_VER "1.2.1"
+#define BB_BT "2006.09.17-17:55+0000"
+
+#define HAVE_DOT_CONFIG 1
+#define ENABLE_DOT_CONFIG 1
+#define USE_DOT_CONFIG(...)  __VA_ARGS__
+#define SKIP_DOT_CONFIG(...)
+
+
+/*
+ * Busybox Settings
+ */
+
+/*
+ * General Configuration
+ */
+#define CONFIG_NITPICK 1
+#define ENABLE_NITPICK 1
+#define USE_NITPICK(...)  __VA_ARGS__
+#define SKIP_NITPICK(...)
+
+#define CONFIG_FEATURE_BUFFERS_USE_MALLOC 1
+#define ENABLE_FEATURE_BUFFERS_USE_MALLOC 1
+#define USE_FEATURE_BUFFERS_USE_MALLOC(...)  __VA_ARGS__
+#define SKIP_FEATURE_BUFFERS_USE_MALLOC(...)
+
+#undef CONFIG_FEATURE_BUFFERS_GO_ON_STACK
+#define ENABLE_FEATURE_BUFFERS_GO_ON_STACK 0
+#define USE_FEATURE_BUFFERS_GO_ON_STACK(...)
+#define SKIP_FEATURE_BUFFERS_GO_ON_STACK(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_BUFFERS_GO_IN_BSS
+#define ENABLE_FEATURE_BUFFERS_GO_IN_BSS 0
+#define USE_FEATURE_BUFFERS_GO_IN_BSS(...)
+#define SKIP_FEATURE_BUFFERS_GO_IN_BSS(...)  __VA_ARGS__
+
+#define CONFIG_SHOW_USAGE 1
+#define ENABLE_SHOW_USAGE 1
+#define USE_SHOW_USAGE(...)  __VA_ARGS__
+#define SKIP_SHOW_USAGE(...)
+
+#undef CONFIG_FEATURE_VERBOSE_USAGE
+#define ENABLE_FEATURE_VERBOSE_USAGE 0
+#define USE_FEATURE_VERBOSE_USAGE(...)
+#define SKIP_FEATURE_VERBOSE_USAGE(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_COMPRESS_USAGE 1
+#define ENABLE_FEATURE_COMPRESS_USAGE 1
+#define USE_FEATURE_COMPRESS_USAGE(...)  __VA_ARGS__
+#define SKIP_FEATURE_COMPRESS_USAGE(...)
+
+#undef CONFIG_FEATURE_INSTALLER
+#define ENABLE_FEATURE_INSTALLER 0
+#define USE_FEATURE_INSTALLER(...)
+#define SKIP_FEATURE_INSTALLER(...)  __VA_ARGS__
+
+#undef CONFIG_LOCALE_SUPPORT
+#define ENABLE_LOCALE_SUPPORT 0
+#define USE_LOCALE_SUPPORT(...)
+#define SKIP_LOCALE_SUPPORT(...)  __VA_ARGS__
+
+#define CONFIG_GETOPT_LONG 1
+#define ENABLE_GETOPT_LONG 1
+#define USE_GETOPT_LONG(...)  __VA_ARGS__
+#define SKIP_GETOPT_LONG(...)
+
+#undef CONFIG_FEATURE_DEVPTS
+#define ENABLE_FEATURE_DEVPTS 0
+#define USE_FEATURE_DEVPTS(...)
+#define SKIP_FEATURE_DEVPTS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_CLEAN_UP
+#define ENABLE_FEATURE_CLEAN_UP 0
+#define USE_FEATURE_CLEAN_UP(...)
+#define SKIP_FEATURE_CLEAN_UP(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_SUID 1
+#define ENABLE_FEATURE_SUID 1
+#define USE_FEATURE_SUID(...)  __VA_ARGS__
+#define SKIP_FEATURE_SUID(...)
+
+#undef CONFIG_FEATURE_SUID_CONFIG
+#define ENABLE_FEATURE_SUID_CONFIG 0
+#define USE_FEATURE_SUID_CONFIG(...)
+#define SKIP_FEATURE_SUID_CONFIG(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_SUID_CONFIG_QUIET
+#define ENABLE_FEATURE_SUID_CONFIG_QUIET 0
+#define USE_FEATURE_SUID_CONFIG_QUIET(...)
+#define SKIP_FEATURE_SUID_CONFIG_QUIET(...)  __VA_ARGS__
+
+#undef CONFIG_SELINUX
+#define ENABLE_SELINUX 0
+#define USE_SELINUX(...)
+#define SKIP_SELINUX(...)  __VA_ARGS__
+
+#define CONFIG_BUSYBOX_EXEC_PATH "/proc/self/exe"
+#define ENABLE_BUSYBOX_EXEC_PATH 1
+#define USE_BUSYBOX_EXEC_PATH(...)  __VA_ARGS__
+#define SKIP_BUSYBOX_EXEC_PATH(...)
+
+
+/*
+ * Build Options
+ */
+#define CONFIG_STATIC 1
+#define ENABLE_STATIC 1
+#define USE_STATIC(...)  __VA_ARGS__
+#define SKIP_STATIC(...)
+
+#undef CONFIG_BUILD_LIBBUSYBOX
+#define ENABLE_BUILD_LIBBUSYBOX 0
+#define USE_BUILD_LIBBUSYBOX(...)
+#define SKIP_BUILD_LIBBUSYBOX(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_FULL_LIBBUSYBOX
+#define ENABLE_FEATURE_FULL_LIBBUSYBOX 0
+#define USE_FEATURE_FULL_LIBBUSYBOX(...)
+#define SKIP_FEATURE_FULL_LIBBUSYBOX(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_SHARED_BUSYBOX
+#define ENABLE_FEATURE_SHARED_BUSYBOX 0
+#define USE_FEATURE_SHARED_BUSYBOX(...)
+#define SKIP_FEATURE_SHARED_BUSYBOX(...)  __VA_ARGS__
+
+#undef CONFIG_LFS
+#define ENABLE_LFS 0
+#define USE_LFS(...)
+#define SKIP_LFS(...)  __VA_ARGS__
+
+#define USING_CROSS_COMPILER 1
+#define ENABLE_CROSS_COMPILER 1
+#define USE_CROSS_COMPILER(...)  __VA_ARGS__
+#define SKIP_CROSS_COMPILER(...)
+
+#define CROSS_COMPILER_PREFIX "arm-elf-"
+#define ENABLE_COMPILER_PREFIX 1
+#define USE_COMPILER_PREFIX(...)  __VA_ARGS__
+#define SKIP_COMPILER_PREFIX(...)
+
+#define CONFIG_BUILD_AT_ONCE 1
+#define ENABLE_BUILD_AT_ONCE 1
+#define USE_BUILD_AT_ONCE(...)  __VA_ARGS__
+#define SKIP_BUILD_AT_ONCE(...)
+
+
+/*
+ * Debugging Options
+ */
+#undef CONFIG_DEBUG
+#define ENABLE_DEBUG 0
+#define USE_DEBUG(...)
+#define SKIP_DEBUG(...)  __VA_ARGS__
+
+#undef CONFIG_DEBUG_PESSIMIZE
+#define ENABLE_DEBUG_PESSIMIZE 0
+#define USE_DEBUG_PESSIMIZE(...)
+#define SKIP_DEBUG_PESSIMIZE(...)  __VA_ARGS__
+
+#undef CONFIG_NO_DEBUG_LIB
+#define ENABLE_NO_DEBUG_LIB 0
+#define USE_NO_DEBUG_LIB(...)
+#define SKIP_NO_DEBUG_LIB(...)  __VA_ARGS__
+
+#undef CONFIG_DMALLOC
+#define ENABLE_DMALLOC 0
+#define USE_DMALLOC(...)
+#define SKIP_DMALLOC(...)  __VA_ARGS__
+
+#undef CONFIG_EFENCE
+#define ENABLE_EFENCE 0
+#define USE_EFENCE(...)
+#define SKIP_EFENCE(...)  __VA_ARGS__
+
+#define CONFIG_DEBUG_YANK_SUSv2 1
+#define ENABLE_DEBUG_YANK_SUSv2 1
+#define USE_DEBUG_YANK_SUSv2(...)  __VA_ARGS__
+#define SKIP_DEBUG_YANK_SUSv2(...)
+
+
+/*
+ * Installation Options
+ */
+#define CONFIG_INSTALL_NO_USR 1
+#define ENABLE_INSTALL_NO_USR 1
+#define USE_INSTALL_NO_USR(...)  __VA_ARGS__
+#define SKIP_INSTALL_NO_USR(...)
+
+#define CONFIG_INSTALL_APPLET_SYMLINKS 1
+#define ENABLE_INSTALL_APPLET_SYMLINKS 1
+#define USE_INSTALL_APPLET_SYMLINKS(...)  __VA_ARGS__
+#define SKIP_INSTALL_APPLET_SYMLINKS(...)
+
+#undef CONFIG_INSTALL_APPLET_HARDLINKS
+#define ENABLE_INSTALL_APPLET_HARDLINKS 0
+#define USE_INSTALL_APPLET_HARDLINKS(...)
+#define SKIP_INSTALL_APPLET_HARDLINKS(...)  __VA_ARGS__
+
+#undef CONFIG_INSTALL_APPLET_DONT
+#define ENABLE_INSTALL_APPLET_DONT 0
+#define USE_INSTALL_APPLET_DONT(...)
+#define SKIP_INSTALL_APPLET_DONT(...)  __VA_ARGS__
+
+#define PREFIX "./_install"
+#define ENABLE_PREFIX 1
+#define USE_PREFIX(...)  __VA_ARGS__
+#define SKIP_PREFIX(...)
+
+
+/*
+ * Busybox Library Tuning
+ */
+#define CONFIG_MD5_SIZE_VS_SPEED 3
+#define ENABLE_MD5_SIZE_VS_SPEED 1
+#define USE_MD5_SIZE_VS_SPEED(...)  __VA_ARGS__
+#define SKIP_MD5_SIZE_VS_SPEED(...)
+
+
+/*
+ * Applets
+ */
+
+/*
+ * Archival Utilities
+ */
+#undef CONFIG_AR
+#define ENABLE_AR 0
+#define USE_AR(...)
+#define SKIP_AR(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_AR_LONG_FILENAMES
+#define ENABLE_FEATURE_AR_LONG_FILENAMES 0
+#define USE_FEATURE_AR_LONG_FILENAMES(...)
+#define SKIP_FEATURE_AR_LONG_FILENAMES(...)  __VA_ARGS__
+
+#undef CONFIG_BUNZIP2
+#define ENABLE_BUNZIP2 0
+#define USE_BUNZIP2(...)
+#define SKIP_BUNZIP2(...)  __VA_ARGS__
+
+#undef CONFIG_CPIO
+#define ENABLE_CPIO 0
+#define USE_CPIO(...)
+#define SKIP_CPIO(...)  __VA_ARGS__
+
+#undef CONFIG_DPKG
+#define ENABLE_DPKG 0
+#define USE_DPKG(...)
+#define SKIP_DPKG(...)  __VA_ARGS__
+
+#undef CONFIG_DPKG_DEB
+#define ENABLE_DPKG_DEB 0
+#define USE_DPKG_DEB(...)
+#define SKIP_DPKG_DEB(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY
+#define ENABLE_FEATURE_DPKG_DEB_EXTRACT_ONLY 0
+#define USE_FEATURE_DPKG_DEB_EXTRACT_ONLY(...)
+#define SKIP_FEATURE_DPKG_DEB_EXTRACT_ONLY(...)  __VA_ARGS__
+
+#undef CONFIG_GUNZIP
+#define ENABLE_GUNZIP 0
+#define USE_GUNZIP(...)
+#define SKIP_GUNZIP(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_GUNZIP_UNCOMPRESS
+#define ENABLE_FEATURE_GUNZIP_UNCOMPRESS 0
+#define USE_FEATURE_GUNZIP_UNCOMPRESS(...)
+#define SKIP_FEATURE_GUNZIP_UNCOMPRESS(...)  __VA_ARGS__
+
+#undef CONFIG_GZIP
+#define ENABLE_GZIP 0
+#define USE_GZIP(...)
+#define SKIP_GZIP(...)  __VA_ARGS__
+
+#undef CONFIG_RPM2CPIO
+#define ENABLE_RPM2CPIO 0
+#define USE_RPM2CPIO(...)
+#define SKIP_RPM2CPIO(...)  __VA_ARGS__
+
+#undef CONFIG_RPM
+#define ENABLE_RPM 0
+#define USE_RPM(...)
+#define SKIP_RPM(...)  __VA_ARGS__
+
+#define CONFIG_TAR 1
+#define ENABLE_TAR 1
+#define USE_TAR(...)  __VA_ARGS__
+#define SKIP_TAR(...)
+
+#undef CONFIG_FEATURE_TAR_CREATE
+#define ENABLE_FEATURE_TAR_CREATE 0
+#define USE_FEATURE_TAR_CREATE(...)
+#define SKIP_FEATURE_TAR_CREATE(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_TAR_BZIP2 1
+#define ENABLE_FEATURE_TAR_BZIP2 1
+#define USE_FEATURE_TAR_BZIP2(...)  __VA_ARGS__
+#define SKIP_FEATURE_TAR_BZIP2(...)
+
+#undef CONFIG_FEATURE_TAR_LZMA
+#define ENABLE_FEATURE_TAR_LZMA 0
+#define USE_FEATURE_TAR_LZMA(...)
+#define SKIP_FEATURE_TAR_LZMA(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_TAR_FROM
+#define ENABLE_FEATURE_TAR_FROM 0
+#define USE_FEATURE_TAR_FROM(...)
+#define SKIP_FEATURE_TAR_FROM(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_TAR_GZIP 1
+#define ENABLE_FEATURE_TAR_GZIP 1
+#define USE_FEATURE_TAR_GZIP(...)  __VA_ARGS__
+#define SKIP_FEATURE_TAR_GZIP(...)
+
+#undef CONFIG_FEATURE_TAR_COMPRESS
+#define ENABLE_FEATURE_TAR_COMPRESS 0
+#define USE_FEATURE_TAR_COMPRESS(...)
+#define SKIP_FEATURE_TAR_COMPRESS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY
+#define ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY 0
+#define USE_FEATURE_TAR_OLDGNU_COMPATIBILITY(...)
+#define SKIP_FEATURE_TAR_OLDGNU_COMPATIBILITY(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
+#define ENABLE_FEATURE_TAR_GNU_EXTENSIONS 0
+#define USE_FEATURE_TAR_GNU_EXTENSIONS(...)
+#define SKIP_FEATURE_TAR_GNU_EXTENSIONS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_TAR_LONG_OPTIONS
+#define ENABLE_FEATURE_TAR_LONG_OPTIONS 0
+#define USE_FEATURE_TAR_LONG_OPTIONS(...)
+#define SKIP_FEATURE_TAR_LONG_OPTIONS(...)  __VA_ARGS__
+
+#undef CONFIG_UNCOMPRESS
+#define ENABLE_UNCOMPRESS 0
+#define USE_UNCOMPRESS(...)
+#define SKIP_UNCOMPRESS(...)  __VA_ARGS__
+
+#undef CONFIG_UNLZMA
+#define ENABLE_UNLZMA 0
+#define USE_UNLZMA(...)
+#define SKIP_UNLZMA(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_LZMA_FAST
+#define ENABLE_FEATURE_LZMA_FAST 0
+#define USE_FEATURE_LZMA_FAST(...)
+#define SKIP_FEATURE_LZMA_FAST(...)  __VA_ARGS__
+
+#undef CONFIG_UNZIP
+#define ENABLE_UNZIP 0
+#define USE_UNZIP(...)
+#define SKIP_UNZIP(...)  __VA_ARGS__
+
+
+/*
+ * Common options for cpio and tar
+ */
+#undef CONFIG_FEATURE_UNARCHIVE_TAPE
+#define ENABLE_FEATURE_UNARCHIVE_TAPE 0
+#define USE_FEATURE_UNARCHIVE_TAPE(...)
+#define SKIP_FEATURE_UNARCHIVE_TAPE(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_DEB_TAR_GZ
+#define ENABLE_FEATURE_DEB_TAR_GZ 0
+#define USE_FEATURE_DEB_TAR_GZ(...)
+#define SKIP_FEATURE_DEB_TAR_GZ(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_DEB_TAR_BZ2
+#define ENABLE_FEATURE_DEB_TAR_BZ2 0
+#define USE_FEATURE_DEB_TAR_BZ2(...)
+#define SKIP_FEATURE_DEB_TAR_BZ2(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_DEB_TAR_LZMA
+#define ENABLE_FEATURE_DEB_TAR_LZMA 0
+#define USE_FEATURE_DEB_TAR_LZMA(...)
+#define SKIP_FEATURE_DEB_TAR_LZMA(...)  __VA_ARGS__
+
+
+/*
+ * Coreutils
+ */
+#define CONFIG_BASENAME 1
+#define ENABLE_BASENAME 1
+#define USE_BASENAME(...)  __VA_ARGS__
+#define SKIP_BASENAME(...)
+
+#undef CONFIG_CAL
+#define ENABLE_CAL 0
+#define USE_CAL(...)
+#define SKIP_CAL(...)  __VA_ARGS__
+
+#define CONFIG_CAT 1
+#define ENABLE_CAT 1
+#define USE_CAT(...)  __VA_ARGS__
+#define SKIP_CAT(...)
+
+#undef CONFIG_CATV
+#define ENABLE_CATV 0
+#define USE_CATV(...)
+#define SKIP_CATV(...)  __VA_ARGS__
+
+#undef CONFIG_CHGRP
+#define ENABLE_CHGRP 0
+#define USE_CHGRP(...)
+#define SKIP_CHGRP(...)  __VA_ARGS__
+
+#define CONFIG_CHMOD 1
+#define ENABLE_CHMOD 1
+#define USE_CHMOD(...)  __VA_ARGS__
+#define SKIP_CHMOD(...)
+
+#undef CONFIG_CHOWN
+#define ENABLE_CHOWN 0
+#define USE_CHOWN(...)
+#define SKIP_CHOWN(...)  __VA_ARGS__
+
+#define CONFIG_CHROOT 1
+#define ENABLE_CHROOT 1
+#define USE_CHROOT(...)  __VA_ARGS__
+#define SKIP_CHROOT(...)
+
+#undef CONFIG_CKSUM
+#define ENABLE_CKSUM 0
+#define USE_CKSUM(...)
+#define SKIP_CKSUM(...)  __VA_ARGS__
+
+#undef CONFIG_CMP
+#define ENABLE_CMP 0
+#define USE_CMP(...)
+#define SKIP_CMP(...)  __VA_ARGS__
+
+#undef CONFIG_COMM
+#define ENABLE_COMM 0
+#define USE_COMM(...)
+#define SKIP_COMM(...)  __VA_ARGS__
+
+#define CONFIG_CP 1
+#define ENABLE_CP 1
+#define USE_CP(...)  __VA_ARGS__
+#define SKIP_CP(...)
+
+#define CONFIG_CUT 1
+#define ENABLE_CUT 1
+#define USE_CUT(...)  __VA_ARGS__
+#define SKIP_CUT(...)
+
+#define CONFIG_DATE 1
+#define ENABLE_DATE 1
+#define USE_DATE(...)  __VA_ARGS__
+#define SKIP_DATE(...)
+
+#undef CONFIG_FEATURE_DATE_ISOFMT
+#define ENABLE_FEATURE_DATE_ISOFMT 0
+#define USE_FEATURE_DATE_ISOFMT(...)
+#define SKIP_FEATURE_DATE_ISOFMT(...)  __VA_ARGS__
+
+#define CONFIG_DD 1
+#define ENABLE_DD 1
+#define USE_DD(...)  __VA_ARGS__
+#define SKIP_DD(...)
+
+#undef CONFIG_FEATURE_DD_SIGNAL_HANDLING
+#define ENABLE_FEATURE_DD_SIGNAL_HANDLING 0
+#define USE_FEATURE_DD_SIGNAL_HANDLING(...)
+#define SKIP_FEATURE_DD_SIGNAL_HANDLING(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_DD_IBS_OBS
+#define ENABLE_FEATURE_DD_IBS_OBS 0
+#define USE_FEATURE_DD_IBS_OBS(...)
+#define SKIP_FEATURE_DD_IBS_OBS(...)  __VA_ARGS__
+
+#define CONFIG_DF 1
+#define ENABLE_DF 1
+#define USE_DF(...)  __VA_ARGS__
+#define SKIP_DF(...)
+
+#undef CONFIG_DIFF
+#define ENABLE_DIFF 0
+#define USE_DIFF(...)
+#define SKIP_DIFF(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_DIFF_BINARY
+#define ENABLE_FEATURE_DIFF_BINARY 0
+#define USE_FEATURE_DIFF_BINARY(...)
+#define SKIP_FEATURE_DIFF_BINARY(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_DIFF_DIR
+#define ENABLE_FEATURE_DIFF_DIR 0
+#define USE_FEATURE_DIFF_DIR(...)
+#define SKIP_FEATURE_DIFF_DIR(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_DIFF_MINIMAL
+#define ENABLE_FEATURE_DIFF_MINIMAL 0
+#define USE_FEATURE_DIFF_MINIMAL(...)
+#define SKIP_FEATURE_DIFF_MINIMAL(...)  __VA_ARGS__
+
+#undef CONFIG_DIRNAME
+#define ENABLE_DIRNAME 0
+#define USE_DIRNAME(...)
+#define SKIP_DIRNAME(...)  __VA_ARGS__
+
+#undef CONFIG_DOS2UNIX
+#define ENABLE_DOS2UNIX 0
+#define USE_DOS2UNIX(...)
+#define SKIP_DOS2UNIX(...)  __VA_ARGS__
+
+#undef CONFIG_UNIX2DOS
+#define ENABLE_UNIX2DOS 0
+#define USE_UNIX2DOS(...)
+#define SKIP_UNIX2DOS(...)  __VA_ARGS__
+
+#define CONFIG_DU 1
+#define ENABLE_DU 1
+#define USE_DU(...)  __VA_ARGS__
+#define SKIP_DU(...)
+
+#undef CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
+#define ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K 0
+#define USE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(...)
+#define SKIP_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(...)  __VA_ARGS__
+
+#define CONFIG_ECHO 1
+#define ENABLE_ECHO 1
+#define USE_ECHO(...)  __VA_ARGS__
+#define SKIP_ECHO(...)
+
+#undef CONFIG_FEATURE_FANCY_ECHO
+#define ENABLE_FEATURE_FANCY_ECHO 0
+#define USE_FEATURE_FANCY_ECHO(...)
+#define SKIP_FEATURE_FANCY_ECHO(...)  __VA_ARGS__
+
+#define CONFIG_ENV 1
+#define ENABLE_ENV 1
+#define USE_ENV(...)  __VA_ARGS__
+#define SKIP_ENV(...)
+
+#undef CONFIG_FEATURE_ENV_LONG_OPTIONS
+#define ENABLE_FEATURE_ENV_LONG_OPTIONS 0
+#define USE_FEATURE_ENV_LONG_OPTIONS(...)
+#define SKIP_FEATURE_ENV_LONG_OPTIONS(...)  __VA_ARGS__
+
+#define CONFIG_EXPR 1
+#define ENABLE_EXPR 1
+#define USE_EXPR(...)  __VA_ARGS__
+#define SKIP_EXPR(...)
+
+#undef CONFIG_EXPR_MATH_SUPPORT_64
+#define ENABLE_EXPR_MATH_SUPPORT_64 0
+#define USE_EXPR_MATH_SUPPORT_64(...)
+#define SKIP_EXPR_MATH_SUPPORT_64(...)  __VA_ARGS__
+
+#define CONFIG_FALSE 1
+#define ENABLE_FALSE 1
+#define USE_FALSE(...)  __VA_ARGS__
+#define SKIP_FALSE(...)
+
+#define CONFIG_FOLD 1
+#define ENABLE_FOLD 1
+#define USE_FOLD(...)  __VA_ARGS__
+#define SKIP_FOLD(...)
+
+#define CONFIG_HEAD 1
+#define ENABLE_HEAD 1
+#define USE_HEAD(...)  __VA_ARGS__
+#define SKIP_HEAD(...)
+
+#undef CONFIG_FEATURE_FANCY_HEAD
+#define ENABLE_FEATURE_FANCY_HEAD 0
+#define USE_FEATURE_FANCY_HEAD(...)
+#define SKIP_FEATURE_FANCY_HEAD(...)  __VA_ARGS__
+
+#undef CONFIG_HOSTID
+#define ENABLE_HOSTID 0
+#define USE_HOSTID(...)
+#define SKIP_HOSTID(...)  __VA_ARGS__
+
+#undef CONFIG_ID
+#define ENABLE_ID 0
+#define USE_ID(...)
+#define SKIP_ID(...)  __VA_ARGS__
+
+#undef CONFIG_INSTALL
+#define ENABLE_INSTALL 0
+#define USE_INSTALL(...)
+#define SKIP_INSTALL(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_INSTALL_LONG_OPTIONS
+#define ENABLE_FEATURE_INSTALL_LONG_OPTIONS 0
+#define USE_FEATURE_INSTALL_LONG_OPTIONS(...)
+#define SKIP_FEATURE_INSTALL_LONG_OPTIONS(...)  __VA_ARGS__
+
+#undef CONFIG_LENGTH
+#define ENABLE_LENGTH 0
+#define USE_LENGTH(...)
+#define SKIP_LENGTH(...)  __VA_ARGS__
+
+#define CONFIG_LN 1
+#define ENABLE_LN 1
+#define USE_LN(...)  __VA_ARGS__
+#define SKIP_LN(...)
+
+#undef CONFIG_LOGNAME
+#define ENABLE_LOGNAME 0
+#define USE_LOGNAME(...)
+#define SKIP_LOGNAME(...)  __VA_ARGS__
+
+#define CONFIG_LS 1
+#define ENABLE_LS 1
+#define USE_LS(...)  __VA_ARGS__
+#define SKIP_LS(...)
+
+#undef CONFIG_FEATURE_LS_FILETYPES
+#define ENABLE_FEATURE_LS_FILETYPES 0
+#define USE_FEATURE_LS_FILETYPES(...)
+#define SKIP_FEATURE_LS_FILETYPES(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_LS_FOLLOWLINKS 1
+#define ENABLE_FEATURE_LS_FOLLOWLINKS 1
+#define USE_FEATURE_LS_FOLLOWLINKS(...)  __VA_ARGS__
+#define SKIP_FEATURE_LS_FOLLOWLINKS(...)
+
+#undef CONFIG_FEATURE_LS_RECURSIVE
+#define ENABLE_FEATURE_LS_RECURSIVE 0
+#define USE_FEATURE_LS_RECURSIVE(...)
+#define SKIP_FEATURE_LS_RECURSIVE(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_LS_SORTFILES 1
+#define ENABLE_FEATURE_LS_SORTFILES 1
+#define USE_FEATURE_LS_SORTFILES(...)  __VA_ARGS__
+#define SKIP_FEATURE_LS_SORTFILES(...)
+
+#define CONFIG_FEATURE_LS_TIMESTAMPS 1
+#define ENABLE_FEATURE_LS_TIMESTAMPS 1
+#define USE_FEATURE_LS_TIMESTAMPS(...)  __VA_ARGS__
+#define SKIP_FEATURE_LS_TIMESTAMPS(...)
+
+#undef CONFIG_FEATURE_LS_USERNAME
+#define ENABLE_FEATURE_LS_USERNAME 0
+#define USE_FEATURE_LS_USERNAME(...)
+#define SKIP_FEATURE_LS_USERNAME(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_LS_COLOR 1
+#define ENABLE_FEATURE_LS_COLOR 1
+#define USE_FEATURE_LS_COLOR(...)  __VA_ARGS__
+#define SKIP_FEATURE_LS_COLOR(...)
+
+#define CONFIG_FEATURE_LS_COLOR_IS_DEFAULT 1
+#define ENABLE_FEATURE_LS_COLOR_IS_DEFAULT 1
+#define USE_FEATURE_LS_COLOR_IS_DEFAULT(...)  __VA_ARGS__
+#define SKIP_FEATURE_LS_COLOR_IS_DEFAULT(...)
+
+#undef CONFIG_MD5SUM
+#define ENABLE_MD5SUM 0
+#define USE_MD5SUM(...)
+#define SKIP_MD5SUM(...)  __VA_ARGS__
+
+#define CONFIG_MKDIR 1
+#define ENABLE_MKDIR 1
+#define USE_MKDIR(...)  __VA_ARGS__
+#define SKIP_MKDIR(...)
+
+#undef CONFIG_FEATURE_MKDIR_LONG_OPTIONS
+#define ENABLE_FEATURE_MKDIR_LONG_OPTIONS 0
+#define USE_FEATURE_MKDIR_LONG_OPTIONS(...)
+#define SKIP_FEATURE_MKDIR_LONG_OPTIONS(...)  __VA_ARGS__
+
+#define CONFIG_MKFIFO 1
+#define ENABLE_MKFIFO 1
+#define USE_MKFIFO(...)  __VA_ARGS__
+#define SKIP_MKFIFO(...)
+
+#undef CONFIG_MKNOD
+#define ENABLE_MKNOD 0
+#define USE_MKNOD(...)
+#define SKIP_MKNOD(...)  __VA_ARGS__
+
+#define CONFIG_MV 1
+#define ENABLE_MV 1
+#define USE_MV(...)  __VA_ARGS__
+#define SKIP_MV(...)
+
+#undef CONFIG_FEATURE_MV_LONG_OPTIONS
+#define ENABLE_FEATURE_MV_LONG_OPTIONS 0
+#define USE_FEATURE_MV_LONG_OPTIONS(...)
+#define SKIP_FEATURE_MV_LONG_OPTIONS(...)  __VA_ARGS__
+
+#undef CONFIG_NICE
+#define ENABLE_NICE 0
+#define USE_NICE(...)
+#define SKIP_NICE(...)  __VA_ARGS__
+
+#undef CONFIG_NOHUP
+#define ENABLE_NOHUP 0
+#define USE_NOHUP(...)
+#define SKIP_NOHUP(...)  __VA_ARGS__
+
+#undef CONFIG_OD
+#define ENABLE_OD 0
+#define USE_OD(...)
+#define SKIP_OD(...)  __VA_ARGS__
+
+#undef CONFIG_PRINTENV
+#define ENABLE_PRINTENV 0
+#define USE_PRINTENV(...)
+#define SKIP_PRINTENV(...)  __VA_ARGS__
+
+#undef CONFIG_PRINTF
+#define ENABLE_PRINTF 0
+#define USE_PRINTF(...)
+#define SKIP_PRINTF(...)  __VA_ARGS__
+
+#define CONFIG_PWD 1
+#define ENABLE_PWD 1
+#define USE_PWD(...)  __VA_ARGS__
+#define SKIP_PWD(...)
+
+#undef CONFIG_REALPATH
+#define ENABLE_REALPATH 0
+#define USE_REALPATH(...)
+#define SKIP_REALPATH(...)  __VA_ARGS__
+
+#define CONFIG_RM 1
+#define ENABLE_RM 1
+#define USE_RM(...)  __VA_ARGS__
+#define SKIP_RM(...)
+
+#define CONFIG_RMDIR 1
+#define ENABLE_RMDIR 1
+#define USE_RMDIR(...)  __VA_ARGS__
+#define SKIP_RMDIR(...)
+
+#define CONFIG_SEQ 1
+#define ENABLE_SEQ 1
+#define USE_SEQ(...)  __VA_ARGS__
+#define SKIP_SEQ(...)
+
+#undef CONFIG_SHA1SUM
+#define ENABLE_SHA1SUM 0
+#define USE_SHA1SUM(...)
+#define SKIP_SHA1SUM(...)  __VA_ARGS__
+
+#define CONFIG_SLEEP 1
+#define ENABLE_SLEEP 1
+#define USE_SLEEP(...)  __VA_ARGS__
+#define SKIP_SLEEP(...)
+
+#undef CONFIG_FEATURE_FANCY_SLEEP
+#define ENABLE_FEATURE_FANCY_SLEEP 0
+#define USE_FEATURE_FANCY_SLEEP(...)
+#define SKIP_FEATURE_FANCY_SLEEP(...)  __VA_ARGS__
+
+#define CONFIG_SORT 1
+#define ENABLE_SORT 1
+#define USE_SORT(...)  __VA_ARGS__
+#define SKIP_SORT(...)
+
+#undef CONFIG_FEATURE_SORT_BIG
+#define ENABLE_FEATURE_SORT_BIG 0
+#define USE_FEATURE_SORT_BIG(...)
+#define SKIP_FEATURE_SORT_BIG(...)  __VA_ARGS__
+
+#undef CONFIG_STAT
+#define ENABLE_STAT 0
+#define USE_STAT(...)
+#define SKIP_STAT(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_STAT_FORMAT
+#define ENABLE_FEATURE_STAT_FORMAT 0
+#define USE_FEATURE_STAT_FORMAT(...)
+#define SKIP_FEATURE_STAT_FORMAT(...)  __VA_ARGS__
+
+#undef CONFIG_STTY
+#define ENABLE_STTY 0
+#define USE_STTY(...)
+#define SKIP_STTY(...)  __VA_ARGS__
+
+#undef CONFIG_SUM
+#define ENABLE_SUM 0
+#define USE_SUM(...)
+#define SKIP_SUM(...)  __VA_ARGS__
+
+#undef CONFIG_SYNC
+#define ENABLE_SYNC 0
+#define USE_SYNC(...)
+#define SKIP_SYNC(...)  __VA_ARGS__
+
+#define CONFIG_TAIL 1
+#define ENABLE_TAIL 1
+#define USE_TAIL(...)  __VA_ARGS__
+#define SKIP_TAIL(...)
+
+#undef CONFIG_FEATURE_FANCY_TAIL
+#define ENABLE_FEATURE_FANCY_TAIL 0
+#define USE_FEATURE_FANCY_TAIL(...)
+#define SKIP_FEATURE_FANCY_TAIL(...)  __VA_ARGS__
+
+#define CONFIG_TEE 1
+#define ENABLE_TEE 1
+#define USE_TEE(...)  __VA_ARGS__
+#define SKIP_TEE(...)
+
+#undef CONFIG_FEATURE_TEE_USE_BLOCK_IO
+#define ENABLE_FEATURE_TEE_USE_BLOCK_IO 0
+#define USE_FEATURE_TEE_USE_BLOCK_IO(...)
+#define SKIP_FEATURE_TEE_USE_BLOCK_IO(...)  __VA_ARGS__
+
+#define CONFIG_TEST 1
+#define ENABLE_TEST 1
+#define USE_TEST(...)  __VA_ARGS__
+#define SKIP_TEST(...)
+
+#undef CONFIG_FEATURE_TEST_64
+#define ENABLE_FEATURE_TEST_64 0
+#define USE_FEATURE_TEST_64(...)
+#define SKIP_FEATURE_TEST_64(...)  __VA_ARGS__
+
+#define CONFIG_TOUCH 1
+#define ENABLE_TOUCH 1
+#define USE_TOUCH(...)  __VA_ARGS__
+#define SKIP_TOUCH(...)
+
+#define CONFIG_TR 1
+#define ENABLE_TR 1
+#define USE_TR(...)  __VA_ARGS__
+#define SKIP_TR(...)
+
+#undef CONFIG_FEATURE_TR_CLASSES
+#define ENABLE_FEATURE_TR_CLASSES 0
+#define USE_FEATURE_TR_CLASSES(...)
+#define SKIP_FEATURE_TR_CLASSES(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_TR_EQUIV
+#define ENABLE_FEATURE_TR_EQUIV 0
+#define USE_FEATURE_TR_EQUIV(...)
+#define SKIP_FEATURE_TR_EQUIV(...)  __VA_ARGS__
+
+#define CONFIG_TRUE 1
+#define ENABLE_TRUE 1
+#define USE_TRUE(...)  __VA_ARGS__
+#define SKIP_TRUE(...)
+
+#undef CONFIG_TTY
+#define ENABLE_TTY 0
+#define USE_TTY(...)
+#define SKIP_TTY(...)  __VA_ARGS__
+
+#define CONFIG_UNAME 1
+#define ENABLE_UNAME 1
+#define USE_UNAME(...)  __VA_ARGS__
+#define SKIP_UNAME(...)
+
+#define CONFIG_UNIQ 1
+#define ENABLE_UNIQ 1
+#define USE_UNIQ(...)  __VA_ARGS__
+#define SKIP_UNIQ(...)
+
+#define CONFIG_USLEEP 1
+#define ENABLE_USLEEP 1
+#define USE_USLEEP(...)  __VA_ARGS__
+#define SKIP_USLEEP(...)
+
+#undef CONFIG_UUDECODE
+#define ENABLE_UUDECODE 0
+#define USE_UUDECODE(...)
+#define SKIP_UUDECODE(...)  __VA_ARGS__
+
+#undef CONFIG_UUENCODE
+#define ENABLE_UUENCODE 0
+#define USE_UUENCODE(...)
+#define SKIP_UUENCODE(...)  __VA_ARGS__
+
+#undef CONFIG_WATCH
+#define ENABLE_WATCH 0
+#define USE_WATCH(...)
+#define SKIP_WATCH(...)  __VA_ARGS__
+
+#define CONFIG_WC 1
+#define ENABLE_WC 1
+#define USE_WC(...)  __VA_ARGS__
+#define SKIP_WC(...)
+
+#undef CONFIG_WHO
+#define ENABLE_WHO 0
+#define USE_WHO(...)
+#define SKIP_WHO(...)  __VA_ARGS__
+
+#undef CONFIG_WHOAMI
+#define ENABLE_WHOAMI 0
+#define USE_WHOAMI(...)
+#define SKIP_WHOAMI(...)  __VA_ARGS__
+
+#define CONFIG_YES 1
+#define ENABLE_YES 1
+#define USE_YES(...)  __VA_ARGS__
+#define SKIP_YES(...)
+
+
+/*
+ * Common options for cp and mv
+ */
+#undef CONFIG_FEATURE_PRESERVE_HARDLINKS
+#define ENABLE_FEATURE_PRESERVE_HARDLINKS 0
+#define USE_FEATURE_PRESERVE_HARDLINKS(...)
+#define SKIP_FEATURE_PRESERVE_HARDLINKS(...)  __VA_ARGS__
+
+
+/*
+ * Common options for ls, more and telnet
+ */
+#define CONFIG_FEATURE_AUTOWIDTH 1
+#define ENABLE_FEATURE_AUTOWIDTH 1
+#define USE_FEATURE_AUTOWIDTH(...)  __VA_ARGS__
+#define SKIP_FEATURE_AUTOWIDTH(...)
+
+
+/*
+ * Common options for df, du, ls
+ */
+#undef CONFIG_FEATURE_HUMAN_READABLE
+#define ENABLE_FEATURE_HUMAN_READABLE 0
+#define USE_FEATURE_HUMAN_READABLE(...)
+#define SKIP_FEATURE_HUMAN_READABLE(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_MD5_SHA1_SUM_CHECK
+#define ENABLE_FEATURE_MD5_SHA1_SUM_CHECK 0
+#define USE_FEATURE_MD5_SHA1_SUM_CHECK(...)
+#define SKIP_FEATURE_MD5_SHA1_SUM_CHECK(...)  __VA_ARGS__
+
+
+/*
+ * Console Utilities
+ */
+#undef CONFIG_CHVT
+#define ENABLE_CHVT 0
+#define USE_CHVT(...)
+#define SKIP_CHVT(...)  __VA_ARGS__
+
+#define CONFIG_CLEAR 1
+#define ENABLE_CLEAR 1
+#define USE_CLEAR(...)  __VA_ARGS__
+#define SKIP_CLEAR(...)
+
+#undef CONFIG_DEALLOCVT
+#define ENABLE_DEALLOCVT 0
+#define USE_DEALLOCVT(...)
+#define SKIP_DEALLOCVT(...)  __VA_ARGS__
+
+#undef CONFIG_DUMPKMAP
+#define ENABLE_DUMPKMAP 0
+#define USE_DUMPKMAP(...)
+#define SKIP_DUMPKMAP(...)  __VA_ARGS__
+
+#undef CONFIG_LOADFONT
+#define ENABLE_LOADFONT 0
+#define USE_LOADFONT(...)
+#define SKIP_LOADFONT(...)  __VA_ARGS__
+
+#undef CONFIG_LOADKMAP
+#define ENABLE_LOADKMAP 0
+#define USE_LOADKMAP(...)
+#define SKIP_LOADKMAP(...)  __VA_ARGS__
+
+#undef CONFIG_OPENVT
+#define ENABLE_OPENVT 0
+#define USE_OPENVT(...)
+#define SKIP_OPENVT(...)  __VA_ARGS__
+
+#undef CONFIG_RESET
+#define ENABLE_RESET 0
+#define USE_RESET(...)
+#define SKIP_RESET(...)  __VA_ARGS__
+
+#undef CONFIG_SETCONSOLE
+#define ENABLE_SETCONSOLE 0
+#define USE_SETCONSOLE(...)
+#define SKIP_SETCONSOLE(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS
+#define ENABLE_FEATURE_SETCONSOLE_LONG_OPTIONS 0
+#define USE_FEATURE_SETCONSOLE_LONG_OPTIONS(...)
+#define SKIP_FEATURE_SETCONSOLE_LONG_OPTIONS(...)  __VA_ARGS__
+
+#undef CONFIG_SETKEYCODES
+#define ENABLE_SETKEYCODES 0
+#define USE_SETKEYCODES(...)
+#define SKIP_SETKEYCODES(...)  __VA_ARGS__
+
+#undef CONFIG_SETLOGCONS
+#define ENABLE_SETLOGCONS 0
+#define USE_SETLOGCONS(...)
+#define SKIP_SETLOGCONS(...)  __VA_ARGS__
+
+
+/*
+ * Debian Utilities
+ */
+#define CONFIG_MKTEMP 1
+#define ENABLE_MKTEMP 1
+#define USE_MKTEMP(...)  __VA_ARGS__
+#define SKIP_MKTEMP(...)
+
+#undef CONFIG_PIPE_PROGRESS
+#define ENABLE_PIPE_PROGRESS 0
+#define USE_PIPE_PROGRESS(...)
+#define SKIP_PIPE_PROGRESS(...)  __VA_ARGS__
+
+#undef CONFIG_READLINK
+#define ENABLE_READLINK 0
+#define USE_READLINK(...)
+#define SKIP_READLINK(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_READLINK_FOLLOW
+#define ENABLE_FEATURE_READLINK_FOLLOW 0
+#define USE_FEATURE_READLINK_FOLLOW(...)
+#define SKIP_FEATURE_READLINK_FOLLOW(...)  __VA_ARGS__
+
+#undef CONFIG_RUN_PARTS
+#define ENABLE_RUN_PARTS 0
+#define USE_RUN_PARTS(...)
+#define SKIP_RUN_PARTS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS
+#define ENABLE_FEATURE_RUN_PARTS_LONG_OPTIONS 0
+#define USE_FEATURE_RUN_PARTS_LONG_OPTIONS(...)
+#define SKIP_FEATURE_RUN_PARTS_LONG_OPTIONS(...)  __VA_ARGS__
+
+#undef CONFIG_START_STOP_DAEMON
+#define ENABLE_START_STOP_DAEMON 0
+#define USE_START_STOP_DAEMON(...)
+#define SKIP_START_STOP_DAEMON(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_START_STOP_DAEMON_FANCY
+#define ENABLE_FEATURE_START_STOP_DAEMON_FANCY 0
+#define USE_FEATURE_START_STOP_DAEMON_FANCY(...)
+#define SKIP_FEATURE_START_STOP_DAEMON_FANCY(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS
+#define ENABLE_FEATURE_START_STOP_DAEMON_LONG_OPTIONS 0
+#define USE_FEATURE_START_STOP_DAEMON_LONG_OPTIONS(...)
+#define SKIP_FEATURE_START_STOP_DAEMON_LONG_OPTIONS(...)  __VA_ARGS__
+
+#define CONFIG_WHICH 1
+#define ENABLE_WHICH 1
+#define USE_WHICH(...)  __VA_ARGS__
+#define SKIP_WHICH(...)
+
+
+/*
+ * Editors
+ */
+#define CONFIG_AWK 1
+#define ENABLE_AWK 1
+#define USE_AWK(...)  __VA_ARGS__
+#define SKIP_AWK(...)
+
+#undef CONFIG_FEATURE_AWK_MATH
+#define ENABLE_FEATURE_AWK_MATH 0
+#define USE_FEATURE_AWK_MATH(...)
+#define SKIP_FEATURE_AWK_MATH(...)  __VA_ARGS__
+
+#undef CONFIG_ED
+#define ENABLE_ED 0
+#define USE_ED(...)
+#define SKIP_ED(...)  __VA_ARGS__
+
+#undef CONFIG_PATCH
+#define ENABLE_PATCH 0
+#define USE_PATCH(...)
+#define SKIP_PATCH(...)  __VA_ARGS__
+
+#define CONFIG_SED 1
+#define ENABLE_SED 1
+#define USE_SED(...)  __VA_ARGS__
+#define SKIP_SED(...)
+
+#undef CONFIG_VI
+#define ENABLE_VI 0
+#define USE_VI(...)
+#define SKIP_VI(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_VI_COLON
+#define ENABLE_FEATURE_VI_COLON 0
+#define USE_FEATURE_VI_COLON(...)
+#define SKIP_FEATURE_VI_COLON(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_VI_YANKMARK
+#define ENABLE_FEATURE_VI_YANKMARK 0
+#define USE_FEATURE_VI_YANKMARK(...)
+#define SKIP_FEATURE_VI_YANKMARK(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_VI_SEARCH
+#define ENABLE_FEATURE_VI_SEARCH 0
+#define USE_FEATURE_VI_SEARCH(...)
+#define SKIP_FEATURE_VI_SEARCH(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_VI_USE_SIGNALS
+#define ENABLE_FEATURE_VI_USE_SIGNALS 0
+#define USE_FEATURE_VI_USE_SIGNALS(...)
+#define SKIP_FEATURE_VI_USE_SIGNALS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_VI_DOT_CMD
+#define ENABLE_FEATURE_VI_DOT_CMD 0
+#define USE_FEATURE_VI_DOT_CMD(...)
+#define SKIP_FEATURE_VI_DOT_CMD(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_VI_READONLY
+#define ENABLE_FEATURE_VI_READONLY 0
+#define USE_FEATURE_VI_READONLY(...)
+#define SKIP_FEATURE_VI_READONLY(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_VI_SETOPTS
+#define ENABLE_FEATURE_VI_SETOPTS 0
+#define USE_FEATURE_VI_SETOPTS(...)
+#define SKIP_FEATURE_VI_SETOPTS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_VI_SET
+#define ENABLE_FEATURE_VI_SET 0
+#define USE_FEATURE_VI_SET(...)
+#define SKIP_FEATURE_VI_SET(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_VI_WIN_RESIZE
+#define ENABLE_FEATURE_VI_WIN_RESIZE 0
+#define USE_FEATURE_VI_WIN_RESIZE(...)
+#define SKIP_FEATURE_VI_WIN_RESIZE(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
+#define ENABLE_FEATURE_VI_OPTIMIZE_CURSOR 0
+#define USE_FEATURE_VI_OPTIMIZE_CURSOR(...)
+#define SKIP_FEATURE_VI_OPTIMIZE_CURSOR(...)  __VA_ARGS__
+
+
+/*
+ * Finding Utilities
+ */
+#define CONFIG_FIND 1
+#define ENABLE_FIND 1
+#define USE_FIND(...)  __VA_ARGS__
+#define SKIP_FIND(...)
+
+#undef CONFIG_FEATURE_FIND_PRINT0
+#define ENABLE_FEATURE_FIND_PRINT0 0
+#define USE_FEATURE_FIND_PRINT0(...)
+#define SKIP_FEATURE_FIND_PRINT0(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_FIND_MTIME
+#define ENABLE_FEATURE_FIND_MTIME 0
+#define USE_FEATURE_FIND_MTIME(...)
+#define SKIP_FEATURE_FIND_MTIME(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_FIND_MMIN
+#define ENABLE_FEATURE_FIND_MMIN 0
+#define USE_FEATURE_FIND_MMIN(...)
+#define SKIP_FEATURE_FIND_MMIN(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_FIND_PERM
+#define ENABLE_FEATURE_FIND_PERM 0
+#define USE_FEATURE_FIND_PERM(...)
+#define SKIP_FEATURE_FIND_PERM(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_FIND_TYPE
+#define ENABLE_FEATURE_FIND_TYPE 0
+#define USE_FEATURE_FIND_TYPE(...)
+#define SKIP_FEATURE_FIND_TYPE(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_FIND_XDEV
+#define ENABLE_FEATURE_FIND_XDEV 0
+#define USE_FEATURE_FIND_XDEV(...)
+#define SKIP_FEATURE_FIND_XDEV(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_FIND_NEWER
+#define ENABLE_FEATURE_FIND_NEWER 0
+#define USE_FEATURE_FIND_NEWER(...)
+#define SKIP_FEATURE_FIND_NEWER(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_FIND_INUM
+#define ENABLE_FEATURE_FIND_INUM 0
+#define USE_FEATURE_FIND_INUM(...)
+#define SKIP_FEATURE_FIND_INUM(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_FIND_EXEC 1
+#define ENABLE_FEATURE_FIND_EXEC 1
+#define USE_FEATURE_FIND_EXEC(...)  __VA_ARGS__
+#define SKIP_FEATURE_FIND_EXEC(...)
+
+#define CONFIG_GREP 1
+#define ENABLE_GREP 1
+#define USE_GREP(...)  __VA_ARGS__
+#define SKIP_GREP(...)
+
+#undef CONFIG_FEATURE_GREP_EGREP_ALIAS
+#define ENABLE_FEATURE_GREP_EGREP_ALIAS 0
+#define USE_FEATURE_GREP_EGREP_ALIAS(...)
+#define SKIP_FEATURE_GREP_EGREP_ALIAS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_GREP_FGREP_ALIAS
+#define ENABLE_FEATURE_GREP_FGREP_ALIAS 0
+#define USE_FEATURE_GREP_FGREP_ALIAS(...)
+#define SKIP_FEATURE_GREP_FGREP_ALIAS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_GREP_CONTEXT
+#define ENABLE_FEATURE_GREP_CONTEXT 0
+#define USE_FEATURE_GREP_CONTEXT(...)
+#define SKIP_FEATURE_GREP_CONTEXT(...)  __VA_ARGS__
+
+#undef CONFIG_XARGS
+#define ENABLE_XARGS 0
+#define USE_XARGS(...)
+#define SKIP_XARGS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION
+#define ENABLE_FEATURE_XARGS_SUPPORT_CONFIRMATION 0
+#define USE_FEATURE_XARGS_SUPPORT_CONFIRMATION(...)
+#define SKIP_FEATURE_XARGS_SUPPORT_CONFIRMATION(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_XARGS_SUPPORT_QUOTES
+#define ENABLE_FEATURE_XARGS_SUPPORT_QUOTES 0
+#define USE_FEATURE_XARGS_SUPPORT_QUOTES(...)
+#define SKIP_FEATURE_XARGS_SUPPORT_QUOTES(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT
+#define ENABLE_FEATURE_XARGS_SUPPORT_TERMOPT 0
+#define USE_FEATURE_XARGS_SUPPORT_TERMOPT(...)
+#define SKIP_FEATURE_XARGS_SUPPORT_TERMOPT(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM
+#define ENABLE_FEATURE_XARGS_SUPPORT_ZERO_TERM 0
+#define USE_FEATURE_XARGS_SUPPORT_ZERO_TERM(...)
+#define SKIP_FEATURE_XARGS_SUPPORT_ZERO_TERM(...)  __VA_ARGS__
+
+
+/*
+ * Init Utilities
+ */
+#undef CONFIG_INIT
+#define ENABLE_INIT 0
+#define USE_INIT(...)
+#define SKIP_INIT(...)  __VA_ARGS__
+
+#undef CONFIG_DEBUG_INIT
+#define ENABLE_DEBUG_INIT 0
+#define USE_DEBUG_INIT(...)
+#define SKIP_DEBUG_INIT(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_USE_INITTAB
+#define ENABLE_FEATURE_USE_INITTAB 0
+#define USE_FEATURE_USE_INITTAB(...)
+#define SKIP_FEATURE_USE_INITTAB(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_INIT_SCTTY
+#define ENABLE_FEATURE_INIT_SCTTY 0
+#define USE_FEATURE_INIT_SCTTY(...)
+#define SKIP_FEATURE_INIT_SCTTY(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_EXTRA_QUIET
+#define ENABLE_FEATURE_EXTRA_QUIET 0
+#define USE_FEATURE_EXTRA_QUIET(...)
+#define SKIP_FEATURE_EXTRA_QUIET(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_INIT_COREDUMPS
+#define ENABLE_FEATURE_INIT_COREDUMPS 0
+#define USE_FEATURE_INIT_COREDUMPS(...)
+#define SKIP_FEATURE_INIT_COREDUMPS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_INITRD
+#define ENABLE_FEATURE_INITRD 0
+#define USE_FEATURE_INITRD(...)
+#define SKIP_FEATURE_INITRD(...)  __VA_ARGS__
+
+#undef CONFIG_HALT
+#define ENABLE_HALT 0
+#define USE_HALT(...)
+#define SKIP_HALT(...)  __VA_ARGS__
+
+#undef CONFIG_MESG
+#define ENABLE_MESG 0
+#define USE_MESG(...)
+#define SKIP_MESG(...)  __VA_ARGS__
+
+
+/*
+ * Login/Password Management Utilities
+ */
+#undef CONFIG_FEATURE_SHADOWPASSWDS
+#define ENABLE_FEATURE_SHADOWPASSWDS 0
+#define USE_FEATURE_SHADOWPASSWDS(...)
+#define SKIP_FEATURE_SHADOWPASSWDS(...)  __VA_ARGS__
+
+#undef CONFIG_USE_BB_SHADOW
+#define ENABLE_USE_BB_SHADOW 0
+#define USE_USE_BB_SHADOW(...)
+#define SKIP_USE_BB_SHADOW(...)  __VA_ARGS__
+
+#undef CONFIG_USE_BB_PWD_GRP
+#define ENABLE_USE_BB_PWD_GRP 0
+#define USE_USE_BB_PWD_GRP(...)
+#define SKIP_USE_BB_PWD_GRP(...)  __VA_ARGS__
+
+#undef CONFIG_ADDGROUP
+#define ENABLE_ADDGROUP 0
+#define USE_ADDGROUP(...)
+#define SKIP_ADDGROUP(...)  __VA_ARGS__
+
+#undef CONFIG_DELGROUP
+#define ENABLE_DELGROUP 0
+#define USE_DELGROUP(...)
+#define SKIP_DELGROUP(...)  __VA_ARGS__
+
+#undef CONFIG_ADDUSER
+#define ENABLE_ADDUSER 0
+#define USE_ADDUSER(...)
+#define SKIP_ADDUSER(...)  __VA_ARGS__
+
+#undef CONFIG_DELUSER
+#define ENABLE_DELUSER 0
+#define USE_DELUSER(...)
+#define SKIP_DELUSER(...)  __VA_ARGS__
+
+#undef CONFIG_GETTY
+#define ENABLE_GETTY 0
+#define USE_GETTY(...)
+#define SKIP_GETTY(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_UTMP
+#define ENABLE_FEATURE_UTMP 0
+#define USE_FEATURE_UTMP(...)
+#define SKIP_FEATURE_UTMP(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_WTMP
+#define ENABLE_FEATURE_WTMP 0
+#define USE_FEATURE_WTMP(...)
+#define SKIP_FEATURE_WTMP(...)  __VA_ARGS__
+
+#undef CONFIG_LOGIN
+#define ENABLE_LOGIN 0
+#define USE_LOGIN(...)
+#define SKIP_LOGIN(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_SECURETTY
+#define ENABLE_FEATURE_SECURETTY 0
+#define USE_FEATURE_SECURETTY(...)
+#define SKIP_FEATURE_SECURETTY(...)  __VA_ARGS__
+
+#undef CONFIG_PASSWD
+#define ENABLE_PASSWD 0
+#define USE_PASSWD(...)
+#define SKIP_PASSWD(...)  __VA_ARGS__
+
+#undef CONFIG_SU
+#define ENABLE_SU 0
+#define USE_SU(...)
+#define SKIP_SU(...)  __VA_ARGS__
+
+#undef CONFIG_SULOGIN
+#define ENABLE_SULOGIN 0
+#define USE_SULOGIN(...)
+#define SKIP_SULOGIN(...)  __VA_ARGS__
+
+#undef CONFIG_VLOCK
+#define ENABLE_VLOCK 0
+#define USE_VLOCK(...)
+#define SKIP_VLOCK(...)  __VA_ARGS__
+
+
+/*
+ * Linux Ext2 FS Progs
+ */
+#undef CONFIG_CHATTR
+#define ENABLE_CHATTR 0
+#define USE_CHATTR(...)
+#define SKIP_CHATTR(...)  __VA_ARGS__
+
+#undef CONFIG_E2FSCK
+#define ENABLE_E2FSCK 0
+#define USE_E2FSCK(...)
+#define SKIP_E2FSCK(...)  __VA_ARGS__
+
+#undef CONFIG_FSCK
+#define ENABLE_FSCK 0
+#define USE_FSCK(...)
+#define SKIP_FSCK(...)  __VA_ARGS__
+
+#undef CONFIG_LSATTR
+#define ENABLE_LSATTR 0
+#define USE_LSATTR(...)
+#define SKIP_LSATTR(...)  __VA_ARGS__
+
+#undef CONFIG_MKE2FS
+#define ENABLE_MKE2FS 0
+#define USE_MKE2FS(...)
+#define SKIP_MKE2FS(...)  __VA_ARGS__
+
+#undef CONFIG_TUNE2FS
+#define ENABLE_TUNE2FS 0
+#define USE_TUNE2FS(...)
+#define SKIP_TUNE2FS(...)  __VA_ARGS__
+
+#undef CONFIG_E2LABEL
+#define ENABLE_E2LABEL 0
+#define USE_E2LABEL(...)
+#define SKIP_E2LABEL(...)  __VA_ARGS__
+
+#undef CONFIG_FINDFS
+#define ENABLE_FINDFS 0
+#define USE_FINDFS(...)
+#define SKIP_FINDFS(...)  __VA_ARGS__
+
+
+/*
+ * Linux Module Utilities
+ */
+#define CONFIG_INSMOD 1
+#define ENABLE_INSMOD 1
+#define USE_INSMOD(...)  __VA_ARGS__
+#define SKIP_INSMOD(...)
+
+#undef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+#define ENABLE_FEATURE_INSMOD_VERSION_CHECKING 0
+#define USE_FEATURE_INSMOD_VERSION_CHECKING(...)
+#define SKIP_FEATURE_INSMOD_VERSION_CHECKING(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
+#define ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS 0
+#define USE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS(...)
+#define SKIP_FEATURE_INSMOD_KSYMOOPS_SYMBOLS(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_INSMOD_LOADINKMEM 1
+#define ENABLE_FEATURE_INSMOD_LOADINKMEM 1
+#define USE_FEATURE_INSMOD_LOADINKMEM(...)  __VA_ARGS__
+#define SKIP_FEATURE_INSMOD_LOADINKMEM(...)
+
+#undef CONFIG_FEATURE_INSMOD_LOAD_MAP
+#define ENABLE_FEATURE_INSMOD_LOAD_MAP 0
+#define USE_FEATURE_INSMOD_LOAD_MAP(...)
+#define SKIP_FEATURE_INSMOD_LOAD_MAP(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
+#define ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL 0
+#define USE_FEATURE_INSMOD_LOAD_MAP_FULL(...)
+#define SKIP_FEATURE_INSMOD_LOAD_MAP_FULL(...)  __VA_ARGS__
+
+#undef CONFIG_RMMOD
+#define ENABLE_RMMOD 0
+#define USE_RMMOD(...)
+#define SKIP_RMMOD(...)  __VA_ARGS__
+
+#define CONFIG_LSMOD 1
+#define ENABLE_LSMOD 1
+#define USE_LSMOD(...)  __VA_ARGS__
+#define SKIP_LSMOD(...)
+
+#undef CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT
+#define ENABLE_FEATURE_LSMOD_PRETTY_2_6_OUTPUT 0
+#define USE_FEATURE_LSMOD_PRETTY_2_6_OUTPUT(...)
+#define SKIP_FEATURE_LSMOD_PRETTY_2_6_OUTPUT(...)  __VA_ARGS__
+
+#define CONFIG_MODPROBE 1
+#define ENABLE_MODPROBE 1
+#define USE_MODPROBE(...)  __VA_ARGS__
+#define SKIP_MODPROBE(...)
+
+#undef CONFIG_FEATURE_MODPROBE_MULTIPLE_OPTIONS
+#define ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS 0
+#define USE_FEATURE_MODPROBE_MULTIPLE_OPTIONS(...)
+#define SKIP_FEATURE_MODPROBE_MULTIPLE_OPTIONS(...)  __VA_ARGS__
+
+
+/*
+ * Options common to multiple modutils
+ */
+#undef CONFIG_FEATURE_CHECK_TAINTED_MODULE
+#define ENABLE_FEATURE_CHECK_TAINTED_MODULE 0
+#define USE_FEATURE_CHECK_TAINTED_MODULE(...)
+#define SKIP_FEATURE_CHECK_TAINTED_MODULE(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_2_4_MODULES 1
+#define ENABLE_FEATURE_2_4_MODULES 1
+#define USE_FEATURE_2_4_MODULES(...)  __VA_ARGS__
+#define SKIP_FEATURE_2_4_MODULES(...)
+
+#undef CONFIG_FEATURE_2_6_MODULES
+#define ENABLE_FEATURE_2_6_MODULES 0
+#define USE_FEATURE_2_6_MODULES(...)
+#define SKIP_FEATURE_2_6_MODULES(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_QUERY_MODULE_INTERFACE 1
+#define ENABLE_FEATURE_QUERY_MODULE_INTERFACE 1
+#define USE_FEATURE_QUERY_MODULE_INTERFACE(...)  __VA_ARGS__
+#define SKIP_FEATURE_QUERY_MODULE_INTERFACE(...)
+
+
+/*
+ * Linux System Utilities
+ */
+#define CONFIG_DMESG 1
+#define ENABLE_DMESG 1
+#define USE_DMESG(...)  __VA_ARGS__
+#define SKIP_DMESG(...)
+
+#undef CONFIG_FBSET
+#define ENABLE_FBSET 0
+#define USE_FBSET(...)
+#define SKIP_FBSET(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_FBSET_FANCY
+#define ENABLE_FEATURE_FBSET_FANCY 0
+#define USE_FEATURE_FBSET_FANCY(...)
+#define SKIP_FEATURE_FBSET_FANCY(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_FBSET_READMODE
+#define ENABLE_FEATURE_FBSET_READMODE 0
+#define USE_FEATURE_FBSET_READMODE(...)
+#define SKIP_FEATURE_FBSET_READMODE(...)  __VA_ARGS__
+
+#undef CONFIG_FDFLUSH
+#define ENABLE_FDFLUSH 0
+#define USE_FDFLUSH(...)
+#define SKIP_FDFLUSH(...)  __VA_ARGS__
+
+#undef CONFIG_FDFORMAT
+#define ENABLE_FDFORMAT 0
+#define USE_FDFORMAT(...)
+#define SKIP_FDFORMAT(...)  __VA_ARGS__
+
+#undef CONFIG_FDISK
+#define ENABLE_FDISK 0
+#define USE_FDISK(...)
+#define SKIP_FDISK(...)  __VA_ARGS__
+
+#undef FDISK_SUPPORT_LARGE_DISKS
+#define ENABLE_SUPPORT_LARGE_DISKS 0
+#define USE_SUPPORT_LARGE_DISKS(...)
+#define SKIP_SUPPORT_LARGE_DISKS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_FDISK_WRITABLE
+#define ENABLE_FEATURE_FDISK_WRITABLE 0
+#define USE_FEATURE_FDISK_WRITABLE(...)
+#define SKIP_FEATURE_FDISK_WRITABLE(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_AIX_LABEL
+#define ENABLE_FEATURE_AIX_LABEL 0
+#define USE_FEATURE_AIX_LABEL(...)
+#define SKIP_FEATURE_AIX_LABEL(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_SGI_LABEL
+#define ENABLE_FEATURE_SGI_LABEL 0
+#define USE_FEATURE_SGI_LABEL(...)
+#define SKIP_FEATURE_SGI_LABEL(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_SUN_LABEL
+#define ENABLE_FEATURE_SUN_LABEL 0
+#define USE_FEATURE_SUN_LABEL(...)
+#define SKIP_FEATURE_SUN_LABEL(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_OSF_LABEL
+#define ENABLE_FEATURE_OSF_LABEL 0
+#define USE_FEATURE_OSF_LABEL(...)
+#define SKIP_FEATURE_OSF_LABEL(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_FDISK_ADVANCED
+#define ENABLE_FEATURE_FDISK_ADVANCED 0
+#define USE_FEATURE_FDISK_ADVANCED(...)
+#define SKIP_FEATURE_FDISK_ADVANCED(...)  __VA_ARGS__
+
+#undef CONFIG_FREERAMDISK
+#define ENABLE_FREERAMDISK 0
+#define USE_FREERAMDISK(...)
+#define SKIP_FREERAMDISK(...)  __VA_ARGS__
+
+#undef CONFIG_FSCK_MINIX
+#define ENABLE_FSCK_MINIX 0
+#define USE_FSCK_MINIX(...)
+#define SKIP_FSCK_MINIX(...)  __VA_ARGS__
+
+#undef CONFIG_MKFS_MINIX
+#define ENABLE_MKFS_MINIX 0
+#define USE_MKFS_MINIX(...)
+#define SKIP_MKFS_MINIX(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_MINIX2
+#define ENABLE_FEATURE_MINIX2 0
+#define USE_FEATURE_MINIX2(...)
+#define SKIP_FEATURE_MINIX2(...)  __VA_ARGS__
+
+#undef CONFIG_GETOPT
+#define ENABLE_GETOPT 0
+#define USE_GETOPT(...)
+#define SKIP_GETOPT(...)  __VA_ARGS__
+
+#undef CONFIG_HEXDUMP
+#define ENABLE_HEXDUMP 0
+#define USE_HEXDUMP(...)
+#define SKIP_HEXDUMP(...)  __VA_ARGS__
+
+#undef CONFIG_HWCLOCK
+#define ENABLE_HWCLOCK 0
+#define USE_HWCLOCK(...)
+#define SKIP_HWCLOCK(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS
+#define ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS 0
+#define USE_FEATURE_HWCLOCK_LONG_OPTIONS(...)
+#define SKIP_FEATURE_HWCLOCK_LONG_OPTIONS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS
+#define ENABLE_FEATURE_HWCLOCK_ADJTIME_FHS 0
+#define USE_FEATURE_HWCLOCK_ADJTIME_FHS(...)
+#define SKIP_FEATURE_HWCLOCK_ADJTIME_FHS(...)  __VA_ARGS__
+
+#undef CONFIG_IPCRM
+#define ENABLE_IPCRM 0
+#define USE_IPCRM(...)
+#define SKIP_IPCRM(...)  __VA_ARGS__
+
+#undef CONFIG_IPCS
+#define ENABLE_IPCS 0
+#define USE_IPCS(...)
+#define SKIP_IPCS(...)  __VA_ARGS__
+
+#undef CONFIG_LOSETUP
+#define ENABLE_LOSETUP 0
+#define USE_LOSETUP(...)
+#define SKIP_LOSETUP(...)  __VA_ARGS__
+
+#undef CONFIG_MDEV
+#define ENABLE_MDEV 0
+#define USE_MDEV(...)
+#define SKIP_MDEV(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_MDEV_CONF
+#define ENABLE_FEATURE_MDEV_CONF 0
+#define USE_FEATURE_MDEV_CONF(...)
+#define SKIP_FEATURE_MDEV_CONF(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_MDEV_EXEC
+#define ENABLE_FEATURE_MDEV_EXEC 0
+#define USE_FEATURE_MDEV_EXEC(...)
+#define SKIP_FEATURE_MDEV_EXEC(...)  __VA_ARGS__
+
+#undef CONFIG_MKSWAP
+#define ENABLE_MKSWAP 0
+#define USE_MKSWAP(...)
+#define SKIP_MKSWAP(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_MKSWAP_V0
+#define ENABLE_FEATURE_MKSWAP_V0 0
+#define USE_FEATURE_MKSWAP_V0(...)
+#define SKIP_FEATURE_MKSWAP_V0(...)  __VA_ARGS__
+
+#define CONFIG_MORE 1
+#define ENABLE_MORE 1
+#define USE_MORE(...)  __VA_ARGS__
+#define SKIP_MORE(...)
+
+#undef CONFIG_FEATURE_USE_TERMIOS
+#define ENABLE_FEATURE_USE_TERMIOS 0
+#define USE_FEATURE_USE_TERMIOS(...)
+#define SKIP_FEATURE_USE_TERMIOS(...)  __VA_ARGS__
+
+#define CONFIG_MOUNT 1
+#define ENABLE_MOUNT 1
+#define USE_MOUNT(...)  __VA_ARGS__
+#define SKIP_MOUNT(...)
+
+#define CONFIG_FEATURE_MOUNT_NFS 1
+#define ENABLE_FEATURE_MOUNT_NFS 1
+#define USE_FEATURE_MOUNT_NFS(...)  __VA_ARGS__
+#define SKIP_FEATURE_MOUNT_NFS(...)
+
+#define CONFIG_PIVOT_ROOT 1
+#define ENABLE_PIVOT_ROOT 1
+#define USE_PIVOT_ROOT(...)  __VA_ARGS__
+#define SKIP_PIVOT_ROOT(...)
+
+#define CONFIG_RDATE 1
+#define ENABLE_RDATE 1
+#define USE_RDATE(...)  __VA_ARGS__
+#define SKIP_RDATE(...)
+
+#undef CONFIG_READPROFILE
+#define ENABLE_READPROFILE 0
+#define USE_READPROFILE(...)
+#define SKIP_READPROFILE(...)  __VA_ARGS__
+
+#undef CONFIG_SETARCH
+#define ENABLE_SETARCH 0
+#define USE_SETARCH(...)
+#define SKIP_SETARCH(...)  __VA_ARGS__
+
+#undef CONFIG_SWAPONOFF
+#define ENABLE_SWAPONOFF 0
+#define USE_SWAPONOFF(...)
+#define SKIP_SWAPONOFF(...)  __VA_ARGS__
+
+#undef CONFIG_SWITCH_ROOT
+#define ENABLE_SWITCH_ROOT 0
+#define USE_SWITCH_ROOT(...)
+#define SKIP_SWITCH_ROOT(...)  __VA_ARGS__
+
+#define CONFIG_UMOUNT 1
+#define ENABLE_UMOUNT 1
+#define USE_UMOUNT(...)  __VA_ARGS__
+#define SKIP_UMOUNT(...)
+
+#undef CONFIG_FEATURE_UMOUNT_ALL
+#define ENABLE_FEATURE_UMOUNT_ALL 0
+#define USE_FEATURE_UMOUNT_ALL(...)
+#define SKIP_FEATURE_UMOUNT_ALL(...)  __VA_ARGS__
+
+
+/*
+ * Common options for mount/umount
+ */
+#define CONFIG_FEATURE_MOUNT_LOOP 1
+#define ENABLE_FEATURE_MOUNT_LOOP 1
+#define USE_FEATURE_MOUNT_LOOP(...)  __VA_ARGS__
+#define SKIP_FEATURE_MOUNT_LOOP(...)
+
+#undef CONFIG_FEATURE_MTAB_SUPPORT
+#define ENABLE_FEATURE_MTAB_SUPPORT 0
+#define USE_FEATURE_MTAB_SUPPORT(...)
+#define SKIP_FEATURE_MTAB_SUPPORT(...)  __VA_ARGS__
+
+
+/*
+ * Miscellaneous Utilities
+ */
+#undef CONFIG_ADJTIMEX
+#define ENABLE_ADJTIMEX 0
+#define USE_ADJTIMEX(...)
+#define SKIP_ADJTIMEX(...)  __VA_ARGS__
+
+#undef CONFIG_BBCONFIG
+#define ENABLE_BBCONFIG 0
+#define USE_BBCONFIG(...)
+#define SKIP_BBCONFIG(...)  __VA_ARGS__
+
+#define CONFIG_CROND 1
+#define ENABLE_CROND 1
+#define USE_CROND(...)  __VA_ARGS__
+#define SKIP_CROND(...)
+
+#undef CONFIG_DEBUG_CROND_OPTION
+#define ENABLE_DEBUG_CROND_OPTION 0
+#define USE_DEBUG_CROND_OPTION(...)
+#define SKIP_DEBUG_CROND_OPTION(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_CROND_CALL_SENDMAIL
+#define ENABLE_FEATURE_CROND_CALL_SENDMAIL 0
+#define USE_FEATURE_CROND_CALL_SENDMAIL(...)
+#define SKIP_FEATURE_CROND_CALL_SENDMAIL(...)  __VA_ARGS__
+
+#define CONFIG_CRONTAB 1
+#define ENABLE_CRONTAB 1
+#define USE_CRONTAB(...)  __VA_ARGS__
+#define SKIP_CRONTAB(...)
+
+#undef CONFIG_DC
+#define ENABLE_DC 0
+#define USE_DC(...)
+#define SKIP_DC(...)  __VA_ARGS__
+
+#undef CONFIG_DEVFSD
+#define ENABLE_DEVFSD 0
+#define USE_DEVFSD(...)
+#define SKIP_DEVFSD(...)  __VA_ARGS__
+
+#undef CONFIG_DEVFSD_MODLOAD
+#define ENABLE_DEVFSD_MODLOAD 0
+#define USE_DEVFSD_MODLOAD(...)
+#define SKIP_DEVFSD_MODLOAD(...)  __VA_ARGS__
+
+#undef CONFIG_DEVFSD_FG_NP
+#define ENABLE_DEVFSD_FG_NP 0
+#define USE_DEVFSD_FG_NP(...)
+#define SKIP_DEVFSD_FG_NP(...)  __VA_ARGS__
+
+#undef CONFIG_DEVFSD_VERBOSE
+#define ENABLE_DEVFSD_VERBOSE 0
+#define USE_DEVFSD_VERBOSE(...)
+#define SKIP_DEVFSD_VERBOSE(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_DEVFS
+#define ENABLE_FEATURE_DEVFS 0
+#define USE_FEATURE_DEVFS(...)
+#define SKIP_FEATURE_DEVFS(...)  __VA_ARGS__
+
+#undef CONFIG_EJECT
+#define ENABLE_EJECT 0
+#define USE_EJECT(...)
+#define SKIP_EJECT(...)  __VA_ARGS__
+
+#undef CONFIG_LAST
+#define ENABLE_LAST 0
+#define USE_LAST(...)
+#define SKIP_LAST(...)  __VA_ARGS__
+
+#undef CONFIG_LESS
+#define ENABLE_LESS 0
+#define USE_LESS(...)
+#define SKIP_LESS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_LESS_BRACKETS
+#define ENABLE_FEATURE_LESS_BRACKETS 0
+#define USE_FEATURE_LESS_BRACKETS(...)
+#define SKIP_FEATURE_LESS_BRACKETS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_LESS_FLAGS
+#define ENABLE_FEATURE_LESS_FLAGS 0
+#define USE_FEATURE_LESS_FLAGS(...)
+#define SKIP_FEATURE_LESS_FLAGS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_LESS_FLAGCS
+#define ENABLE_FEATURE_LESS_FLAGCS 0
+#define USE_FEATURE_LESS_FLAGCS(...)
+#define SKIP_FEATURE_LESS_FLAGCS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_LESS_MARKS
+#define ENABLE_FEATURE_LESS_MARKS 0
+#define USE_FEATURE_LESS_MARKS(...)
+#define SKIP_FEATURE_LESS_MARKS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_LESS_REGEXP
+#define ENABLE_FEATURE_LESS_REGEXP 0
+#define USE_FEATURE_LESS_REGEXP(...)
+#define SKIP_FEATURE_LESS_REGEXP(...)  __VA_ARGS__
+
+#undef CONFIG_HDPARM
+#define ENABLE_HDPARM 0
+#define USE_HDPARM(...)
+#define SKIP_HDPARM(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HDPARM_GET_IDENTITY
+#define ENABLE_FEATURE_HDPARM_GET_IDENTITY 0
+#define USE_FEATURE_HDPARM_GET_IDENTITY(...)
+#define SKIP_FEATURE_HDPARM_GET_IDENTITY(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF
+#define ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF 0
+#define USE_FEATURE_HDPARM_HDIO_SCAN_HWIF(...)
+#define SKIP_FEATURE_HDPARM_HDIO_SCAN_HWIF(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
+#define ENABLE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF 0
+#define USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(...)
+#define SKIP_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET
+#define ENABLE_FEATURE_HDPARM_HDIO_DRIVE_RESET 0
+#define USE_FEATURE_HDPARM_HDIO_DRIVE_RESET(...)
+#define SKIP_FEATURE_HDPARM_HDIO_DRIVE_RESET(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
+#define ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF 0
+#define USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(...)
+#define SKIP_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA
+#define ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA 0
+#define USE_FEATURE_HDPARM_HDIO_GETSET_DMA(...)
+#define SKIP_FEATURE_HDPARM_HDIO_GETSET_DMA(...)  __VA_ARGS__
+
+#undef CONFIG_MAKEDEVS
+#define ENABLE_MAKEDEVS 0
+#define USE_MAKEDEVS(...)
+#define SKIP_MAKEDEVS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_MAKEDEVS_LEAF
+#define ENABLE_FEATURE_MAKEDEVS_LEAF 0
+#define USE_FEATURE_MAKEDEVS_LEAF(...)
+#define SKIP_FEATURE_MAKEDEVS_LEAF(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_MAKEDEVS_TABLE
+#define ENABLE_FEATURE_MAKEDEVS_TABLE 0
+#define USE_FEATURE_MAKEDEVS_TABLE(...)
+#define SKIP_FEATURE_MAKEDEVS_TABLE(...)  __VA_ARGS__
+
+#undef CONFIG_MOUNTPOINT
+#define ENABLE_MOUNTPOINT 0
+#define USE_MOUNTPOINT(...)
+#define SKIP_MOUNTPOINT(...)  __VA_ARGS__
+
+#undef CONFIG_MT
+#define ENABLE_MT 0
+#define USE_MT(...)
+#define SKIP_MT(...)  __VA_ARGS__
+
+#undef CONFIG_RUNLEVEL
+#define ENABLE_RUNLEVEL 0
+#define USE_RUNLEVEL(...)
+#define SKIP_RUNLEVEL(...)  __VA_ARGS__
+
+#undef CONFIG_RX
+#define ENABLE_RX 0
+#define USE_RX(...)
+#define SKIP_RX(...)  __VA_ARGS__
+
+#define CONFIG_STRINGS 1
+#define ENABLE_STRINGS 1
+#define USE_STRINGS(...)  __VA_ARGS__
+#define SKIP_STRINGS(...)
+
+#undef CONFIG_SETSID
+#define ENABLE_SETSID 0
+#define USE_SETSID(...)
+#define SKIP_SETSID(...)  __VA_ARGS__
+
+#undef CONFIG_TASKSET
+#define ENABLE_TASKSET 0
+#define USE_TASKSET(...)
+#define SKIP_TASKSET(...)  __VA_ARGS__
+
+#define CONFIG_TIME 1
+#define ENABLE_TIME 1
+#define USE_TIME(...)  __VA_ARGS__
+#define SKIP_TIME(...)
+
+#undef CONFIG_WATCHDOG
+#define ENABLE_WATCHDOG 0
+#define USE_WATCHDOG(...)
+#define SKIP_WATCHDOG(...)  __VA_ARGS__
+
+
+/*
+ * Networking Utilities
+ */
+#undef CONFIG_FEATURE_IPV6
+#define ENABLE_FEATURE_IPV6 0
+#define USE_FEATURE_IPV6(...)
+#define SKIP_FEATURE_IPV6(...)  __VA_ARGS__
+
+#define CONFIG_ARPING 1
+#define ENABLE_ARPING 1
+#define USE_ARPING(...)  __VA_ARGS__
+#define SKIP_ARPING(...)
+
+#undef CONFIG_DNSD
+#define ENABLE_DNSD 0
+#define USE_DNSD(...)
+#define SKIP_DNSD(...)  __VA_ARGS__
+
+#undef CONFIG_ETHER_WAKE
+#define ENABLE_ETHER_WAKE 0
+#define USE_ETHER_WAKE(...)
+#define SKIP_ETHER_WAKE(...)  __VA_ARGS__
+
+#undef CONFIG_FAKEIDENTD
+#define ENABLE_FAKEIDENTD 0
+#define USE_FAKEIDENTD(...)
+#define SKIP_FAKEIDENTD(...)  __VA_ARGS__
+
+#define CONFIG_FTPGET 1
+#define ENABLE_FTPGET 1
+#define USE_FTPGET(...)  __VA_ARGS__
+#define SKIP_FTPGET(...)
+
+#define CONFIG_FTPPUT 1
+#define ENABLE_FTPPUT 1
+#define USE_FTPPUT(...)  __VA_ARGS__
+#define SKIP_FTPPUT(...)
+
+#undef CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS
+#define ENABLE_FEATURE_FTPGETPUT_LONG_OPTIONS 0
+#define USE_FEATURE_FTPGETPUT_LONG_OPTIONS(...)
+#define SKIP_FEATURE_FTPGETPUT_LONG_OPTIONS(...)  __VA_ARGS__
+
+#undef CONFIG_HOSTNAME
+#define ENABLE_HOSTNAME 0
+#define USE_HOSTNAME(...)
+#define SKIP_HOSTNAME(...)  __VA_ARGS__
+
+#undef CONFIG_HTTPD
+#define ENABLE_HTTPD 0
+#define USE_HTTPD(...)
+#define SKIP_HTTPD(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+#define ENABLE_FEATURE_HTTPD_WITHOUT_INETD 0
+#define USE_FEATURE_HTTPD_WITHOUT_INETD(...)
+#define SKIP_FEATURE_HTTPD_WITHOUT_INETD(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
+#define ENABLE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP 0
+#define USE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP(...)
+#define SKIP_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HTTPD_SETUID
+#define ENABLE_FEATURE_HTTPD_SETUID 0
+#define USE_FEATURE_HTTPD_SETUID(...)
+#define SKIP_FEATURE_HTTPD_SETUID(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+#define ENABLE_FEATURE_HTTPD_BASIC_AUTH 0
+#define USE_FEATURE_HTTPD_BASIC_AUTH(...)
+#define SKIP_FEATURE_HTTPD_BASIC_AUTH(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HTTPD_AUTH_MD5
+#define ENABLE_FEATURE_HTTPD_AUTH_MD5 0
+#define USE_FEATURE_HTTPD_AUTH_MD5(...)
+#define SKIP_FEATURE_HTTPD_AUTH_MD5(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
+#define ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES 0
+#define USE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES(...)
+#define SKIP_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HTTPD_CGI
+#define ENABLE_FEATURE_HTTPD_CGI 0
+#define USE_FEATURE_HTTPD_CGI(...)
+#define SKIP_FEATURE_HTTPD_CGI(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
+#define ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR 0
+#define USE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR(...)
+#define SKIP_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
+#define ENABLE_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV 0
+#define USE_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV(...)
+#define SKIP_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_HTTPD_ENCODE_URL_STR
+#define ENABLE_FEATURE_HTTPD_ENCODE_URL_STR 0
+#define USE_FEATURE_HTTPD_ENCODE_URL_STR(...)
+#define SKIP_FEATURE_HTTPD_ENCODE_URL_STR(...)  __VA_ARGS__
+
+#define CONFIG_IFCONFIG 1
+#define ENABLE_IFCONFIG 1
+#define USE_IFCONFIG(...)  __VA_ARGS__
+#define SKIP_IFCONFIG(...)
+
+#define CONFIG_FEATURE_IFCONFIG_STATUS 1
+#define ENABLE_FEATURE_IFCONFIG_STATUS 1
+#define USE_FEATURE_IFCONFIG_STATUS(...)  __VA_ARGS__
+#define SKIP_FEATURE_IFCONFIG_STATUS(...)
+
+#undef CONFIG_FEATURE_IFCONFIG_SLIP
+#define ENABLE_FEATURE_IFCONFIG_SLIP 0
+#define USE_FEATURE_IFCONFIG_SLIP(...)
+#define SKIP_FEATURE_IFCONFIG_SLIP(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
+#define ENABLE_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ 0
+#define USE_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ(...)
+#define SKIP_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_IFCONFIG_HW
+#define ENABLE_FEATURE_IFCONFIG_HW 0
+#define USE_FEATURE_IFCONFIG_HW(...)
+#define SKIP_FEATURE_IFCONFIG_HW(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS
+#define ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS 0
+#define USE_FEATURE_IFCONFIG_BROADCAST_PLUS(...)
+#define SKIP_FEATURE_IFCONFIG_BROADCAST_PLUS(...)  __VA_ARGS__
+
+#undef CONFIG_IFUPDOWN
+#define ENABLE_IFUPDOWN 0
+#define USE_IFUPDOWN(...)
+#define SKIP_IFUPDOWN(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_IFUPDOWN_IP
+#define ENABLE_FEATURE_IFUPDOWN_IP 0
+#define USE_FEATURE_IFUPDOWN_IP(...)
+#define SKIP_FEATURE_IFUPDOWN_IP(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN
+#define ENABLE_FEATURE_IFUPDOWN_IP_BUILTIN 0
+#define USE_FEATURE_IFUPDOWN_IP_BUILTIN(...)
+#define SKIP_FEATURE_IFUPDOWN_IP_BUILTIN(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_IFUPDOWN_IPV4
+#define ENABLE_FEATURE_IFUPDOWN_IPV4 0
+#define USE_FEATURE_IFUPDOWN_IPV4(...)
+#define SKIP_FEATURE_IFUPDOWN_IPV4(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_IFUPDOWN_IPV6
+#define ENABLE_FEATURE_IFUPDOWN_IPV6 0
+#define USE_FEATURE_IFUPDOWN_IPV6(...)
+#define SKIP_FEATURE_IFUPDOWN_IPV6(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_IFUPDOWN_IPX
+#define ENABLE_FEATURE_IFUPDOWN_IPX 0
+#define USE_FEATURE_IFUPDOWN_IPX(...)
+#define SKIP_FEATURE_IFUPDOWN_IPX(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_IFUPDOWN_MAPPING
+#define ENABLE_FEATURE_IFUPDOWN_MAPPING 0
+#define USE_FEATURE_IFUPDOWN_MAPPING(...)
+#define SKIP_FEATURE_IFUPDOWN_MAPPING(...)  __VA_ARGS__
+
+#undef CONFIG_INETD
+#define ENABLE_INETD 0
+#define USE_INETD(...)
+#define SKIP_INETD(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
+#define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO 0
+#define USE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO(...)
+#define SKIP_FEATURE_INETD_SUPPORT_BUILTIN_ECHO(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
+#define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD 0
+#define USE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD(...)
+#define SKIP_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME
+#define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_TIME 0
+#define USE_FEATURE_INETD_SUPPORT_BUILTIN_TIME(...)
+#define SKIP_FEATURE_INETD_SUPPORT_BUILTIN_TIME(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
+#define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME 0
+#define USE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME(...)
+#define SKIP_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+#define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN 0
+#define USE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN(...)
+#define SKIP_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_INETD_RPC
+#define ENABLE_FEATURE_INETD_RPC 0
+#define USE_FEATURE_INETD_RPC(...)
+#define SKIP_FEATURE_INETD_RPC(...)  __VA_ARGS__
+
+#undef CONFIG_IP
+#define ENABLE_IP 0
+#define USE_IP(...)
+#define SKIP_IP(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_IP_ADDRESS
+#define ENABLE_FEATURE_IP_ADDRESS 0
+#define USE_FEATURE_IP_ADDRESS(...)
+#define SKIP_FEATURE_IP_ADDRESS(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_IP_LINK
+#define ENABLE_FEATURE_IP_LINK 0
+#define USE_FEATURE_IP_LINK(...)
+#define SKIP_FEATURE_IP_LINK(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_IP_ROUTE
+#define ENABLE_FEATURE_IP_ROUTE 0
+#define USE_FEATURE_IP_ROUTE(...)
+#define SKIP_FEATURE_IP_ROUTE(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_IP_TUNNEL
+#define ENABLE_FEATURE_IP_TUNNEL 0
+#define USE_FEATURE_IP_TUNNEL(...)
+#define SKIP_FEATURE_IP_TUNNEL(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_IP_SHORT_FORMS
+#define ENABLE_FEATURE_IP_SHORT_FORMS 0
+#define USE_FEATURE_IP_SHORT_FORMS(...)
+#define SKIP_FEATURE_IP_SHORT_FORMS(...)  __VA_ARGS__
+
+#undef CONFIG_IPADDR
+#define ENABLE_IPADDR 0
+#define USE_IPADDR(...)
+#define SKIP_IPADDR(...)  __VA_ARGS__
+
+#undef CONFIG_IPLINK
+#define ENABLE_IPLINK 0
+#define USE_IPLINK(...)
+#define SKIP_IPLINK(...)  __VA_ARGS__
+
+#undef CONFIG_IPROUTE
+#define ENABLE_IPROUTE 0
+#define USE_IPROUTE(...)
+#define SKIP_IPROUTE(...)  __VA_ARGS__
+
+#undef CONFIG_IPTUNNEL
+#define ENABLE_IPTUNNEL 0
+#define USE_IPTUNNEL(...)
+#define SKIP_IPTUNNEL(...)  __VA_ARGS__
+
+#undef CONFIG_IPCALC
+#define ENABLE_IPCALC 0
+#define USE_IPCALC(...)
+#define SKIP_IPCALC(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_IPCALC_FANCY
+#define ENABLE_FEATURE_IPCALC_FANCY 0
+#define USE_FEATURE_IPCALC_FANCY(...)
+#define SKIP_FEATURE_IPCALC_FANCY(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_IPCALC_LONG_OPTIONS
+#define ENABLE_FEATURE_IPCALC_LONG_OPTIONS 0
+#define USE_FEATURE_IPCALC_LONG_OPTIONS(...)
+#define SKIP_FEATURE_IPCALC_LONG_OPTIONS(...)  __VA_ARGS__
+
+#undef CONFIG_NAMEIF
+#define ENABLE_NAMEIF 0
+#define USE_NAMEIF(...)
+#define SKIP_NAMEIF(...)  __VA_ARGS__
+
+#define CONFIG_NC 1
+#define ENABLE_NC 1
+#define USE_NC(...)  __VA_ARGS__
+#define SKIP_NC(...)
+
+#undef CONFIG_NC_GAPING_SECURITY_HOLE
+#define ENABLE_NC_GAPING_SECURITY_HOLE 0
+#define USE_NC_GAPING_SECURITY_HOLE(...)
+#define SKIP_NC_GAPING_SECURITY_HOLE(...)  __VA_ARGS__
+
+#define CONFIG_NETSTAT 1
+#define ENABLE_NETSTAT 1
+#define USE_NETSTAT(...)  __VA_ARGS__
+#define SKIP_NETSTAT(...)
+
+#define CONFIG_NSLOOKUP 1
+#define ENABLE_NSLOOKUP 1
+#define USE_NSLOOKUP(...)  __VA_ARGS__
+#define SKIP_NSLOOKUP(...)
+
+#define CONFIG_PING 1
+#define ENABLE_PING 1
+#define USE_PING(...)  __VA_ARGS__
+#define SKIP_PING(...)
+
+#undef CONFIG_FEATURE_FANCY_PING
+#define ENABLE_FEATURE_FANCY_PING 0
+#define USE_FEATURE_FANCY_PING(...)
+#define SKIP_FEATURE_FANCY_PING(...)  __VA_ARGS__
+
+#undef CONFIG_PING6
+#define ENABLE_PING6 0
+#define USE_PING6(...)
+#define SKIP_PING6(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_FANCY_PING6
+#define ENABLE_FEATURE_FANCY_PING6 0
+#define USE_FEATURE_FANCY_PING6(...)
+#define SKIP_FEATURE_FANCY_PING6(...)  __VA_ARGS__
+
+#undef CONFIG_ROUTE
+#define ENABLE_ROUTE 0
+#define USE_ROUTE(...)
+#define SKIP_ROUTE(...)  __VA_ARGS__
+
+#undef CONFIG_TELNET
+#define ENABLE_TELNET 0
+#define USE_TELNET(...)
+#define SKIP_TELNET(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_TELNET_TTYPE
+#define ENABLE_FEATURE_TELNET_TTYPE 0
+#define USE_FEATURE_TELNET_TTYPE(...)
+#define SKIP_FEATURE_TELNET_TTYPE(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_TELNET_AUTOLOGIN
+#define ENABLE_FEATURE_TELNET_AUTOLOGIN 0
+#define USE_FEATURE_TELNET_AUTOLOGIN(...)
+#define SKIP_FEATURE_TELNET_AUTOLOGIN(...)  __VA_ARGS__
+
+#undef CONFIG_TELNETD
+#define ENABLE_TELNETD 0
+#define USE_TELNETD(...)
+#define SKIP_TELNETD(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_TELNETD_INETD
+#define ENABLE_FEATURE_TELNETD_INETD 0
+#define USE_FEATURE_TELNETD_INETD(...)
+#define SKIP_FEATURE_TELNETD_INETD(...)  __VA_ARGS__
+
+#define CONFIG_TFTP 1
+#define ENABLE_TFTP 1
+#define USE_TFTP(...)  __VA_ARGS__
+#define SKIP_TFTP(...)
+
+#define CONFIG_FEATURE_TFTP_GET 1
+#define ENABLE_FEATURE_TFTP_GET 1
+#define USE_FEATURE_TFTP_GET(...)  __VA_ARGS__
+#define SKIP_FEATURE_TFTP_GET(...)
+
+#define CONFIG_FEATURE_TFTP_PUT 1
+#define ENABLE_FEATURE_TFTP_PUT 1
+#define USE_FEATURE_TFTP_PUT(...)  __VA_ARGS__
+#define SKIP_FEATURE_TFTP_PUT(...)
+
+#undef CONFIG_FEATURE_TFTP_BLOCKSIZE
+#define ENABLE_FEATURE_TFTP_BLOCKSIZE 0
+#define USE_FEATURE_TFTP_BLOCKSIZE(...)
+#define SKIP_FEATURE_TFTP_BLOCKSIZE(...)  __VA_ARGS__
+
+#undef CONFIG_DEBUG_TFTP
+#define ENABLE_DEBUG_TFTP 0
+#define USE_DEBUG_TFTP(...)
+#define SKIP_DEBUG_TFTP(...)  __VA_ARGS__
+
+#define CONFIG_TRACEROUTE 1
+#define ENABLE_TRACEROUTE 1
+#define USE_TRACEROUTE(...)  __VA_ARGS__
+#define SKIP_TRACEROUTE(...)
+
+#undef CONFIG_FEATURE_TRACEROUTE_VERBOSE
+#define ENABLE_FEATURE_TRACEROUTE_VERBOSE 0
+#define USE_FEATURE_TRACEROUTE_VERBOSE(...)
+#define SKIP_FEATURE_TRACEROUTE_VERBOSE(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
+#define ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 0
+#define USE_FEATURE_TRACEROUTE_SOURCE_ROUTE(...)
+#define SKIP_FEATURE_TRACEROUTE_SOURCE_ROUTE(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
+#define ENABLE_FEATURE_TRACEROUTE_USE_ICMP 0
+#define USE_FEATURE_TRACEROUTE_USE_ICMP(...)
+#define SKIP_FEATURE_TRACEROUTE_USE_ICMP(...)  __VA_ARGS__
+
+
+/*
+ * udhcp Server/Client
+ */
+#undef CONFIG_APP_UDHCPD
+#define ENABLE_APP_UDHCPD 0
+#define USE_APP_UDHCPD(...)
+#define SKIP_APP_UDHCPD(...)  __VA_ARGS__
+
+#undef CONFIG_APP_UDHCPC
+#define ENABLE_APP_UDHCPC 0
+#define USE_APP_UDHCPC(...)
+#define SKIP_APP_UDHCPC(...)  __VA_ARGS__
+
+#undef CONFIG_APP_DUMPLEASES
+#define ENABLE_APP_DUMPLEASES 0
+#define USE_APP_DUMPLEASES(...)
+#define SKIP_APP_DUMPLEASES(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_UDHCP_SYSLOG
+#define ENABLE_FEATURE_UDHCP_SYSLOG 0
+#define USE_FEATURE_UDHCP_SYSLOG(...)
+#define SKIP_FEATURE_UDHCP_SYSLOG(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_UDHCP_DEBUG
+#define ENABLE_FEATURE_UDHCP_DEBUG 0
+#define USE_FEATURE_UDHCP_DEBUG(...)
+#define SKIP_FEATURE_UDHCP_DEBUG(...)  __VA_ARGS__
+
+#undef CONFIG_VCONFIG
+#define ENABLE_VCONFIG 0
+#define USE_VCONFIG(...)
+#define SKIP_VCONFIG(...)  __VA_ARGS__
+
+#define CONFIG_WGET 1
+#define ENABLE_WGET 1
+#define USE_WGET(...)  __VA_ARGS__
+#define SKIP_WGET(...)
+
+#undef CONFIG_FEATURE_WGET_STATUSBAR
+#define ENABLE_FEATURE_WGET_STATUSBAR 0
+#define USE_FEATURE_WGET_STATUSBAR(...)
+#define SKIP_FEATURE_WGET_STATUSBAR(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_WGET_AUTHENTICATION
+#define ENABLE_FEATURE_WGET_AUTHENTICATION 0
+#define USE_FEATURE_WGET_AUTHENTICATION(...)
+#define SKIP_FEATURE_WGET_AUTHENTICATION(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_WGET_IP6_LITERAL
+#define ENABLE_FEATURE_WGET_IP6_LITERAL 0
+#define USE_FEATURE_WGET_IP6_LITERAL(...)
+#define SKIP_FEATURE_WGET_IP6_LITERAL(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_WGET_LONG_OPTIONS
+#define ENABLE_FEATURE_WGET_LONG_OPTIONS 0
+#define USE_FEATURE_WGET_LONG_OPTIONS(...)
+#define SKIP_FEATURE_WGET_LONG_OPTIONS(...)  __VA_ARGS__
+
+#undef CONFIG_ZCIP
+#define ENABLE_ZCIP 0
+#define USE_ZCIP(...)
+#define SKIP_ZCIP(...)  __VA_ARGS__
+
+
+/*
+ * Process Utilities
+ */
+#define CONFIG_FREE 1
+#define ENABLE_FREE 1
+#define USE_FREE(...)  __VA_ARGS__
+#define SKIP_FREE(...)
+
+#undef CONFIG_FUSER
+#define ENABLE_FUSER 0
+#define USE_FUSER(...)
+#define SKIP_FUSER(...)  __VA_ARGS__
+
+#define CONFIG_KILL 1
+#define ENABLE_KILL 1
+#define USE_KILL(...)  __VA_ARGS__
+#define SKIP_KILL(...)
+
+#define CONFIG_KILLALL 1
+#define ENABLE_KILLALL 1
+#define USE_KILLALL(...)  __VA_ARGS__
+#define SKIP_KILLALL(...)
+
+#undef CONFIG_PIDOF
+#define ENABLE_PIDOF 0
+#define USE_PIDOF(...)
+#define SKIP_PIDOF(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_PIDOF_SINGLE
+#define ENABLE_FEATURE_PIDOF_SINGLE 0
+#define USE_FEATURE_PIDOF_SINGLE(...)
+#define SKIP_FEATURE_PIDOF_SINGLE(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_PIDOF_OMIT
+#define ENABLE_FEATURE_PIDOF_OMIT 0
+#define USE_FEATURE_PIDOF_OMIT(...)
+#define SKIP_FEATURE_PIDOF_OMIT(...)  __VA_ARGS__
+
+#define CONFIG_PS 1
+#define ENABLE_PS 1
+#define USE_PS(...)  __VA_ARGS__
+#define SKIP_PS(...)
+
+#undef CONFIG_FEATURE_PS_WIDE
+#define ENABLE_FEATURE_PS_WIDE 0
+#define USE_FEATURE_PS_WIDE(...)
+#define SKIP_FEATURE_PS_WIDE(...)  __VA_ARGS__
+
+#undef CONFIG_RENICE
+#define ENABLE_RENICE 0
+#define USE_RENICE(...)
+#define SKIP_RENICE(...)  __VA_ARGS__
+
+#define CONFIG_BB_SYSCTL 1
+#define ENABLE_BB_SYSCTL 1
+#define USE_BB_SYSCTL(...)  __VA_ARGS__
+#define SKIP_BB_SYSCTL(...)
+
+#define CONFIG_TOP 1
+#define ENABLE_TOP 1
+#define USE_TOP(...)  __VA_ARGS__
+#define SKIP_TOP(...)
+
+#define CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 1
+#define ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 1
+#define USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(...)  __VA_ARGS__
+#define SKIP_FEATURE_TOP_CPU_USAGE_PERCENTAGE(...)
+
+#define CONFIG_UPTIME 1
+#define ENABLE_UPTIME 1
+#define USE_UPTIME(...)  __VA_ARGS__
+#define SKIP_UPTIME(...)
+
+
+/*
+ * Shells
+ */
+#undef CONFIG_FEATURE_SH_IS_ASH
+#define ENABLE_FEATURE_SH_IS_ASH 0
+#define USE_FEATURE_SH_IS_ASH(...)
+#define SKIP_FEATURE_SH_IS_ASH(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_SH_IS_HUSH
+#define ENABLE_FEATURE_SH_IS_HUSH 0
+#define USE_FEATURE_SH_IS_HUSH(...)
+#define SKIP_FEATURE_SH_IS_HUSH(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_SH_IS_LASH
+#define ENABLE_FEATURE_SH_IS_LASH 0
+#define USE_FEATURE_SH_IS_LASH(...)
+#define SKIP_FEATURE_SH_IS_LASH(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_SH_IS_MSH 1
+#define ENABLE_FEATURE_SH_IS_MSH 1
+#define USE_FEATURE_SH_IS_MSH(...)  __VA_ARGS__
+#define SKIP_FEATURE_SH_IS_MSH(...)
+
+#undef CONFIG_FEATURE_SH_IS_NONE
+#define ENABLE_FEATURE_SH_IS_NONE 0
+#define USE_FEATURE_SH_IS_NONE(...)
+#define SKIP_FEATURE_SH_IS_NONE(...)  __VA_ARGS__
+
+#undef CONFIG_ASH
+#define ENABLE_ASH 0
+#define USE_ASH(...)
+#define SKIP_ASH(...)  __VA_ARGS__
+
+#undef CONFIG_ASH_JOB_CONTROL
+#define ENABLE_ASH_JOB_CONTROL 0
+#define USE_ASH_JOB_CONTROL(...)
+#define SKIP_ASH_JOB_CONTROL(...)  __VA_ARGS__
+
+#undef CONFIG_ASH_READ_NCHARS
+#define ENABLE_ASH_READ_NCHARS 0
+#define USE_ASH_READ_NCHARS(...)
+#define SKIP_ASH_READ_NCHARS(...)  __VA_ARGS__
+
+#undef CONFIG_ASH_READ_TIMEOUT
+#define ENABLE_ASH_READ_TIMEOUT 0
+#define USE_ASH_READ_TIMEOUT(...)
+#define SKIP_ASH_READ_TIMEOUT(...)  __VA_ARGS__
+
+#undef CONFIG_ASH_ALIAS
+#define ENABLE_ASH_ALIAS 0
+#define USE_ASH_ALIAS(...)
+#define SKIP_ASH_ALIAS(...)  __VA_ARGS__
+
+#undef CONFIG_ASH_MATH_SUPPORT
+#define ENABLE_ASH_MATH_SUPPORT 0
+#define USE_ASH_MATH_SUPPORT(...)
+#define SKIP_ASH_MATH_SUPPORT(...)  __VA_ARGS__
+
+#undef CONFIG_ASH_MATH_SUPPORT_64
+#define ENABLE_ASH_MATH_SUPPORT_64 0
+#define USE_ASH_MATH_SUPPORT_64(...)
+#define SKIP_ASH_MATH_SUPPORT_64(...)  __VA_ARGS__
+
+#undef CONFIG_ASH_GETOPTS
+#define ENABLE_ASH_GETOPTS 0
+#define USE_ASH_GETOPTS(...)
+#define SKIP_ASH_GETOPTS(...)  __VA_ARGS__
+
+#undef CONFIG_ASH_BUILTIN_ECHO
+#define ENABLE_ASH_BUILTIN_ECHO 0
+#define USE_ASH_BUILTIN_ECHO(...)
+#define SKIP_ASH_BUILTIN_ECHO(...)  __VA_ARGS__
+
+#undef CONFIG_ASH_BUILTIN_TEST
+#define ENABLE_ASH_BUILTIN_TEST 0
+#define USE_ASH_BUILTIN_TEST(...)
+#define SKIP_ASH_BUILTIN_TEST(...)  __VA_ARGS__
+
+#undef CONFIG_ASH_CMDCMD
+#define ENABLE_ASH_CMDCMD 0
+#define USE_ASH_CMDCMD(...)
+#define SKIP_ASH_CMDCMD(...)  __VA_ARGS__
+
+#undef CONFIG_ASH_MAIL
+#define ENABLE_ASH_MAIL 0
+#define USE_ASH_MAIL(...)
+#define SKIP_ASH_MAIL(...)  __VA_ARGS__
+
+#undef CONFIG_ASH_OPTIMIZE_FOR_SIZE
+#define ENABLE_ASH_OPTIMIZE_FOR_SIZE 0
+#define USE_ASH_OPTIMIZE_FOR_SIZE(...)
+#define SKIP_ASH_OPTIMIZE_FOR_SIZE(...)  __VA_ARGS__
+
+#undef CONFIG_ASH_RANDOM_SUPPORT
+#define ENABLE_ASH_RANDOM_SUPPORT 0
+#define USE_ASH_RANDOM_SUPPORT(...)
+#define SKIP_ASH_RANDOM_SUPPORT(...)  __VA_ARGS__
+
+#undef CONFIG_ASH_EXPAND_PRMT
+#define ENABLE_ASH_EXPAND_PRMT 0
+#define USE_ASH_EXPAND_PRMT(...)
+#define SKIP_ASH_EXPAND_PRMT(...)  __VA_ARGS__
+
+#undef CONFIG_HUSH
+#define ENABLE_HUSH 0
+#define USE_HUSH(...)
+#define SKIP_HUSH(...)  __VA_ARGS__
+
+#undef CONFIG_LASH
+#define ENABLE_LASH 0
+#define USE_LASH(...)
+#define SKIP_LASH(...)  __VA_ARGS__
+
+#define CONFIG_MSH 1
+#define ENABLE_MSH 1
+#define USE_MSH(...)  __VA_ARGS__
+#define SKIP_MSH(...)
+
+
+/*
+ * Bourne Shell Options
+ */
+#undef CONFIG_FEATURE_SH_EXTRA_QUIET
+#define ENABLE_FEATURE_SH_EXTRA_QUIET 0
+#define USE_FEATURE_SH_EXTRA_QUIET(...)
+#define SKIP_FEATURE_SH_EXTRA_QUIET(...)  __VA_ARGS__
+
+#undef CONFIG_FEATURE_SH_STANDALONE_SHELL
+#define ENABLE_FEATURE_SH_STANDALONE_SHELL 0
+#define USE_FEATURE_SH_STANDALONE_SHELL(...)
+#define SKIP_FEATURE_SH_STANDALONE_SHELL(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_COMMAND_EDITING 1
+#define ENABLE_FEATURE_COMMAND_EDITING 1
+#define USE_FEATURE_COMMAND_EDITING(...)  __VA_ARGS__
+#define SKIP_FEATURE_COMMAND_EDITING(...)
+
+#undef CONFIG_FEATURE_COMMAND_EDITING_VI
+#define ENABLE_FEATURE_COMMAND_EDITING_VI 0
+#define USE_FEATURE_COMMAND_EDITING_VI(...)
+#define SKIP_FEATURE_COMMAND_EDITING_VI(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_COMMAND_HISTORY 15
+#define ENABLE_FEATURE_COMMAND_HISTORY 1
+#define USE_FEATURE_COMMAND_HISTORY(...)  __VA_ARGS__
+#define SKIP_FEATURE_COMMAND_HISTORY(...)
+
+#undef CONFIG_FEATURE_COMMAND_SAVEHISTORY
+#define ENABLE_FEATURE_COMMAND_SAVEHISTORY 0
+#define USE_FEATURE_COMMAND_SAVEHISTORY(...)
+#define SKIP_FEATURE_COMMAND_SAVEHISTORY(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_COMMAND_TAB_COMPLETION 1
+#define ENABLE_FEATURE_COMMAND_TAB_COMPLETION 1
+#define USE_FEATURE_COMMAND_TAB_COMPLETION(...)  __VA_ARGS__
+#define SKIP_FEATURE_COMMAND_TAB_COMPLETION(...)
+
+#undef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION
+#define ENABLE_FEATURE_COMMAND_USERNAME_COMPLETION 0
+#define USE_FEATURE_COMMAND_USERNAME_COMPLETION(...)
+#define SKIP_FEATURE_COMMAND_USERNAME_COMPLETION(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_SH_FANCY_PROMPT 1
+#define ENABLE_FEATURE_SH_FANCY_PROMPT 1
+#define USE_FEATURE_SH_FANCY_PROMPT(...)  __VA_ARGS__
+#define SKIP_FEATURE_SH_FANCY_PROMPT(...)
+
+
+/*
+ * System Logging Utilities
+ */
+#define CONFIG_SYSLOGD 1
+#define ENABLE_SYSLOGD 1
+#define USE_SYSLOGD(...)  __VA_ARGS__
+#define SKIP_SYSLOGD(...)
+
+#undef CONFIG_FEATURE_ROTATE_LOGFILE
+#define ENABLE_FEATURE_ROTATE_LOGFILE 0
+#define USE_FEATURE_ROTATE_LOGFILE(...)
+#define SKIP_FEATURE_ROTATE_LOGFILE(...)  __VA_ARGS__
+
+#define CONFIG_FEATURE_REMOTE_LOG 1
+#define ENABLE_FEATURE_REMOTE_LOG 1
+#define USE_FEATURE_REMOTE_LOG(...)  __VA_ARGS__
+#define SKIP_FEATURE_REMOTE_LOG(...)
+
+#define CONFIG_FEATURE_IPC_SYSLOG 1
+#define ENABLE_FEATURE_IPC_SYSLOG 1
+#define USE_FEATURE_IPC_SYSLOG(...)  __VA_ARGS__
+#define SKIP_FEATURE_IPC_SYSLOG(...)
+
+#define CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE 16
+#define ENABLE_FEATURE_IPC_SYSLOG_BUFFER_SIZE 1
+#define USE_FEATURE_IPC_SYSLOG_BUFFER_SIZE(...)  __VA_ARGS__
+#define SKIP_FEATURE_IPC_SYSLOG_BUFFER_SIZE(...)
+
+#define CONFIG_LOGREAD 1
+#define ENABLE_LOGREAD 1
+#define USE_LOGREAD(...)  __VA_ARGS__
+#define SKIP_LOGREAD(...)
+
+#undef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
+#define ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING 0
+#define USE_FEATURE_LOGREAD_REDUCED_LOCKING(...)
+#define SKIP_FEATURE_LOGREAD_REDUCED_LOCKING(...)  __VA_ARGS__
+
+#define CONFIG_KLOGD 1
+#define ENABLE_KLOGD 1
+#define USE_KLOGD(...)  __VA_ARGS__
+#define SKIP_KLOGD(...)
+
+#define CONFIG_LOGGER 1
+#define ENABLE_LOGGER 1
+#define USE_LOGGER(...)  __VA_ARGS__
+#define SKIP_LOGGER(...)
+
+#endif /* BB_CONFIG_H */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/busybox.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/busybox.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/busybox.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,49 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Busybox main internal header file
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+#ifndef	_BB_INTERNAL_H_
+#define	_BB_INTERNAL_H_    1
+
+#include "bb_config.h"
+
+#include "libbb.h"
+
+/* order matters:  used as index into "install_dir[]" in busybox.c */
+enum Location {
+	_BB_DIR_ROOT = 0,
+	_BB_DIR_BIN,
+	_BB_DIR_SBIN,
+	_BB_DIR_USR_BIN,
+	_BB_DIR_USR_SBIN
+};
+
+enum SUIDRoot {
+	_BB_SUID_NEVER = 0,
+	_BB_SUID_MAYBE,
+	_BB_SUID_ALWAYS
+};
+
+struct BB_applet {
+	const char *name;
+	int (*main) (int argc, char **argv);
+	__extension__ enum Location location:4;
+	__extension__ enum SUIDRoot need_suid:4;
+};
+
+/* From busybox.c */
+extern const struct BB_applet applets[];
+
+/* Automagically pull in all the applet function prototypes and
+ * applet usage strings.  These are all of the form:
+ *		extern int foo_main(int argc, char **argv);
+ *		extern const char foo_usage[];
+ * These are all autogenerated from the set of currently defined applets.
+ */
+#define PROTOTYPES
+#include "applets.h"
+#undef PROTOTYPES
+
+#endif							/* _BB_INTERNAL_H_ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/bb/bt.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/bb/bt.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/bb/bt.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define BB_BT "2006.09.17-17:55+0000"

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/bb/ver.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/bb/ver.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/bb/ver.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define BB_VER "1.2.1"

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ar.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ar.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ar.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_AR

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/alias.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/alias.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/alias.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_ASH_ALIAS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/builtin/echo.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/builtin/echo.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/builtin/echo.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_ASH_BUILTIN_ECHO

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/builtin/test.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/builtin/test.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/builtin/test.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_ASH_BUILTIN_TEST

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/cmdcmd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/cmdcmd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/cmdcmd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_ASH_CMDCMD

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/expand/prmt.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/expand/prmt.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/expand/prmt.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_ASH_EXPAND_PRMT

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/getopts.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/getopts.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/getopts.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_ASH_GETOPTS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/job/control.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/job/control.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/job/control.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_ASH_JOB_CONTROL

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/mail.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/mail.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/mail.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_ASH_MAIL

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/math/support.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/math/support.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/math/support.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_ASH_MATH_SUPPORT

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/math/support_64.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/math/support_64.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/math/support_64.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_ASH_MATH_SUPPORT_64

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/optimize/for/size.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/optimize/for/size.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/optimize/for/size.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_ASH_OPTIMIZE_FOR_SIZE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/random/support.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/random/support.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/random/support.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_ASH_RANDOM_SUPPORT

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/read/nchars.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/read/nchars.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/read/nchars.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_ASH_READ_NCHARS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/read/timeout.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/read/timeout.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash/read/timeout.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_ASH_READ_TIMEOUT

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ash.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_ASH

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/busybox/exec/path.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/busybox/exec/path.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/busybox/exec/path.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_BUSYBOX_EXEC_PATH "/proc/self/exe"

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/debug/tftp.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/debug/tftp.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/debug/tftp.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_DEBUG_TFTP

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/debug.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/debug.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/debug.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_DEBUG

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/devfsd/verbose.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/devfsd/verbose.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/devfsd/verbose.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_DEVFSD_VERBOSE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/e2label.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/e2label.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/e2label.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_E2LABEL

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/aix/label.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/aix/label.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/aix/label.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_AIX_LABEL

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ar/long/filenames.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ar/long/filenames.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ar/long/filenames.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_AR_LONG_FILENAMES

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/autowidth.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/autowidth.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/autowidth.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_AUTOWIDTH 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/awk/math.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/awk/math.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/awk/math.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_AWK_MATH

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/buffers/go/in/bss.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/buffers/go/in/bss.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/buffers/go/in/bss.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_BUFFERS_GO_IN_BSS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/buffers/go/on/stack.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/buffers/go/on/stack.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/buffers/go/on/stack.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_BUFFERS_GO_ON_STACK

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/check/tainted/module.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/check/tainted/module.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/check/tainted/module.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_CHECK_TAINTED_MODULE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/clean/up.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/clean/up.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/clean/up.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_CLEAN_UP

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/editing/vi.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/editing/vi.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/editing/vi.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_COMMAND_EDITING_VI

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/editing.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/editing.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/editing.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_COMMAND_EDITING 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/history.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/history.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/history.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_COMMAND_HISTORY 15

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/savehistory.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/savehistory.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/savehistory.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_COMMAND_SAVEHISTORY

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/tab/completion.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/tab/completion.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/tab/completion.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_COMMAND_TAB_COMPLETION 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/username/completion.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/username/completion.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/command/username/completion.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/deb/tar/bz2.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/deb/tar/bz2.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/deb/tar/bz2.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_DEB_TAR_BZ2

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/deb/tar/gz.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/deb/tar/gz.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/deb/tar/gz.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_DEB_TAR_GZ

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/devfs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/devfs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/devfs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_DEVFS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/devpts.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/devpts.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/devpts.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_DEVPTS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/du/default/blocksize_1k.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/du/default/blocksize_1k.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/du/default/blocksize_1k.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/extra/quiet.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/extra/quiet.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/extra/quiet.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_EXTRA_QUIET

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/echo.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/echo.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/echo.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FANCY_ECHO

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/ping.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/ping.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/ping.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FANCY_PING

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/ping6.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/ping6.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/ping6.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FANCY_PING6

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/sleep.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/sleep.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/sleep.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FANCY_SLEEP

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/tail.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/tail.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fancy/tail.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FANCY_TAIL

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fbset/fancy.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fbset/fancy.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fbset/fancy.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FBSET_FANCY

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fbset/readmode.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fbset/readmode.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fbset/readmode.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FBSET_READMODE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fdisk/advanced.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fdisk/advanced.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fdisk/advanced.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FDISK_ADVANCED

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fdisk/writable.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fdisk/writable.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/fdisk/writable.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FDISK_WRITABLE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/exec.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/exec.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/exec.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_FIND_EXEC 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/inum.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/inum.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/inum.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FIND_INUM

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/mmin.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/mmin.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/mmin.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FIND_MMIN

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/mtime.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/mtime.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/mtime.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FIND_MTIME

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/newer.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/newer.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/newer.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FIND_NEWER

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/perm.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/perm.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/perm.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FIND_PERM

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/print0.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/print0.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/print0.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FIND_PRINT0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/type.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/type.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/type.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FIND_TYPE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/xdev.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/xdev.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/find/xdev.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_FIND_XDEV

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/gunzip/uncompress.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/gunzip/uncompress.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/gunzip/uncompress.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_GUNZIP_UNCOMPRESS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/get/identity.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/get/identity.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/get/identity.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HDPARM_GET_IDENTITY

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/drive/reset.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/drive/reset.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/drive/reset.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/getset/dma.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/getset/dma.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/getset/dma.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/scan/hwif.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/scan/hwif.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/scan/hwif.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/tristate/hwif.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/tristate/hwif.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/tristate/hwif.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/unregister/hwif.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/unregister/hwif.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hdparm/hdio/unregister/hwif.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/auth/md5.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/auth/md5.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/auth/md5.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HTTPD_AUTH_MD5

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/basic/auth.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/basic/auth.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/basic/auth.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HTTPD_BASIC_AUTH

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/cgi.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/cgi.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/cgi.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HTTPD_CGI

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/config/with/mime/types.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/config/with/mime/types.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/config/with/mime/types.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/config/with/script/interpr.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/config/with/script/interpr.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/config/with/script/interpr.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/encode/url/str.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/encode/url/str.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/encode/url/str.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HTTPD_ENCODE_URL_STR

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/reload/config/sighup.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/reload/config/sighup.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/reload/config/sighup.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/set/remote/port/to/env.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/set/remote/port/to/env.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/set/remote/port/to/env.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/setuid.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/setuid.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/setuid.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HTTPD_SETUID

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/without/inetd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/without/inetd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/httpd/without/inetd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HTTPD_WITHOUT_INETD

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/human/readable.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/human/readable.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/human/readable.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HUMAN_READABLE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hwclock/adjtime/fhs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hwclock/adjtime/fhs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/hwclock/adjtime/fhs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/broadcast/plus.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/broadcast/plus.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/broadcast/plus.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/hw.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/hw.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/hw.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_IFCONFIG_HW

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/memstart/ioaddr/irq.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/memstart/ioaddr/irq.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/memstart/ioaddr/irq.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/slip.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/slip.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/slip.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_IFCONFIG_SLIP

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/status.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/status.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifconfig/status.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_IFCONFIG_STATUS 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/ip.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/ip.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/ip.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_IFUPDOWN_IP

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/ipv4.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/ipv4.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/ipv4.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_IFUPDOWN_IPV4

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/ipv6.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/ipv6.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/ipv6.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_IFUPDOWN_IPV6

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/mapping.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/mapping.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ifupdown/mapping.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_IFUPDOWN_MAPPING

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/rpc.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/rpc.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/rpc.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_INETD_RPC

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/chargen.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/chargen.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/chargen.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/daytime.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/daytime.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/daytime.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/discard.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/discard.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/discard.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/echo.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/echo.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/echo.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/time.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/time.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/inetd/support/builtin/time.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/init/coredumps.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/init/coredumps.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/init/coredumps.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_INIT_COREDUMPS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/init/sctty.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/init/sctty.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/init/sctty.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_INIT_SCTTY

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/ksymoops/symbols.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/ksymoops/symbols.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/ksymoops/symbols.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/load/map/full.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/load/map/full.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/load/map/full.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/load/map.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/load/map.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/load/map.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_INSMOD_LOAD_MAP

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/loadinkmem.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/loadinkmem.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/loadinkmem.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_INSMOD_LOADINKMEM 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/version/checking.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/version/checking.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/insmod/version/checking.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_INSMOD_VERSION_CHECKING

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/installer.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/installer.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/installer.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_INSTALLER

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/address.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/address.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/address.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_IP_ADDRESS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/link.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/link.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/link.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_IP_LINK

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/route.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/route.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/route.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_IP_ROUTE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/tunnel.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/tunnel.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ip/tunnel.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_IP_TUNNEL

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipc/syslog/buffer/size.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipc/syslog/buffer/size.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipc/syslog/buffer/size.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE 16

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipc/syslog.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipc/syslog.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipc/syslog.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_IPC_SYSLOG 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipcalc/fancy.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipcalc/fancy.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipcalc/fancy.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_IPCALC_FANCY

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipv6.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipv6.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ipv6.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_IPV6

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/brackets.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/brackets.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/brackets.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_LESS_BRACKETS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/flagcs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/flagcs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/flagcs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_LESS_FLAGCS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/flags.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/flags.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/flags.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_LESS_FLAGS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/marks.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/marks.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/marks.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_LESS_MARKS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/regexp.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/regexp.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/less/regexp.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_LESS_REGEXP

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/logread/reduced/locking.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/logread/reduced/locking.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/logread/reduced/locking.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/color/is/default.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/color/is/default.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/color/is/default.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_LS_COLOR_IS_DEFAULT 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/color.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/color.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/color.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_LS_COLOR 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/filetypes.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/filetypes.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/filetypes.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_LS_FILETYPES

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/followlinks.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/followlinks.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/followlinks.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_LS_FOLLOWLINKS 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/recursive.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/recursive.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/recursive.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_LS_RECURSIVE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/sortfiles.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/sortfiles.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/sortfiles.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_LS_SORTFILES 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/timestamps.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/timestamps.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/timestamps.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_LS_TIMESTAMPS 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/username.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/username.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/ls/username.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_LS_USERNAME

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/lsmod/pretty_2_6/output.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/lsmod/pretty_2_6/output.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/lsmod/pretty_2_6/output.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/lzma/fast.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/lzma/fast.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/lzma/fast.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_LZMA_FAST

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/makedevs/leaf.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/makedevs/leaf.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/makedevs/leaf.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_MAKEDEVS_LEAF

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/makedevs/table.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/makedevs/table.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/makedevs/table.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_MAKEDEVS_TABLE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/md5/sha1/sum/check.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/md5/sha1/sum/check.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/md5/sha1/sum/check.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_MD5_SHA1_SUM_CHECK

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/minix2.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/minix2.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/minix2.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_MINIX2

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/mount/loop.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/mount/loop.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/mount/loop.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_MOUNT_LOOP 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/mtab/support.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/mtab/support.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/mtab/support.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_MTAB_SUPPORT

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/osf/label.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/osf/label.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/osf/label.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_OSF_LABEL

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/query/module/interface.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/query/module/interface.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/query/module/interface.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_QUERY_MODULE_INTERFACE 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/readlink/follow.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/readlink/follow.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/readlink/follow.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_READLINK_FOLLOW

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/remote/log.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/remote/log.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/remote/log.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_REMOTE_LOG 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/rotate/logfile.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/rotate/logfile.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/rotate/logfile.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_ROTATE_LOGFILE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/securetty.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/securetty.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/securetty.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_SECURETTY

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sgi/label.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sgi/label.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sgi/label.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_SGI_LABEL

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sh/extra/quiet.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sh/extra/quiet.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sh/extra/quiet.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_SH_EXTRA_QUIET

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sh/fancy/prompt.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sh/fancy/prompt.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sh/fancy/prompt.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_SH_FANCY_PROMPT 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sh/standalone/shell.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sh/standalone/shell.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sh/standalone/shell.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_SH_STANDALONE_SHELL

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/shadowpasswds.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/shadowpasswds.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/shadowpasswds.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_SHADOWPASSWDS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sort/big.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sort/big.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sort/big.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_SORT_BIG

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/stat/format.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/stat/format.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/stat/format.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_STAT_FORMAT

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/suid/config/quiet.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/suid/config/quiet.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/suid/config/quiet.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_SUID_CONFIG_QUIET

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/suid/config.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/suid/config.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/suid/config.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_SUID_CONFIG

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/suid.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/suid.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/suid.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_SUID 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sun/label.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sun/label.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/sun/label.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_SUN_LABEL

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/bzip2.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/bzip2.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/bzip2.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_TAR_BZIP2 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/compress.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/compress.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/compress.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_TAR_COMPRESS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/create.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/create.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/create.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_TAR_CREATE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/from.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/from.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/from.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_TAR_FROM

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/gnu/extensions.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/gnu/extensions.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/gnu/extensions.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_TAR_GNU_EXTENSIONS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/gzip.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/gzip.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/gzip.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_TAR_GZIP 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/long/options.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/long/options.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/long/options.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_TAR_LONG_OPTIONS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/lzma.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/lzma.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/lzma.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_TAR_LZMA

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/oldgnu/compatibility.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/oldgnu/compatibility.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tar/oldgnu/compatibility.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tee/use/block/io.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tee/use/block/io.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tee/use/block/io.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_TEE_USE_BLOCK_IO

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/telnet/autologin.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/telnet/autologin.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/telnet/autologin.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_TELNET_AUTOLOGIN

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/telnet/ttype.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/telnet/ttype.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/telnet/ttype.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_TELNET_TTYPE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/telnetd/inetd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/telnetd/inetd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/telnetd/inetd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_TELNETD_INETD

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/test_64.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/test_64.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/test_64.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_TEST_64

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tftp/blocksize.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tftp/blocksize.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tftp/blocksize.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_TFTP_BLOCKSIZE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tftp/get.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tftp/get.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tftp/get.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_TFTP_GET 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tftp/put.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tftp/put.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/tftp/put.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_TFTP_PUT 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/top/cpu/usage/percentage.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/top/cpu/usage/percentage.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/top/cpu/usage/percentage.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/traceroute/source/route.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/traceroute/source/route.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/traceroute/source/route.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/traceroute/use/icmp.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/traceroute/use/icmp.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/traceroute/use/icmp.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_TRACEROUTE_USE_ICMP

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/traceroute/verbose.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/traceroute/verbose.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/traceroute/verbose.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_TRACEROUTE_VERBOSE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/udhcp/debug.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/udhcp/debug.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/udhcp/debug.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_UDHCP_DEBUG

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/udhcp/syslog.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/udhcp/syslog.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/udhcp/syslog.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_UDHCP_SYSLOG

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/unarchive/tape.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/unarchive/tape.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/unarchive/tape.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_UNARCHIVE_TAPE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/use/inittab.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/use/inittab.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/use/inittab.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_USE_INITTAB

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/use/termios.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/use/termios.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/use/termios.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_USE_TERMIOS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/utmp.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/utmp.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/utmp.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_UTMP

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/verbose/usage.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/verbose/usage.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/verbose/usage.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_VERBOSE_USAGE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/colon.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/colon.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/colon.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_VI_COLON

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/dot/cmd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/dot/cmd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/dot/cmd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_VI_DOT_CMD

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/optimize/cursor.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/optimize/cursor.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/optimize/cursor.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/readonly.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/readonly.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/readonly.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_VI_READONLY

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/search.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/search.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/search.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_VI_SEARCH

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/set.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/set.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/set.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_VI_SET

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/setopts.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/setopts.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/setopts.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_VI_SETOPTS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/use/signals.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/use/signals.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/use/signals.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_VI_USE_SIGNALS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/win/resize.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/win/resize.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/win/resize.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_VI_WIN_RESIZE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/yankmark.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/yankmark.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/vi/yankmark.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_VI_YANKMARK

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wget/authentication.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wget/authentication.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wget/authentication.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_WGET_AUTHENTICATION

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wget/ip6/literal.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wget/ip6/literal.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wget/ip6/literal.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_WGET_IP6_LITERAL

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wget/statusbar.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wget/statusbar.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wget/statusbar.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_WGET_STATUSBAR

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wtmp.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wtmp.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/wtmp.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_WTMP

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/confirmation.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/confirmation.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/confirmation.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/quotes.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/quotes.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/quotes.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_XARGS_SUPPORT_QUOTES

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/termopt.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/termopt.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/termopt.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/zero/term.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/zero/term.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature/xargs/support/zero/term.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature_2_4/modules.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature_2_4/modules.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature_2_4/modules.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_FEATURE_2_4_MODULES 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature_2_6/modules.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature_2_6/modules.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/feature_2_6/modules.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FEATURE_2_6_MODULES

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/findfs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/findfs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/findfs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_FINDFS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/gunzip.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/gunzip.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/gunzip.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_GUNZIP

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/init.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/init.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/init.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_INIT

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/install/no/usr.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/install/no/usr.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/install/no/usr.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_INSTALL_NO_USR 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/killall.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/killall.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/killall.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_KILLALL 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/lfs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/lfs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/lfs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_LFS

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/locale/support.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/locale/support.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/locale/support.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_LOCALE_SUPPORT

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/login.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/login.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/login.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_LOGIN

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/md5/size/vs/speed.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/md5/size/vs/speed.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/md5/size/vs/speed.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_MD5_SIZE_VS_SPEED 3

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/md5sum.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/md5sum.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/md5sum.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_MD5SUM

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/nc/gaping/security/hole.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/nc/gaping/security/hole.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/nc/gaping/security/hole.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_NC_GAPING_SECURITY_HOLE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ps.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ps.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/ps.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_PS 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/route.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/route.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/route.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_ROUTE

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/selinux.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/selinux.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/selinux.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_SELINUX

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/sha1sum.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/sha1sum.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/sha1sum.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_SHA1SUM

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/syslogd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/syslogd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/syslogd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_SYSLOGD 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/tar.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/tar.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/tar.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define CONFIG_TAR 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/use/bb/pwd/grp.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/use/bb/pwd/grp.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/use/bb/pwd/grp.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_USE_BB_PWD_GRP

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/use/bb/shadow.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/use/bb/shadow.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/config/use/bb/shadow.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#undef CONFIG_USE_BB_SHADOW

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/alias.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/alias.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/alias.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_ASH_ALIAS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/builtin/echo.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/builtin/echo.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/builtin/echo.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_ASH_BUILTIN_ECHO 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/builtin/test.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/builtin/test.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/builtin/test.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_ASH_BUILTIN_TEST 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/cmdcmd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/cmdcmd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/cmdcmd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_ASH_CMDCMD 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/job/control.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/job/control.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ash/job/control.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_ASH_JOB_CONTROL 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug/crond/option.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug/crond/option.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug/crond/option.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_DEBUG_CROND_OPTION 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug/init.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug/init.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug/init.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_DEBUG_INIT 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug/yank/susv2.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug/yank/susv2.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug/yank/susv2.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_DEBUG_YANK_SUSv2 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/debug.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_DEBUG 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/deluser.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/deluser.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/deluser.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_DELUSER 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/devfsd/fg/np.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/devfsd/fg/np.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/devfsd/fg/np.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_DEVFSD_FG_NP 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/devfsd/modload.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/devfsd/modload.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/devfsd/modload.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_DEVFSD_MODLOAD 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/devfsd/verbose.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/devfsd/verbose.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/devfsd/verbose.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_DEVFSD_VERBOSE 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/e2label.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/e2label.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/e2label.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_E2LABEL 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/expr/math/support_64.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/expr/math/support_64.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/expr/math/support_64.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_EXPR_MATH_SUPPORT_64 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/fdflush.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/fdflush.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/fdflush.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FDFLUSH 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/autowidth.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/autowidth.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/autowidth.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_AUTOWIDTH 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/check/tainted/module.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/check/tainted/module.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/check/tainted/module.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_CHECK_TAINTED_MODULE 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/clean/up.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/clean/up.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/clean/up.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_CLEAN_UP 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/command/editing.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/command/editing.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/command/editing.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_COMMAND_EDITING 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/compress/usage.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/compress/usage.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/compress/usage.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_COMPRESS_USAGE 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/crond/call/sendmail.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/crond/call/sendmail.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/crond/call/sendmail.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_CROND_CALL_SENDMAIL 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/date/isofmt.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/date/isofmt.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/date/isofmt.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_DATE_ISOFMT 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/dd/ibs/obs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/dd/ibs/obs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/dd/ibs/obs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_DD_IBS_OBS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/dd/signal/handling.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/dd/signal/handling.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/dd/signal/handling.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_DD_SIGNAL_HANDLING 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/deb/tar/lzma.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/deb/tar/lzma.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/deb/tar/lzma.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_DEB_TAR_LZMA 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/diff/binary.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/diff/binary.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/diff/binary.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_DIFF_BINARY 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/diff/dir.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/diff/dir.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/diff/dir.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_DIFF_DIR 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/diff/minimal.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/diff/minimal.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/diff/minimal.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_DIFF_MINIMAL 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/env/long/options.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/env/long/options.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/env/long/options.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_ENV_LONG_OPTIONS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/fancy/head.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/fancy/head.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/fancy/head.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_FANCY_HEAD 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/fancy/tail.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/fancy/tail.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/fancy/tail.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_FANCY_TAIL 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ftpgetput/long/options.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ftpgetput/long/options.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ftpgetput/long/options.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_FTPGETPUT_LONG_OPTIONS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/grep/context.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/grep/context.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/grep/context.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_GREP_CONTEXT 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/grep/egrep/alias.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/grep/egrep/alias.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/grep/egrep/alias.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_GREP_EGREP_ALIAS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/grep/fgrep/alias.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/grep/fgrep/alias.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/grep/fgrep/alias.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_GREP_FGREP_ALIAS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hdparm/get/identity.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hdparm/get/identity.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hdparm/get/identity.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_HDPARM_GET_IDENTITY 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hdparm/hdio/scan/hwif.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hdparm/hdio/scan/hwif.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hdparm/hdio/scan/hwif.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hwclock/long/options.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hwclock/long/options.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/hwclock/long/options.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ifupdown/ipv4.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ifupdown/ipv4.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ifupdown/ipv4.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_IFUPDOWN_IPV4 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ifupdown/ipv6.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ifupdown/ipv6.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ifupdown/ipv6.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_IFUPDOWN_IPV6 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/initrd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/initrd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/initrd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_INITRD 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/install/long/options.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/install/long/options.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/install/long/options.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_INSTALL_LONG_OPTIONS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/installer.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/installer.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/installer.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_INSTALLER 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ipcalc/fancy.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ipcalc/fancy.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ipcalc/fancy.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_IPCALC_FANCY 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ipcalc/long/options.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ipcalc/long/options.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ipcalc/long/options.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_IPCALC_LONG_OPTIONS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ls/recursive.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ls/recursive.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ls/recursive.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_LS_RECURSIVE 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ls/sortfiles.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ls/sortfiles.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ls/sortfiles.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_LS_SORTFILES 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ls/timestamps.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ls/timestamps.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ls/timestamps.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_LS_TIMESTAMPS 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/md5/sha1/sum/check.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/md5/sha1/sum/check.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/md5/sha1/sum/check.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_MD5_SHA1_SUM_CHECK 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mdev/conf.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mdev/conf.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mdev/conf.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_MDEV_CONF 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mdev/exec.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mdev/exec.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mdev/exec.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_MDEV_EXEC 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mkdir/long/options.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mkdir/long/options.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mkdir/long/options.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_MKDIR_LONG_OPTIONS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mkswap/v0.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mkswap/v0.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mkswap/v0.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_MKSWAP_V0 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/modprobe/multiple/options.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/modprobe/multiple/options.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/modprobe/multiple/options.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mount/loop.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mount/loop.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mount/loop.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_MOUNT_LOOP 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mount/nfs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mount/nfs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mount/nfs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_MOUNT_NFS 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mtab/support.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mtab/support.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mtab/support.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_MTAB_SUPPORT 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mv/long/options.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mv/long/options.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/mv/long/options.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_MV_LONG_OPTIONS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/pidof/omit.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/pidof/omit.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/pidof/omit.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_PIDOF_OMIT 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/pidof/single.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/pidof/single.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/pidof/single.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_PIDOF_SINGLE 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/preserve/hardlinks.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/preserve/hardlinks.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/preserve/hardlinks.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_PRESERVE_HARDLINKS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ps/wide.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ps/wide.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/ps/wide.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_PS_WIDE 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/readlink/follow.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/readlink/follow.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/readlink/follow.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_READLINK_FOLLOW 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/setconsole/long/options.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/setconsole/long/options.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/setconsole/long/options.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_SETCONSOLE_LONG_OPTIONS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/sh/extra/quiet.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/sh/extra/quiet.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/sh/extra/quiet.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_SH_EXTRA_QUIET 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/sh/standalone/shell.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/sh/standalone/shell.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/sh/standalone/shell.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_SH_STANDALONE_SHELL 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/shadowpasswds.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/shadowpasswds.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/shadowpasswds.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_SHADOWPASSWDS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/sort/big.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/sort/big.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/sort/big.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_SORT_BIG 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/start/stop/daemon/fancy.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/start/stop/daemon/fancy.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/start/stop/daemon/fancy.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_START_STOP_DAEMON_FANCY 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/start/stop/daemon/long/options.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/start/stop/daemon/long/options.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/start/stop/daemon/long/options.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_START_STOP_DAEMON_LONG_OPTIONS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/suid/config.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/suid/config.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/suid/config.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_SUID_CONFIG 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/suid.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/suid.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/suid.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_SUID 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/bzip2.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/bzip2.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/bzip2.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_TAR_BZIP2 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/compress.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/compress.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/compress.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_TAR_COMPRESS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/create.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/create.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/create.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_TAR_CREATE 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/from.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/from.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/from.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_TAR_FROM 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/gzip.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/gzip.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/gzip.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_TAR_GZIP 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/long/options.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/long/options.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/long/options.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_TAR_LONG_OPTIONS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/lzma.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/lzma.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tar/lzma.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_TAR_LZMA 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tftp/get.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tftp/get.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tftp/get.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_TFTP_GET 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tftp/put.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tftp/put.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tftp/put.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_TFTP_PUT 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tr/classes.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tr/classes.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tr/classes.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_TR_CLASSES 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tr/equiv.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tr/equiv.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/tr/equiv.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_TR_EQUIV 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/udhcp/debug.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/udhcp/debug.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/udhcp/debug.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_UDHCP_DEBUG 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/udhcp/syslog.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/udhcp/syslog.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/udhcp/syslog.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_UDHCP_SYSLOG 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/umount/all.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/umount/all.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/umount/all.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_UMOUNT_ALL 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/vi/win/resize.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/vi/win/resize.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature/vi/win/resize.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_VI_WIN_RESIZE 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature_2_4/modules.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature_2_4/modules.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature_2_4/modules.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_2_4_MODULES 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature_2_6/modules.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature_2_6/modules.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/feature_2_6/modules.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FEATURE_2_6_MODULES 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/findfs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/findfs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/findfs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FINDFS 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/freeramdisk.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/freeramdisk.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/freeramdisk.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FREERAMDISK 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ftpget.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ftpget.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ftpget.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FTPGET 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ftpput.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ftpput.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/ftpput.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_FTPPUT 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/getopt/long.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/getopt/long.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/getopt/long.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_GETOPT_LONG 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/init.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/init.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/init.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_INIT 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/locale/support.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/locale/support.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/locale/support.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_LOCALE_SUPPORT 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/md5sum.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/md5sum.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/md5sum.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_MD5SUM 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/selinux.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/selinux.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/selinux.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_SELINUX 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/sha1sum.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/sha1sum.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/sha1sum.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_SHA1SUM 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/show/usage.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/show/usage.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/show/usage.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_SHOW_USAGE 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/swaponoff.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/swaponoff.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/enable/swaponoff.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define ENABLE_SWAPONOFF 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/du/default/blocksize_1k.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/du/default/blocksize_1k.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/du/default/blocksize_1k.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define SKIP_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/auth/md5.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/auth/md5.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/auth/md5.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define SKIP_FEATURE_HTTPD_AUTH_MD5(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/basic/auth.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/basic/auth.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/basic/auth.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define SKIP_FEATURE_HTTPD_BASIC_AUTH(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/encode/url/str.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/encode/url/str.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/encode/url/str.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define SKIP_FEATURE_HTTPD_ENCODE_URL_STR(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/setuid.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/setuid.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/setuid.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define SKIP_FEATURE_HTTPD_SETUID(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/without/inetd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/without/inetd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/httpd/without/inetd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define SKIP_FEATURE_HTTPD_WITHOUT_INETD(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/human/readable.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/human/readable.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/human/readable.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define SKIP_FEATURE_HUMAN_READABLE(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/start/stop/daemon/fancy.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/start/stop/daemon/fancy.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/skip/feature/start/stop/daemon/fancy.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define SKIP_FEATURE_START_STOP_DAEMON_FANCY(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/addgroup.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/addgroup.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/addgroup.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_ADDGROUP(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/adduser.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/adduser.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/adduser.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_ADDUSER(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/adjtimex.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/adjtimex.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/adjtimex.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_ADJTIMEX(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/app/dumpleases.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/app/dumpleases.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/app/dumpleases.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_APP_DUMPLEASES(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/app/udhcpc.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/app/udhcpc.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/app/udhcpc.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_APP_UDHCPC(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/app/udhcpd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/app/udhcpd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/app/udhcpd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_APP_UDHCPD(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ar.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ar.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ar.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_AR(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/arping.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/arping.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/arping.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_ARPING(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ash.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ash.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ash.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_ASH(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/awk.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/awk.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/awk.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_AWK(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/basename.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/basename.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/basename.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_BASENAME(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/bb/sysctl.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/bb/sysctl.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/bb/sysctl.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_BB_SYSCTL(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/bbconfig.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/bbconfig.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/bbconfig.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_BBCONFIG(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/bunzip2.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/bunzip2.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/bunzip2.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_BUNZIP2(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cal.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cal.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cal.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CAL(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cat.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cat.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cat.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CAT(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/catv.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/catv.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/catv.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CATV(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chattr.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chattr.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chattr.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CHATTR(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chgrp.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chgrp.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chgrp.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CHGRP(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chmod.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chmod.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chmod.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CHMOD(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chown.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chown.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chown.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CHOWN(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chroot.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chroot.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chroot.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CHROOT(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chvt.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chvt.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/chvt.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CHVT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cksum.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cksum.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cksum.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CKSUM(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/clear.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/clear.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/clear.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CLEAR(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cmp.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cmp.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cmp.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CMP(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/comm.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/comm.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/comm.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_COMM(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cp.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cp.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cp.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CP(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cpio.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cpio.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cpio.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CPIO(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/crond.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/crond.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/crond.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CROND(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/crontab.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/crontab.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/crontab.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CRONTAB(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cut.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cut.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/cut.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_CUT(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/date.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/date.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/date.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DATE(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dc.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dc.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dc.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DC(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DD(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/deallocvt.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/deallocvt.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/deallocvt.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DEALLOCVT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/delgroup.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/delgroup.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/delgroup.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DELGROUP(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/deluser.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/deluser.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/deluser.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DELUSER(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/devfsd/fg/np.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/devfsd/fg/np.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/devfsd/fg/np.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DEVFSD_FG_NP(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/devfsd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/devfsd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/devfsd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DEVFSD(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/df.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/df.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/df.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DF(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/diff.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/diff.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/diff.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DIFF(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dirname.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dirname.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dirname.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DIRNAME(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dmesg.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dmesg.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dmesg.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DMESG(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dnsd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dnsd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dnsd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DNSD(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dos2unix.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dos2unix.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dos2unix.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DOS2UNIX(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dpkg/deb.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dpkg/deb.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dpkg/deb.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DPKG_DEB(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dpkg.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dpkg.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dpkg.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DPKG(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/du.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/du.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/du.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DU(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dumpkmap.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dumpkmap.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/dumpkmap.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_DUMPKMAP(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/e2fsck.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/e2fsck.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/e2fsck.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_E2FSCK(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/e2label.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/e2label.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/e2label.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_E2LABEL(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/echo.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/echo.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/echo.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_ECHO(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ed.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ed.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ed.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_ED(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/eject.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/eject.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/eject.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_EJECT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/env.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/env.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/env.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_ENV(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ether/wake.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ether/wake.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ether/wake.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_ETHER_WAKE(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/expr.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/expr.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/expr.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_EXPR(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fakeidentd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fakeidentd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fakeidentd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FAKEIDENTD(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/false.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/false.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/false.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FALSE(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fbset.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fbset.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fbset.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FBSET(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fdflush.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fdflush.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fdflush.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FDFLUSH(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fdformat.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fdformat.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fdformat.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FDFORMAT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fdisk.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fdisk.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fdisk.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FDISK(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/command/editing.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/command/editing.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/command/editing.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_COMMAND_EDITING(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/date/isofmt.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/date/isofmt.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/date/isofmt.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_DATE_ISOFMT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/dd/ibs/obs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/dd/ibs/obs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/dd/ibs/obs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_DD_IBS_OBS(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/du/default/blocksize_1k.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/du/default/blocksize_1k.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/du/default/blocksize_1k.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/fancy/echo.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/fancy/echo.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/fancy/echo.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_FANCY_ECHO(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/fancy/head.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/fancy/head.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/fancy/head.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_FANCY_HEAD(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/exec.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/exec.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/exec.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_FIND_EXEC(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/inum.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/inum.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/inum.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_FIND_INUM(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/mmin.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/mmin.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/mmin.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_FIND_MMIN(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/mtime.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/mtime.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/mtime.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_FIND_MTIME(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/newer.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/newer.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/newer.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_FIND_NEWER(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/perm.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/perm.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/perm.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_FIND_PERM(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/print0.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/print0.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/print0.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_FIND_PRINT0(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/type.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/type.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/find/type.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_FIND_TYPE(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/grep/context.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/grep/context.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/grep/context.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_GREP_CONTEXT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/grep/egrep/alias.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/grep/egrep/alias.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/grep/egrep/alias.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_GREP_EGREP_ALIAS(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/grep/fgrep/alias.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/grep/fgrep/alias.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/grep/fgrep/alias.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_GREP_FGREP_ALIAS(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/get/identity.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/get/identity.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/get/identity.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_HDPARM_GET_IDENTITY(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/drive/reset.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/drive/reset.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/drive/reset.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_HDPARM_HDIO_DRIVE_RESET(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/getset/dma.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/getset/dma.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/getset/dma.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_HDPARM_HDIO_GETSET_DMA(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/scan/hwif.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/scan/hwif.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/scan/hwif.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_HDPARM_HDIO_SCAN_HWIF(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/tristate/hwif.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/tristate/hwif.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/tristate/hwif.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/unregister/hwif.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/unregister/hwif.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/hdparm/hdio/unregister/hwif.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/auth/md5.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/auth/md5.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/auth/md5.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_HTTPD_AUTH_MD5(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/basic/auth.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/basic/auth.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/basic/auth.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_HTTPD_BASIC_AUTH(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/cgi.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/cgi.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/cgi.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_HTTPD_CGI(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/encode/url/str.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/encode/url/str.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/encode/url/str.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_HTTPD_ENCODE_URL_STR(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/setuid.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/setuid.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/setuid.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_HTTPD_SETUID(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/without/inetd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/without/inetd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/httpd/without/inetd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_HTTPD_WITHOUT_INETD(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/human/readable.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/human/readable.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/human/readable.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_HUMAN_READABLE(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/initrd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/initrd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/initrd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_INITRD(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/ipcalc/fancy.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/ipcalc/fancy.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/ipcalc/fancy.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_IPCALC_FANCY(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/ls/sortfiles.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/ls/sortfiles.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/ls/sortfiles.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_LS_SORTFILES(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/mdev/exec.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/mdev/exec.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/mdev/exec.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_MDEV_EXEC(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/mtab/support.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/mtab/support.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/mtab/support.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_MTAB_SUPPORT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/ash.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/ash.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/ash.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_SH_IS_ASH(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/hush.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/hush.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/hush.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_SH_IS_HUSH(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/lash.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/lash.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/lash.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_SH_IS_LASH(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/msh.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/msh.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/sh/is/msh.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_SH_IS_MSH(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/start/stop/daemon/fancy.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/start/stop/daemon/fancy.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/start/stop/daemon/fancy.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_START_STOP_DAEMON_FANCY(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/stat/format.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/stat/format.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/stat/format.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_STAT_FORMAT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/tftp/blocksize.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/tftp/blocksize.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/tftp/blocksize.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_TFTP_BLOCKSIZE(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/top/cpu/usage/percentage.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/top/cpu/usage/percentage.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/feature/top/cpu/usage/percentage.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/find.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/find.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/find.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FIND(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/findfs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/findfs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/findfs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FINDFS(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fold.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fold.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fold.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FOLD(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/free.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/free.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/free.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FREE(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/freeramdisk.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/freeramdisk.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/freeramdisk.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FREERAMDISK(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fsck/minix.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fsck/minix.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fsck/minix.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FSCK_MINIX(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fsck.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fsck.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fsck.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FSCK(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ftpget.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ftpget.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ftpget.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FTPGET(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ftpput.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ftpput.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ftpput.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FTPPUT(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fuser.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fuser.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/fuser.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_FUSER(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/getopt.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/getopt.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/getopt.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_GETOPT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/getty.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/getty.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/getty.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_GETTY(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/grep.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/grep.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/grep.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_GREP(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/gunzip.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/gunzip.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/gunzip.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_GUNZIP(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/gzip.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/gzip.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/gzip.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_GZIP(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/halt.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/halt.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/halt.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_HALT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hdparm.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hdparm.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hdparm.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_HDPARM(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/head.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/head.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/head.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_HEAD(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hexdump.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hexdump.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hexdump.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_HEXDUMP(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hostid.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hostid.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hostid.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_HOSTID(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hostname.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hostname.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hostname.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_HOSTNAME(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/httpd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/httpd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/httpd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_HTTPD(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hush.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hush.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hush.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_HUSH(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hwclock.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hwclock.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/hwclock.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_HWCLOCK(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/id.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/id.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/id.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_ID(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ifconfig.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ifconfig.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ifconfig.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_IFCONFIG(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ifupdown.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ifupdown.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ifupdown.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_IFUPDOWN(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/inetd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/inetd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/inetd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_INETD(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/init.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/init.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/init.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_INIT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/insmod.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/insmod.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/insmod.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_INSMOD(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/install.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/install.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/install.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_INSTALL(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ip.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ip.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ip.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_IP(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ipaddr.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ipaddr.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ipaddr.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_IPADDR(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ipcalc.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ipcalc.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ipcalc.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_IPCALC(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ipcrm.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ipcrm.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ipcrm.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_IPCRM(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ipcs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ipcs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ipcs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_IPCS(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/iplink.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/iplink.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/iplink.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_IPLINK(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/iproute.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/iproute.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/iproute.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_IPROUTE(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/iptunnel.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/iptunnel.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/iptunnel.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_IPTUNNEL(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/kill.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/kill.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/kill.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_KILL(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/killall.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/killall.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/killall.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_KILLALL(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/klogd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/klogd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/klogd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_KLOGD(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/lash.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/lash.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/lash.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_LASH(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/last.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/last.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/last.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_LAST(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/length.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/length.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/length.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_LENGTH(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/less.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/less.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/less.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_LESS(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ln.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ln.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ln.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_LN(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/loadfont.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/loadfont.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/loadfont.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_LOADFONT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/loadkmap.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/loadkmap.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/loadkmap.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_LOADKMAP(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/logger.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/logger.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/logger.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_LOGGER(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/login.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/login.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/login.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_LOGIN(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/logname.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/logname.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/logname.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_LOGNAME(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/logread.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/logread.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/logread.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_LOGREAD(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/losetup.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/losetup.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/losetup.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_LOSETUP(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ls.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ls.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ls.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_LS(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/lsattr.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/lsattr.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/lsattr.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_LSATTR(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/lsmod.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/lsmod.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/lsmod.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_LSMOD(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/makedevs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/makedevs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/makedevs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MAKEDEVS(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/md5sum.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/md5sum.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/md5sum.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MD5SUM(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mdev.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mdev.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mdev.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MDEV(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mesg.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mesg.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mesg.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MESG(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkdir.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkdir.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkdir.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MKDIR(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mke2fs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mke2fs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mke2fs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MKE2FS(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkfifo.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkfifo.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkfifo.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MKFIFO(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkfs/minix.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkfs/minix.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkfs/minix.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MKFS_MINIX(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mknod.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mknod.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mknod.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MKNOD(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkswap.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkswap.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mkswap.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MKSWAP(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mktemp.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mktemp.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mktemp.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MKTEMP(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/modprobe.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/modprobe.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/modprobe.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MODPROBE(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/more.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/more.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/more.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MORE(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mount.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mount.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mount.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MOUNT(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mountpoint.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mountpoint.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mountpoint.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MOUNTPOINT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/msh.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/msh.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/msh.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MSH(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mt.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mt.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mt.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mv.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mv.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/mv.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_MV(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nameif.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nameif.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nameif.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_NAMEIF(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nc.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nc.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nc.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_NC(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/netstat.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/netstat.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/netstat.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_NETSTAT(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nice.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nice.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nice.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_NICE(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nohup.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nohup.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nohup.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_NOHUP(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nslookup.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nslookup.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/nslookup.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_NSLOOKUP(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/od.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/od.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/od.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_OD(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/openvt.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/openvt.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/openvt.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_OPENVT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/passwd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/passwd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/passwd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_PASSWD(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/patch.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/patch.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/patch.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_PATCH(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pidof.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pidof.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pidof.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_PIDOF(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ping.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ping.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ping.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_PING(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ping6.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ping6.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ping6.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_PING6(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pipe/progress.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pipe/progress.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pipe/progress.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_PIPE_PROGRESS(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pivot/root.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pivot/root.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pivot/root.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_PIVOT_ROOT(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/printenv.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/printenv.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/printenv.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_PRINTENV(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/printf.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/printf.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/printf.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_PRINTF(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ps.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ps.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/ps.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_PS(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pwd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pwd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/pwd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_PWD(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rdate.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rdate.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rdate.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_RDATE(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/readlink.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/readlink.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/readlink.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_READLINK(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/readprofile.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/readprofile.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/readprofile.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_READPROFILE(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/realpath.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/realpath.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/realpath.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_REALPATH(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/renice.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/renice.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/renice.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_RENICE(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/reset.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/reset.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/reset.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_RESET(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rm.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rm.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rm.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_RM(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rmdir.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rmdir.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rmdir.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_RMDIR(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rmmod.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rmmod.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rmmod.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_RMMOD(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/route.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/route.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/route.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_ROUTE(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rpm.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rpm.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rpm.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_RPM(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rpm2cpio.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rpm2cpio.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rpm2cpio.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_RPM2CPIO(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/run/parts.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/run/parts.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/run/parts.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_RUN_PARTS(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/runlevel.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/runlevel.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/runlevel.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_RUNLEVEL(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rx.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rx.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/rx.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_RX(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sed.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sed.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sed.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SED(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/seq.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/seq.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/seq.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SEQ(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setarch.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setarch.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setarch.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SETARCH(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setconsole.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setconsole.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setconsole.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SETCONSOLE(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setkeycodes.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setkeycodes.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setkeycodes.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SETKEYCODES(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setlogcons.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setlogcons.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setlogcons.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SETLOGCONS(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setsid.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setsid.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/setsid.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SETSID(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sha1sum.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sha1sum.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sha1sum.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SHA1SUM(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sleep.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sleep.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sleep.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SLEEP(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sort.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sort.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sort.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SORT(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/start/stop/daemon.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/start/stop/daemon.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/start/stop/daemon.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_START_STOP_DAEMON(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/stat.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/stat.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/stat.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_STAT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/strings.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/strings.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/strings.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_STRINGS(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/stty.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/stty.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/stty.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_STTY(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/su.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/su.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/su.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SU(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sulogin.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sulogin.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sulogin.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SULOGIN(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sum.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sum.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sum.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SUM(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/swaponoff.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/swaponoff.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/swaponoff.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SWAPONOFF(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/switch/root.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/switch/root.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/switch/root.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SWITCH_ROOT(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sync.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sync.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/sync.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SYNC(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/syslogd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/syslogd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/syslogd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_SYSLOGD(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tail.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tail.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tail.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_TAIL(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tar.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tar.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tar.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_TAR(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tee.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tee.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tee.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_TEE(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/telnet.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/telnet.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/telnet.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_TELNET(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/telnetd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/telnetd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/telnetd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_TELNETD(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/test.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/test.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/test.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_TEST(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tftp.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tftp.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tftp.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_TFTP(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/time.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/time.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/time.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_TIME(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/top.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/top.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/top.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_TOP(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/touch.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/touch.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/touch.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_TOUCH(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tr.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tr.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tr.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_TR(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/traceroute.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/traceroute.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/traceroute.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_TRACEROUTE(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/true.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/true.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/true.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_TRUE(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tty.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tty.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tty.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_TTY(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tune2fs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tune2fs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/tune2fs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_TUNE2FS(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/umount.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/umount.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/umount.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_UMOUNT(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uname.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uname.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uname.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_UNAME(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uncompress.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uncompress.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uncompress.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_UNCOMPRESS(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uniq.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uniq.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uniq.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_UNIQ(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/unix2dos.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/unix2dos.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/unix2dos.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_UNIX2DOS(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/unlzma.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/unlzma.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/unlzma.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_UNLZMA(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/unzip.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/unzip.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/unzip.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_UNZIP(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uptime.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uptime.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uptime.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_UPTIME(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/usleep.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/usleep.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/usleep.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_USLEEP(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uudecode.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uudecode.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uudecode.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_UUDECODE(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uuencode.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uuencode.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/uuencode.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_UUENCODE(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/vconfig.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/vconfig.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/vconfig.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_VCONFIG(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/vi.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/vi.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/vi.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_VI(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/vlock.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/vlock.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/vlock.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_VLOCK(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/watch.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/watch.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/watch.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_WATCH(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/watchdog.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/watchdog.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/watchdog.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_WATCHDOG(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/wc.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/wc.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/wc.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_WC(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/wget.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/wget.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/wget.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_WGET(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/which.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/which.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/which.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_WHICH(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/who.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/who.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/who.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_WHO(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/whoami.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/whoami.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/whoami.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_WHOAMI(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/xargs.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/xargs.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/xargs.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_XARGS(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/yes.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/yes.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/yes.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_YES(...)  __VA_ARGS__

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/zcip.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/zcip.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/config/use/zcip.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+#define USE_ZCIP(...)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/dump.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/dump.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/dump.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,49 @@
+#define	F_IGNORE	0x01		/* %_A */
+#define	F_SETREP	0x02		/* rep count set, not default */
+#define	F_ADDRESS	0x001		/* print offset */
+#define	F_BPAD		0x002		/* blank pad */
+#define	F_C		0x004		/* %_c */
+#define	F_CHAR		0x008		/* %c */
+#define	F_DBL		0x010		/* %[EefGf] */
+#define	F_INT		0x020		/* %[di] */
+#define	F_P		0x040		/* %_p */
+#define	F_STR		0x080		/* %s */
+#define	F_U		0x100		/* %_u */
+#define	F_UINT		0x200		/* %[ouXx] */
+#define	F_TEXT		0x400		/* no conversions */
+
+enum _vflag { ALL, DUP, FIRST, WAIT };	/* -v values */
+
+typedef struct _pr {
+	struct _pr *nextpr;		/* next print unit */
+	unsigned int flags;			/* flag values */
+	int bcnt;			/* byte count */
+	char *cchar;			/* conversion character */
+	char *fmt;			/* printf format */
+	char *nospace;			/* no whitespace version */
+} PR;
+
+typedef struct _fu {
+	struct _fu *nextfu;		/* next format unit */
+	struct _pr *nextpr;		/* next print unit */
+	unsigned int flags;			/* flag values */
+	int reps;			/* repetition count */
+	int bcnt;			/* byte count */
+	char *fmt;			/* format string */
+} FU;
+
+typedef struct _fs {			/* format strings */
+	struct _fs *nextfs;		/* linked list of format strings */
+	struct _fu *nextfu;		/* linked list of format units */
+	int bcnt;
+} FS;
+
+extern void bb_dump_add(const char *fmt);
+extern int bb_dump_dump (char **argv);
+extern int bb_dump_size(FS * fs);
+
+extern FS *bb_dump_fshead;		/* head of format strings */
+extern int bb_dump_blocksize;				/* data block size */
+extern int bb_dump_length;			/* max bytes to read */
+extern enum _vflag bb_dump_vflag;
+extern off_t bb_dump_skip;                      /* bytes to skip */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/grp_.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/grp_.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/grp_.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,116 @@
+/* Copyright (C) 1991,92,95,96,97,98,99,2000,01 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/*
+ *	POSIX Standard: 9.2.1 Group Database Access	<grp.h>
+ */
+
+
+#if !defined CONFIG_USE_BB_PWD_GRP
+#include <grp.h>
+
+#else
+
+#ifndef	_GRP_H
+#define	_GRP_H	1
+
+
+#include <sys/types.h>
+#include <features.h>
+#include <stdio.h>
+
+
+/* The group structure.	 */
+struct group
+{
+    char *gr_name;		/* Group name.	*/
+    char *gr_passwd;		/* Password.	*/
+    gid_t gr_gid;		/* Group ID.	*/
+    char **gr_mem;		/* Member list.	*/
+};
+
+
+/* Rewind the group-file stream.  */
+extern void setgrent (void);
+
+/* Close the group-file stream.  */
+extern void endgrent (void);
+
+/* Read an entry from the group-file stream, opening it if necessary.  */
+extern struct group *getgrent (void);
+
+/* Read a group entry from STREAM.  */
+extern struct group *fgetgrent (FILE *__stream);
+
+/* Write the given entry onto the given stream.  */
+extern int putgrent (__const struct group *__restrict __p,
+		     FILE *__restrict __f);
+
+/* Search for an entry with a matching group ID.  */
+extern struct group *getgrgid (gid_t __gid);
+
+/* Search for an entry with a matching group name.  */
+extern struct group *getgrnam (__const char *__name);
+
+/* Reentrant versions of some of the functions above.
+
+   PLEASE NOTE: the `getgrent_r' function is not (yet) standardized.
+   The interface may change in later versions of this library.  But
+   the interface is designed following the principals used for the
+   other reentrant functions so the chances are good this is what the
+   POSIX people would choose.  */
+
+extern int getgrent_r (struct group *__restrict __resultbuf,
+		       char *__restrict __buffer, size_t __buflen,
+		       struct group **__restrict __result);
+
+/* Search for an entry with a matching group ID.  */
+extern int getgrgid_r (gid_t __gid, struct group *__restrict __resultbuf,
+		       char *__restrict __buffer, size_t __buflen,
+		       struct group **__restrict __result);
+
+/* Search for an entry with a matching group name.  */
+extern int getgrnam_r (__const char *__restrict __name,
+		       struct group *__restrict __resultbuf,
+		       char *__restrict __buffer, size_t __buflen,
+		       struct group **__restrict __result);
+
+/* Read a group entry from STREAM.  This function is not standardized
+   an probably never will.  */
+extern int fgetgrent_r (FILE *__restrict __stream,
+			struct group *__restrict __resultbuf,
+			char *__restrict __buffer, size_t __buflen,
+			struct group **__restrict __result);
+
+/* Set the group set for the current user to GROUPS (N of them).  */
+extern int setgroups (size_t __n, __const gid_t *__groups);
+
+/* Store at most *NGROUPS members of the group set for USER into
+   *GROUPS.  Also include GROUP.  The actual number of groups found is
+   returned in *NGROUPS.  Return -1 if the if *NGROUPS is too small.  */
+extern int getgrouplist (__const char *__user, gid_t __group,
+			 gid_t *__groups, int *__ngroups);
+
+/* Initialize the group set for the current user
+   by reading the group database and using all groups
+   of which USER is a member.  Also include GROUP.  */
+extern int initgroups (__const char *__user, gid_t __group);
+
+
+#endif /* grp.h  */
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/inet_common.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/inet_common.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/inet_common.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,33 @@
+/*
+ * stolen from net-tools-1.59 and stripped down for busybox by
+ *                      Erik Andersen <andersen at codepoet.org>
+ *
+ * Heavily modified by Manuel Novoa III       Mar 12, 2001
+ *
+ * Version:     $Id: inet_common.h,v 1.4 2004/03/10 07:42:37 mjn3 Exp $
+ *
+ */
+
+#include <features.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include "platform.h"
+
+
+extern const char bb_INET_default[];    /* = "default" */
+
+/* hostfirst!=0 If we expect this to be a hostname,
+   try hostname database first
+ */
+extern int INET_resolve(const char *name, struct sockaddr_in *s_in, int hostfirst);
+
+
+/* numeric: & 0x8000: default instead of *,
+ *          & 0x4000: host instead of net,
+ *          & 0x0fff: don't resolve
+ */
+extern int INET_rresolve(char *name, size_t len, struct sockaddr_in *s_in,
+			 int numeric, unsigned int netmask);
+
+extern int INET6_resolve(const char *name, struct sockaddr_in6 *sin6);
+extern int INET6_rresolve(char *name, size_t len, struct sockaddr_in6 *sin6, int numeric);

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/libbb.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/libbb.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/libbb.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,556 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Busybox main internal header file
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ * Based in part on code from sash, Copyright (c) 1999 by David I. Bell
+ * Permission has been granted to redistribute this code under the GPL.
+ *
+ */
+#ifndef	__LIBBUSYBOX_H__
+#define	__LIBBUSYBOX_H__    1
+
+#include "bb_config.h"
+#include "platform.h"
+
+#include <ctype.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <termios.h>
+#include <unistd.h>
+
+#ifdef CONFIG_SELINUX
+#include <selinux/selinux.h>
+#endif
+
+#include "pwd_.h"
+#include "grp_.h"
+#ifdef CONFIG_FEATURE_SHADOWPASSWDS
+#include "shadow_.h"
+#endif
+#ifdef CONFIG_FEATURE_SHA1_PASSWORDS
+# include "sha1.h"
+#endif
+
+/* Try to pull in PATH_MAX */
+#include <limits.h>
+#include <sys/param.h>
+#ifndef PATH_MAX
+#define  PATH_MAX         256
+#endif
+
+#ifdef DMALLOC
+#include <dmalloc.h>
+#endif
+
+/* Some useful definitions */
+#undef FALSE
+#define FALSE   ((int) 0)
+#undef TRUE
+#define TRUE    ((int) 1)
+#undef SKIP
+#define SKIP	((int) 2)
+
+/* for mtab.c */
+#define MTAB_GETMOUNTPT '1'
+#define MTAB_GETDEVICE  '2'
+
+#define BUF_SIZE        8192
+#define EXPAND_ALLOC    1024
+
+/* Macros for min/max.  */
+#ifndef MIN
+#define	MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
+#ifndef MAX
+#define	MAX(a,b) (((a)>(b))?(a):(b))
+#endif
+
+/* buffer allocation schemes */
+#ifdef CONFIG_FEATURE_BUFFERS_GO_ON_STACK
+#define RESERVE_CONFIG_BUFFER(buffer,len)           char buffer[len]
+#define RESERVE_CONFIG_UBUFFER(buffer,len) unsigned char buffer[len]
+#define RELEASE_CONFIG_BUFFER(buffer)      ((void)0)
+#else
+#ifdef CONFIG_FEATURE_BUFFERS_GO_IN_BSS
+#define RESERVE_CONFIG_BUFFER(buffer,len)  static          char buffer[len]
+#define RESERVE_CONFIG_UBUFFER(buffer,len) static unsigned char buffer[len]
+#define RELEASE_CONFIG_BUFFER(buffer)      ((void)0)
+#else
+#define RESERVE_CONFIG_BUFFER(buffer,len)           char *buffer=xmalloc(len)
+#define RESERVE_CONFIG_UBUFFER(buffer,len) unsigned char *buffer=xmalloc(len)
+#define RELEASE_CONFIG_BUFFER(buffer)      free (buffer)
+#endif
+#endif
+
+
+typedef struct llist_s {
+	char *data;
+	struct llist_s *link;
+} llist_t;
+extern void llist_add_to(llist_t **old_head, void *data);
+extern void llist_add_to_end(llist_t **list_head, void *data);
+extern void *llist_pop(llist_t **elm);
+extern void llist_free(llist_t *elm, void (*freeit)(void *data));
+
+
+extern void bb_show_usage(void) ATTRIBUTE_NORETURN ATTRIBUTE_EXTERNALLY_VISIBLE;
+extern void bb_error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2)));
+extern void bb_error_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2)));
+extern void bb_perror_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2)));
+extern void bb_perror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2)));
+extern void bb_vherror_msg(const char *s, va_list p);
+extern void bb_herror_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2)));
+extern void bb_herror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2)));
+
+extern void bb_perror_nomsg_and_die(void) ATTRIBUTE_NORETURN;
+extern void bb_perror_nomsg(void);
+
+/* These two are used internally -- you shouldn't need to use them */
+extern void bb_verror_msg(const char *s, va_list p) __attribute__ ((format (printf, 1, 0)));
+extern void bb_vperror_msg(const char *s, va_list p)  __attribute__ ((format (printf, 1, 0)));
+
+extern int bb_echo(int argc, char** argv);
+extern int bb_test(int argc, char** argv);
+
+extern const char *bb_mode_string(int mode);
+extern int is_directory(const char *name, int followLinks, struct stat *statBuf);
+extern DIR *bb_opendir(const char *path);
+extern DIR *bb_xopendir(const char *path);
+
+extern int remove_file(const char *path, int flags);
+extern int copy_file(const char *source, const char *dest, int flags);
+extern ssize_t safe_read(int fd, void *buf, size_t count);
+extern ssize_t bb_full_read(int fd, void *buf, size_t len);
+extern ssize_t safe_write(int fd, const void *buf, size_t count);
+extern ssize_t bb_full_write(int fd, const void *buf, size_t len);
+extern int recursive_action(const char *fileName, int recurse,
+	  int followLinks, int depthFirst,
+	  int (*fileAction) (const char *fileName, struct stat* statbuf, void* userData),
+	  int (*dirAction) (const char *fileName, struct stat* statbuf, void* userData),
+	  void* userData);
+
+extern int bb_parse_mode( const char* s, mode_t* theMode);
+extern long bb_xgetlarg(const char *arg, int base, long lower, long upper);
+
+extern unsigned int tty_baud_to_value(speed_t speed);
+extern speed_t tty_value_to_baud(unsigned int value);
+
+extern int get_linux_version_code(void);
+
+extern int get_console_fd(void);
+extern struct mntent *find_mount_point(const char *name, const char *table);
+extern void erase_mtab(const char * name);
+extern long *find_pid_by_name( const char* pidName);
+extern long *pidlist_reverse(long *pidList);
+extern char *find_block_device(char *path);
+extern char *bb_get_line_from_file(FILE *file);
+extern char *bb_get_chomped_line_from_file(FILE *file);
+extern char *bb_get_chunk_from_file(FILE *file, int *end);
+extern int bb_copyfd_size(int fd1, int fd2, const off_t size);
+extern int bb_copyfd_eof(int fd1, int fd2);
+extern void  bb_xprint_and_close_file(FILE *file);
+extern int   bb_xprint_file_by_name(const char *filename);
+extern char  bb_process_escape_sequence(const char **ptr);
+extern char *bb_get_last_path_component(char *path);
+extern FILE *bb_wfopen(const char *path, const char *mode);
+extern FILE *bb_wfopen_input(const char *filename);
+extern FILE *bb_xfopen(const char *path, const char *mode);
+
+extern int   bb_fclose_nonstdin(FILE *f);
+extern void  bb_fflush_stdout_and_exit(int retval) ATTRIBUTE_NORETURN;
+
+extern void xstat(const char *filename, struct stat *buf);
+extern int  bb_xsocket(int domain, int type, int protocol);
+extern pid_t bb_spawn(char **argv);
+extern pid_t bb_xspawn(char **argv);
+extern int wait4pid(int pid);
+extern void bb_xdaemon(int nochdir, int noclose);
+extern void bb_xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
+extern void bb_xlisten(int s, int backlog);
+extern void bb_xchdir(const char *path);
+extern void xsetgid(gid_t gid);
+extern void xsetuid(uid_t uid);
+
+#define BB_GETOPT_ERROR 0x80000000UL
+extern const char *bb_opt_complementally;
+extern const struct option *bb_applet_long_options;
+extern unsigned long bb_getopt_ulflags(int argc, char **argv, const char *applet_opts, ...);
+
+extern int bb_vfprintf(FILE * __restrict stream, const char * __restrict format,
+					   va_list arg) __attribute__ ((format (printf, 2, 0)));
+extern int bb_vprintf(const char * __restrict format, va_list arg)
+	__attribute__ ((format (printf, 1, 0)));
+extern int bb_fprintf(FILE * __restrict stream, const char * __restrict format, ...)
+	__attribute__ ((format (printf, 2, 3)));
+extern int bb_printf(const char * __restrict format, ...)
+	__attribute__ ((format (printf, 1, 2)));
+
+//#warning rename to xferror_filename?
+extern void bb_xferror(FILE *fp, const char *fn);
+extern void bb_xferror_stdout(void);
+extern void bb_xfflush_stdout(void);
+
+extern void bb_warn_ignoring_args(int n);
+
+extern void chomp(char *s);
+extern void trim(char *s);
+extern char *skip_whitespace(const char *);
+
+extern struct BB_applet *find_applet_by_name(const char *name);
+void run_applet_by_name(const char *name, int argc, char **argv);
+
+/* dmalloc will redefine these to it's own implementation. It is safe
+ * to have the prototypes here unconditionally.  */
+extern void *xmalloc(size_t size);
+extern void *xrealloc(void *old, size_t size);
+extern void *xzalloc(size_t size);
+extern void *xcalloc(size_t nmemb, size_t size);
+
+extern char *bb_xstrdup (const char *s);
+extern char *bb_xstrndup (const char *s, int n);
+extern char *safe_strncpy(char *dst, const char *src, size_t size);
+extern int safe_strtoi(char *arg, int* value);
+extern int safe_strtod(char *arg, double* value);
+extern int safe_strtol(char *arg, long* value);
+extern int safe_strtoul(char *arg, unsigned long* value);
+
+struct suffix_mult {
+	const char *suffix;
+	unsigned int mult;
+};
+
+extern unsigned long bb_xgetularg_bnd_sfx(const char *arg, int base,
+										  unsigned long lower,
+										  unsigned long upper,
+										  const struct suffix_mult *suffixes);
+extern unsigned long bb_xgetularg_bnd(const char *arg, int base,
+									  unsigned long lower,
+									  unsigned long upper);
+extern unsigned long bb_xgetularg10_bnd(const char *arg,
+										unsigned long lower,
+										unsigned long upper);
+extern unsigned long bb_xgetularg10(const char *arg);
+
+extern long bb_xgetlarg_bnd_sfx(const char *arg, int base,
+								long lower,
+								long upper,
+								const struct suffix_mult *suffixes);
+extern long bb_xgetlarg10_sfx(const char *arg, const struct suffix_mult *suffixes);
+
+
+//#warning pitchable now?
+extern unsigned long bb_xparse_number(const char *numstr,
+		const struct suffix_mult *suffixes);
+
+
+/* These parse entries in /etc/passwd and /etc/group.  This is desirable
+ * for BusyBox since we want to avoid using the glibc NSS stuff, which
+ * increases target size and is often not needed on embedded systems.  */
+extern long bb_xgetpwnam(const char *name);
+extern long bb_xgetgrnam(const char *name);
+extern char * bb_getug(char *buffer, char *idname, long id, int bufsize, char prefix);
+extern char * bb_getpwuid(char *name, long uid, int bufsize);
+extern char * bb_getgrgid(char *group, long gid, int bufsize);
+extern char *bb_askpass(int timeout, const char * prompt);
+
+extern int device_open(const char *device, int mode);
+
+extern char *query_loop(const char *device);
+extern int del_loop(const char *device);
+extern int set_loop(char **device, const char *file, int offset);
+
+#if (__GLIBC__ < 2)
+extern int vdprintf(int d, const char *format, va_list ap);
+#endif
+
+int nfsmount(const char *spec, const char *node, int *flags,
+	     char **mount_opts, int running_bg);
+
+/* Include our own copy of struct sysinfo to avoid binary compatibility
+ * problems with Linux 2.4, which changed things.  Grumble, grumble. */
+struct sysinfo {
+	long uptime;			/* Seconds since boot */
+	unsigned long loads[3];		/* 1, 5, and 15 minute load averages */
+	unsigned long totalram;		/* Total usable main memory size */
+	unsigned long freeram;		/* Available memory size */
+	unsigned long sharedram;	/* Amount of shared memory */
+	unsigned long bufferram;	/* Memory used by buffers */
+	unsigned long totalswap;	/* Total swap space size */
+	unsigned long freeswap;		/* swap space still available */
+	unsigned short procs;		/* Number of current processes */
+	unsigned short pad;			/* Padding needed for m68k */
+	unsigned long totalhigh;	/* Total high memory size */
+	unsigned long freehigh;		/* Available high memory size */
+	unsigned int mem_unit;		/* Memory unit size in bytes */
+	char _f[20-2*sizeof(long)-sizeof(int)];	/* Padding: libc5 uses this.. */
+};
+extern int sysinfo (struct sysinfo* info);
+
+enum {
+	KILOBYTE = 1024,
+	MEGABYTE = (KILOBYTE*1024),
+	GIGABYTE = (MEGABYTE*1024)
+};
+const char *make_human_readable_str(unsigned long long size,
+		unsigned long block_size, unsigned long display_unit);
+
+int bb_ask_confirmation(void);
+int klogctl(int type, char * b, int len);
+
+char *xgetcwd(char *cwd);
+char *xreadlink(const char *path);
+char *concat_path_file(const char *path, const char *filename);
+char *concat_subpath_file(const char *path, const char *filename);
+char *last_char_is(const char *s, int c);
+
+int read_package_field(const char *package_buffer, char **field_name, char **field_value);
+//#warning yuk!
+char *fgets_str(FILE *file, const char *terminating_string);
+
+extern int uncompress(int fd_in, int fd_out);
+extern int inflate(int in, int out);
+
+extern struct hostent *xgethostbyname(const char *name);
+extern struct hostent *xgethostbyname2(const char *name, int af);
+extern int create_icmp_socket(void);
+extern int create_icmp6_socket(void);
+extern int xconnect(struct sockaddr_in *s_addr);
+extern unsigned short bb_lookup_port(const char *port, const char *protocol, unsigned short default_port);
+extern void bb_lookup_host(struct sockaddr_in *s_in, const char *host);
+
+//#warning wrap this?
+char *dirname (char *path);
+
+int bb_make_directory (char *path, long mode, int flags);
+
+const char *u_signal_names(const char *str_sig, int *signo, int startnum);
+char *bb_simplify_path(const char *path);
+
+enum {	/* DO NOT CHANGE THESE VALUES!  cp.c depends on them. */
+	FILEUTILS_PRESERVE_STATUS = 1,
+	FILEUTILS_DEREFERENCE = 2,
+	FILEUTILS_RECUR = 4,
+	FILEUTILS_FORCE = 8,
+	FILEUTILS_INTERACTIVE = 16
+};
+
+extern const char *bb_applet_name;
+
+extern const char * const bb_msg_full_version;
+extern const char * const bb_msg_memory_exhausted;
+extern const char * const bb_msg_invalid_date;
+extern const char * const bb_msg_io_error;
+extern const char * const bb_msg_read_error;
+extern const char * const bb_msg_write_error;
+extern const char * const bb_msg_name_longer_than_foo;
+extern const char * const bb_msg_unknown;
+extern const char * const bb_msg_can_not_create_raw_socket;
+extern const char * const bb_msg_perm_denied_are_you_root;
+extern const char * const bb_msg_requires_arg;
+extern const char * const bb_msg_invalid_arg;
+extern const char * const bb_msg_standard_input;
+extern const char * const bb_msg_standard_output;
+
+extern const char * const bb_path_nologin_file;
+extern const char * const bb_path_passwd_file;
+extern const char * const bb_path_shadow_file;
+extern const char * const bb_path_gshadow_file;
+extern const char * const bb_path_group_file;
+extern const char * const bb_path_securetty_file;
+extern const char * const bb_path_motd_file;
+extern const char * const bb_path_wtmp_file;
+extern const char * const bb_dev_null;
+
+#ifndef BUFSIZ
+#define BUFSIZ 4096
+#endif
+extern char bb_common_bufsiz1[BUFSIZ+1];
+
+/*
+ * You can change LIBBB_DEFAULT_LOGIN_SHELL, but don`t use,
+ * use bb_default_login_shell and next defines,
+ * if you LIBBB_DEFAULT_LOGIN_SHELL change,
+ * don`t lose change increment constant!
+ */
+#define LIBBB_DEFAULT_LOGIN_SHELL      "-/bin/sh"
+
+extern const char * const bb_default_login_shell;
+/* "/bin/sh" */
+#define DEFAULT_SHELL     (bb_default_login_shell+1)
+/* "sh" */
+#define DEFAULT_SHELL_SHORT_NAME     (bb_default_login_shell+6)
+
+
+extern const char bb_path_mtab_file[];
+
+extern int bb_default_error_retval;
+
+#ifdef CONFIG_FEATURE_DEVFS
+# define CURRENT_VC "/dev/vc/0"
+# define VC_1 "/dev/vc/1"
+# define VC_2 "/dev/vc/2"
+# define VC_3 "/dev/vc/3"
+# define VC_4 "/dev/vc/4"
+# define VC_5 "/dev/vc/5"
+#if defined(__sh__) || defined(__H8300H__) || defined(__H8300S__)
+/* Yes, this sucks, but both SH (including sh64) and H8 have a SCI(F) for their
+   respective serial ports .. as such, we can't use the common device paths for
+   these. -- PFM */
+#  define SC_0 "/dev/ttsc/0"
+#  define SC_1 "/dev/ttsc/1"
+#  define SC_FORMAT "/dev/ttsc/%d"
+#else
+#  define SC_0 "/dev/tts/0"
+#  define SC_1 "/dev/tts/1"
+#  define SC_FORMAT "/dev/tts/%d"
+#endif
+# define VC_FORMAT "/dev/vc/%d"
+# define LOOP_FORMAT "/dev/loop/%d"
+# define FB_0 "/dev/fb/0"
+#else
+# define CURRENT_VC "/dev/tty0"
+# define VC_1 "/dev/tty1"
+# define VC_2 "/dev/tty2"
+# define VC_3 "/dev/tty3"
+# define VC_4 "/dev/tty4"
+# define VC_5 "/dev/tty5"
+#if defined(__sh__) || defined(__H8300H__) || defined(__H8300S__)
+#  define SC_0 "/dev/ttySC0"
+#  define SC_1 "/dev/ttySC1"
+#  define SC_FORMAT "/dev/ttySC%d"
+#else
+#  define SC_0 "/dev/ttyS0"
+#  define SC_1 "/dev/ttyS1"
+#  define SC_FORMAT "/dev/ttyS%d"
+#endif
+# define VC_FORMAT "/dev/tty%d"
+# define LOOP_FORMAT "/dev/loop%d"
+# define FB_0 "/dev/fb0"
+#endif
+
+//#warning put these in .o files
+
+/* The following devices are the same on devfs and non-devfs systems.  */
+#define CURRENT_TTY "/dev/tty"
+#define CONSOLE_DEV "/dev/console"
+
+int is_in_ino_dev_hashtable(const struct stat *statbuf, char **name);
+void add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name);
+void reset_ino_dev_hashtable(void);
+
+char *bb_xasprintf(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
+
+#define FAIL_DELAY    3
+extern void bb_do_delay(int seconds);
+extern void change_identity ( const struct passwd *pw );
+extern const char *change_identity_e2str ( const struct passwd *pw );
+extern void run_shell ( const char *shell, int loginshell, const char *command, const char **additional_args);
+#ifdef CONFIG_SELINUX
+extern void renew_current_security_context(void);
+extern void set_current_security_context(security_context_t sid);
+#endif
+extern int run_parts(char **args, const unsigned char test_mode, char **env);
+extern int restricted_shell ( const char *shell );
+extern void setup_environment ( const char *shell, int loginshell, int changeenv, const struct passwd *pw );
+extern int correct_password ( const struct passwd *pw );
+extern char *pw_encrypt(const char *clear, const char *salt);
+extern struct spwd *pwd_to_spwd(const struct passwd *pw);
+extern int obscure(const char *old, const char *newval, const struct passwd *pwdp);
+
+extern int bb_xopen(const char *pathname, int flags);
+extern int bb_xopen3(const char *pathname, int flags, int mode);
+extern ssize_t bb_xread(int fd, void *buf, size_t count);
+extern void bb_xread_all(int fd, void *buf, size_t count);
+extern unsigned char bb_xread_char(int fd);
+
+#ifndef COMM_LEN
+#ifdef TASK_COMM_LEN
+#define COMM_LEN TASK_COMM_LEN
+#else
+/* synchronize with sizeof(task_struct.comm) in /usr/include/linux/sched.h */
+#define COMM_LEN 16
+#endif
+#endif
+typedef struct {
+	int pid;
+	char user[9];
+	char state[4];
+	unsigned long rss;
+	int ppid;
+#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+	unsigned pcpu;
+	unsigned pscpu;
+	unsigned long stime, utime;
+#endif
+	char *cmd;
+
+	/* basename of executable file in call to exec(2),
+		size from kernel headers */
+	char short_cmd[COMM_LEN];
+} procps_status_t;
+
+extern procps_status_t * procps_scan(int save_user_arg0);
+extern int compare_string_array(const char * const string_array[], const char *key);
+
+extern int my_query_module(const char *name, int which, void **buf, size_t *bufsize, size_t *ret);
+
+extern void print_login_issue(const char *issue_file, const char *tty);
+extern void print_login_prompt(void);
+
+#ifdef BB_NOMMU
+extern void vfork_daemon(int nochdir, int noclose);
+extern void vfork_daemon_rexec(int nochdir, int noclose,
+		int argc, char **argv, char *foreground_opt);
+#endif
+
+extern int get_terminal_width_height(int fd, int *width, int *height);
+extern unsigned long get_ug_id(const char *s, long (*__bb_getxxnam)(const char *));
+
+typedef struct _sha1_ctx_t_ {
+	uint32_t count[2];
+	uint32_t hash[5];
+	uint32_t wbuf[16];
+} sha1_ctx_t;
+
+void sha1_begin(sha1_ctx_t *ctx);
+void sha1_hash(const void *data, size_t length, sha1_ctx_t *ctx);
+void *sha1_end(void *resbuf, sha1_ctx_t *ctx);
+
+typedef struct _md5_ctx_t_ {
+	uint32_t A;
+	uint32_t B;
+	uint32_t C;
+	uint32_t D;
+	uint64_t total;
+	uint32_t buflen;
+	char buffer[128];
+} md5_ctx_t;
+
+void md5_begin(md5_ctx_t *ctx);
+void md5_hash(const void *data, size_t length, md5_ctx_t *ctx);
+void *md5_end(void *resbuf, md5_ctx_t *ctx);
+
+extern uint32_t *bb_crc32_filltable (int endian);
+
+#ifndef RB_POWER_OFF
+/* Stop system and switch power off if possible.  */
+#define RB_POWER_OFF   0x4321fedc
+#endif
+
+extern const char BB_BANNER[];
+
+#endif /* __LIBBUSYBOX_H__ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/platform.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/platform.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/platform.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,233 @@
+/* vi: set sw=4 ts=4: */
+/*
+   Copyright 2006, Bernhard Fischer
+
+   Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+*/
+#ifndef	__PLATFORM_H
+#define __PLATFORM_H	1
+
+/* Convenience macros to test the version of gcc. */
+#undef __GNUC_PREREQ
+#if defined __GNUC__ && defined __GNUC_MINOR__
+# define __GNUC_PREREQ(maj, min) \
+	        ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#else
+# define __GNUC_PREREQ(maj, min) 0
+#endif
+
+/* __restrict is known in EGCS 1.2 and above. */
+#if !__GNUC_PREREQ (2,92)
+# ifndef __restrict
+#  define __restrict     /* Ignore */
+# endif
+#endif
+
+/* Define macros for some gcc attributes.  This permits us to use the
+   macros freely, and know that they will come into play for the
+   version of gcc in which they are supported.  */
+
+#if !__GNUC_PREREQ (2,7)
+# ifndef __attribute__
+#  define __attribute__(x)
+# endif
+#endif
+
+#undef inline
+#if __STDC_VERSION__ > 199901L
+/* it's a keyword */
+#else
+# if __GNUC_PREREQ (2,7)
+#  define inline __inline__
+# else
+#  define inline
+# endif
+#endif
+
+#ifndef __const
+# define __const const
+#endif
+
+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
+# define ATTRIBUTE_PACKED __attribute__ ((__packed__))
+# define ATTRIBUTE_ALIGNED(m) __attribute__ ((__aligned__(m)))
+# if __GNUC_PREREQ (3,0)
+#  define ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline)) inline
+# else
+#  define ATTRIBUTE_ALWAYS_INLINE inline
+# endif
+
+/* -fwhole-program makes all symbols local. The attribute externally_visible
+   forces a symbol global.  */
+# if __GNUC_PREREQ (4,1)
+#  define ATTRIBUTE_EXTERNALLY_VISIBLE __attribute__ ((__externally_visible__))
+# else
+#  define ATTRIBUTE_EXTERNALLY_VISIBLE
+# endif /* GNUC >= 4.1 */
+
+/* We use __extension__ in some places to suppress -pedantic warnings
+   about GCC extensions.  This feature didn't work properly before
+   gcc 2.8.  */
+#if !__GNUC_PREREQ (2,8)
+# ifndef __extension__
+#  define __extension__
+# endif
+#endif
+
+/* ---- Endian Detection ------------------------------------ */
+
+#if (defined __digital__ && defined __unix__)
+# include <sex.h>
+# define __BIG_ENDIAN__ (BYTE_ORDER == BIG_ENDIAN)
+# define __BYTE_ORDER BYTE_ORDER
+#elif !defined __APPLE__
+# include <byteswap.h>
+# include <endian.h>
+#endif
+
+#ifdef __BIG_ENDIAN__
+# define BB_BIG_ENDIAN 1
+# define BB_LITTLE_ENDIAN 0
+#elif __BYTE_ORDER == __BIG_ENDIAN
+# define BB_BIG_ENDIAN 1
+# define BB_LITTLE_ENDIAN 0
+#else
+# define BB_BIG_ENDIAN 0
+# define BB_LITTLE_ENDIAN 1
+#endif
+
+#if BB_BIG_ENDIAN
+#define SWAP_BE16(x) (x)
+#define SWAP_BE32(x) (x)
+#define SWAP_BE64(x) (x)
+#define SWAP_LE16(x) bswap_16(x)
+#define SWAP_LE32(x) bswap_32(x)
+#define SWAP_LE64(x) bswap_64(x)
+#else
+#define SWAP_BE16(x) bswap_16(x)
+#define SWAP_BE32(x) bswap_32(x)
+#define SWAP_BE64(x) bswap_64(x)
+#define SWAP_LE16(x) (x)
+#define SWAP_LE32(x) (x)
+#define SWAP_LE64(x) (x)
+#endif
+
+/* ---- Networking ------------------------------------------ */
+#ifndef __APPLE__
+# include <arpa/inet.h>
+#else
+# include <netinet/in.h>
+#endif
+
+#ifndef __socklen_t_defined
+typedef int socklen_t;
+#endif
+
+/* ---- Compiler dependent settings ------------------------- */
+#ifndef __GNUC__
+#if defined __INTEL_COMPILER
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
+#endif /* __INTEL_COMPILER */
+#endif /* ifndef __GNUC__ */
+
+#if (defined __digital__ && defined __unix__)
+# undef HAVE_MNTENT_H
+#else
+# define HAVE_MNTENT_H 1
+#endif /* ___digital__ && __unix__ */
+
+/*----- Kernel versioning ------------------------------------*/
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+
+/* ---- miscellaneous --------------------------------------- */
+
+#if defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ < 5 && \
+	!defined(__dietlibc__) && \
+	!defined(_NEWLIB_VERSION) && \
+	!(defined __digital__ && defined __unix__)
+# error "Sorry, this libc version is not supported :("
+#endif
+
+// Don't perpetuate e2fsck crap into the headers.  Clean up e2fsck instead.
+
+#if defined __GLIBC__ || defined __UCLIBC__ \
+	|| defined __dietlibc__ || defined _NEWLIB_VERSION
+#include <features.h>
+#define HAVE_FEATURES_H
+#include <stdint.h>
+#define HAVE_STDINT_H
+#else
+/* Largest integral types.  */
+#if __BIG_ENDIAN__
+typedef long int                intmax_t;
+typedef unsigned long int       uintmax_t;
+#else
+__extension__
+typedef long long int           intmax_t;
+__extension__
+typedef unsigned long long int  uintmax_t;
+#endif
+#endif
+
+/* uclibc does not implement daemon for no-mmu systems.
+ * For 0.9.29 and svn, __ARCH_USE_MMU__ indicates no-mmu reliably.
+ * For earlier versions there is no reliable way to check if we are building
+ * for a mmu-less system; the user should pass EXTRA_CFLAGS="-DBB_NOMMU"
+ * on his own.
+ */
+#if defined __UCLIBC__ && __UCLIBC_MAJOR__ >= 0 && __UCLIBC_MINOR__ >= 9 && \
+    __UCLIBC_SUBLEVEL__ > 28 && !defined __ARCH_USE_MMU__
+#define BB_NOMMU
+#endif
+
+/* Platforms that haven't got dprintf need to implement fdprintf() in
+ * libbb.  This would require a platform.c.  It's not going to be cleaned
+ * out of the tree, so stop saying it should be. */
+#define fdprintf dprintf
+
+/* THIS SHOULD BE CLEANED OUT OF THE TREE ENTIRELY */
+/* FIXME: fix tar.c! */
+#ifndef FNM_LEADING_DIR
+#define FNM_LEADING_DIR 0
+#endif
+
+#if (defined __digital__ && defined __unix__)
+#include <standards.h>
+#define HAVE_STANDARDS_H
+#include <inttypes.h>
+#define HAVE_INTTYPES_H
+#define PRIu32 "u"
+
+/* use legacy setpgrp(pidt_,pid_t) for now.  move to platform.c */
+#define bb_setpgrp do{pid_t __me = getpid();setpgrp(__me,__me);}while(0)
+
+#if !defined ADJ_OFFSET_SINGLESHOT && defined MOD_CLKA && defined MOD_OFFSET
+#define ADJ_OFFSET_SINGLESHOT (MOD_CLKA | MOD_OFFSET)
+#endif
+#if !defined ADJ_FREQUENCY && defined MOD_FREQUENCY
+#define ADJ_FREQUENCY MOD_FREQUENCY
+#endif
+#if !defined ADJ_TIMECONST && defined MOD_TIMECONST
+#define ADJ_TIMECONST MOD_TIMECONST
+#endif
+#if !defined ADJ_TICK && defined MOD_CLKB
+#define ADJ_TICK MOD_CLKB
+#endif
+
+#else
+#define bb_setpgrp setpgrp()
+#endif
+
+#if defined(__linux__)
+#include <sys/mount.h>
+#if !defined(BLKSSZGET)
+#define BLKSSZGET _IO(0x12, 104)
+#endif
+#if !defined(BLKGETSIZE64)
+#define BLKGETSIZE64 _IOR(0x12,114,size_t)
+#endif
+#endif
+
+#endif	/* platform.h	*/

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/pwd_.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/pwd_.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/pwd_.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,106 @@
+/* Copyright (C) 1991,92,95,96,97,98,99,2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/*
+ *	POSIX Standard: 9.2.2 User Database Access	<pwd.h>
+ */
+
+#if !defined CONFIG_USE_BB_PWD_GRP
+#include <pwd.h>
+
+#else
+
+#ifndef	_PWD_H
+#define	_PWD_H	1
+
+#include <sys/types.h>
+#include <features.h>
+#include <stdio.h>
+
+/* The passwd structure.  */
+struct passwd
+{
+    char *pw_name;		/* Username.  */
+    char *pw_passwd;		/* Password.  */
+    uid_t pw_uid;			/* User ID.  */
+    gid_t pw_gid;			/* Group ID.  */
+    char *pw_gecos;		/* Real name.  */
+    char *pw_dir;			/* Home directory.  */
+    char *pw_shell;		/* Shell program.  */
+};
+
+
+/* Rewind the password-file stream.  */
+extern void setpwent (void);
+
+/* Close the password-file stream.  */
+extern void endpwent (void);
+
+/* Read an entry from the password-file stream, opening it if necessary.  */
+extern struct passwd *getpwent (void);
+
+/* Read an entry from STREAM.  */
+extern struct passwd *fgetpwent (FILE *__stream);
+
+/* Write the given entry onto the given stream.  */
+extern int putpwent (__const struct passwd *__restrict __p,
+		     FILE *__restrict __f);
+
+/* Search for an entry with a matching user ID.  */
+extern struct passwd *getpwuid (uid_t __uid);
+
+/* Search for an entry with a matching username.  */
+extern struct passwd *getpwnam (__const char *__name);
+
+/* Reentrant versions of some of the functions above.
+
+   PLEASE NOTE: the `getpwent_r' function is not (yet) standardized.
+   The interface may change in later versions of this library.  But
+   the interface is designed following the principals used for the
+   other reentrant functions so the chances are good this is what the
+   POSIX people would choose.  */
+
+extern int getpwent_r (struct passwd *__restrict __resultbuf,
+		       char *__restrict __buffer, size_t __buflen,
+		       struct passwd **__restrict __result);
+
+extern int getpwuid_r (uid_t __uid,
+		       struct passwd *__restrict __resultbuf,
+		       char *__restrict __buffer, size_t __buflen,
+		       struct passwd **__restrict __result);
+
+extern int getpwnam_r (__const char *__restrict __name,
+		       struct passwd *__restrict __resultbuf,
+		       char *__restrict __buffer, size_t __buflen,
+		       struct passwd **__restrict __result);
+
+
+/* Read an entry from STREAM.  This function is not standardized and
+   probably never will.  */
+extern int fgetpwent_r (FILE *__restrict __stream,
+			struct passwd *__restrict __resultbuf,
+			char *__restrict __buffer, size_t __buflen,
+			struct passwd **__restrict __result);
+
+/* Re-construct the password-file line for the given uid
+   in the given buffer.  This knows the format that the caller
+   will expect, but this need not be the format of the password file.  */
+extern int getpw (uid_t __uid, char *__buffer);
+
+#endif /* pwd.h  */
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/shadow_.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/shadow_.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/shadow_.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,98 @@
+/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Declaration of types and functions for shadow password suite.  */
+
+#if !defined CONFIG_USE_BB_SHADOW
+#include <shadow.h>
+#else
+
+#ifndef _SHADOW_H
+#define _SHADOW_H	1
+
+#include <stdio.h>
+
+/* Paths to the user database files.  */
+#ifndef _PATH_SHADOW
+#define	_PATH_SHADOW	"/etc/shadow"
+#endif
+#define	SHADOW _PATH_SHADOW
+
+
+/* Structure of the password file.  */
+struct spwd
+{
+    char *sp_namp;		/* Login name.  */
+    char *sp_pwdp;		/* Encrypted password.  */
+    long int sp_lstchg;		/* Date of last change.  */
+    long int sp_min;		/* Minimum number of days between changes.  */
+    long int sp_max;		/* Maximum number of days between changes.  */
+    long int sp_warn;		/* Number of days to warn user to change
+				   the password.  */
+    long int sp_inact;		/* Number of days the account may be
+				   inactive.  */
+    long int sp_expire;		/* Number of days since 1970-01-01 until
+				   account expires.  */
+    unsigned long int sp_flag;	/* Reserved.  */
+};
+
+
+/* Open database for reading.  */
+extern void setspent (void);
+
+/* Close database.  */
+extern void endspent (void);
+
+/* Get next entry from database, perhaps after opening the file.  */
+extern struct spwd *getspent (void);
+
+/* Get shadow entry matching NAME.  */
+extern struct spwd *getspnam (__const char *__name);
+
+/* Read shadow entry from STRING.  */
+extern struct spwd *sgetspent (__const char *__string);
+
+/* Read next shadow entry from STREAM.  */
+extern struct spwd *fgetspent (FILE *__stream);
+
+/* Write line containing shadow password entry to stream.  */
+extern int putspent (__const struct spwd *__p, FILE *__stream);
+
+/* Reentrant versions of some of the functions above.  */
+extern int getspent_r (struct spwd *__result_buf, char *__buffer,
+		       size_t __buflen, struct spwd **__result);
+
+extern int getspnam_r (__const char *__name, struct spwd *__result_buf,
+		       char *__buffer, size_t __buflen,
+		       struct spwd **__result);
+
+extern int sgetspent_r (__const char *__string, struct spwd *__result_buf,
+			char *__buffer, size_t __buflen,
+			struct spwd **__result);
+
+extern int fgetspent_r (FILE *__stream, struct spwd *__result_buf,
+			char *__buffer, size_t __buflen,
+			struct spwd **__result);
+/* Protect password file against multi writers.  */
+extern int lckpwdf (void);
+
+/* Unlock password file.  */
+extern int ulckpwdf (void);
+
+#endif /* shadow.h */
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/unarchive.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/unarchive.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/unarchive.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,115 @@
+/* vi: set sw=4 ts=4: */
+#ifndef	__UNARCHIVE_H__
+#define	__UNARCHIVE_H__
+
+#define ARCHIVE_PRESERVE_DATE           1
+#define ARCHIVE_CREATE_LEADING_DIRS     2
+#define ARCHIVE_EXTRACT_UNCONDITIONAL   4
+#define ARCHIVE_EXTRACT_QUIET           8
+#define ARCHIVE_EXTRACT_NEWER           16
+#define ARCHIVE_NOPRESERVE_OWN          32
+#define ARCHIVE_NOPRESERVE_PERM         64
+
+#include <sys/types.h>
+#include <stdio.h>
+#include "libbb.h"
+
+typedef struct file_headers_s {
+	char *name;
+	char *link_name;
+	off_t size;
+	uid_t uid;
+	gid_t gid;
+	mode_t mode;
+	time_t mtime;
+	dev_t device;
+} file_header_t;
+
+typedef struct archive_handle_s {
+	/* define if the header and data component should processed */
+	char (*filter)(struct archive_handle_s *);
+	llist_t *accept;
+	/* List of files that have been rejected */
+	llist_t *reject;
+	/* List of files that have successfully been worked on */
+	llist_t *passed;
+
+	/* Contains the processed header entry */
+	file_header_t *file_header;
+
+	/* process the header component, e.g. tar -t */
+	void (*action_header)(const file_header_t *);
+
+	/* process the data component, e.g. extract to filesystem */
+	void (*action_data)(struct archive_handle_s *);
+
+	/* How to process any sub archive, e.g. get_header_tar_gz */
+	char (*action_data_subarchive)(struct archive_handle_s *);
+
+	/* Contains the handle to a sub archive */
+	struct archive_handle_s *sub_archive;
+
+	/* The raw stream as read from disk or stdin */
+	int src_fd;
+
+	/* Count the number of bytes processed */
+	off_t offset;
+
+	/* Function that skips data: read_by_char or read_by_skip */
+	void (*seek)(const struct archive_handle_s *archive_handle, const unsigned int amount);
+
+	/* Temporary storage */
+	char *buffer;
+
+	/* Flags and misc. stuff */
+	unsigned char flags;
+
+} archive_handle_t;
+
+extern archive_handle_t *init_handle(void);
+
+extern char filter_accept_all(archive_handle_t *archive_handle);
+extern char filter_accept_list(archive_handle_t *archive_handle);
+extern char filter_accept_list_reassign(archive_handle_t *archive_handle);
+extern char filter_accept_reject_list(archive_handle_t *archive_handle);
+
+extern void unpack_ar_archive(archive_handle_t *ar_archive);
+
+extern void data_skip(archive_handle_t *archive_handle);
+extern void data_extract_all(archive_handle_t *archive_handle);
+extern void data_extract_to_stdout(archive_handle_t *archive_handle);
+extern void data_extract_to_buffer(archive_handle_t *archive_handle);
+
+extern void header_skip(const file_header_t *file_header);
+extern void header_list(const file_header_t *file_header);
+extern void header_verbose_list(const file_header_t *file_header);
+
+extern void check_header_gzip(int src_fd);
+
+extern char get_header_ar(archive_handle_t *archive_handle);
+extern char get_header_cpio(archive_handle_t *archive_handle);
+extern char get_header_tar(archive_handle_t *archive_handle);
+extern char get_header_tar_bz2(archive_handle_t *archive_handle);
+extern char get_header_tar_lzma(archive_handle_t *archive_handle);
+extern char get_header_tar_gz(archive_handle_t *archive_handle);
+
+extern void seek_by_jump(const archive_handle_t *archive_handle, const unsigned int amount);
+extern void seek_by_char(const archive_handle_t *archive_handle, const unsigned int amount);
+
+extern void archive_xread_all(const archive_handle_t *archive_handle, void *buf, const size_t count);
+extern ssize_t archive_xread_all_eof(archive_handle_t *archive_handle, unsigned char *buf, size_t count);
+
+extern void data_align(archive_handle_t *archive_handle, const unsigned short boundary);
+extern const llist_t *find_list_entry(const llist_t *list, const char *filename);
+
+extern int uncompressStream(int src_fd, int dst_fd);
+extern void inflate_init(unsigned int bufsize);
+extern void inflate_cleanup(void);
+extern int inflate_unzip(int in, int out);
+extern int inflate_gunzip(int in, int out);
+extern int unlzma(int src_fd, int dst_fd);
+
+extern int open_transformer(int src_fd, int (*transformer)(int src_fd, int dst_fd));
+
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/usage.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/usage.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/usage.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3460 @@
+#ifndef __BB_USAGE_H__
+#define __BB_USAGE_H__
+
+#define addgroup_trivial_usage \
+	"[-g GID] group_name [user_name]"
+#define addgroup_full_usage \
+	"Adds a group to the system\n\n" \
+	"Options:\n" \
+	"\t-g GID\t\tspecify gid"
+
+#define adduser_trivial_usage \
+	"[OPTIONS] user_name"
+#define adduser_full_usage \
+	"Adds a user to the system\n\n" \
+	"Options:\n" \
+	"\t-h DIR\t\tAssign home directory DIR\n" \
+	"\t-g GECOS\tAssign gecos field GECOS\n" \
+	"\t-s SHELL\tAssign login shell SHELL\n" \
+	"\t-G\t\tAdd the user to existing group GROUP\n" \
+	"\t-S\t\tcreate a system user (ignored)\n" \
+	"\t-D\t\tDo not assign a password (logins still possible via ssh)\n" \
+	"\t-H\t\tDo not create the home directory"
+
+#define adjtimex_trivial_usage \
+	"[-q] [-o offset] [-f frequency] [-p timeconstant] [-t tick]"
+#define adjtimex_full_usage \
+	"Reads and optionally sets system timebase parameters.\n" \
+	"See adjtimex(2).\n\n" \
+	"Options:\n" \
+	"\t-q\t\tquiet mode - do not print\n" \
+	"\t-o offset\ttime offset, microseconds\n" \
+	"\t-f frequency\tfrequency adjust, integer kernel units (65536 is 1ppm)\n" \
+	"\t\t\t(positive values make the system clock run fast)\n" \
+	"\t-t tick\t\tmicroseconds per tick, usually 10000\n" \
+	"\t-p timeconstant"
+
+#define ar_trivial_usage \
+	"[-o] [-v] [-p] [-t] [-x] ARCHIVE FILES"
+#define ar_full_usage \
+	"Extract or list FILES from an ar archive.\n\n" \
+	"Options:\n" \
+	"\t-o\t\tpreserve original dates\n" \
+	"\t-p\t\textract to stdout\n" \
+	"\t-t\t\tlist\n" \
+	"\t-x\t\textract\n" \
+	"\t-v\t\tverbosely list files processed"
+
+#define arping_trivial_usage \
+	"[-fqbDUA] [-c count] [-w timeout] [-i device] [-s sender] target"
+#define arping_full_usage \
+	"Ping hosts by ARP requests/replies.\n\n" \
+	"Options:\n" \
+	"\t-f\t\tQuit on first ARP reply\n" \
+	"\t-q\t\tBe quiet\n" \
+	"\t-b\t\tKeep broadcasting, don't go unicast\n" \
+	"\t-D\t\tDuplicated address detection mode\n" \
+	"\t-U\t\tUnsolicited ARP mode, update your neighbours\n" \
+	"\t-A\t\tARP answer mode, update your neighbours\n" \
+	"\t-c count\tStop after sending count ARP request packets\n" \
+	"\t-w timeout\tTime to wait for ARP reply, in seconds\n" \
+	"\t-i device\tOutgoing interface name, default is eth0\n" \
+	"\t-s sender\tSet specific sender IP address\n" \
+	"\ttarget\t\tTarget IP address of ARP request"
+
+#define ash_trivial_usage \
+	"[FILE]...\n" \
+	"or: ash -c command [args]..."
+#define ash_full_usage \
+	"The ash shell (command interpreter)"
+
+#define awk_trivial_usage \
+	"[OPTION]... [program-text] [FILE ...]"
+#define awk_full_usage \
+	"Options:\n" \
+	"\t-v var=val\tassign value 'val' to variable 'var'\n" \
+	"\t-F sep\t\tuse 'sep' as field separator\n" \
+	"\t-f progname\tread program source from file 'progname'"
+
+#define basename_trivial_usage \
+	"FILE [SUFFIX]"
+#define basename_full_usage \
+	"Strips directory path and suffixes from FILE.\n" \
+	"If specified, also removes any trailing SUFFIX."
+#define basename_example_usage \
+	"$ basename /usr/local/bin/foo\n" \
+	"foo\n" \
+	"$ basename /usr/local/bin/\n" \
+	"bin\n" \
+	"$ basename /foo/bar.txt .txt\n" \
+	"bar"
+
+#define bunzip2_trivial_usage \
+	"[OPTION]... [FILE]"
+#define bunzip2_full_usage \
+	"Uncompress FILE (or standard input if FILE is '-' or omitted).\n\n" \
+	"Options:\n" \
+	"\t-c\tWrite output to standard output\n" \
+	"\t-f\tForce"
+
+#define busybox_notes_usage \
+	"Hello world!\n"
+
+#define bzcat_trivial_usage \
+	"FILE"
+#define bzcat_full_usage \
+	"Uncompress to stdout."
+
+#define unlzma_trivial_usage \
+	"[OPTION]... [FILE]"
+#define unlzma_full_usage \
+	"Uncompress FILE (or standard input if FILE is '-' or omitted).\n\n" \
+	"Options:\n" \
+	"\t-c\tWrite output to standard output\n" \
+	"\t-f\tForce"
+
+#define lzmacat_trivial_usage \
+	"FILE"
+#define lzmacat_full_usage \
+	"Uncompress to stdout."
+
+#define cal_trivial_usage \
+	"[-jy] [[month] year]"
+#define cal_full_usage \
+	"Display a calendar.\n" \
+	"\nOptions:\n" \
+	"\t-j\tUse julian dates\n" \
+	"\t-y\tDisplay the entire year"
+
+#define cat_trivial_usage \
+	"[-u] [FILE]..."
+#define cat_full_usage \
+	"Concatenates FILE(s) and prints them to stdout.\n\n" \
+	"Options:\n" \
+	"\t-u\tignored since unbuffered i/o is always used"
+#define cat_example_usage \
+	"$ cat /proc/uptime\n" \
+	"110716.72 17.67"
+
+#define catv_trivial_usage \
+	"[-etv] [FILE]..."
+#define catv_full_usage \
+	"Display nonprinting characters as ^x or M-x.\n\n"\
+	"\t-e\tEnd each line with $\n" \
+	"\t-t\tShow tabs as ^I\n" \
+	"\t-v\tDon't use ^x or M-x escapes."
+#define chattr_trivial_usage \
+	"[-R] [-+=AacDdijsStTu] [-v version] files..."
+#define chattr_full_usage \
+	"change file attributes on an ext2 fs\n\n" \
+	"Modifiers:\n" \
+	"\t-\tremove attributes\n" \
+	"\t+\tadd attributes\n" \
+	"\t=\tset attributes\n" \
+	"Attributes:\n" \
+	"\tA\tdon't track atime\n" \
+	"\ta\tappend mode only\n" \
+	"\tc\tenable compress\n" \
+	"\tD\twrite dir contents synchronously\n" \
+	"\td\tdo not backup with dump\n" \
+	"\ti\tcannot be modified (immutable)\n" \
+	"\tj\twrite all data to journal first\n" \
+	"\ts\tzero disk storage when deleted\n" \
+	"\tS\twrite file contents synchronously\n" \
+	"\tt\tdisable tail-merging of partial blocks with other files\n" \
+	"\tu\tallow file to be undeleted\n" \
+	"Options:\n" \
+	"\t-R\trecursively list subdirectories\n" \
+	"\t-v\tset the file's version/generation number"
+
+#define chgrp_trivial_usage \
+	"[OPTION]... GROUP FILE..."
+#define chgrp_full_usage \
+	"Change the group membership of each FILE to GROUP.\n" \
+	"\nOptions:\n" \
+	"\t-R\tChanges files and directories recursively"
+#define chgrp_example_usage \
+	"$ ls -l /tmp/foo\n" \
+	"-r--r--r--    1 andersen andersen        0 Apr 12 18:25 /tmp/foo\n" \
+	"$ chgrp root /tmp/foo\n" \
+	"$ ls -l /tmp/foo\n" \
+	"-r--r--r--    1 andersen root            0 Apr 12 18:25 /tmp/foo\n"
+
+#define chmod_trivial_usage \
+	"[-R] MODE[,MODE]... FILE..."
+#define chmod_full_usage \
+	"Each MODE is one or more of the letters ugoa, one of the\n" \
+	"symbols +-= and one or more of the letters rwxst.\n\n" \
+	"Options:\n" \
+	"\t-R\tChanges files and directories recursively"
+#define chmod_example_usage \
+	"$ ls -l /tmp/foo\n" \
+	"-rw-rw-r--    1 root     root            0 Apr 12 18:25 /tmp/foo\n" \
+	"$ chmod u+x /tmp/foo\n" \
+	"$ ls -l /tmp/foo\n" \
+	"-rwxrw-r--    1 root     root            0 Apr 12 18:25 /tmp/foo*\n" \
+	"$ chmod 444 /tmp/foo\n" \
+	"$ ls -l /tmp/foo\n" \
+	"-r--r--r--    1 root     root            0 Apr 12 18:25 /tmp/foo\n"
+
+#define chown_trivial_usage \
+	"[ -Rh ]...  OWNER[<.|:>[GROUP]] FILE..."
+#define chown_full_usage \
+	"Change the owner and/or group of each FILE to OWNER and/or GROUP.\n" \
+	"\nOptions:\n" \
+	"\t-R\tChanges files and directories recursively\n" \
+	"\t-h\tDo not dereference symbolic links"
+#define chown_example_usage \
+	"$ ls -l /tmp/foo\n" \
+	"-r--r--r--    1 andersen andersen        0 Apr 12 18:25 /tmp/foo\n" \
+	"$ chown root /tmp/foo\n" \
+	"$ ls -l /tmp/foo\n" \
+	"-r--r--r--    1 root     andersen        0 Apr 12 18:25 /tmp/foo\n" \
+	"$ chown root.root /tmp/foo\n" \
+	"ls -l /tmp/foo\n" \
+	"-r--r--r--    1 root     root            0 Apr 12 18:25 /tmp/foo\n"
+
+#define chroot_trivial_usage \
+	"NEWROOT [COMMAND...]"
+#define chroot_full_usage \
+	"Run COMMAND with root directory set to NEWROOT."
+#define chroot_example_usage \
+	"$ ls -l /bin/ls\n" \
+	"lrwxrwxrwx    1 root     root          12 Apr 13 00:46 /bin/ls -> /BusyBox\n" \
+	"# mount /dev/hdc1 /mnt -t minix\n" \
+	"# chroot /mnt\n" \
+	"# ls -l /bin/ls\n" \
+	"-rwxr-xr-x    1 root     root        40816 Feb  5 07:45 /bin/ls*\n"
+
+#define chvt_trivial_usage \
+	"N"
+#define chvt_full_usage \
+	"Changes the foreground virtual terminal to /dev/ttyN"
+
+#define cksum_trivial_usage \
+	"FILES..."
+#define cksum_full_usage \
+	"Calculates the CRC32 checksums of FILES."
+
+#define clear_trivial_usage \
+	""
+#define clear_full_usage \
+	"Clear screen."
+
+#define cmp_trivial_usage \
+	"[-l] [-s] FILE1 [FILE2]"
+#define cmp_full_usage \
+	"Compares FILE1 vs stdin if FILE2 is not specified.\n\n" \
+	"Options:\n" \
+	"\t-l\tWrite the byte numbers (decimal) and values (octal)\n" \
+	"\t\t  for all differing bytes\n" \
+	"\t-s\tquiet mode - do not print"
+
+#define comm_trivial_usage \
+	"[-123] FILE1 FILE2"
+#define comm_full_usage \
+	"Compares FILE1 to FILE2, or to stdin if = is specified.\n\n" \
+	"Options:\n" \
+	"\t-1\tSuppress lines unique to FILE1\n" \
+	"\t-2\tSuppress lines unique to FILE2\n" \
+	"\t-3\tSuppress lines common to both files"
+
+#define bbconfig_trivial_usage \
+	""
+#define bbconfig_full_usage \
+	"Print the config file which built busybox"
+
+#define cp_trivial_usage \
+	"[OPTION]... SOURCE DEST"
+#define cp_full_usage \
+	"Copies SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n" \
+	"\n" \
+	"\t-a\tSame as -dpR\n" \
+	"\t-d,-P\tPreserves links\n" \
+	"\t-H,-L\tDereference all symlinks (implied by default)\n" \
+	"\t-p\tPreserves file attributes if possible\n" \
+	"\t-f\tforce (implied; ignored) - always set\n" \
+	"\t-i\tinteractive, prompt before overwrite\n" \
+	"\t-R,-r\tCopies directories recursively"
+
+#define cpio_trivial_usage \
+	"-[dimtuv][F cpiofile]"
+#define cpio_full_usage \
+	"Extract or list files from a cpio archive\n" \
+	"Main operation mode:\n" \
+	"\td\t\tmake leading directories\n" \
+	"\ti\t\textract\n" \
+	"\tm\t\tpreserve mtime\n" \
+	"\tt\t\tlist\n" \
+	"\tv\t\tverbose\n" \
+	"\tu\t\tunconditional overwrite\n" \
+	"\tF\t\tinput from file"
+
+#define crond_trivial_usage \
+	"-d[#] -c <crondir> -f -b"
+#define crond_full_usage \
+	"\t-d [#] -l [#] -S -L logfile -f -b -c dir\n" \
+	"\t-d num\tdebug level\n" \
+	"\t-l num\tlog level (8 - default)\n" \
+	"\t-S\tlog to syslogd (default)\n" \
+	"\t-L file\tlog to file\n" \
+	"\t-f\trun in foreground\n" \
+	"\t-b\trun in background (default)\n" \
+	"\t-c dir\tworking dir"
+
+#define crontab_trivial_usage \
+	"[-c dir] {file|-}|[-u|-l|-e|-d user]"
+#define crontab_full_usage \
+	"\tfile <opts>  replace crontab from file\n" \
+	"\t-    <opts>  replace crontab from stdin\n" \
+	"\t-u user      specify user\n" \
+	"\t-l [user]    list crontab for user\n" \
+	"\t-e [user]    edit crontab for user\n" \
+	"\t-d [user]    delete crontab for user\n" \
+	"\t-c dir       specify crontab directory"
+
+
+#define cut_trivial_usage \
+	"[OPTION]... [FILE]..."
+#define cut_full_usage \
+	"Prints selected fields from each input FILE to standard output.\n\n" \
+	"Options:\n" \
+	"\t-b LIST\t\tOutput only bytes from LIST\n" \
+	"\t-c LIST\t\tOutput only characters from LIST\n" \
+	"\t-d CHAR\t\tUse CHAR instead of tab as the field delimiter\n" \
+	"\t-s\t\tOutput only the lines containing delimiter\n" \
+	"\t-f N\t\tPrint only these fields\n" \
+	"\t-n\t\tIgnored"
+#define cut_example_usage \
+	"$ echo \"Hello world\" | cut -f 1 -d ' '\n" \
+	"Hello\n" \
+	"$ echo \"Hello world\" | cut -f 2 -d ' '\n" \
+	"world\n"
+
+#define date_trivial_usage \
+	"[OPTION]... [MMDDhhmm[[CC]YY][.ss]] [+FORMAT]"
+#define date_full_usage \
+	"Displays the current time in the given FORMAT, or sets the system date.\n" \
+	"\nOptions:\n" \
+	"\t-R\t\tOutputs RFC-822 compliant date string\n" \
+	"\t-d STRING\tDisplays time described by STRING, not `now'\n" \
+USE_FEATURE_DATE_ISOFMT( \
+	"\t-I[TIMESPEC]\tOutputs an ISO-8601 compliant date/time string\n" \
+	"\t\t\tTIMESPEC=`date' (or missing) for date only,\n" \
+	"\t\t\t`hours', `minutes', or `seconds' for date and,\n" \
+	"\t\t\ttime to the indicated precision\n" \
+	"\t-D hint\t\tUse 'hint' as date format, via strptime()\n" \
+) \
+	"\t-s\t\tSets time described by STRING\n" \
+	"\t-r FILE\t\tDisplays the last modification time of FILE\n" \
+	"\t-u\t\tPrints or sets Coordinated Universal Time"
+#define date_example_usage \
+	"$ date\n" \
+	"Wed Apr 12 18:52:41 MDT 2000\n"
+
+#define dc_trivial_usage \
+	"expression ..."
+#define dc_full_usage \
+	"This is a Tiny RPN calculator that understands the\n" \
+	"following operations: +, add, -, sub, *, mul, /, div, %, mod, " \
+	"**, exp, and, or, not, eor.\n" \
+	"For example: 'dc 2 2 add' -> 4, and 'dc 8 8 \\* 2 2 + /' -> 16.\n" \
+	"\nOptions:\n" \
+	"p - Prints the value on the top of the stack, without altering the stack\n" \
+	"f - Prints the entire contents of the stack without altering anything\n" \
+	"o - Pops the value off the top of the stack and uses it to set the output radix\n" \
+	"    Only 10 and 16 are supported"
+#define dc_example_usage \
+	"$ dc 2 2 + p\n" \
+	"4\n" \
+	"$ dc 8 8 \\* 2 2 + / p\n" \
+	"16\n" \
+	"$ dc 0 1 and p\n" \
+	"0\n" \
+	"$ dc 0 1 or p\n" \
+	"1\n" \
+	"$ echo 72 9 div 8 mul p | dc\n" \
+	"64\n"
+
+#define dd_trivial_usage \
+	"[if=FILE] [of=FILE] " USE_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" \
+	"\t  [seek=N]" USE_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync]")
+#define dd_full_usage \
+	"Copy a file, converting and formatting according to options\n\n" \
+	"\tif=FILE\t\tread from FILE instead of stdin\n" \
+	"\tof=FILE\t\twrite to FILE instead of stdout\n" \
+	"\tbs=N\t\tread and write N bytes at a time\n" \
+	USE_FEATURE_DD_IBS_OBS("\tibs=N\t\tread N bytes at a time\n") \
+	USE_FEATURE_DD_IBS_OBS("\tobs=N\t\twrite N bytes at a time\n") \
+	"\tcount=N\t\tcopy only N input blocks\n" \
+	"\tskip=N\t\tskip N input blocks\n" \
+	"\tseek=N\t\tskip N output blocks\n" \
+	USE_FEATURE_DD_IBS_OBS( \
+		"\tconv=notrunc\tdon't truncate output file\n" \
+		"\tconv=noerror\tcontinue after read errors\n" \
+		"\tconv=sync\tpad blocks with zeros\n" \
+	) \
+	"\n" \
+	"Numbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k (x1024),\n" \
+	"MD (x1000000), M (x1048576), GD (x1000000000) or G (x1073741824)"
+#define dd_example_usage \
+	"$ dd if=/dev/zero of=/dev/ram1 bs=1M count=4\n" \
+	"4+0 records in\n" \
+	"4+0 records out\n"
+
+#define deallocvt_trivial_usage \
+	"[N]"
+#define deallocvt_full_usage \
+	 "Deallocate unused virtual terminal /dev/ttyN"
+
+#define delgroup_trivial_usage \
+	"GROUP"
+#define delgroup_full_usage \
+	 "Deletes group GROUP from the system"
+
+#define deluser_trivial_usage \
+	"USER"
+#define deluser_full_usage \
+	 "Deletes user USER from the system"
+
+#define devfsd_trivial_usage \
+	"mntpnt [-v]" \
+	USE_DEVFSD_FG_NP("[-fg][-np]" )
+#define devfsd_full_usage \
+	"Optional daemon for managing devfs permissions and old device name symlinks.\n" \
+	"\nOptions:\n" \
+	"\tmntpnt\tThe mount point where devfs is mounted.\n\n" \
+	"\t-v\tPrint the protocol version numbers for devfsd\n" \
+	"\t\tand the kernel-side protocol version and exits." \
+	USE_DEVFSD_FG_NP( "\n\n\t-fg\tRun the daemon in the foreground.\n\n" \
+	"\t-np\tExit  after  parsing  the configuration file\n" \
+	"\t\tand processing synthetic REGISTER events.\n" \
+	"\t\tDo not poll for events.")
+
+#define df_trivial_usage \
+	"[-" USE_FEATURE_HUMAN_READABLE("hm") "k] [FILESYSTEM ...]"
+#define df_full_usage \
+	"Print the filesystem space used and space available.\n\n" \
+	"Options:\n" \
+	USE_FEATURE_HUMAN_READABLE( \
+		"\n\t-h\tprint sizes in human readable format (e.g., 1K 243M 2G )\n" \
+		"\t-m\tprint sizes in megabytes\n" \
+		"\t-k\tprint sizes in kilobytes(default)" \
+	) \
+	SKIP_FEATURE_HUMAN_READABLE("\n\t-k\tignored")
+#define df_example_usage \
+	"$ df\n" \
+	"Filesystem           1k-blocks      Used Available Use% Mounted on\n" \
+	"/dev/sda3              8690864   8553540    137324  98% /\n" \
+	"/dev/sda1                64216     36364     27852  57% /boot\n" \
+	"$ df /dev/sda3\n" \
+	"Filesystem           1k-blocks      Used Available Use% Mounted on\n" \
+	"/dev/sda3              8690864   8553540    137324  98% /\n"
+
+#define diff_trivial_usage \
+	"[-abdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] FILE1 FILE2"
+#define diff_full_usage \
+	"Compare files line by line and output the differences between them.\n" \
+	"This diff implementation only supports unified diffs.\n\n" \
+	"Options:\n" \
+	"\t-a\tTreat all files as text\n" \
+	"\t-b\tIgnore changes in the amount of whitespace\n" \
+	"\t-d\tTry hard to find a smaller set of changes\n" \
+	"\t-i\tIgnore case differences\n" \
+	"\t-L\tUse LABEL instead of the filename in the unified header\n" \
+	"\t-N\tTreat absent files as empty\n" \
+	"\t-q\tOutput only whether files differ\n" \
+	"\t-r\tRecursively compare any subdirectories\n" \
+	"\t-S\tStart with FILE when comparing directories\n" \
+	"\t-T\tMake tabs line up by prefixing a tab when necessary\n" \
+	"\t-s\tReport when two files are the same\n" \
+	"\t-t\tExpand tabs to spaces in output\n" \
+	"\t-U\tOutput LINES lines of context\n" \
+	"\t-w\tIgnore all whitespace\n"
+
+#define dirname_trivial_usage \
+	"FILENAME"
+#define dirname_full_usage \
+	"Strips non-directory suffix from FILENAME"
+#define dirname_example_usage \
+	"$ dirname /tmp/foo\n" \
+	"/tmp\n" \
+	"$ dirname /tmp/foo/\n" \
+	"/tmp\n"
+
+#define dmesg_trivial_usage \
+	"[-c] [-n LEVEL] [-s SIZE]"
+#define dmesg_full_usage \
+	"Prints or controls the kernel ring buffer\n\n" \
+	"Options:\n" \
+	"\t-c\t\tClears the ring buffer's contents after printing\n" \
+	"\t-n LEVEL\tSets console logging level\n" \
+	"\t-s SIZE\t\tUse a buffer of size SIZE"
+
+#define dnsd_trivial_usage \
+        "[-c config] [-t seconds] [-p port] [-i iface-ip] [-d]"
+#define dnsd_full_usage \
+        "Small and static DNS server daemon\n\n" \
+	"Options:\n" \
+	"\t-c\t\tconfig filename\n" \
+	"\t-t\t\tTTL in seconds\n" \
+	"\t-p\t\tlistening port\n" \
+	"\t-i\t\tlistening iface ip (default all)\n" \
+	"\t-d\t\tdaemonize"
+
+#define dos2unix_trivial_usage \
+	"[option] [FILE]"
+#define dos2unix_full_usage \
+	"Converts FILE from dos format to unix format.  When no option\n" \
+	"is given, the input is converted to the opposite output format.\n" \
+	"When no file is given, uses stdin for input and stdout for output.\n\n" \
+	"Options:\n" \
+	"\t-u\toutput will be in UNIX format\n" \
+	"\t-d\toutput will be in DOS format"
+
+#define dpkg_trivial_usage \
+	"[-ilCPru] [-F option] package_name"
+#define dpkg_full_usage \
+	"dpkg is a utility to install, remove and manage Debian packages.\n\n" \
+	"Options:\n" \
+	"\t-i\t\tInstall the package\n" \
+	"\t-l\t\tList of installed packages\n" \
+	"\t-C\t\tConfigure an unpackaged package\n" \
+	"\t-F depends\tIgnore dependency problems\n" \
+	"\t-P\t\tPurge all files of a package\n" \
+	"\t-r\t\tRemove all but the configuration files for a package\n" \
+	"\t-u\t\tUnpack a package, but don't configure it"
+
+#define dpkg_deb_trivial_usage \
+	"[-cefxX] FILE [argument]"
+#define dpkg_deb_full_usage \
+	"Perform actions on Debian packages (.debs)\n\n" \
+	"Options:\n" \
+	"\t-c\tList contents of filesystem tree\n" \
+	"\t-e\tExtract control files to [argument] directory\n" \
+	"\t-f\tDisplay control field name starting with [argument]\n" \
+	"\t-x\tExtract packages filesystem tree to directory\n" \
+	"\t-X\tVerbose extract"
+#define dpkg_deb_example_usage \
+	"$ dpkg-deb -X ./busybox_0.48-1_i386.deb /tmp\n"
+
+#define du_trivial_usage \
+	"[-aHLdclsx" USE_FEATURE_HUMAN_READABLE("hm") "k] [FILE]..."
+#define du_full_usage \
+	"Summarizes disk space used for each FILE and/or directory.\n" \
+	"Disk space is printed in units of " \
+	USE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K("1024") \
+	SKIP_FEATURE_DU_DEFAULT_BLOCKSIZE_1K("512") \
+	" bytes.\n\n" \
+	"Options:\n" \
+	"\t-a\tshow sizes of files in addition to directories\n" \
+	"\t-H\tfollow symbolic links that are FILE command line args\n" \
+	"\t-L\tfollow all symbolic links encountered\n" \
+	"\t-d N\tlimit output to directories (and files with -a) of depth < N\n" \
+	"\t-c\toutput a grand total\n" \
+	"\t-l\tcount sizes many times if hard linked\n" \
+	"\t-s\tdisplay only a total for each argument\n" \
+	"\t-x\tskip directories on different filesystems\n" \
+	USE_FEATURE_HUMAN_READABLE( \
+		"\t-h\tprint sizes in human readable format (e.g., 1K 243M 2G )\n" \
+		"\t-m\tprint sizes in megabytes\n" \
+	) \
+	"\t-k\tprint sizes in kilobytes" \
+	USE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K("(default)")
+#define du_example_usage \
+	"$ du\n" \
+	"16      ./CVS\n" \
+	"12      ./kernel-patches/CVS\n" \
+	"80      ./kernel-patches\n" \
+	"12      ./tests/CVS\n" \
+	"36      ./tests\n" \
+	"12      ./scripts/CVS\n" \
+	"16      ./scripts\n" \
+	"12      ./docs/CVS\n" \
+	"104     ./docs\n" \
+	"2417    .\n"
+
+#define dumpkmap_trivial_usage \
+	"> keymap"
+#define dumpkmap_full_usage \
+	"Prints out a binary keyboard translation table to standard output."
+#define dumpkmap_example_usage \
+	"$ dumpkmap > keymap\n"
+
+#define dumpleases_trivial_usage \
+	"[-r|-a] [-f LEASEFILE]"
+#define dumpleases_full_usage \
+	"Displays the DHCP leases granted by udhcpd.\n\n" \
+	"Options:\n" \
+	"\t-f,\t--file=FILENAME\tLeases file to load\n" \
+	"\t-r,\t--remaining\tInterpret lease times as time remaining\n" \
+	"\t-a,\t--absolute\tInterpret lease times as expire time"
+
+#define e2fsck_trivial_usage \
+	"[-panyrcdfvstDFSV] [-b superblock] [-B blocksize] " \
+	"[-I inode_buffer_blocks] [-P process_inode_size] " \
+	"[-l|-L bad_blocks_file] [-C fd] [-j external_journal] " \
+	"[-E extended-options] device"
+#define e2fsck_full_usage \
+	"Check a Linux ext2/ext3 file system.\n\n" \
+	"Options:\n" \
+	"\t-p\tAutomatic repair (no questions)\n" \
+	"\t-n\tMake no changes to the filesystem\n" \
+	"\t-y\tAssume 'yes' to all questions\n" \
+	"\t-c\tCheck for bad blocks and add them to the badblock list\n" \
+	"\t-f\tForce checking even if filesystem is marked clean\n" \
+	"\t-v\tBe verbose\n" \
+	"\t-b superblock\tUse alternative superblock\n" \
+	"\t-B blocksize\tForce blocksize when looking for superblock\n" \
+	"\t-j journal\tSet location of the external journal\n" \
+	"\t-l file\tAdd to badblocks list\n" \
+	"\t-L file\tSet badblocks list"
+
+#define echo_trivial_usage \
+	USE_FEATURE_FANCY_ECHO("[-neE] ") "[ARG ...]"
+#define echo_full_usage \
+	"Prints the specified ARGs to stdout\n\n" \
+	USE_FEATURE_FANCY_ECHO( \
+		"Options:\n" \
+		"\t-n\tsuppress trailing newline\n" \
+		"\t-e\tinterpret backslash-escaped characters (i.e., \\t=tab)\n" \
+		"\t-E\tdisable interpretation of backslash-escaped characters" \
+	)
+#define echo_example_usage \
+	"$ echo \"Erik is cool\"\n" \
+	"Erik is cool\n" \
+	USE_FEATURE_FANCY_ECHO("$  echo -e \"Erik\\nis\\ncool\"\n" \
+	"Erik\n" \
+	"is\n" \
+	"cool\n" \
+	"$ echo \"Erik\\nis\\ncool\"\n" \
+	"Erik\\nis\\ncool\n")
+
+#define eject_trivial_usage \
+	"[-t] [DEVICE]"
+#define eject_full_usage \
+	"Eject specified DEVICE (or default /dev/cdrom).\n\n" \
+	"Options:\n" \
+	"\t-t\tclose tray"
+
+#define ed_trivial_usage ""
+#define ed_full_usage ""
+
+#define env_trivial_usage \
+	"[-iu] [-] [name=value]... [command]"
+#define env_full_usage \
+	"Prints the current environment or runs a program after setting\n" \
+	"up the specified environment.\n\n" \
+	"Options:\n" \
+	"\t-, -i\tstart with an empty environment\n" \
+	"\t-u\tremove variable from the environment"
+
+#define ether_wake_trivial_usage \
+	"[-b] [-i iface] [-p aa:bb:cc:dd[:ee:ff]] MAC"
+#define ether_wake_full_usage \
+	"Send a magic packet to wake up sleeping machines.\n" \
+	"MAC must be a station address (00:11:22:33:44:55) or\n" \
+	"    a hostname with a known 'ethers' entry.\n\n" \
+	"Options:\n" \
+	"\t-b\t\tSend wake-up packet to the broadcast address\n" \
+	"\t-i iface\tUse interface ifname instead of the default \"eth0\"\n" \
+	"\t-p pass\tAppend the four or six byte password PW to the packet"
+
+#define expr_trivial_usage \
+	"EXPRESSION"
+#define expr_full_usage \
+	"Prints the value of EXPRESSION to standard output.\n\n" \
+	"EXPRESSION may be:\n" \
+	"\tARG1 |  ARG2	ARG1 if it is neither null nor 0, otherwise ARG2\n" \
+	"\tARG1 &  ARG2	ARG1 if neither argument is null or 0, otherwise 0\n" \
+	"\tARG1 <  ARG2	ARG1 is less than ARG2\n" \
+	"\tARG1 <= ARG2	ARG1 is less than or equal to ARG2\n" \
+	"\tARG1 =  ARG2	ARG1 is equal to ARG2\n" \
+	"\tARG1 != ARG2	ARG1 is unequal to ARG2\n" \
+	"\tARG1 >= ARG2	ARG1 is greater than or equal to ARG2\n" \
+	"\tARG1 >  ARG2	ARG1 is greater than ARG2\n" \
+	"\tARG1 +  ARG2	arithmetic sum of ARG1 and ARG2\n" \
+	"\tARG1 -  ARG2	arithmetic difference of ARG1 and ARG2\n" \
+	"\tARG1 *  ARG2	arithmetic product of ARG1 and ARG2\n" \
+	"\tARG1 /  ARG2	arithmetic quotient of ARG1 divided by ARG2\n" \
+	"\tARG1 %  ARG2	arithmetic remainder of ARG1 divided by ARG2\n" \
+	"\tSTRING : REGEXP             anchored pattern match of REGEXP in STRING\n" \
+	"\tmatch STRING REGEXP         same as STRING : REGEXP\n" \
+	"\tsubstr STRING POS LENGTH    substring of STRING, POS counted from 1\n" \
+	"\tindex STRING CHARS          index in STRING where any CHARS is found,\n" \
+	"\t                            or 0\n" \
+	"\tlength STRING               length of STRING\n" \
+	"\tquote TOKEN                 interpret TOKEN as a string, even if\n" \
+	"\t                            it is a keyword like `match' or an\n" \
+	"\t                            operator like `/'\n" \
+	"\t( EXPRESSION )              value of EXPRESSION\n\n" \
+	"Beware that many operators need to be escaped or quoted for shells.\n" \
+	"Comparisons are arithmetic if both ARGs are numbers, else\n" \
+	"lexicographical.  Pattern matches return the string matched between \n" \
+	"\\( and \\) or null; if \\( and \\) are not used, they return the number \n" \
+	"of characters matched or 0."
+
+#define fakeidentd_trivial_usage \
+	"[-b ip] [STRING]"
+#define fakeidentd_full_usage \
+	"Returns a set string to auth requests\n\n" \
+	"\t-b\tBind to ip address\n" \
+	"\tSTRING\tThe ident answer string (default is nobody)"
+
+#define false_trivial_usage \
+	""
+#define false_full_usage \
+	"Return an exit code of FALSE (1)."
+#define false_example_usage \
+	"$ false\n" \
+	"$ echo $?\n" \
+	"1\n"
+
+#define fbset_trivial_usage \
+	"[options] [mode]"
+#define fbset_full_usage \
+	"Show and modify frame buffer settings"
+#define fbset_example_usage \
+	"$ fbset\n" \
+	"mode \"1024x768-76\"\n" \
+	"\t# D: 78.653 MHz, H: 59.949 kHz, V: 75.694 Hz\n" \
+	"\tgeometry 1024 768 1024 768 16\n" \
+	"\ttimings 12714 128 32 16 4 128 4\n" \
+	"\taccel false\n" \
+	"\trgba 5/11,6/5,5/0,0/0\n" \
+	"endmode\n"
+
+#define fdflush_trivial_usage \
+	"DEVICE"
+#define fdflush_full_usage \
+	"Forces floppy disk drive to detect disk change"
+
+#define fdformat_trivial_usage \
+	"[-n] DEVICE"
+#define fdformat_full_usage \
+	"Low-level formats a floppy disk\n\n" \
+	"Options:\n" \
+	"\t-n\tDon't verify after format"
+
+#define fdisk_trivial_usage \
+	"[-luv] [-C CYLINDERS] [-H HEADS] [-S SECTORS] [-b SSZ] DISK"
+#define fdisk_full_usage \
+	"Change partition table\n" \
+	"Options:\n" \
+	"\t-l  List partition table(s)\n" \
+	"\t-u  Give Start and End in sector (instead of cylinder) units\n" \
+	"\t-s PARTITION  Give partition size(s) in blocks\n" \
+	"\t-b 2048: (for certain MO disks) use 2048-byte sectors\n" \
+	"\t-C CYLINDERS  Set the number of cylinders\n" \
+	"\t-H HEADS  Set the number of heads\n" \
+	"\t-S SECTORS  Set the number of sectors\n" \
+	"\t-v  Give fdisk version"
+
+#define find_trivial_usage \
+	"[PATH...] [EXPRESSION]"
+#define find_full_usage \
+	"Search for files in a directory hierarchy.  The default PATH is\n" \
+	"the current directory; default EXPRESSION is '-print'\n" \
+	"\nEXPRESSION may consist of:\n" \
+	"\t-follow\t\tDereference symbolic links\n" \
+	"\t-name PATTERN\tFile name (leading directories removed) matches PATTERN\n" \
+	"\t-print\t\tPrint (default and assumed)\n" \
+	USE_FEATURE_FIND_PRINT0( \
+	"\t-print0\t\tDelimit output with null characters rather than\n\t\t\tnewlines" \
+) USE_FEATURE_FIND_TYPE( \
+	"\n\t-type X\t\tFiletype matches X (where X is one of: f,d,l,b,c,...)" \
+) USE_FEATURE_FIND_PERM( \
+	"\n\t-perm PERMS\tPermissions match any of (+NNN); all of (-NNN);\n\t\t\tor exactly (NNN)" \
+) USE_FEATURE_FIND_MTIME( \
+	"\n\t-mtime DAYS\tModified time is greater than (+N); less than (-N);\n\t\t\tor exactly (N) days" \
+) USE_FEATURE_FIND_MMIN( \
+	"\n\t-mmin MINS\tModified time is greater than (+N); less than (-N);\n\t\t\tor exactly (N) minutes" \
+) USE_FEATURE_FIND_NEWER( \
+	"\n\t-newer FILE\tModified time is more recent than FILE's" \
+) USE_FEATURE_FIND_INUM( \
+	"\n\t-inum N\t\tFile has inode number N" \
+) USE_FEATURE_FIND_EXEC( \
+	"\n\t-exec CMD\tExecute CMD with all instances of {} replaced by the" \
+	"\n\t\t\tfiles matching EXPRESSION")
+
+#define find_example_usage \
+	"$ find / -name passwd\n" \
+	"/etc/passwd\n"
+
+#define fold_trivial_usage \
+	"[-bs] [-w WIDTH] [FILE]"
+#define fold_full_usage \
+	"Wrap input lines in each FILE (standard input by default), writing to\n" \
+	"standard output.\n\n" \
+	"Options:\n" \
+	"\t-b\tcount bytes rather than columns\n" \
+	"\t-s\tbreak at spaces\n" \
+	"\t-w\tuse WIDTH columns instead of 80"
+
+#define free_trivial_usage \
+	""
+#define free_full_usage \
+	"Displays the amount of free and used system memory"
+#define free_example_usage \
+	"$ free\n" \
+	"              total         used         free       shared      buffers\n" \
+	"  Mem:       257628       248724         8904        59644        93124\n" \
+	" Swap:       128516         8404       120112\n" \
+	"Total:       386144       257128       129016\n" \
+
+#define freeramdisk_trivial_usage \
+	"DEVICE"
+#define freeramdisk_full_usage \
+	"Frees all memory used by the specified ramdisk."
+#define freeramdisk_example_usage \
+	"$ freeramdisk /dev/ram2\n"
+
+#define fsck_trivial_usage \
+	"[-ANPRTV] [ -C [ fd ] ] [-t fstype] [fs-options] [filesys ...]"
+#define fsck_full_usage \
+	"Check and repair filesystems.\n\n" \
+	"Options:\n" \
+	"\t-A\tWalk /etc/fstab and check all filesystems\n" \
+	"\t-N\tDon't execute, just show what would be done\n" \
+	"\t-P\tWhen using -A, check filesystems in parallel\n" \
+	"\t-R\tWhen using -A, skip the root filesystem\n" \
+	"\t-T\tDon't show title on startup\n" \
+	"\t-V\tVerbose mode\n" \
+	"\t-C\tWrite status information to specified filedescriptor\n" \
+	"\t-t\tList of filesystem types to check"
+
+#define fsck_minix_trivial_usage \
+	"[-larvsmf] /dev/name"
+#define fsck_minix_full_usage \
+	"Performs a consistency check for MINIX filesystems.\n\n" \
+	"Options:\n" \
+	"\t-l\tLists all filenames\n" \
+	"\t-r\tPerform interactive repairs\n" \
+	"\t-a\tPerform automatic repairs\n" \
+	"\t-v\tverbose\n" \
+	"\t-s\tOutputs super-block information\n" \
+	"\t-m\tActivates MINIX-like \"mode not cleared\" warnings\n" \
+	"\t-f\tForce file system check"
+
+#define ftpget_trivial_usage \
+	"[options] remote-host local-file remote-file"
+#define ftpget_full_usage \
+	"Retrieve a remote file via FTP.\n\n" \
+	"Options:\n" \
+	"\t-c, --continue         Continue a previous transfer\n" \
+	"\t-v, --verbose          Verbose\n" \
+	"\t-u, --username         Username to be used\n" \
+	"\t-p, --password         Password to be used\n" \
+	"\t-P, --port             Port number to be used"
+
+#define ftpput_trivial_usage \
+	"[options] remote-host remote-file local-file"
+#define ftpput_full_usage \
+	"Store a local file on a remote machine via FTP.\n\n" \
+	"Options:\n" \
+	"\t-v, --verbose          Verbose\n" \
+	"\t-u, --username         Username to be used\n" \
+	"\t-p, --password         Password to be used\n" \
+	"\t-P, --port             Port number to be used"
+
+#define fuser_trivial_usage \
+	"[options] file OR port/proto"
+#define fuser_full_usage \
+	"Options:\n" \
+	"\t-m         Show all processes on the same mounted fs\n" \
+	"\t-k         Kill all processes that match.\n" \
+	"\t-s         Don't print or kill anything.\n" \
+	"\t-4         When using port/proto only search IPv4 space\n" \
+	"\t-6         When using port/proto only search IPv6 space\n" \
+	"\t-SIGNAL    When used with -k, this signal will be used to kill"
+
+#define getopt_trivial_usage \
+	"[OPTIONS]..."
+#define getopt_full_usage \
+	"Parse command options\n" \
+	"\t-a, --alternative		Allow long options starting with single -\n" \
+	"\t-l, --longoptions=longopts	Long options to be recognized\n" \
+	"\t-n, --name=progname		The name under which errors are reported\n" \
+	"\t-o, --options=optstring	Short options to be recognized\n" \
+	"\t-q, --quiet			Disable error reporting by getopt(3)\n" \
+	"\t-Q, --quiet-output		No normal output\n" \
+	"\t-s, --shell=shell		Set shell quoting conventions\n" \
+	"\t-T, --test			Test for getopt(1) version\n" \
+	"\t-u, --unquoted		Do not quote the output"
+#define getopt_example_usage \
+	"$ cat getopt.test\n" \
+	"#!/bin/sh\n" \
+	"GETOPT=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \\\n" \
+	"       -n 'example.busybox' -- \"$@\"`\n" \
+	"if [ $? != 0 ] ; then  exit 1 ; fi\n" \
+	"eval set -- \"$GETOPT\"\n" \
+	"while true ; do\n" \
+	" case $1 in\n" \
+	"   -a|--a-long) echo \"Option a\" ; shift ;;\n" \
+	"   -b|--b-long) echo \"Option b, argument `$2'\" ; shift 2 ;;\n" \
+	"   -c|--c-long)\n" \
+	"     case \"$2\" in\n" \
+	"       \"\") echo \"Option c, no argument\"; shift 2 ;;\n" \
+	"       *)  echo \"Option c, argument `$2'\" ; shift 2 ;;\n" \
+	"     esac ;;\n" \
+	"   --) shift ; break ;;\n" \
+	"   *) echo \"Internal error!\" ; exit 1 ;;\n" \
+	" esac\n" \
+	"done\n"
+
+#define getty_trivial_usage \
+	"[OPTIONS]... baud_rate,... line [termtype]"
+#define getty_full_usage \
+	"Opens a tty, prompts for a login name, then invokes /bin/login\n\n" \
+	"Options:\n" \
+	"\t-h\t\tEnable hardware (RTS/CTS) flow control\n" \
+	"\t-i\t\tDo not display /etc/issue before running login\n" \
+	"\t-L\t\tLocal line, so do not do carrier detect\n" \
+	"\t-m\t\tGet baud rate from modem's CONNECT status message\n" \
+	"\t-w\t\tWait for a CR or LF before sending /etc/issue\n" \
+	"\t-n\t\tDo not prompt the user for a login name\n" \
+	"\t-f issue_file\tDisplay issue_file instead of /etc/issue\n" \
+	"\t-l login_app\tInvoke login_app instead of /bin/login\n" \
+	"\t-t timeout\tTerminate after timeout if no username is read\n" \
+	"\t-I initstring\tSets the init string to send before anything else\n" \
+	"\t-H login_host\tLog login_host into the utmp file as the hostname"
+
+#define grep_trivial_usage \
+	"[-ihHnqvs" \
+	USE_FEATURE_GREP_EGREP_ALIAS("E") \
+	USE_FEATURE_GREP_CONTEXT("ABC") \
+	"] PATTERN [FILEs...]"
+#define grep_full_usage \
+	"Search for PATTERN in each FILE or standard input.\n\n" \
+	"Options:\n" \
+	"\t-H\tprefix output lines with filename where match was found\n" \
+	"\t-h\tsuppress the prefixing filename on output\n" \
+	"\t-i\tignore case distinctions\n" \
+	"\t-l\tlist names of files that match\n" \
+	"\t-L\tlist names of files that do not match\n" \
+	"\t-n\tprint line number with output lines\n" \
+	"\t-q\tbe quiet. Returns 0 if PATTERN was found, 1 otherwise\n" \
+	"\t-v\tselect non-matching lines\n" \
+	"\t-s\tsuppress file open/read error messages\n" \
+	"\t-c\tonly print count of matching lines\n" \
+	"\t-f\tread PATTERN from file\n" \
+	"\t-e\tPATTERN is a regular expression\n" \
+	"\t-F\tPATTERN is a set of newline-separated strings" \
+	USE_FEATURE_GREP_EGREP_ALIAS("\n\t-E\tPATTERN is an extended regular expression") \
+	USE_FEATURE_GREP_CONTEXT("\n\t-A\tprint NUM lines of trailing context") \
+	USE_FEATURE_GREP_CONTEXT("\n\t-B\tprint NUM lines of leading context") \
+	USE_FEATURE_GREP_CONTEXT("\n\t-C\tprint NUM lines of output context")
+
+#define grep_example_usage \
+	"$ grep root /etc/passwd\n" \
+	"root:x:0:0:root:/root:/bin/bash\n" \
+	"$ grep ^[rR]oo. /etc/passwd\n" \
+	"root:x:0:0:root:/root:/bin/bash\n"
+
+#define gunzip_trivial_usage \
+	"[OPTION]... FILE"
+#define gunzip_full_usage \
+	"Uncompress FILE (or standard input if FILE is '-').\n\n" \
+	"Options:\n" \
+	"\t-c\tWrite output to standard output\n" \
+	"\t-f\tForce read when source is a terminal\n" \
+	"\t-t\tTest compressed file integrity"
+#define gunzip_example_usage \
+	"$ ls -la /tmp/BusyBox*\n" \
+	"-rw-rw-r--    1 andersen andersen   557009 Apr 11 10:55 /tmp/BusyBox-0.43.tar.gz\n" \
+	"$ gunzip /tmp/BusyBox-0.43.tar.gz\n" \
+	"$ ls -la /tmp/BusyBox*\n" \
+	"-rw-rw-r--    1 andersen andersen  1761280 Apr 14 17:47 /tmp/BusyBox-0.43.tar\n"
+
+#define gzip_trivial_usage \
+	"[OPTION]... [FILE]..."
+#define gzip_full_usage \
+	"Compress FILE(s) with maximum compression.\n" \
+	"When FILE is '-' or unspecified, reads standard input.  Implies -c.\n\n" \
+	"Options:\n" \
+	"\t-c\tWrite output to standard output instead of FILE.gz\n" \
+	"\t-d\tDecompress\n" \
+	"\t-f\tForce write when destination is a terminal"
+#define gzip_example_usage \
+	"$ ls -la /tmp/busybox*\n" \
+	"-rw-rw-r--    1 andersen andersen  1761280 Apr 14 17:47 /tmp/busybox.tar\n" \
+	"$ gzip /tmp/busybox.tar\n" \
+	"$ ls -la /tmp/busybox*\n" \
+	"-rw-rw-r--    1 andersen andersen   554058 Apr 14 17:49 /tmp/busybox.tar.gz\n"
+
+#define halt_trivial_usage \
+	"[-d<delay>] [-n<nosync>] [-f<force>]"
+#define halt_full_usage \
+	"Halt the system.\n" \
+	"Options:\n" \
+	"\t-d\t\tdelay interval for halting\n" \
+	"\t-n\t\tno call to sync()\n" \
+	"\t-f\t\tforce halt (don't go through init)"
+
+#define hdparm_trivial_usage \
+	"[options] [device] .."
+#define hdparm_full_usage \
+	USE_FEATURE_HDPARM_GET_IDENTITY("\tIf no device name is specified try to read from stdin.\n") \
+	"\nOptions:\n" \
+	"\t-a   get/set fs readahead\n" \
+	"\t-A   set drive read-lookahead flag (0/1)\n" \
+	"\t-b   get/set bus state (0 == off, 1 == on, 2 == tristate)\n" \
+	"\t-B   set Advanced Power Management setting (1-255)\n" \
+	"\t-c   get/set IDE 32-bit IO setting\n" \
+	"\t-C   check IDE power mode status\n" \
+	USE_FEATURE_HDPARM_HDIO_GETSET_DMA("\t-d   get/set using_dma flag\n") \
+	"\t-D   enable/disable drive defect-mgmt\n" \
+	"\t-f   flush buffer cache for device on exit\n" \
+	"\t-g   display drive geometry\n" \
+	"\t-h   display terse usage information\n" \
+	USE_FEATURE_HDPARM_GET_IDENTITY("\t-i   display drive identification\n") \
+	USE_FEATURE_HDPARM_GET_IDENTITY("\t-I   detailed/current information directly from drive\n") \
+	"\t-k   get/set keep_settings_over_reset flag (0/1)\n" \
+	"\t-K   set drive keep_features_over_reset flag (0/1)\n" \
+	"\t-L   set drive doorlock (0/1) (removable harddisks only)\n" \
+	"\t-m   get/set multiple sector count\n" \
+	"\t-n   get/set ignore-write-errors flag (0/1)\n" \
+	"\t-p   set PIO mode on IDE interface chipset (0,1,2,3,4,...)\n" \
+	"\t-P   set drive prefetch count\n" \
+	"\t-q   change next setting quietly\n" \
+	"\t-Q   get/set DMA tagged-queuing depth (if supported)\n" \
+	"\t-r   get/set readonly flag (DANGEROUS to set)\n" \
+	USE_FEATURE_HDPARM_HDIO_SCAN_HWIF("\t-R   register an IDE interface (DANGEROUS)\n") \
+	"\t-S   set standby (spindown) timeout\n" \
+	"\t-t   perform device read timings\n" \
+	"\t-T   perform cache read timings\n" \
+	"\t-u   get/set unmaskirq flag (0/1)\n" \
+	USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF("\t-U   un-register an IDE interface (DANGEROUS)\n") \
+	"\t-v   defaults; same as -mcudkrag for IDE drives\n" \
+	"\t-V   display program version and exit immediately\n" \
+	USE_FEATURE_HDPARM_HDIO_DRIVE_RESET("\t-w   perform device reset (DANGEROUS)\n") \
+	"\t-W   set drive write-caching flag (0/1) (DANGEROUS)\n" \
+	USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF("\t-x   tristate device for hotswap (0/1) (DANGEROUS)\n") \
+	"\t-X   set IDE xfer mode (DANGEROUS)\n" \
+	"\t-y   put IDE drive in standby mode\n" \
+	"\t-Y   put IDE drive to sleep\n" \
+	"\t-Z   disable Seagate auto-powersaving mode\n" \
+	"\t-z   re-read partition table"
+
+#define head_trivial_usage \
+	"[OPTION]... [FILE]..."
+#define head_full_usage \
+	"Print first 10 lines of each FILE to standard output.\n" \
+	"With more than one FILE, precede each with a header giving the\n" \
+	"file name. With no FILE, or when FILE is -, read standard input.\n\n" \
+	"Options:\n" \
+	"\t-n NUM\t\tPrint first NUM lines instead of first 10" \
+	USE_FEATURE_FANCY_HEAD( \
+	"\n\t-c NUM\t\toutput the first NUM bytes\n" \
+	"\t-q\t\tnever output headers giving file names\n" \
+	"\t-v\t\talways output headers giving file names" )
+#define head_example_usage \
+	"$ head -n 2 /etc/passwd\n" \
+	"root:x:0:0:root:/root:/bin/bash\n" \
+	"daemon:x:1:1:daemon:/usr/sbin:/bin/sh\n"
+
+#define hexdump_trivial_usage \
+	"[-[bcCdefnosvx]] [OPTION] FILE"
+#define hexdump_full_usage \
+	"The hexdump utility is a filter which displays the specified files,\n" \
+	"or the standard input, if no files are specified, in a user specified\n" \
+	"format\n" \
+	"\t-b\t\tOne-byte octal display\n" \
+	"\t-c\t\tOne-byte character display\n" \
+	"\t-C\t\tCanonical hex+ASCII, 16 bytes per line\n" \
+	"\t-d\t\tTwo-byte decimal display\n" \
+	"\t-e FORMAT STRING\n" \
+	"\t-f FORMAT FILE\n" \
+	"\t-n LENGTH\tInterpret only length bytes of input\n" \
+	"\t-o\t\tTwo-byte octal display\n" \
+	"\t-s OFFSET\tSkip offset byte\n" \
+	"\t-v\t\tdisplay all input data\n" \
+	"\t-x\t\tTwo-byte hexadecimal display"
+
+#define hostid_trivial_usage \
+	""
+#define hostid_full_usage \
+	"Print out a unique 32-bit identifier for the machine."
+
+#define hostname_trivial_usage \
+	"[OPTION] {hostname | -F FILE}"
+#define hostname_full_usage \
+	"Get or set the hostname or DNS domain name. If a hostname is given\n" \
+	"(or FILE with the -F parameter), the host name will be set.\n\n" \
+	"Options:\n" \
+	"\t-s\tShort\n" \
+	"\t-i\tAddresses for the hostname\n" \
+	"\t-d\tDNS domain name\n" \
+	"\t-f\tFully qualified domain name\n" \
+	"\t-F FILE\tUse the contents of FILE to specify the hostname"
+#define hostname_example_usage \
+	"$ hostname\n" \
+	"sage\n"
+
+#define httpd_trivial_usage \
+	"[-c <conf file>]" \
+	USE_FEATURE_HTTPD_WITHOUT_INETD(" [-p <port>]") \
+	USE_FEATURE_HTTPD_SETUID(" [-u user]") \
+	USE_FEATURE_HTTPD_BASIC_AUTH(" [-r <realm>]") \
+	USE_FEATURE_HTTPD_AUTH_MD5(" [-m pass]") \
+	" [-h home]" \
+	" [-d/-e <string>]"
+#define httpd_full_usage \
+	"Listens for incoming http server requests.\n\n" \
+	"Options:\n" \
+	"\t-c FILE\t\tSpecifies configuration file. (default httpd.conf)\n" \
+	USE_FEATURE_HTTPD_WITHOUT_INETD("\t-p PORT\tServer port (default 80)\n") \
+	USE_FEATURE_HTTPD_SETUID("\t-u USER\tSet uid to USER after listening privileges port\n") \
+	USE_FEATURE_HTTPD_BASIC_AUTH("\t-r REALM\tAuthentication Realm for Basic Authentication\n") \
+	USE_FEATURE_HTTPD_AUTH_MD5("\t-m PASS\t\tCrypt PASS with md5 algorithm\n") \
+	"\t-h HOME  \tSpecifies http HOME directory (default ./)\n" \
+	"\t-e STRING\tHtml encode STRING\n" \
+	"\t-d STRING\tURL decode STRING"
+
+#define hwclock_trivial_usage \
+	"[-r|--show] [-s|--hctosys] [-w|--systohc] [-l|--localtime] [-u|--utc]"
+#define hwclock_full_usage \
+	"Query and set the hardware clock (RTC)\n\n" \
+	"Options:\n" \
+	"\t-r\tread hardware clock and print result\n" \
+	"\t-s\tset the system time from the hardware clock\n" \
+	"\t-w\tset the hardware clock to the current system time\n" \
+	"\t-u\tthe hardware clock is kept in coordinated universal time\n" \
+	"\t-l\tthe hardware clock is kept in local time"
+
+#ifdef CONFIG_SELINUX
+#  define USAGE_SELINUX(a) a
+#else
+#  define USAGE_SELINUX(a)
+#endif
+
+#define id_trivial_usage \
+	"[OPTIONS]... [USERNAME]"
+#define id_full_usage \
+	"Print information for USERNAME or the current user\n\n" \
+	"Options:\n" \
+	USAGE_SELINUX("\t-c\tprints only the security context\n") \
+	"\t-g\tprints only the group ID\n" \
+	"\t-u\tprints only the user ID\n" \
+	"\t-n\tprint a name instead of a number\n" \
+	"\t-r\tprints the real user ID instead of the effective ID"
+#define id_example_usage \
+	"$ id\n" \
+	"uid=1000(andersen) gid=1000(andersen)\n"
+
+#ifdef CONFIG_FEATURE_IFCONFIG_SLIP
+#  define USAGE_SIOCSKEEPALIVE(a) a
+#else
+#  define USAGE_SIOCSKEEPALIVE(a)
+#endif
+#ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
+#  define USAGE_IFCONFIG_MII(a) a
+#else
+#  define USAGE_IFCONFIG_MII(a)
+#endif
+#ifdef CONFIG_FEATURE_IFCONFIG_HW
+#  define USAGE_IFCONFIG_HW(a) a
+#else
+#  define USAGE_IFCONFIG_HW(a)
+#endif
+#ifdef CONFIG_FEATURE_IFCONFIG_STATUS
+#  define USAGE_IFCONFIG_OPT_A(a) a
+#else
+#  define USAGE_IFCONFIG_OPT_A(a)
+#endif
+#ifdef CONFIG_FEATURE_IPV6
+#  define USAGE_IPV6(a) a
+#else
+#  define USAGE_IPV6(a)
+#endif
+
+#define ifconfig_trivial_usage \
+	USAGE_IFCONFIG_OPT_A("[-a]") " <interface> [<address>]"
+#define ifconfig_full_usage \
+	"configure a network interface\n\n" \
+	"Options:\n" \
+	USAGE_IPV6("\t[add <address>[/<prefixlen>]]\n") \
+	USAGE_IPV6("\t[del <address>[/<prefixlen>]]\n") \
+	"\t[[-]broadcast [<address>]]  [[-]pointopoint [<address>]]\n" \
+	"\t[netmask <address>]  [dstaddr <address>]\n" \
+	USAGE_SIOCSKEEPALIVE("\t[outfill <NN>] [keepalive <NN>]\n") \
+	"\t" USAGE_IFCONFIG_HW("[hw ether <address>]  ") \
+	"[metric <NN>]  [mtu <NN>]\n" \
+	"\t[[-]trailers]  [[-]arp]  [[-]allmulti]\n" \
+	"\t[multicast]  [[-]promisc]  [txqueuelen <NN>]  [[-]dynamic]\n" \
+	USAGE_IFCONFIG_MII("\t[mem_start <NN>]  [io_addr <NN>]  [irq <NN>]\n") \
+	"\t[up|down] ..."
+
+#define ifup_trivial_usage \
+	"<-ahinv> <ifaces...>"
+#define ifup_full_usage \
+	"ifup <options> <ifaces...>\n\n" \
+	"Options:\n" \
+	"\t-h\tthis help\n" \
+	"\t-a\tde/configure all interfaces automatically\n" \
+	"\t-i FILE\tuse FILE for interface definitions\n" \
+	"\t-n\tprint out what would happen, but don't do it\n" \
+	"\t\t\t(note that this option doesn't disable mappings)\n" \
+	"\t-v\tprint out what would happen before doing it\n" \
+	"\t-m\tdon't run any mappings\n" \
+	"\t-f\tforce de/configuration"
+
+#define ifdown_trivial_usage \
+	"<-ahinv> <ifaces...>"
+#define ifdown_full_usage \
+	"ifdown <options> <ifaces...>\n\n" \
+	"Options:\n" \
+	"\t-h\tthis help\n" \
+	"\t-a\tde/configure all interfaces automatically\n" \
+	"\t-i FILE\tuse FILE for interface definitions\n" \
+	"\t-n\tprint out what would happen, but don't do it\n" \
+	"\t\t(note that this option doesn't disable mappings)\n" \
+	"\t-v\tprint out what would happen before doing it\n" \
+	"\t-m\tdon't run any mappings\n" \
+	"\t-f\tforce de/configuration"
+
+#define inetd_trivial_usage \
+	"[-f] [-q len] [conf]"
+#define inetd_full_usage \
+	"Listens for network connections and launches programs\n\n" \
+	"Option:\n" \
+	"\t-f\tRun as a foreground progress\n" \
+	"\t-q\tSets the size of the socket listen queue to\n" \
+	"\t\tthe specified value. Default is 128"
+
+#define init_trivial_usage \
+	""
+#define init_full_usage \
+	"Init is the parent of all processes."
+#define init_notes_usage \
+"This version of init is designed to be run only by the kernel.\n" \
+"\n" \
+"BusyBox init doesn't support multiple runlevels.  The runlevels field of\n" \
+"the /etc/inittab file is completely ignored by BusyBox init. If you want \n" \
+"runlevels, use sysvinit.\n" \
+"\n" \
+"BusyBox init works just fine without an inittab.  If no inittab is found, \n" \
+"it has the following default behavior:\n" \
+"\n" \
+"	::sysinit:/etc/init.d/rcS\n" \
+"	::askfirst:/bin/sh\n" \
+"	::ctrlaltdel:/sbin/reboot\n" \
+"	::shutdown:/sbin/swapoff -a\n" \
+"	::shutdown:/bin/umount -a -r\n" \
+"	::restart:/sbin/init\n" \
+"\n" \
+"if it detects that /dev/console is _not_ a serial console, it will also run:\n" \
+"\n" \
+"	tty2::askfirst:/bin/sh\n" \
+"	tty3::askfirst:/bin/sh\n" \
+"	tty4::askfirst:/bin/sh\n" \
+"\n" \
+"If you choose to use an /etc/inittab file, the inittab entry format is as follows:\n" \
+"\n" \
+"	<id>:<runlevels>:<action>:<process>\n" \
+"\n" \
+"	<id>:\n" \
+"\n" \
+"		WARNING: This field has a non-traditional meaning for BusyBox init!\n" \
+"		The id field is used by BusyBox init to specify the controlling tty for\n" \
+"		the specified process to run on.  The contents of this field are\n" \
+"		appended to \"/dev/\" and used as-is.  There is no need for this field to\n" \
+"		be unique, although if it isn't you may have strange results.  If this\n" \
+"		field is left blank, the controlling tty is set to the console.  Also\n" \
+"		note that if BusyBox detects that a serial console is in use, then only\n" \
+"		entries whose controlling tty is either the serial console or /dev/null\n" \
+"		will be run.  BusyBox init does nothing with utmp.  We don't need no\n" \
+"		stinkin' utmp.\n" \
+"\n" \
+"	<runlevels>:\n" \
+"\n" \
+"		The runlevels field is completely ignored.\n" \
+"\n" \
+"	<action>:\n" \
+"\n" \
+"		Valid actions include: sysinit, respawn, askfirst, wait,\n" \
+"		once, restart, ctrlaltdel, and shutdown.\n" \
+"\n" \
+"		The available actions can be classified into two groups: actions\n" \
+"		that are run only once, and actions that are re-run when the specified\n" \
+"		process exits.\n" \
+"\n" \
+"		Run only-once actions:\n" \
+"\n" \
+"			'sysinit' is the first item run on boot.  init waits until all\n" \
+"			sysinit actions are completed before continuing.  Following the\n" \
+"			completion of all sysinit actions, all 'wait' actions are run.\n" \
+"			'wait' actions, like  'sysinit' actions, cause init to wait until\n" \
+"			the specified task completes.  'once' actions are asynchronous,\n" \
+"			therefore, init does not wait for them to complete.  'restart' is\n" \
+"			the action taken to restart the init process.  By default this should\n" \
+"			simply run /sbin/init, but can be a script which runs pivot_root or it\n" \
+"			can do all sorts of other interesting things.  The 'ctrlaltdel' init\n" \
+"			actions are run when the system detects that someone on the system\n" \
+"                       console has pressed the CTRL-ALT-DEL key combination.  Typically one\n" \
+"                       wants to run 'reboot' at this point to cause the system to reboot.\n" \
+"			Finally the 'shutdown' action specifies the actions to taken when\n" \
+"                       init is told to reboot.  Unmounting filesystems and disabling swap\n" \
+"                       is a very good here\n" \
+"\n" \
+"		Run repeatedly actions:\n" \
+"\n" \
+"			'respawn' actions are run after the 'once' actions.  When a process\n" \
+"			started with a 'respawn' action exits, init automatically restarts\n" \
+"			it.  Unlike sysvinit, BusyBox init does not stop processes from\n" \
+"			respawning out of control.  The 'askfirst' actions acts just like\n" \
+"			respawn, except that before running the specified process it\n" \
+"			displays the line \"Please press Enter to activate this console.\"\n" \
+"			and then waits for the user to press enter before starting the\n" \
+"			specified process.\n" \
+"\n" \
+"		Unrecognized actions (like initdefault) will cause init to emit an\n" \
+"		error message, and then go along with its business.  All actions are\n" \
+"		run in the order they appear in /etc/inittab.\n" \
+"\n" \
+"	<process>:\n" \
+"\n" \
+"		Specifies the process to be executed and its command line.\n" \
+"\n" \
+"Example /etc/inittab file:\n" \
+"\n" \
+"	# This is run first except when booting in single-user mode.\n" \
+"	#\n" \
+"	::sysinit:/etc/init.d/rcS\n" \
+"	\n" \
+"	# /bin/sh invocations on selected ttys\n" \
+"	#\n" \
+"	# Start an \"askfirst\" shell on the console (whatever that may be)\n" \
+"	::askfirst:-/bin/sh\n" \
+"	# Start an \"askfirst\" shell on /dev/tty2-4\n" \
+"	tty2::askfirst:-/bin/sh\n" \
+"	tty3::askfirst:-/bin/sh\n" \
+"	tty4::askfirst:-/bin/sh\n" \
+"	\n" \
+"	# /sbin/getty invocations for selected ttys\n" \
+"	#\n" \
+"	tty4::respawn:/sbin/getty 38400 tty4\n" \
+"	tty5::respawn:/sbin/getty 38400 tty5\n" \
+"	\n" \
+"	\n" \
+"	# Example of how to put a getty on a serial line (for a terminal)\n" \
+"	#\n" \
+"	#::respawn:/sbin/getty -L ttyS0 9600 vt100\n" \
+"	#::respawn:/sbin/getty -L ttyS1 9600 vt100\n" \
+"	#\n" \
+"	# Example how to put a getty on a modem line.\n" \
+"	#::respawn:/sbin/getty 57600 ttyS2\n" \
+"	\n" \
+"	# Stuff to do when restarting the init process\n" \
+"	::restart:/sbin/init\n" \
+"	\n" \
+"	# Stuff to do before rebooting\n" \
+"	::ctrlaltdel:/sbin/reboot\n" \
+"	::shutdown:/bin/umount -a -r\n" \
+"	::shutdown:/sbin/swapoff -a\n"
+
+#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
+#  define USAGE_INSMOD_MAP(a) a
+#else
+#  define USAGE_INSMOD_MAP(a)
+#endif
+#define insmod_trivial_usage \
+	"[OPTION]... MODULE [symbol=value]..."
+#define insmod_full_usage \
+	"Loads the specified kernel modules into the kernel.\n\n" \
+	"Options:\n" \
+	"\t-f\tForce module to load into the wrong kernel version\n" \
+	"\t-k\tMake module autoclean-able\n" \
+	"\t-v\tverbose output\n"  \
+	"\t-q\tquiet output\n" \
+	"\t-L\tLock to prevent simultaneous loads of a module\n" \
+	USAGE_INSMOD_MAP("\t-m\tOutput load map to stdout\n") \
+	"\t-o NAME\tSet internal module name to NAME\n" \
+	"\t-x\tdo not export externs"
+
+#define install_trivial_usage \
+	"[-cgmops] [sources] <dest|directory>"
+#define install_full_usage \
+	"Copies files and set attributes\n\n" \
+	"Options:\n" \
+	"\t-c\tcopy the file, default\n" \
+	"\t-d\tcreate directories\n" \
+	"\t-g\tset group ownership\n" \
+	"\t-m\tset permission modes\n" \
+	"\t-o\tset ownership\n" \
+	"\t-p\tpreserve date\n" \
+	"\t-s\tstrip symbol tables"
+
+#define ip_trivial_usage \
+	"[ OPTIONS ] { address | link | route | tunnel } { COMMAND | help }"
+#define ip_full_usage \
+	"ip [ OPTIONS ] OBJECT { COMMAND | help }\n" \
+	"where  OBJECT := { link | addr | route | tunnel }\n" \
+	"OPTIONS := { -f[amily] { inet | inet6 | link } | -o[neline] }"
+
+#define ipaddr_trivial_usage \
+	"{ {add|del} IFADDR dev STRING | {show|flush}\n" \
+	"\t\t[ dev STRING ] [ to PREFIX ] }"
+#define ipaddr_full_usage \
+	"ipaddr {add|delete} IFADDR dev STRING\n" \
+	"ipaddr {show|flush} [ dev STRING ] [ scope SCOPE-ID ]\n" \
+	"\t\t\t[ to PREFIX ] [ label PATTERN ]\n" \
+	"\t\t\tIFADDR := PREFIX | ADDR peer PREFIX\n" \
+	"\t\t\t[ broadcast ADDR ] [ anycast ADDR ]\n" \
+	"\t\t\t[ label STRING ] [ scope SCOPE-ID ]\n" \
+	"\t\t\tSCOPE-ID := [ host | link | global | NUMBER ]"
+
+#ifdef CONFIG_FEATURE_IPCALC_FANCY
+#  define XUSAGE_IPCALC_FANCY(a) a
+#else
+#  define XUSAGE_IPCALC_FANCY(a)
+#endif
+#define ipcalc_trivial_usage \
+	"[OPTION]... <ADDRESS>[[/]<NETMASK>] [NETMASK]"
+#define ipcalc_full_usage \
+	"Calculate IP network settings from a IP address\n\n" \
+	"Options:\n" \
+	"\t-b\t--broadcast\tDisplay calculated broadcast address\n" \
+	"\t-n\t--network\tDisplay calculated network address\n" \
+	"\t-m\t--netmask\tDisplay default netmask for IP" \
+	XUSAGE_IPCALC_FANCY( \
+	"\n\t-p\t--prefix\tDisplay the prefix for IP/NETMASK\n" \
+	"\t-h\t--hostname\tDisplay first resolved host name\n" \
+	"\t-s\t--silent\tDon't ever display error messages")
+
+#define ipcrm_trivial_usage \
+	"[-[MQS] key] [-[mqs] id]"
+#define ipcrm_full_usage \
+	"The upper-case options MQS are used to remove a shared memory\n" \
+	"segment by an shmkey value. The lower-case options mqs are used\n" \
+	"to remove a segment by shmid value.\n" \
+	"\t-m | -M\tRemove the memory segment after the last detach\n" \
+	"\t-q | -Q\tRemove the message queue\n" \
+	"\t-s | -S\tRemove the semaphore"
+
+#define ipcs_trivial_usage \
+	"[[-smq] -i shmid] | [[-asmq] [-tclup]]"
+#define ipcs_full_usage \
+	"\t-i\tspecify a specific resource id\n" \
+	"Resource specification:\n" \
+	"\t-m\tshared memory segments\n" \
+	"\t-q\tmessage queues\n" \
+	"\t-s\tsemaphore arrays\n" \
+	"\t-a\tall (default)\n" \
+	"Output format:\n" \
+	"\t-t\ttime\n" \
+	"\t-p\tpid\n" \
+	"\t-s\tcreator\n" \
+	"\t-a\tlimits\n" \
+	"\t-i\tsummary"
+
+#define iplink_trivial_usage \
+	"{ set DEVICE { up | down | arp { on | off } | show [ DEVICE ] }"
+#define iplink_full_usage \
+	"iplink set DEVICE { up | down | arp { on | off } |\n" \
+	"\t\t\tdynamic { on | off } |\n" \
+	"\t\t\tmtu MTU }\n" \
+	"\tiplink show [ DEVICE ]"
+
+#define iproute_trivial_usage \
+	"{ list | flush | { add | del | change | append |\n" \
+	"\t\treplace | monitor } ROUTE }"
+#define iproute_full_usage \
+	"iproute { list | flush } SELECTOR\n" \
+	"iproute get ADDRESS [ from ADDRESS iif STRING ]\n" \
+	"\t\t\t[ oif STRING ]  [ tos TOS ]\n" \
+	"\tiproute { add | del | change | append | replace | monitor } ROUTE\n" \
+	"\t\t\tSELECTOR := [ root PREFIX ] [ match PREFIX ] [ proto RTPROTO ]\n" \
+	"\t\t\tROUTE := [ TYPE ] PREFIX [ tos TOS ] [ proto RTPROTO ]"
+
+#define iptunnel_trivial_usage \
+	"{ add | change | del | show } [ NAME ]\n" \
+	"\t\t[ mode { ipip | gre | sit } ]\n" \
+	"\t\t[ remote ADDR ] [ local ADDR ] [ ttl TTL ]"
+#define iptunnel_full_usage \
+	"iptunnel { add | change | del | show } [ NAME ]\n" \
+	"\t\t\t[ mode { ipip | gre | sit } ] [ remote ADDR ] [ local ADDR ]\n" \
+	"\t\t\t[ [i|o]seq ] [ [i|o]key KEY ] [ [i|o]csum ]\n" \
+	"\t\t\t[ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]"
+
+#define kill_trivial_usage \
+	"[-signal] process-id [process-id ...]"
+#define kill_full_usage \
+	"Send a signal (default is SIGTERM) to the specified process(es).\n\n" \
+	"Options:\n" \
+	"\t-l\tList all signal names and numbers"
+#define kill_example_usage \
+	"$ ps | grep apache\n" \
+	"252 root     root     S [apache]\n" \
+	"263 www-data www-data S [apache]\n" \
+	"264 www-data www-data S [apache]\n" \
+	"265 www-data www-data S [apache]\n" \
+	"266 www-data www-data S [apache]\n" \
+	"267 www-data www-data S [apache]\n" \
+	"$ kill 252\n"
+
+#define killall_trivial_usage \
+	"[-q] [-signal] process-name [process-name ...]"
+#define killall_full_usage \
+	"Send a signal (default is SIGTERM) to the specified process(es).\n\n" \
+	"Options:\n" \
+	"\t-l\tList all signal names and numbers\n" \
+	"\t-q\tDo not complain if no processes were killed"
+#define killall_example_usage \
+	"$ killall apache\n"
+
+#define klogd_trivial_usage \
+	"[-c n] [-n]"
+#define klogd_full_usage \
+	"Kernel logger.\n" \
+	"Options:\n" \
+	"\t-c n\tSets the default log level of console messages to n\n" \
+	"\t-n\tRun as a foreground process"
+
+#define length_trivial_usage \
+	"STRING"
+#define length_full_usage \
+	"Prints out the length of the specified STRING."
+#define length_example_usage \
+	"$ length Hello\n" \
+	"5\n"
+
+#define less_trivial_usage \
+	"[-EMNmh~?] FILE1 FILE2..."
+#define less_full_usage \
+	"View a file or list of files. The position within files can be\n" \
+	"changed, and files can be manipulated in various ways with the\n" \
+	"following options:\n\n" \
+	"\t-E\tQuit once the end of a file is reached\n" \
+	"\t-M\tDisplay a status line containing the current line numbers\n" \
+	"\t\tand the percentage through the file\n" \
+	"\t-N\tPrefix line numbers to each line\n" \
+	"\t-m\tDisplay a status line containing the percentage through the\n" \
+	"\t\tfile\n" \
+	"\t-~\tSuppress ~s displayed when input past the end of the file is\n" \
+	"\t\treached.\n" \
+	"\t-h, -?\tDisplay this help message"
+
+#define setarch_trivial_usage \
+	"<personality> <program> [args ...]"
+#define setarch_full_usage \
+	"Personality may be:\n" \
+	"\tlinux32\tSet 32bit uname emulation\n" \
+	"\tlinux64\tSet 64bit uname emulation"
+
+#define ln_trivial_usage \
+	"[OPTION] TARGET... LINK_NAME|DIRECTORY"
+#define ln_full_usage \
+	"Create a link named LINK_NAME or DIRECTORY to the specified TARGET\n" \
+	"\nYou may use '--' to indicate that all following arguments are non-options.\n\n" \
+	"Options:\n" \
+	"\t-s\tmake symbolic links instead of hard links\n" \
+	"\t-f\tremove existing destination files\n" \
+	"\t-n\tno dereference symlinks - treat like normal file\n" \
+	"\t-b\tmake a backup of the target (if exists) before link operation\n" \
+	"\t-S suffix\tuse suffix instead of ~ when making backup files"
+#define ln_example_usage \
+	"$ ln -s BusyBox /tmp/ls\n" \
+	"$ ls -l /tmp/ls\n" \
+	"lrwxrwxrwx    1 root     root            7 Apr 12 18:39 ls -> BusyBox*\n"
+
+#define loadfont_trivial_usage \
+	"< font"
+#define loadfont_full_usage \
+	"Loads a console font from standard input."
+#define loadfont_example_usage \
+	"$ loadfont < /etc/i18n/fontname\n"
+
+#define loadkmap_trivial_usage \
+	"< keymap"
+#define loadkmap_full_usage \
+	"Loads a binary keyboard translation table from standard input."
+#define loadkmap_example_usage \
+	"$ loadkmap < /etc/i18n/lang-keymap\n"
+
+#define logger_trivial_usage \
+	"[OPTION]... [MESSAGE]"
+#define logger_full_usage \
+	"Write MESSAGE to the system log.  If MESSAGE is omitted, log stdin.\n\n" \
+	"Options:\n" \
+	"\t-s\tLog to stderr as well as the system log\n" \
+	"\t-t TAG\tLog using the specified tag (defaults to user name)\n" \
+	"\t-p PRIORITY\tEnter the message with the specified priority\n" \
+	"\t\tThis may be numerical or a ``facility.level'' pair"
+#define logger_example_usage \
+	"$ logger \"hello\"\n"
+
+#define login_trivial_usage \
+	"[OPTION]... [username] [ENV=VAR ...]"
+#define login_full_usage \
+	"Begin a new session on the system\n\n" \
+	"Options:\n" \
+	"\t-f\tDo not authenticate (user already authenticated)\n" \
+	"\t-h\tName of the remote host for this login\n" \
+	"\t-p\tPreserve environment"
+
+#define logname_trivial_usage \
+	""
+#define logname_full_usage \
+	"Print the name of the current user."
+#define logname_example_usage \
+	"$ logname\n" \
+	"root\n"
+
+#define logread_trivial_usage \
+	"[OPTION]..."
+#define logread_full_usage \
+	"Shows the messages from syslogd (using circular buffer).\n\n" \
+	"Options:\n" \
+	"\t-f\t\toutput data as the log grows"
+
+#define losetup_trivial_usage \
+	"[-od] LOOPDEVICE [FILE]"
+#define losetup_full_usage \
+	"Associate LOOPDEVICE with FILE, or display current association.\n\n" \
+	"Options:\n" \
+	"\t-d\t\tDisassociate LOOPDEVICE\n" \
+	"\t-o OFFSET\tStart OFFSET bytes into FILE"
+#define losetup_notes_usage \
+	"One argument (losetup /dev/loop1) will display the current association\n" \
+	"(if any), or disassociate it (with -d).  The display shows the offset\n" \
+	"and filename of the file the loop device is currently bound to.\n\n" \
+	"Two arguments (losetup /dev/loop1 file.img) create a new association,\n" \
+	"with an optional offset (-o 12345).  Encryption is not yet supported.\n\n"
+
+#ifdef CONFIG_FEATURE_LS_TIMESTAMPS
+#  define USAGE_LS_TIMESTAMPS(a) a
+#else
+#  define USAGE_LS_TIMESTAMPS(a)
+#endif
+#ifdef CONFIG_FEATURE_LS_FILETYPES
+#  define USAGE_LS_FILETYPES(a) a
+#else
+#  define USAGE_LS_FILETYPES(a)
+#endif
+#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS
+#  define USAGE_LS_FOLLOWLINKS(a) a
+#else
+#  define USAGE_LS_FOLLOWLINKS(a)
+#endif
+#ifdef CONFIG_FEATURE_LS_RECURSIVE
+#  define USAGE_LS_RECURSIVE(a) a
+#else
+#  define USAGE_LS_RECURSIVE(a)
+#endif
+#ifdef CONFIG_FEATURE_LS_SORTFILES
+#  define USAGE_LS_SORTFILES(a) a
+#else
+#  define USAGE_LS_SORTFILES(a)
+#endif
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+#  define USAGE_AUTOWIDTH(a) a
+#else
+#  define USAGE_AUTOWIDTH(a)
+#endif
+#ifdef CONFIG_FEATURE_LS_COLOR
+  #define USAGE_LS_COLOR(a) a
+#else
+  #define USAGE_LS_COLOR(a)
+#endif
+
+#define ls_trivial_usage \
+	"[-1Aa" USAGE_LS_TIMESTAMPS("c") "Cd" USAGE_LS_TIMESTAMPS("e") USAGE_LS_FILETYPES("F") "iln" USAGE_LS_FILETYPES("p") USAGE_LS_FOLLOWLINKS("L") USAGE_LS_RECURSIVE("R") USAGE_LS_SORTFILES("rS") "s" USAGE_AUTOWIDTH("T") USAGE_LS_TIMESTAMPS("tu") USAGE_LS_SORTFILES("v") USAGE_AUTOWIDTH("w") "x" USAGE_LS_SORTFILES("X") USE_FEATURE_HUMAN_READABLE("h") "k" USAGE_SELINUX("K") "] [filenames...]"
+#define ls_full_usage \
+	"List directory contents\n\n" \
+	"Options:\n" \
+	"\t-1\tlist files in a single column\n" \
+	"\t-A\tdo not list implied . and ..\n" \
+	"\t-a\tdo not hide entries starting with .\n" \
+	"\t-C\tlist entries by columns\n" \
+	USAGE_LS_TIMESTAMPS("\t-c\twith -l: show ctime\n") \
+	USAGE_LS_COLOR("\t--color[={always,never,auto}]\tto control coloring\n") \
+	"\t-d\tlist directory entries instead of contents\n" \
+	USAGE_LS_TIMESTAMPS("\t-e\tlist both full date and full time\n") \
+	USAGE_LS_FILETYPES("\t-F\tappend indicator (one of */=@|) to entries\n") \
+	"\t-i\tlist the i-node for each file\n" \
+	"\t-l\tuse a long listing format\n" \
+	"\t-n\tlist numeric UIDs and GIDs instead of names\n" \
+	USAGE_LS_FILETYPES("\t-p\tappend indicator (one of /=@|) to entries\n") \
+	USAGE_LS_FOLLOWLINKS("\t-L\tlist entries pointed to by symbolic links\n") \
+	USAGE_LS_RECURSIVE("\t-R\tlist subdirectories recursively\n") \
+	USAGE_LS_SORTFILES("\t-r\tsort the listing in reverse order\n") \
+	USAGE_LS_SORTFILES("\t-S\tsort the listing by file size\n") \
+	"\t-s\tlist the size of each file, in blocks\n" \
+	USAGE_AUTOWIDTH("\t-T NUM\tassume Tabstop every NUM columns\n") \
+	USAGE_LS_TIMESTAMPS("\t-t\twith -l: show modification time\n") \
+	USAGE_LS_TIMESTAMPS("\t-u\twith -l: show access time\n") \
+	USAGE_LS_SORTFILES("\t-v\tsort the listing by version\n") \
+	USAGE_AUTOWIDTH("\t-w NUM\tassume the terminal is NUM columns wide\n") \
+	"\t-x\tlist entries by lines instead of by columns\n" \
+	USAGE_LS_SORTFILES("\t-X\tsort the listing by extension\n") \
+	USE_FEATURE_HUMAN_READABLE( \
+	"\t-h\tprint sizes in human readable format (e.g., 1K 243M 2G )\n") \
+	USAGE_SELINUX("\t-k\tprint security context\n") \
+	USAGE_SELINUX("\t-K\tprint security context in long format\n")
+
+#define lsattr_trivial_usage \
+	"[-Radlv] [files...]"
+#define lsattr_full_usage \
+	"list file attributes on an ext2 fs\n\n" \
+	"Options:\n" \
+	"\t-R\trecursively list subdirectories\n" \
+	"\t-a\tdo not hide entries starting with .\n" \
+	"\t-d\tlist directory entries instead of contents\n" \
+	"\t-l\tprint long flag names\n" \
+	"\t-v\tlist the file's version/generation number"
+
+#define lsmod_trivial_usage \
+	""
+#define lsmod_full_usage \
+	"List the currently loaded kernel modules."
+
+#ifdef CONFIG_FEATURE_MAKEDEVS_LEAF
+#define makedevs_trivial_usage \
+	"NAME TYPE MAJOR MINOR FIRST LAST [s]"
+#define makedevs_full_usage \
+	"Creates a range of block or character special files\n\n" \
+	"TYPEs include:\n" \
+	"\tb:\tMake a block (buffered) device.\n" \
+	"\tc or u:\tMake a character (un-buffered) device.\n" \
+	"\tp:\tMake a named pipe. MAJOR and MINOR are ignored for named pipes.\n\n" \
+	"FIRST specifies the number appended to NAME to create the first device.\n" \
+	"LAST specifies the number of the last item that should be created\n" \
+	"If 's' is the last argument, the base device is created as well.\n\n" \
+	"For example:\n" \
+	"\tmakedevs /dev/ttyS c 4 66 2 63   ->  ttyS2-ttyS63\n" \
+	"\tmakedevs /dev/hda b 3 0 0 8 s    ->  hda,hda1-hda8"
+#define makedevs_example_usage \
+	"# makedevs /dev/ttyS c 4 66 2 63\n" \
+	"[creates ttyS2-ttyS63]\n" \
+	"# makedevs /dev/hda b 3 0 0 8 s\n" \
+	"[creates hda,hda1-hda8]\n"
+#endif
+
+#ifdef CONFIG_FEATURE_MAKEDEVS_TABLE
+#define makedevs_trivial_usage \
+	"[-d device_table] rootdir"
+#define makedevs_full_usage \
+	"Creates a range of special files as specified in a device table.\n" \
+	"Device table entries take the form of:\n" \
+	"<type> <mode> <uid> <gid> <major> <minor> <start> <inc> <count>\n" \
+	"Where name is the file name,  type can be one of:\n" \
+	"      f       A regular file\n" \
+	"      d       Directory\n" \
+	"      c       Character special device file\n" \
+	"      b       Block special device file\n" \
+	"      p       Fifo (named pipe)\n" \
+	"uid is the user id for the target file, gid is the group id for the\n" \
+	"target file.  The rest of the entries (major, minor, etc) apply to\n" \
+	"to device special files.  A '-' may be used for blank entries."
+#define makedevs_example_usage \
+	"For example:\n" \
+	"<name>    <type> <mode><uid><gid><major><minor><start><inc><count>\n" \
+	"/dev         d   755    0    0    -      -      -      -    -\n" \
+	"/dev/console c   666    0    0    5      1      -      -    -\n" \
+	"/dev/null    c   666    0    0    1      3      0      0    -\n" \
+	"/dev/zero    c   666    0    0    1      5      0      0    -\n" \
+	"/dev/hda     b   640    0    0    3      0      0      0    -\n" \
+	"/dev/hda     b   640    0    0    3      1      1      1    15\n\n" \
+	"Will Produce:\n" \
+	"/dev\n" \
+	"/dev/console\n" \
+	"/dev/null\n" \
+	"/dev/zero\n" \
+	"/dev/hda\n" \
+	"/dev/hda[0-15]\n"
+#endif
+
+#ifdef CONFIG_FEATURE_MD5_SHA1_SUM_CHECK
+#define USAGE_MD5_SHA1_SUM_CHECK(a) a
+#else
+#define USAGE_MD5_SHA1_SUM_CHECK(a)
+#endif
+
+#define md5sum_trivial_usage \
+	"[OPTION] [FILEs...]" \
+	USAGE_MD5_SHA1_SUM_CHECK("\n   or: md5sum [OPTION] -c [FILE]")
+#define md5sum_full_usage \
+	"Print" USAGE_MD5_SHA1_SUM_CHECK(" or check") " MD5 checksums.\n\n" \
+	"Options:\n" \
+	"With no FILE, or when FILE is -, read standard input." \
+	USAGE_MD5_SHA1_SUM_CHECK("\n\n" \
+	"\t-c\tcheck MD5 sums against given list\n" \
+	"\nThe following two options are useful only when verifying checksums:\n" \
+	"\t-s\tdon't output anything, status code shows success\n" \
+	"\t-w\twarn about improperly formated MD5 checksum lines")
+#define md5sum_example_usage \
+	"$ md5sum < busybox\n" \
+	"6fd11e98b98a58f64ff3398d7b324003\n" \
+	"$ md5sum busybox\n" \
+	"6fd11e98b98a58f64ff3398d7b324003  busybox\n" \
+	"$ md5sum -c -\n" \
+	"6fd11e98b98a58f64ff3398d7b324003  busybox\n" \
+	"busybox: OK\n" \
+	"^D\n"
+
+#define mdev_trivial_usage \
+	"[-s]"
+#define mdev_full_usage \
+	"\t-s\tScan /sys and populate /dev during system boot\n\n" \
+	"Called with no options (via hotplug) it uses environment variables\n" \
+	"to determine which device to add/remove."
+#define mdev_notes_usage "" \
+USE_FEATURE_MDEV_CONFIG( \
+	"The mdev config file contains lines that look like:\n" \
+	"  hd[a-z][0-9]* 0:3 660\n\n" \
+	"That's device name (with regex match), uid:gid, and permissions.\n\n" \
+	USE_FEATURE_MDEV_EXEC( \
+		"Optionally, that can be followed (on the same line) by a special character\n" \
+		"and a command line to run after creating/before deleting the corresponding\n" \
+		"device(s).  The environment variable $MDEV indicates the active device node\n" \
+		"(which is useful if it's a regex match).  For example:\n\n" \
+		"  hdc root:cdrom 660  *ln -s $MDEV cdrom\n\n" \
+		"The special characters are @ (run after creating), $ (run before deleting),\n" \
+		"and * (run both after creating and before deleting).  The commands run in\n" \
+		"the /dev directory, and use system() which calls /bin/sh.\n\n" \
+	) \
+	"Config file parsing stops on the first matching line.  If no config\n"\
+	"entry is matched, devices are created with default 0:0 660.  (Make\n"\
+	"the last line match .* to override this.)\n\n" \
+)
+
+#define mesg_trivial_usage \
+	"[y|n]"
+#define mesg_full_usage \
+	"mesg controls write access to your terminal\n" \
+	"\ty\tAllow write access to your terminal\n" \
+	"\tn\tDisallow write access to your terminal"
+
+#define mkdir_trivial_usage \
+	"[OPTION] DIRECTORY..."
+#define mkdir_full_usage \
+	"Create the DIRECTORY(ies) if they do not already exist\n\n" \
+	"Options:\n" \
+	"\t-m\tset permission mode (as in chmod), not rwxrwxrwx - umask\n" \
+	"\t-p\tno error if existing, make parent directories as needed"
+#define mkdir_example_usage \
+	"$ mkdir /tmp/foo\n" \
+	"$ mkdir /tmp/foo\n" \
+	"/tmp/foo: File exists\n" \
+	"$ mkdir /tmp/foo/bar/baz\n" \
+	"/tmp/foo/bar/baz: No such file or directory\n" \
+	"$ mkdir -p /tmp/foo/bar/baz\n"
+
+#define mke2fs_trivial_usage \
+	"[-c|-l filename] [-b block-size] [-f fragment-size] [-g blocks-per-group] " \
+	"[-i bytes-per-inode] [-j] [-J journal-options] [-N number-of-inodes] [-n] " \
+	"[-m reserved-blocks-percentage] [-o creator-os] [-O feature[,...]] [-q] " \
+	"[r fs-revision-level] [-E extended-options] [-v] [-F] [-L volume-label] " \
+	"[-M last-mounted-directory] [-S] [-T filesystem-type] " \
+	"device [blocks-count]"
+#define mke2fs_full_usage \
+	"\t-b size\tblock size in bytes\n" \
+	"\t-c\tcheck for bad blocks before creating\n" \
+	"\t-E opts\tset extended options\n" \
+	"\t-f size\tfragment size in bytes\n" \
+	"\t-F\tforce (ignore sanity checks)\n" \
+	"\t-g num\tnumber of blocks in a block group\n" \
+	"\t-i ratio\tthe bytes/inode ratio\n" \
+	"\t-j\tcreate a journal (ext3)\n" \
+	"\t-J opts\tset journal options (size/device)\n" \
+	"\t-l file\tread bad blocks list from file\n" \
+	"\t-L lbl\tset the volume label\n" \
+	"\t-m percent\tpercent of fs blocks to reserve for admin\n" \
+	"\t-M dir\tset last mounted directory\n" \
+	"\t-n\tdo not actually create anything\n" \
+	"\t-N num\tnumber of inodes to create\n" \
+	"\t-o os\tset the 'creator os' field\n" \
+	"\t-O features\tdir_index/filetype/has_journal/journal_dev/sparse_super\n" \
+	"\t-q\tquiet execution\n" \
+	"\t-r rev\tset filesystem revision\n" \
+	"\t-S\twrite superblock and group descriptors only\n" \
+	"\t-T fs-type\tset usage type (news/largefile/largefile4)\n" \
+	"\t-v\tverbose execution"
+
+#define mkfifo_trivial_usage \
+	"[OPTIONS] name"
+#define mkfifo_full_usage \
+	"Creates a named pipe (identical to 'mknod name p')\n\n" \
+	"Options:\n" \
+	"\t-m\tcreate the pipe using the specified mode (default a=rw)"
+
+#define mkfs_minix_trivial_usage \
+	"[-c | -l filename] [-nXX] [-iXX] /dev/name [blocks]"
+#define mkfs_minix_full_usage \
+	"Make a MINIX filesystem.\n\n" \
+	"Options:\n" \
+	"\t-c\t\tCheck the device for bad blocks\n" \
+	"\t-n [14|30]\tSpecify the maximum length of filenames\n" \
+	"\t-i INODES\tSpecify the number of inodes for the filesystem\n" \
+	"\t-l FILENAME\tRead the bad blocks list from FILENAME\n" \
+	"\t-v\t\tMake a Minix version 2 filesystem"
+
+#define mknod_trivial_usage \
+	"[OPTIONS] NAME TYPE MAJOR MINOR"
+#define mknod_full_usage \
+	"Create a special file (block, character, or pipe).\n\n" \
+	"Options:\n" \
+	"\t-m\tcreate the special file using the specified mode (default a=rw)\n\n" \
+	"TYPEs include:\n" \
+	"\tb:\tMake a block (buffered) device\n" \
+	"\tc or u:\tMake a character (un-buffered) device\n" \
+	"\tp:\tMake a named pipe. MAJOR and MINOR are ignored for named pipes"
+#define mknod_example_usage \
+	"$ mknod /dev/fd0 b 2 0\n" \
+	"$ mknod -m 644 /tmp/pipe p\n"
+
+#define mkswap_trivial_usage \
+	"[-c] [-v0|-v1] device [block-count]"
+#define mkswap_full_usage \
+	"Prepare a disk partition to be used as a swap partition.\n\n" \
+	"Options:\n" \
+	"\t-c\t\tCheck for read-ability\n" \
+	"\t-v0\t\tMake version 0 swap [max 128 Megs]\n" \
+	"\t-v1\t\tMake version 1 swap [big!] (default for kernels >\n\t\t\t2.1.117)\n" \
+	"\tblock-count\tNumber of block to use (default is entire partition)"
+
+#define mktemp_trivial_usage \
+	"[-dq] TEMPLATE"
+#define mktemp_full_usage \
+	"Creates a temporary file with its name based on TEMPLATE.\n" \
+	"TEMPLATE is any name with six `Xs' (i.e., /tmp/temp.XXXXXX).\n\n" \
+	"Options:\n" \
+	"\t-d\t\tMake a directory instead of a file\n" \
+	"\t-q\t\tFail silently if an error occurs"
+#define mktemp_example_usage \
+	"$ mktemp /tmp/temp.XXXXXX\n" \
+	"/tmp/temp.mWiLjM\n" \
+	"$ ls -la /tmp/temp.mWiLjM\n" \
+	"-rw-------    1 andersen andersen        0 Apr 25 17:10 /tmp/temp.mWiLjM\n"
+
+#define modprobe_trivial_usage \
+	"[-knqrsv] MODULE [symbol=value ...]"
+#define modprobe_full_usage \
+	"Options:\n" \
+	"\t-k\tMake module autoclean-able\n" \
+	"\t-n\tJust show what would be done\n" \
+	"\t-q\tQuiet output\n" \
+	"\t-r\tRemove module (stacks) or do autoclean\n" \
+	"\t-s\tReport via syslog instead of stderr\n" \
+	"\t-v\tVerbose output"
+#define modprobe_notes_usage \
+"modprobe can (un)load a stack of modules, passing each module options (when\n" \
+"loading). modprobe uses a configuration file to determine what option(s) to\n" \
+"pass each module it loads.\n" \
+"\n" \
+"The configuration file is searched (in order) amongst:\n" \
+"\n" \
+"    /etc/modprobe.conf (2.6 only)\n" \
+"    /etc/modules.conf\n" \
+"    /etc/conf.modules (deprecated)\n" \
+"\n" \
+"They all have the same syntax (see below). If none is present, it is\n" \
+"_not_ an error; each loaded module is then expected to load without\n" \
+"options. Once a file is found, the others are tested for.\n" \
+"\n" \
+"/etc/modules.conf entry format:\n" \
+"\n" \
+"  alias <alias_name> <mod_name>\n" \
+"    Makes it possible to modprobe alias_name, when there is no such module.\n" \
+"    It makes sense if your mod_name is long, or you want a more representative\n" \
+"    name for that module (eg. 'scsi' in place of 'aha7xxx').\n" \
+"    This makes it also possible to use a different set of options (below) for\n" \
+"    the module and the alias.\n" \
+"    A module can be aliased more than once.\n" \
+"\n" \
+"  options <mod_name|alias_name> <symbol=value ...>\n" \
+"    When loading module mod_name (or the module aliased by alias_name), pass\n" \
+"    the \"symbol=value\" pairs as option to that module.\n" \
+"\n" \
+"Sample /etc/modules.conf file:\n" \
+"\n" \
+"  options tulip irq=3\n" \
+"  alias tulip tulip2\n" \
+"  options tulip2 irq=4 io=0x308\n" \
+"\n" \
+"Other functionality offered by 'classic' modprobe is not available in\n" \
+"this implementation.\n" \
+"\n" \
+"If module options are present both in the config file, and on the command line,\n" \
+"then the options from the command line will be passed to the module _after_\n" \
+"the options from the config file. That way, you can have defaults in the config\n" \
+"file, and override them for a specific usage from the command line.\n"
+#define modprobe_example_usage \
+	"(with the above /etc/modules.conf):\n\n" \
+	"$ modprobe tulip\n" \
+	"   will load the module 'tulip' with default option 'irq=3'\n\n" \
+	"$ modprobe tulip irq=5\n" \
+	"   will load the module 'tulip' with option 'irq=5', thus overriding the default\n\n" \
+	"$ modprobe tulip2\n" \
+	"   will load the module 'tulip' with default options 'irq=4 io=0x308',\n" \
+	"   which are the default for alias 'tulip2'\n\n" \
+	"$ modprobe tulip2 irq=8\n" \
+	"   will load the module 'tulip' with default options 'irq=4 io=0x308 irq=8',\n" \
+	"   which are the default for alias 'tulip2' overridden by the option 'irq=8'\n\n" \
+	"   from the command line\n\n" \
+	"$ modprobe tulip2 irq=2 io=0x210\n" \
+	"   will load the module 'tulip' with default options 'irq=4 io=0x308 irq=4 io=0x210',\n" \
+	"   which are the default for alias 'tulip2' overridden by the options 'irq=2 io=0x210'\n\n" \
+	"   from the command line\n"
+
+#define more_trivial_usage \
+	"[FILE ...]"
+#define more_full_usage \
+	"More is a filter for viewing FILE one screenful at a time."
+#define more_example_usage \
+	"$ dmesg | more\n"
+
+#ifdef CONFIG_FEATURE_MOUNT_LOOP
+#  define USAGE_MOUNT_LOOP(a) a
+#else
+#  define USAGE_MOUNT_LOOP(a)
+#endif
+#ifdef CONFIG_FEATURE_MTAB_SUPPORT
+#  define USAGE_MTAB(a) a
+#else
+#  define USAGE_MTAB(a)
+#endif
+#define mount_trivial_usage \
+	"[flags] DEVICE NODE [-o options,more-options]"
+#define mount_full_usage \
+	"Mount a filesystem.  Filesystem autodetection requires /proc be mounted.\n\n" \
+	"Flags:\n"  \
+	"\t-a:\t\tMount all filesystems in fstab\n" \
+	USAGE_MTAB( \
+	"\t-f:\t\t\"Fake\" Add entry to mount table but don't mount it\n" \
+	"\t-n:\t\tDon't write a mount table entry\n" \
+	) \
+	"\t-o option:\tOne of many filesystem options, listed below\n" \
+	"\t-r:\t\tMount the filesystem read-only\n" \
+	"\t-t fs-type:\tSpecify the filesystem type\n" \
+	"\t-w:\t\tMount for reading and writing (default)\n" \
+	"\n" \
+	"Options for use with the \"-o\" flag:\n" \
+	"\tasync/sync:\tWrites are asynchronous / synchronous\n" \
+	"\tatime/noatime:\tEnable / disable updates to inode access times\n" \
+	"\tdev/nodev:\tAllow use of special device files / disallow them\n" \
+	"\texec/noexec:\tAllow use of executable files / disallow them\n" \
+	USAGE_MOUNT_LOOP( \
+	"\tloop:\t\t Ignored (loop devices are autodetected)\n" \
+	) \
+	"\tsuid/nosuid:\tAllow set-user-id-root programs / disallow them\n" \
+	"\tremount:\tRe-mount a mounted filesystem, changing its flags\n" \
+	"\tro/rw:\t\tMount for read-only / read-write\n" \
+	"\tbind:\t\tBind a directory to an additional location\n" \
+	"\tmove:\t\tRelocate an existing mount point.\n" \
+	"\nThere are EVEN MORE flags that are specific to each filesystem\n" \
+	"You'll have to see the written documentation for those filesystems"
+#define mount_example_usage \
+	"$ mount\n" \
+	"/dev/hda3 on / type minix (rw)\n" \
+	"proc on /proc type proc (rw)\n" \
+	"devpts on /dev/pts type devpts (rw)\n" \
+	"$ mount /dev/fd0 /mnt -t msdos -o ro\n" \
+	"$ mount /tmp/diskimage /opt -t ext2 -o loop\n" \
+	"$ mount cd_image.iso mydir\n"
+#define mount_notes_usage \
+	"Returns 0 for success, number of failed mounts for -a, or errno for one mount." 
+
+#define mountpoint_trivial_usage \
+	"[-q] <[-d] DIR | -x DEVICE>"
+#define mountpoint_full_usage \
+	"mountpoint checks if the directory is a mountpoint\n\n" \
+	"Options:\n"  \
+	"\t-q:\t\tBe more quiet\n" \
+	"\t-d:\t\tPrint major/minor device number of the filesystem\n" \
+	"\t-x:\t\tPrint major/minor device number of the blockdevice"
+#define mountpoint_example_usage \
+	"$ mountpoint /proc\n" \
+	"/proc is not a mountpoint\n" \
+	"$ mountpoint /sys\n" \
+	"/sys is a mountpoint\n"
+
+#define mt_trivial_usage \
+	"[-f device] opcode value"
+#define mt_full_usage \
+	"Control magnetic tape drive operation\n" \
+	"\nAvailable Opcodes:\n\n" \
+	"bsf bsfm bsr bss datacompression drvbuffer eof eom erase\n" \
+	"fsf fsfm fsr fss load lock mkpart nop offline ras1 ras2\n" \
+	"ras3 reset retension rewind rewoffline seek setblk setdensity\n" \
+	"setpart tell unload unlock weof wset"
+
+#define mv_trivial_usage \
+	"[OPTION]... SOURCE DEST\n" \
+	"or: mv [OPTION]... SOURCE... DIRECTORY"
+#define mv_full_usage \
+	"Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n\n" \
+	"Options:\n" \
+	"\t-f\tdon't prompt before overwriting\n" \
+	"\t-i\tinteractive, prompt before overwrite"
+#define mv_example_usage \
+	"$ mv /tmp/foo /bin/bar\n"
+
+#define nameif_trivial_usage \
+	"[-s] [-c FILE] [{IFNAME MACADDR}]"
+#define nameif_full_usage \
+	"Nameif renaming network interface while it in the down state.\n\n" \
+	"Options:\n" \
+	"\t-c FILE\t\tUse configuration file (default is /etc/mactab)\n" \
+	"\t-s\t\tUse syslog (LOCAL0 facility)\n" \
+	"\tIFNAME MACADDR\tnew_interface_name interface_mac_address"
+#define nameif_example_usage \
+	"$ nameif -s dmz0 00:A0:C9:8C:F6:3F\n" \
+	" or\n" \
+	"$ nameif -c /etc/my_mactab_file\n" \
+
+#ifdef CONFIG_NC_GAPING_SECURITY_HOLE
+#  define USAGE_NC_EXEC(a) a
+#else
+#  define USAGE_NC_EXEC(a)
+#endif
+#define nc_trivial_usage \
+	"[OPTIONS] [IP] [port]"
+#define nc_full_usage \
+	"Netcat opens a pipe to IP:port\n\n" \
+	"Options:\n" \
+	"\t-l\t\tlisten mode, for inbound connects\n" \
+	"\t-p PORT\t\tlocal port number\n" \
+	"\t-i SECS\t\tdelay interval for lines sent\n" \
+	USAGE_NC_EXEC( \
+	"\t-e PROG\t\tprogram to exec after connect (dangerous!)\n" \
+	) \
+	"\t-w SECS\t\ttimeout for connects and final net reads"
+#define nc_example_usage \
+	"$ nc foobar.somedomain.com 25\n" \
+	"220 foobar ESMTP Exim 3.12 #1 Sat, 15 Apr 2000 00:03:02 -0600\n" \
+	"help\n" \
+	"214-Commands supported:\n" \
+	"214-    HELO EHLO MAIL RCPT DATA AUTH\n" \
+	"214     NOOP QUIT RSET HELP\n" \
+	"quit\n" \
+	"221 foobar closing connection\n"
+
+#define netstat_trivial_usage \
+	"[-laenrtuwx]"
+#define netstat_full_usage \
+	"Netstat displays Linux networking information.\n\n" \
+	"Options:\n" \
+	"\t-l display listening server sockets\n" \
+	"\t-a display all sockets (default: connected)\n" \
+	"\t-e display other/more information\n" \
+	"\t-n don't resolve names\n" \
+	"\t-r display routing table\n" \
+	"\t-t tcp sockets\n" \
+	"\t-u udp sockets\n" \
+	"\t-w raw sockets\n" \
+	"\t-x unix sockets"
+
+#define nice_trivial_usage \
+	"[-n ADJUST] [COMMAND [ARG] ...]"
+#define nice_full_usage \
+	"Nice runs a program with modified scheduling priority.\n\n" \
+	"Options:\n" \
+	"\t-n ADJUST\tAdjust the scheduling priority by ADJUST"
+
+#define nohup_trivial_usage \
+	"COMMAND [ARGS]"
+#define nohup_full_usage \
+	"run a command immune to hangups, with output to a non-tty"
+#define nohup_example_usage \
+	"$ nohup make &"
+
+#define nslookup_trivial_usage \
+	"[HOST] [SERVER]"
+#define nslookup_full_usage \
+	"Queries the nameserver for the IP address of the given HOST\n" \
+	"optionally using a specified DNS server"
+#define nslookup_example_usage \
+	"$ nslookup localhost\n" \
+	"Server:     default\n" \
+	"Address:    default\n" \
+	"\n" \
+	"Name:       debian\n" \
+	"Address:    127.0.0.1\n"
+
+#define od_trivial_usage \
+	"[-aBbcDdeFfHhIiLlOovXx] [FILE]"
+#define od_full_usage \
+	"Write an unambiguous representation, octal bytes by default, of FILE\n" \
+	"to standard output.  With no FILE, or when FILE is -, read standard input."
+
+#define openvt_trivial_usage \
+	"<vtnum> <COMMAND> [ARGS...]"
+#define openvt_full_usage \
+	"Start a command on a new virtual terminal"
+#define openvt_example_usage \
+	"openvt 2 /bin/ash\n"
+
+#ifdef CONFIG_FEATURE_SHA1_PASSWORDS
+#  define PASSWORD_ALG_TYPES(a) a
+#else
+#  define PASSWORD_ALG_TYPES(a)
+#endif
+#define passwd_trivial_usage \
+	"[OPTION] [name]"
+#define passwd_full_usage \
+	"Change a user password. If no name is specified,\n" \
+	"changes the password for the current user.\n" \
+	"Options:\n" \
+	"\t-a\tDefine which algorithm shall be used for the password\n" \
+	"\t\t\t(Choices: des, md5" \
+	PASSWORD_ALG_TYPES(", sha1") \
+	")\n\t-d\tDelete the password for the specified user account\n" \
+	"\t-l\tLocks (disables) the specified user account\n" \
+	"\t-u\tUnlocks (re-enables) the specified user account"
+
+#define patch_trivial_usage \
+	"[-p<num>] [-i <diff>]"
+#define patch_full_usage \
+	"\t-p <num>\tStrip <num> leading components from file names\n" \
+	"\t-i <diff>\tRead <diff> instead of stdin"
+#define patch_example_usage \
+	"$ patch -p1 < example.diff\n" \
+	"$ patch -p0 -i example.diff"
+
+#if ENABLE_FEATURE_PIDOF_SINGLE
+#define USAGE_FEATURE_PIDOF_SINGLE(a) a
+#else
+#define USAGE_FEATURE_PIDOF_SINGLE(a)
+#endif
+#if ENABLE_FEATURE_PIDOF_OMIT
+#define USAGE_FEATURE_PIDOF_OMIT(a) a
+#else
+#define USAGE_FEATURE_PIDOF_OMIT(a)
+#endif
+#if (ENABLE_FEATURE_PIDOF_SINGLE || ENABLE_FEATURE_PIDOF_OMIT)
+#define USAGE_PIDOF "Options:"
+#else
+#define USAGE_PIDOF "\n\tThis version of pidof accepts no options."
+#endif
+
+#define pidof_trivial_usage \
+	"process-name [OPTION] [process-name ...]"
+
+#define pidof_full_usage \
+	"Lists the PIDs of all processes with names that match the\n" \
+	"names on the command line.\n" \
+	USAGE_PIDOF \
+	USAGE_FEATURE_PIDOF_SINGLE("\n\t-s\t\tdisplay only a single PID") \
+	USAGE_FEATURE_PIDOF_OMIT("\n\t-o\t\tomit given pid.") \
+	USAGE_FEATURE_PIDOF_OMIT("\n\t\t\tUse %PPID to omit the parent pid of pidof itself")
+#define pidof_example_usage \
+	"$ pidof init\n" \
+	"1\n" \
+	USAGE_FEATURE_PIDOF_OMIT("$ pidof /bin/sh\n20351 5973 5950\n") \
+	USAGE_FEATURE_PIDOF_OMIT("$ pidof /bin/sh -o %PPID\n20351 5950")
+
+#ifndef CONFIG_FEATURE_FANCY_PING
+#define ping_trivial_usage "host"
+#define ping_full_usage    "Send ICMP ECHO_REQUEST packets to network hosts"
+#else
+#define ping_trivial_usage \
+	"[OPTION]... host"
+#define ping_full_usage \
+	"Send ICMP ECHO_REQUEST packets to network hosts.\n\n" \
+	"Options:\n" \
+	"\t-c COUNT\tSend only COUNT pings\n" \
+	"\t-s SIZE\t\tSend SIZE data bytes in packets (default=56)\n" \
+	"\t-q\t\tQuiet mode, only displays output at start\n" \
+	"\t\t\tand when finished"
+#endif
+#define ping_example_usage \
+	"$ ping localhost\n" \
+	"PING slag (127.0.0.1): 56 data bytes\n" \
+	"64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=20.1 ms\n" \
+	"\n" \
+	"--- debian ping statistics ---\n" \
+	"1 packets transmitted, 1 packets received, 0% packet loss\n" \
+	"round-trip min/avg/max = 20.1/20.1/20.1 ms\n"
+
+#ifndef CONFIG_FEATURE_FANCY_PING6
+#define ping6_trivial_usage "host"
+#define ping6_full_usage    "Send ICMP ECHO_REQUEST packets to network hosts"
+#else
+#define ping6_trivial_usage \
+	"[OPTION]... host"
+#define ping6_full_usage \
+	"Send ICMP ECHO_REQUEST packets to network hosts.\n\n" \
+	"Options:\n" \
+	"\t-c COUNT\tSend only COUNT pings\n" \
+	"\t-s SIZE\t\tSend SIZE data bytes in packets (default=56)\n" \
+	"\t-q\t\tQuiet mode, only displays output at start\n" \
+	"\t\t\tand when finished"
+#endif
+#define ping6_example_usage \
+	"$ ping6 ip6-localhost\n" \
+	"PING ip6-localhost (::1): 56 data bytes\n" \
+	"64 bytes from ::1: icmp6_seq=0 ttl=64 time=20.1 ms\n" \
+	"\n" \
+	"--- ip6-localhost ping statistics ---\n" \
+	"1 packets transmitted, 1 packets received, 0% packet loss\n" \
+	"round-trip min/avg/max = 20.1/20.1/20.1 ms\n"
+
+#define pivot_root_trivial_usage \
+	"NEW_ROOT PUT_OLD"
+#define pivot_root_full_usage \
+	"Move the current root file system to PUT_OLD and make NEW_ROOT\n" \
+	"the new root file system."
+
+#define poweroff_trivial_usage \
+	"[-d<delay>] [-n<nosync>] [-f<force>]"
+#define poweroff_full_usage \
+	"Halt and shut off power.\n" \
+	"Options:\n" \
+	"\t-d\t\tdelay interval for halting\n" \
+	"\t-n\t\tno call to sync()\n" \
+	"\t-f\t\tforce power off (don't go through init)"
+
+#define printenv_trivial_usage \
+	"[VARIABLES...]"
+#define printenv_full_usage \
+	"print all or part of environment\n\n" \
+	"If no environment VARIABLE specified, print them all."
+
+#define printf_trivial_usage \
+	"FORMAT [ARGUMENT...]"
+#define printf_full_usage \
+	"Formats and prints ARGUMENT(s) according to FORMAT,\n" \
+	"Where FORMAT controls the output exactly as in C printf."
+#define printf_example_usage \
+	"$ printf \"Val=%d\\n\" 5\n" \
+	"Val=5\n"
+
+#if !defined CONFIG_SELINUX && !ENABLE_FEATURE_PS_WIDE
+#define USAGE_PS "\n\tThis version of ps accepts no options."
+#else
+#define USAGE_PS "\nOptions:"
+#endif
+#if ENABLE_FEATURE_PS_WIDE
+#define USAGE_PS_WIDE(a) a
+#else
+#define USAGE_PS_WIDE(a)
+#endif
+
+#define ps_trivial_usage \
+	""
+#define ps_full_usage \
+	"Report process status\n" \
+	USAGE_PS \
+	USAGE_SELINUX("\n\t-c\tshow SE Linux context") \
+	USAGE_PS_WIDE("\n\tw\twide output")
+
+#define ps_example_usage \
+	"$ ps\n" \
+	"  PID  Uid      Gid State Command\n" \
+	"    1 root     root     S init\n" \
+	"    2 root     root     S [kflushd]\n" \
+	"    3 root     root     S [kupdate]\n" \
+	"    4 root     root     S [kpiod]\n" \
+	"    5 root     root     S [kswapd]\n" \
+	"  742 andersen andersen S [bash]\n" \
+	"  743 andersen andersen S -bash\n" \
+	"  745 root     root     S [getty]\n" \
+	" 2990 andersen andersen R ps\n"
+
+#define pwd_trivial_usage \
+	""
+#define pwd_full_usage \
+	"Print the full filename of the current working directory."
+#define pwd_example_usage \
+	"$ pwd\n" \
+	"/root\n"
+
+#define rdate_trivial_usage \
+	"[-sp] HOST"
+#define rdate_full_usage \
+	"Get and possibly set the system date and time from a remote HOST.\n\n" \
+	"Options:\n" \
+	"\t-s\tSet the system date and time (default)\n" \
+	"\t-p\tPrint the date and time"
+
+#ifdef CONFIG_FEATURE_READLINK_FOLLOW
+#define USAGE_READLINK_FOLLOW(a) a
+#else
+#define USAGE_READLINK_FOLLOW(a)
+#endif
+
+#define readlink_trivial_usage \
+	USAGE_READLINK_FOLLOW("[-f] ") "FILE"
+#define readlink_full_usage \
+	"Displays the value of a symbolic link." \
+	USAGE_READLINK_FOLLOW("\n\nOptions:\n" \
+	"\t-f\tcanonicalize by following all symlinks")
+
+#define readprofile_trivial_usage \
+	"[OPTIONS]..."
+#define readprofile_full_usage \
+	"Options:\n" \
+	"\t -m <mapfile>  (default: /boot/System.map)\n" \
+	"\t -p <profile>  (default: /proc/profile)\n" \
+	"\t -M <mult>     set the profiling multiplier to <mult>\n" \
+	"\t -i            print only info about the sampling step\n" \
+	"\t -v            print verbose data\n" \
+	"\t -a            print all symbols, even if count is 0\n" \
+	"\t -b            print individual histogram-bin counts\n" \
+	"\t -s            print individual counters within functions\n" \
+	"\t -r            reset all the counters (root only)\n" \
+	"\t -n            disable byte order auto-detection"
+
+#define realpath_trivial_usage \
+	"pathname  ..."
+#define realpath_full_usage \
+	"Returns the absolute pathnames of given argument."
+
+#define reboot_trivial_usage \
+	"[-d<delay>] [-n<nosync>] [-f<force>]"
+#define reboot_full_usage \
+	"Reboot the system.\n" \
+	"Options:\n" \
+	"\t-d\t\tdelay interval for rebooting\n" \
+	"\t-n\t\tno call to sync()\n" \
+	"\t-f\t\tforce reboot (don't go through init)"
+
+#define renice_trivial_usage \
+	"{{-n INCREMENT} | PRIORITY} [[ -p | -g | -u ] ID ...]"
+#define renice_full_usage \
+	"Changes priority of running processes.\n\n" \
+	"Options:\n" \
+	"\t-n\tadjusts current nice value (smaller is faster)\n" \
+	"\t-p\tprocess id(s) (default)\n" \
+	"\t-g\tprocess group id(s)\n" \
+	"\t-u\tprocess user name(s) and/or id(s)"
+
+#define reset_trivial_usage \
+	""
+#define reset_full_usage \
+	"Resets the screen."
+
+#define rm_trivial_usage \
+	"[OPTION]... FILE..."
+#define rm_full_usage \
+	"Remove (unlink) the FILE(s).  You may use '--' to\n" \
+	"indicate that all following arguments are non-options.\n\n" \
+	"Options:\n" \
+	"\t-i\t\talways prompt before removing each destination\n" \
+	"\t-f\t\tremove existing destinations, never prompt\n" \
+	"\t-r or -R\tremove the contents of directories recursively"
+#define rm_example_usage \
+	"$ rm -rf /tmp/foo\n"
+
+#define rmdir_trivial_usage \
+	"[OPTION]... DIRECTORY..."
+#define rmdir_full_usage \
+	"Remove the DIRECTORY(ies), if they are empty."
+#define rmdir_example_usage \
+	"# rmdir /tmp/foo\n"
+
+#define rmmod_trivial_usage \
+	"[OPTION]... [MODULE]..."
+#define rmmod_full_usage \
+	"Unloads the specified kernel modules from the kernel.\n\n" \
+	"Options:\n" \
+	"\t-a\tRemove all unused modules (recursively)"
+#define rmmod_example_usage \
+	"$ rmmod tulip\n"
+
+#ifdef CONFIG_FEATURE_IPV6
+#  define USAGE_ROUTE_IPV6(a) a
+#else
+#  define USAGE_ROUTE_IPV6(a) "\t"
+#endif
+
+
+#define route_trivial_usage \
+	"[{add|del|delete}]"
+#define route_full_usage \
+	"Edit the kernel's routing tables.\n\n" \
+	"Options:\n" \
+	"\t-n\t\tDont resolve names\n" \
+	"\t-e\t\tDisplay other/more information\n" \
+	"\t-A inet" USAGE_ROUTE_IPV6("{6}") "\tSelect address family"
+
+#define rpm_trivial_usage \
+	"-i -q[ildc]p package.rpm"
+#define rpm_full_usage \
+	"Manipulates RPM packages" \
+	"\n\nOptions:" \
+	"\n\t-i Install package" \
+	"\n\t-q Query package" \
+	"\n\t-p Query uninstalled package" \
+	"\n\t-i Show information" \
+	"\n\t-l List contents" \
+	"\n\t-d List documents" \
+	"\n\t-c List config files"
+
+#define rpm2cpio_trivial_usage \
+	"package.rpm"
+#define rpm2cpio_full_usage \
+	"Outputs a cpio archive of the rpm file."
+
+#define run_parts_trivial_usage \
+	"[-t] [-a ARG] [-u MASK] DIRECTORY"
+#define run_parts_full_usage \
+	"Run a bunch of scripts in a directory.\n\n" \
+	"Options:\n" \
+	"\t-t\tPrints what would be run, but does not actually run anything\n" \
+	"\t-a ARG\tPass ARG as an argument for every program invoked\n" \
+	"\t-u MASK\tSet the umask to MASK before executing every program"
+
+#define runlevel_trivial_usage \
+	"[utmp]"
+#define runlevel_full_usage \
+	"Find the current and previous system runlevel.\n\n" \
+	"If no utmp file exists or if no runlevel record can be found,\n" \
+	"runlevel prints \"unknown\""
+#define runlevel_example_usage \
+	"$ runlevel /var/run/utmp\n" \
+	"N 2"
+
+#define rx_trivial_usage \
+	"FILE"
+#define rx_full_usage \
+	"Receive a file using the xmodem protocol."
+#define rx_example_usage \
+	"$ rx /tmp/foo\n"
+
+#define sed_trivial_usage \
+	"[-efinr] pattern [files...]"
+#define sed_full_usage \
+	"Options:\n" \
+	"\t-e script\tadd the script to the commands to be executed\n" \
+	"\t-f scriptfile\tadd script-file contents to the\n" \
+	"\t\t\tcommands to be executed\n" \
+	"\t-i\t\tedit files in-place\n" \
+	"\t-n\t\tsuppress automatic printing of pattern space\n" \
+	"\t-r\t\tuse extended regular expression syntax\n" \
+	"\n" \
+	"If no -e or -f is given, the first non-option argument is taken as the sed\n" \
+	"script to interpret. All remaining arguments are names of input files; if no\n" \
+	"input files are specified, then the standard input is read.  Source files\n" \
+	"will not be modified unless -i option is given."
+
+#define sed_example_usage \
+	"$ echo \"foo\" | sed -e 's/f[a-zA-Z]o/bar/g'\n" \
+	"bar\n"
+
+#define seq_trivial_usage \
+	"[first [increment]] last"
+#define seq_full_usage \
+	"Print numbers from FIRST to LAST, in steps of INCREMENT.\n" \
+	"FIRST, INCREMENT default to 1\n" \
+	"Arguments:\n" \
+	"\tLAST\n" \
+	"\tFIRST\tLAST\n" \
+	"\tFIRST\tINCREMENT\tLAST"
+
+#define setconsole_trivial_usage \
+	"[-r|--reset] [DEVICE]"
+#define setconsole_full_usage \
+	"Redirects system console output to DEVICE (default: /dev/tty).\n\n" \
+	"Options:\n" \
+	"\t-r\tReset output to /dev/console."
+
+#define setkeycodes_trivial_usage \
+	"SCANCODE KEYCODE ..."
+#define setkeycodes_full_usage \
+	"Set entries into the kernel's scancode-to-keycode map,\n" \
+	"allowing unusual keyboards to generate usable keycodes.\n\n" \
+	"SCANCODE may be either xx or e0xx (hexadecimal),\n" \
+	"and KEYCODE is given in decimal"
+#define setkeycodes_example_usage \
+	"$ setkeycodes e030 127\n"
+
+#define setlogcons_trivial_usage \
+	"N"
+#define setlogcons_full_usage \
+	"Redirects the kernel output to console N (0 for current)."
+
+#define setsid_trivial_usage \
+	"program [arg ...]"
+#define setsid_full_usage \
+	"Runs any program in a new session by calling setsid() before\n" \
+	"exec'ing the rest of its arguments.  See setsid(2) for details."
+
+#define lash_trivial_usage \
+	"[FILE]...\n" \
+	"or: sh -c command [args]..."
+#define lash_full_usage \
+	"The BusyBox LAme SHell (command interpreter)"
+#define lash_notes_usage \
+	"This command does not yet have proper documentation.\n\n" \
+	"Use lash just as you would use any other shell.  It properly handles pipes,\n" \
+	"redirects, job control, can be used as the shell for scripts, and has a\n" \
+	"sufficient set of builtins to do what is needed.  It does not (yet) support\n" \
+	"Bourne Shell syntax.  If you need things like \"if-then-else\", \"while\", and such\n" \
+	"use ash or bash.  If you just need a very simple and extremely small shell,\n" \
+	"this will do the job."
+
+#define last_trivial_usage \
+	""
+#define last_full_usage \
+	"Shows listing of the last users that logged into the system"
+
+#define sha1sum_trivial_usage \
+	"[OPTION] [FILEs...]" \
+	USAGE_MD5_SHA1_SUM_CHECK("\n   or: sha1sum [OPTION] -c [FILE]")
+#define sha1sum_full_usage \
+	"Print" USAGE_MD5_SHA1_SUM_CHECK(" or check") " SHA1 checksums.\n\n" \
+	"Options:\n" \
+	"With no FILE, or when FILE is -, read standard input." \
+	USAGE_MD5_SHA1_SUM_CHECK("\n\n" \
+	"\t-c\tcheck SHA1 sums against given list\n" \
+	"\nThe following two options are useful only when verifying checksums:\n" \
+	"\t-s\tdon't output anything, status code shows success\n" \
+	"\t-w\twarn about improperly formated SHA1 checksum lines")
+
+#ifdef CONFIG_FEATURE_FANCY_SLEEP
+#  define USAGE_FANCY_SLEEP(a) a
+#  define USAGE_NOT_FANCY_SLEEP(a)
+#else
+#  define USAGE_FANCY_SLEEP(a)
+#  define USAGE_NOT_FANCY_SLEEP(a) a
+#endif
+
+#define sleep_trivial_usage \
+	USAGE_FANCY_SLEEP("[") "N" USAGE_FANCY_SLEEP("]...")
+#define sleep_full_usage \
+	USAGE_NOT_FANCY_SLEEP("Pause for N seconds.") \
+	USAGE_FANCY_SLEEP( \
+	"Pause for a time equal to the total of the args given, where each arg can\n" \
+	"\t\thave an optional suffix of (s)econds, (m)inutes, (h)ours, or (d)ays.")
+#define sleep_example_usage \
+	"$ sleep 2\n" \
+	"[2 second delay results]\n" \
+	USAGE_FANCY_SLEEP("$ sleep 1d 3h 22m 8s\n" \
+	"[98528 second delay results]\n")
+
+#if ENABLE_FEATURE_SORT_BIG
+#  define USAGE_SORT_BIG(a) a
+#else
+#  define USAGE_SORT_BIG(a)
+#endif
+
+#define sort_trivial_usage \
+	"[-nru" USAGE_SORT_BIG("gMcszbdfimSTokt] [-o outfile] [-k start[.offset][opts][,end[.offset][opts]] [-t char") "] [FILE]..."
+#define sort_full_usage \
+	"Sorts lines of text in the specified files\n\n" \
+	"Options:\n" \
+	USAGE_SORT_BIG( \
+		"\t-b\tignore leading blanks\n" \
+		"\t-c\tcheck whether input is sorted\n" \
+		"\t-d\tdictionary order (blank or alphanumeric only)\n" \
+		"\t-f\tignore case\n" \
+		"\t-g\tgeneral numerical sort\n" \
+		"\t-i\tignore unprintable characters\n" \
+		"\t-k\tspecify sort key\n" \
+		"\t-M\tsort month\n" \
+	) \
+	"\t-n\tsort numbers\n" \
+	USAGE_SORT_BIG( \
+		"\t-o\toutput to file\n" \
+		"\t-k\tsort by key\n" \
+		"\t-t\tuse key separator other than whitespace\n" \
+	) \
+	"\t-r\treverse sort order\n" \
+	USAGE_SORT_BIG("\t-s\tstable (don't sort ties alphabetically)\n") \
+	"\t-u\tsuppress duplicate lines" \
+	USAGE_SORT_BIG("\n\t-z\tinput terminated by nulls, not newlines\n") \
+	USAGE_SORT_BIG("\t-mST\tignored for GNU compatibility") \
+	""
+#define sort_example_usage \
+	"$ echo -e \"e\\nf\\nb\\nd\\nc\\na\" | sort\n" \
+	"a\n" \
+	"b\n" \
+	"c\n" \
+	"d\n" \
+	"e\n" \
+	"f\n" \
+	USAGE_SORT_BIG( \
+		"$ echo -e \"c 3\\nb 2\\nd 2\" | $SORT -k 2,2n -k 1,1r\n" \
+		"d 2\n" \
+		"b 2\n" \
+		"c 3\n" \
+	) \
+	""
+
+#define start_stop_daemon_trivial_usage \
+	"[OPTIONS] [--start|--stop] ... [-- arguments...]"
+#define start_stop_daemon_full_usage \
+	"Program to start and stop services." \
+	"\n\nOptions:" \
+	"\n\t-S|--start\t\t\tstart" \
+	"\n\t-K|--stop\t\t\tstop" \
+	"\n\t-a|--startas <pathname>\t\tstarts process specified by pathname" \
+	"\n\t-b|--background\t\t\tforce process into background" \
+	"\n\t-u|--user <username>|<uid>\tstop this user's processes" \
+	"\n\t-x|--exec <executable>\t\tprogram to either start or check" \
+	"\n\t-m|--make-pidfile <filename>\tcreate the -p file and enter pid in it" \
+	"\n\t-n|--name <process-name>\tstop processes with this name" \
+	"\n\t-p|--pidfile <pid-file>\t\tsave or load pid using a pid-file" \
+	"\n\t-q|--quiet\t\t\tbe quiet" \
+USE_FEATURE_START_STOP_DAEMON_FANCY( \
+	"\n\t-o|--oknodo\t\t\texit status 0 if nothing done" \
+	"\n\t-v|--verbose\t\t\tbe verbose" \
+) \
+	"\n\t-s|--signal <signal>\t\tsignal to send (default TERM)"
+
+#ifdef CONFIG_FEATURE_STAT_FORMAT
+#  define USAGE_STAT_FORMAT(a) a
+#else
+#  define USAGE_STAT_FORMAT(a)
+#endif
+#define stat_trivial_usage \
+	"[OPTION] FILE..."
+#define stat_full_usage \
+	"display file (default) or filesystem status.\n\n" \
+	"Options:\n" \
+	USAGE_STAT_FORMAT("\t-c fmt\tuse the specified format\n") \
+	"\t-f\tdisplay filesystem status\n" \
+	"\t-L,-l\tdereference links\n" \
+	"\t-t\tdisplay info in terse form\n" \
+	USAGE_STAT_FORMAT( \
+	"\nValid format sequences for files:\n" \
+	"  %a   Access rights in octal\n" \
+	"  %A   Access rights in human readable form\n" \
+	"  %b   Number of blocks allocated (see %B)\n" \
+	"  %B   The size in bytes of each block reported by %b\n" \
+	"  %d   Device number in decimal\n" \
+	"  %D   Device number in hex\n" \
+	"  %f   Raw mode in hex\n" \
+	"  %F   File type\n" \
+	"  %g   Group ID of owner\n" \
+	"  %G   Group name of owner\n" \
+	"  %h   Number of hard links\n" \
+	"  %i   Inode number\n" \
+	"  %n   File name\n" \
+	"  %N   Quoted file name with dereference if symbolic link\n" \
+	"  %o   I/O block size\n" \
+	"  %s   Total size, in bytes\n" \
+	"  %t   Major device type in hex\n" \
+	"  %T   Minor device type in hex\n" \
+	"  %u   User ID of owner\n" \
+	"  %U   User name of owner\n" \
+	"  %x   Time of last access\n" \
+	"  %X   Time of last access as seconds since Epoch\n" \
+	"  %y   Time of last modification\n" \
+	"  %Y   Time of last modification as seconds since Epoch\n" \
+	"  %z   Time of last change\n" \
+	"  %Z   Time of last change as seconds since Epoch\n" \
+	"\nValid format sequences for file systems:\n" \
+	"  %a   Free blocks available to non-superuser\n" \
+	"  %b   Total data blocks in file system\n" \
+	"  %c   Total file nodes in file system\n" \
+	"  %d   Free file nodes in file system\n" \
+	"  %f   Free blocks in file system\n" \
+	"  %i   File System ID in hex\n" \
+	"  %l   Maximum length of filenames\n" \
+	"  %n   File name\n" \
+	"  %s   Block size (for faster transfers)\n" \
+	"  %S   Fundamental block size (for block counts)\n" \
+	"  %t   Type in hex\n" \
+	"  %T   Type in human readable form\n" \
+	)
+
+#define strings_trivial_usage \
+	"[-afo] [-n length] [file ... ]"
+#define strings_full_usage \
+	"Display printable strings in a binary file." \
+	"\n\nOptions:" \
+	"\n\t-a\tScan the whole files (this is the default)." \
+	"\n\t-f\tPrecede each string with the name of the file where it was found." \
+	"\n\t-n N\tSpecifies that at least N characters forms a sequence (default 4)" \
+	"\n\t-o\tEach string is preceded by its decimal offset in the file"
+
+#define stty_trivial_usage \
+	"[-a|g] [-F DEVICE] [SETTING]..."
+#define stty_full_usage \
+	"Without arguments, prints baud rate, line discipline," \
+	"\nand deviations from stty sane." \
+	"\n\nOptions:" \
+	"\n\t-F DEVICE\topen device instead of stdin" \
+	"\n\t-a\t\tprint all current settings in human-readable form" \
+	"\n\t-g\t\tprint in stty-readable form" \
+	"\n\t[SETTING]\tsee manpage"
+
+#define su_trivial_usage \
+	"[OPTION]... [-] [username]"
+#define su_full_usage \
+	"Change user id or become root.\n" \
+	"Options:\n" \
+	"\t-p, -m\tPreserve environment" \
+	"\n\t-c\tCommand to pass to 'sh -c'" \
+	"\n\t-s\tShell to use instead of default shell"
+
+#define sulogin_trivial_usage \
+	"[OPTION]... [tty-device]"
+#define sulogin_full_usage \
+	"Single user login\n" \
+	"Options:\n" \
+	"\t-f\tDo not authenticate (user already authenticated)\n" \
+	"\t-h\tName of the remote host for this login\n" \
+	"\t-p\tPreserve environment"
+
+#define sum_trivial_usage \
+	"[rs] [files...]"
+#define sum_full_usage \
+	"checksum and count the blocks in a file\n\n" \
+	"Options:\n" \
+	"\t-r\tuse BSD sum algorithm (1K blocks)\n" \
+	"\t-s\tuse System V sum algorithm (512byte blocks)"
+
+#define swapoff_trivial_usage \
+	"[-a] [DEVICE]"
+#define swapoff_full_usage \
+	"Stop swapping virtual memory pages on DEVICE.\n\n" \
+	"Options:\n" \
+	"\t-a\tStop swapping on all swap devices"
+
+#define swapon_trivial_usage \
+	"[-a] [DEVICE]"
+#define swapon_full_usage \
+	"Start swapping virtual memory pages on DEVICE.\n\n" \
+	"Options:\n" \
+	"\t-a\tStart swapping on all swap devices"
+
+#define switch_root_trivial_usage \
+	"[-c /dev/console] NEW_ROOT NEW_INIT [ARGUMENTS_TO_INIT]"
+#define switch_root_full_usage \
+	"Use from PID 1 under initramfs to free initramfs, chroot to NEW_ROOT,\n" \
+	"and exec NEW_INIT.\n\n" \
+	"Options:\n" \
+	"\t-c\tRedirect console to device on new root"
+
+#define sync_trivial_usage \
+	""
+#define sync_full_usage \
+	"Write all buffered filesystem blocks to disk."
+
+
+#ifdef CONFIG_FEATURE_ROTATE_LOGFILE
+#  define USAGE_ROTATE_LOGFILE(a) a
+#else
+#  define USAGE_ROTATE_LOGFILE(a)
+#endif
+#ifdef CONFIG_FEATURE_REMOTE_LOG
+#  define USAGE_REMOTE_LOG(a) a
+#else
+#  define USAGE_REMOTE_LOG(a)
+#endif
+#ifdef CONFIG_FEATURE_IPC_SYSLOG
+#  define USAGE_IPC_LOG(a) a
+#else
+#  define USAGE_IPC_LOG(a)
+#endif
+
+#define sysctl_trivial_usage \
+	"[OPTIONS]... [VALUE]..."
+#define sysctl_full_usage \
+	"configure kernel parameters at runtime\n\n" \
+	"Options:\n" \
+	"\t-n\tUse this option to disable printing of the key name when printing values\n" \
+	"\t-w\tUse this option when you want to change a sysctl setting\n" \
+	"\t-p\tLoad in sysctl settings from the file specified or /etc/sysctl.conf if none given\n" \
+	"\t-a\tDisplay all values currently available\n" \
+	"\t-A\tDisplay all values currently available in table form"
+#define sysctl_example_usage \
+	"sysctl [-n] variable ...\n" \
+	"sysctl [-n] -w variable=value ...\n" \
+	"sysctl [-n] -a\n" \
+	"sysctl [-n] -p <file>\t(default /etc/sysctl.conf)\n" \
+	"sysctl [-n] -A\n"
+
+#define syslogd_trivial_usage \
+	"[OPTION]..."
+#define syslogd_full_usage \
+	"Linux system and kernel logging utility.\n" \
+	"Note that this version of syslogd ignores /etc/syslog.conf.\n\n" \
+	"Options:\n" \
+	"\t-m MIN\t\tMinutes between MARK lines (default=20, 0=off)\n" \
+	"\t-n\t\tRun as a foreground process\n" \
+	"\t-O FILE\t\tUse an alternate log file (default=/var/log/messages)\n" \
+	"\t-S\t\tMake logging output smaller." \
+	USAGE_ROTATE_LOGFILE( \
+	"\n\t-s SIZE\t\tMax size (KB) before rotate (default=200KB, 0=off)\n" \
+	"\t-b NUM\t\tNumber of rotated logs to keep (default=1, max=99, 0=purge)") \
+	USAGE_REMOTE_LOG( \
+	"\n\t-R HOST[:PORT]\tLog to IP or hostname on PORT (default PORT=514/UDP)\n" \
+	"\t-L\t\tLog locally and via network logging (default is network only)") \
+	USAGE_IPC_LOG( \
+	"\n\t-C [size(KiB)]\tLog to a circular buffer (read the buffer using logread)")
+#define syslogd_example_usage \
+	"$ syslogd -R masterlog:514\n" \
+	"$ syslogd -R 192.168.1.1:601\n"
+
+
+#ifndef CONFIG_FEATURE_FANCY_TAIL
+#  define USAGE_UNSIMPLE_TAIL(a)
+#else
+#  define USAGE_UNSIMPLE_TAIL(a) a
+#endif
+#define tail_trivial_usage \
+	"[OPTION]... [FILE]..."
+#define tail_full_usage \
+	"Print last 10 lines of each FILE to standard output.\n" \
+	"With more than one FILE, precede each with a header giving the\n" \
+	"file name. With no FILE, or when FILE is -, read standard input.\n\n" \
+	"Options:\n" \
+	USAGE_UNSIMPLE_TAIL("\t-c N[kbm]\toutput the last N bytes\n") \
+	"\t-n N[kbm]\tprint last N lines instead of last 10\n" \
+	"\t-f\t\toutput data as the file grows" \
+	USAGE_UNSIMPLE_TAIL( "\n\t-q\t\tnever output headers giving file names\n" \
+	"\t-s SEC\t\twait SEC seconds between reads with -f\n" \
+	"\t-v\t\talways output headers giving file names\n\n" \
+	"If the first character of N (bytes or lines) is a '+', output begins with \n" \
+	"the Nth item from the start of each file, otherwise, print the last N items\n" \
+	"in the file. N bytes may be suffixed by k (x1024), b (x512), or m (1024^2)." )
+#define tail_example_usage \
+	"$ tail -n 1 /etc/resolv.conf\n" \
+	"nameserver 10.0.0.1\n"
+
+#ifdef CONFIG_FEATURE_TAR_CREATE
+#  define USAGE_TAR_CREATE(a) a
+#else
+#  define USAGE_TAR_CREATE(a)
+#endif
+#ifdef CONFIG_FEATURE_TAR_EXCLUDE
+#  define USAGE_TAR_EXCLUDE(a) a
+#else
+#  define USAGE_TAR_EXCLUDE(a)
+#endif
+#ifdef CONFIG_FEATURE_TAR_GZIP
+#  define USAGE_TAR_GZIP(a) a
+#else
+#  define USAGE_TAR_GZIP(a)
+#endif
+#ifdef CONFIG_FEATURE_TAR_BZIP2
+#  define USAGE_TAR_BZIP2(a) a
+#else
+#  define USAGE_TAR_BZIP2(a)
+#endif
+#ifdef CONFIG_FEATURE_TAR_LZMA
+#  define USAGE_TAR_LZMA(a) a
+#else
+#  define USAGE_TAR_LZMA(a)
+#endif
+#ifdef CONFIG_FEATURE_TAR_COMPRESS
+#  define USAGE_TAR_COMPRESS(a) a
+#else
+#  define USAGE_TAR_COMPRESS(a)
+#endif
+
+#define tar_trivial_usage \
+	"-[" USAGE_TAR_CREATE("c") USAGE_TAR_GZIP("z") USAGE_TAR_BZIP2("j") USAGE_TAR_LZMA("a") USAGE_TAR_COMPRESS("Z") "xtvO] " \
+	USAGE_TAR_EXCLUDE("[-X FILE]") \
+	"[-f TARFILE] [-C DIR] [FILE(s)] ..."
+#define tar_full_usage \
+	"Create, extract, or list files from a tar file.\n\n" \
+	"Options:\n" \
+	USAGE_TAR_CREATE("\tc\t\tcreate\n") \
+	"\tx\t\textract\n" \
+	"\tt\t\tlist\n" \
+	"\nArchive format selection:\n" \
+	USAGE_TAR_GZIP("\tz\t\tFilter the archive through gzip\n") \
+	USAGE_TAR_BZIP2("\tj\t\tFilter the archive through bzip2\n") \
+	USAGE_TAR_LZMA("\ta\t\tFilter the archive through lzma\n") \
+	USAGE_TAR_COMPRESS("\tZ\t\tFilter the archive through compress\n") \
+	"\nFile selection:\n" \
+	"\tf\t\tname of TARFILE or \"-\" for stdin\n" \
+	"\tO\t\textract to stdout\n" \
+	USAGE_TAR_EXCLUDE( \
+	"\texclude\t\tfile to exclude\n" \
+	 "\tX\t\tfile with names to exclude\n" \
+	) \
+	"\tC\t\tchange to directory DIR before operation\n" \
+	"\tv\t\tverbosely list files processed"
+#define tar_example_usage \
+	"$ zcat /tmp/tarball.tar.gz | tar -xf -\n" \
+	"$ tar -cf /tmp/tarball.tar /usr/local\n"
+
+#define tee_trivial_usage \
+	"[OPTION]... [FILE]..."
+#define tee_full_usage \
+	"Copy standard input to each FILE, and also to standard output.\n\n" \
+	"Options:\n" \
+	"\t-a\tappend to the given FILEs, do not overwrite\n" \
+	"\t-i\tignore interrupt signals (SIGINT)"
+#define tee_example_usage \
+	"$ echo \"Hello\" | tee /tmp/foo\n" \
+	"$ cat /tmp/foo\n" \
+	"Hello\n"
+
+#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
+#define telnet_trivial_usage \
+	"[-a] [-l USER] HOST [PORT]"
+#define telnet_full_usage \
+	"Telnet is used to establish interactive communication with another\n" \
+	"computer over a network using the TELNET protocol.\n\n" \
+	"Options:\n" \
+	"\t-a\t\tAttempt an automatic login with the USER variable\n" \
+	"\t-l USER\t\tAttempt an automatic login with the USER argument\n" \
+	"\tHOST\t\tThe official name, alias or the IP address of the\n" \
+	"\t\t\tremote host.\n" \
+	"\tPORT\t\tThe remote port number to connect to.  If it is not\n" \
+	"\t\t\tspecified, the default telnet (23) port is used."
+#else
+#define telnet_trivial_usage \
+	"HOST [PORT]"
+#define telnet_full_usage \
+	"Telnet is used to establish interactive communication with another\n" \
+	"computer over a network using the TELNET protocol."
+#endif
+
+#ifdef CONFIG_FEATURE_TELNETD_INETD
+#define telnetd_trivial_usage \
+	"(inetd mode) [OPTION]"
+#define telnetd_full_usage \
+	"Telnetd uses incoming TELNET connections via inetd.\n" \
+	"Options:\n" \
+	"\t-l LOGIN\texec LOGIN on connect (default /bin/sh)\n" \
+	"\t-f issue_file\tDisplay issue_file instead of /etc/issue"
+#else
+#define telnetd_trivial_usage \
+	"[OPTION]"
+#define telnetd_full_usage \
+	"Telnetd listens for incoming TELNET connections on PORT.\n" \
+	"Options:\n" \
+	"\t-p PORT\tlisten for connections on PORT (default 23)\n" \
+	"\t-l LOGIN\texec LOGIN on connect (default /bin/sh)\n" \
+	"\t-f issue_file\tDisplay issue_file instead of /etc/issue"
+#endif
+
+#define test_trivial_usage \
+	"EXPRESSION\n  or   [ EXPRESSION ]"
+#define test_full_usage \
+	"Checks file types and compares values returning an exit\n" \
+	"code determined by the value of EXPRESSION."
+#define test_example_usage \
+	"$ test 1 -eq 2\n" \
+	"$ echo $?\n" \
+	"1\n" \
+	"$ test 1 -eq 1\n" \
+	"$ echo $?\n" \
+	"0\n" \
+	"$ [ -d /etc ]\n" \
+	"$ echo $?\n" \
+	"0\n" \
+	"$ [ -d /junk ]\n" \
+	"$ echo $?\n" \
+	"1\n"
+
+#ifdef CONFIG_FEATURE_TFTP_GET
+#  define USAGE_TFTP_GET(a) a
+#else
+#  define USAGE_TFTP_GET(a)
+#endif
+#ifdef CONFIG_FEATURE_TFTP_PUT
+#  define USAGE_TFTP_PUT(a) a
+#else
+#  define USAGE_TFTP_PUT(a)
+#endif
+#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE
+#  define USAGE_TFTP_BS(a) a
+#else
+#  define USAGE_TFTP_BS(a)
+#endif
+
+#define tftp_trivial_usage \
+	"[OPTION]... HOST [PORT]"
+#define tftp_full_usage \
+	"Transfers a file from/to a tftp server using \"octet\" mode.\n\n" \
+	"Options:\n" \
+	"\t-l FILE\tLocal FILE\n" \
+	"\t-r FILE\tRemote FILE" \
+	USAGE_TFTP_GET( \
+	"\n\t-g\tGet file" \
+	) \
+	USAGE_TFTP_PUT( \
+	"\n\t-p\tPut file" \
+	) \
+	USAGE_TFTP_BS( \
+	"\n\t-b SIZE\tTransfer blocks of SIZE octets" \
+	)
+#define time_trivial_usage \
+	"[OPTION]... COMMAND [ARGS...]"
+#define time_full_usage \
+	"Runs the program COMMAND with arguments ARGS.  When COMMAND finishes,\n" \
+	"COMMAND's resource usage information is displayed\n\n" \
+	"Options:\n" \
+	"\t-v\tDisplays verbose resource usage information"
+
+#define top_trivial_usage \
+	"[-d <seconds>]"
+#define top_full_usage \
+	"top provides an view of processor activity in real time.\n" \
+	"This utility reads the status for all processes in /proc each <seconds>\n" \
+	"and shows the status for however many processes will fit on the screen.\n" \
+	"This utility will not show processes that are started after program startup,\n" \
+	"but it will show the EXIT status for and PIDs that exit while it is running."
+
+#define touch_trivial_usage \
+	"[-c] FILE [FILE ...]"
+#define touch_full_usage \
+	"Update the last-modified date on the given FILE[s].\n\n" \
+	"Options:\n" \
+	"\t-c\tDo not create any files"
+#define touch_example_usage \
+	"$ ls -l /tmp/foo\n" \
+	"/bin/ls: /tmp/foo: No such file or directory\n" \
+	"$ touch /tmp/foo\n" \
+	"$ ls -l /tmp/foo\n" \
+	"-rw-rw-r--    1 andersen andersen        0 Apr 15 01:11 /tmp/foo\n"
+
+#define tr_trivial_usage \
+	"[-cds] STRING1 [STRING2]"
+#define tr_full_usage \
+	"Translate, squeeze, and/or delete characters from\n" \
+	"standard input, writing to standard output.\n\n" \
+	"Options:\n" \
+	"\t-c\ttake complement of STRING1\n" \
+	"\t-d\tdelete input characters coded STRING1\n" \
+	"\t-s\tsqueeze multiple output characters of STRING2 into one character"
+#define tr_example_usage \
+	"$ echo \"gdkkn vnqkc\" | tr [a-y] [b-z]\n" \
+	"hello world\n"
+
+#define traceroute_trivial_usage \
+	"[-FIldnrv] [-f 1st_ttl] [-m max_ttl] [-p port#] [-q nqueries]\n" \
+	"\t[-s src_addr] [-t tos] [-w wait] [-g gateway] [-i iface]\n" \
+	"\t[-z pausemsecs] host [data size]"
+#define traceroute_full_usage \
+	"trace the route ip packets follow going to \"host\"\n" \
+	"Options:\n" \
+	"\t-F\tSet the don't fragment bit\n" \
+	"\t-I\tUse ICMP ECHO instead of UDP datagrams\n" \
+	"\t-l\tDisplay the ttl value of the returned packet\n" \
+	"\t-d\tSet SO_DEBUG options to socket\n" \
+	"\t-n\tPrint hop addresses numerically rather than symbolically\n" \
+	"\t-r\tBypass the normal routing tables and send directly to a host\n" \
+	"\t-v\tVerbose output\n" \
+	"\t-m max_ttl\tSet the max time-to-live (max number of hops)\n" \
+	"\t-p port#\tSet the base UDP port number used in probes\n" \
+	"\t\t(default is 33434)\n" \
+	"\t-q nqueries\tSet the number of probes per ``ttl'' to nqueries\n" \
+	"\t\t(default is 3)\n" \
+	"\t-s src_addr\tUse the following IP address as the source address\n" \
+	"\t-t tos\tSet the type-of-service in probe packets to the following value\n" \
+	"\t\t(default 0)\n" \
+	"\t-w wait\tSet the time (in seconds) to wait for a response to a probe\n" \
+	"\t\t(default 3 sec)\n" \
+	"\t-g\tSpecify a loose source route gateway (8 maximum)"
+
+
+#define true_trivial_usage \
+	""
+#define true_full_usage \
+	"Return an exit code of TRUE (0)."
+#define true_example_usage \
+	"$ true\n" \
+	"$ echo $?\n" \
+	"0\n"
+
+#define tty_trivial_usage \
+	""
+#define tty_full_usage \
+	"Print the file name of the terminal connected to standard input.\n\n" \
+	"Options:\n" \
+	"\t-s\tprint nothing, only return an exit status"
+#define tty_example_usage \
+	"$ tty\n" \
+	"/dev/tty2\n"
+
+#define tune2fs_trivial_usage \
+	"[-c max-mounts-count] [-e errors-behavior] [-g group] " \
+	"[-i interval[d|m|w]] [-j] [-J journal-options] [-l] [-s sparse-flag] " \
+	"[-m reserved-blocks-percent] [-o [^]mount-options[,...]] " \
+	"[-r reserved-blocks-count] [-u user] [-C mount-count] " \
+	"[-L volume-label] [-M last-mounted-dir] [-O [^]feature[,...]] " \
+	"[-T last-check-time] [-U UUID] device"
+#define tune2fs_full_usage \
+	"Adjust filesystem options on ext[23] filesystems."
+
+#define udhcpc_trivial_usage \
+	"[-Cfbnqtv] [-c CID] [-V VCLS] [-H HOSTNAME] [-i INTERFACE]\n[-p pidfile] [-r IP] [-s script]"
+#define udhcpc_full_usage \
+	"\t-c,\t--clientid=CLIENTID\tSet client identifier\n" \
+	"\t-C,\t--clientid-none\tSuppress default client identifier\n" \
+	"\t-V,\t--vendorclass=CLASSID\tSet vendor class identifier\n" \
+	"\t-H,\t--hostname=HOSTNAME\tClient hostname\n" \
+	"\t-h,\t                   \tAlias for -H\n" \
+	"\t-f,\t--foreground\tDo not fork after getting lease\n" \
+	"\t-b,\t--background\tFork to background if lease cannot be immediately negotiated\n" \
+	"\t-i,\t--interface=INTERFACE\tInterface to use (default: eth0)\n" \
+	"\t-n,\t--now\tExit with failure if lease cannot be immediately negotiated\n" \
+	"\t-p,\t--pidfile=file\tStore process ID of daemon in file\n" \
+	"\t-q,\t--quit\tQuit after obtaining lease\n" \
+	"\t-r,\t--request=IP\tIP address to request (default: none)\n" \
+	"\t-s,\t--script=file\tRun file at dhcp events (default: /usr/share/udhcpc/default.script)\n" \
+	"\t-t,\t--retries=NUM\tSend up to NUM request packets\n"\
+	"\t-v,\t--version\tDisplay version"
+
+#define udhcpd_trivial_usage \
+	"[configfile]\n" \
+
+#define udhcpd_full_usage \
+	""
+
+#ifdef CONFIG_FEATURE_MOUNT_FORCE
+#  define USAGE_MOUNT_FORCE(a) a
+#else
+#  define USAGE_MOUNT_FORCE(a)
+#endif
+#define umount_trivial_usage \
+	"[flags] FILESYSTEM|DIRECTORY"
+#define umount_full_usage \
+	"Unmount file systems\n" \
+	"\nFlags:\n" "\t-a\tUnmount all file systems" \
+	USAGE_MTAB(" in /etc/mtab\n\t-n\tDon't erase /etc/mtab entries") \
+	"\n\t-r\tTry to remount devices as read-only if mount is busy" \
+	"\n\t-l\tLazy umount (detach filesystem)" \
+	"\n\t-f\tForce umount (i.e., unreachable NFS server)" \
+	USAGE_MOUNT_LOOP("\n\t-D\tDo not free loop device (if a loop device has been used)")
+#define umount_example_usage \
+	"$ umount /dev/hdc1 \n"
+
+#define uname_trivial_usage \
+	"[OPTION]..."
+#define uname_full_usage \
+	"Print certain system information.  With no OPTION, same as -s.\n\n" \
+	"Options:\n" \
+	"\t-a\tprint all information\n" \
+	"\t-m\tthe machine (hardware) type\n" \
+	"\t-n\tprint the machine's network node hostname\n" \
+	"\t-r\tprint the operating system release\n" \
+	"\t-s\tprint the operating system name\n" \
+	"\t-p\tprint the host processor type\n" \
+	"\t-v\tprint the operating system version"
+#define uname_example_usage \
+	"$ uname -a\n" \
+	"Linux debian 2.4.23 #2 Tue Dec 23 17:09:10 MST 2003 i686 GNU/Linux\n"
+
+#define uncompress_trivial_usage \
+	"[-c] [-f] [ name ... ]"
+#define uncompress_full_usage \
+	"Uncompress .Z file[s]\n" \
+	"Options:\n" \
+	"\t-c\textract to stdout\n" \
+	"\t-f\tforce overwrite an existing file"
+
+#define uniq_trivial_usage \
+	"[-fscdu]... [INPUT [OUTPUT]]"
+#define uniq_full_usage \
+	"Discard all but one of successive identical lines from INPUT\n" \
+	"(or standard input), writing to OUTPUT (or standard output).\n\n" \
+	"Options:\n" \
+	"\t-c\tprefix lines by the number of occurrences\n" \
+	"\t-d\tonly print duplicate lines\n" \
+	"\t-u\tonly print unique lines\n" \
+	"\t-f N\tskip the first N fields\n" \
+	"\t-s N\tskip the first N chars (after any skipped fields)"
+#define uniq_example_usage \
+	"$ echo -e \"a\\na\\nb\\nc\\nc\\na\" | sort | uniq\n" \
+	"a\n" \
+	"b\n" \
+	"c\n"
+
+#define unix2dos_trivial_usage \
+	"[option] [FILE]"
+#define unix2dos_full_usage \
+	"Converts FILE from unix format to dos format.  When no option\n" \
+	"is given, the input is converted to the opposite output format.\n" \
+	"When no file is given, uses stdin for input and stdout for output.\n" \
+	"Options:\n" \
+	"\t-u\toutput will be in UNIX format\n" \
+	"\t-d\toutput will be in DOS format"
+
+#define unzip_trivial_usage \
+	"[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]"
+#define unzip_full_usage \
+	"Extracts files from ZIP archives.\n\n" \
+	"Options:\n" \
+	"\t-l\tlist archive contents (short form)\n" \
+	"\t-n\tnever overwrite existing files (default)\n" \
+	"\t-o\toverwrite files without prompting\n" \
+	"\t-p\tsend output to stdout\n" \
+	"\t-q\tbe quiet\n" \
+	"\t-x\texclude these files\n" \
+	"\t-d\textract files into this directory"
+
+#define uptime_trivial_usage \
+	""
+#define uptime_full_usage \
+	"Display the time since the last boot."
+#define uptime_example_usage \
+	"$ uptime\n" \
+	"  1:55pm  up  2:30, load average: 0.09, 0.04, 0.00\n"
+
+#define usleep_trivial_usage \
+	"N"
+#define usleep_full_usage \
+	"Pause for N microseconds."
+#define usleep_example_usage \
+	"$ usleep 1000000\n" \
+	"[pauses for 1 second]\n"
+
+#define uudecode_trivial_usage \
+	"[FILE]..."
+#define uudecode_full_usage \
+	"Uudecode a file that is uuencoded.\n\n" \
+	"Options:\n" \
+	"\t-o FILE\tdirect output to FILE"
+#define uudecode_example_usage \
+	"$ uudecode -o busybox busybox.uu\n" \
+	"$ ls -l busybox\n" \
+	"-rwxr-xr-x   1 ams      ams        245264 Jun  7 21:35 busybox\n"
+
+#define uuencode_trivial_usage \
+	"[OPTION] [INFILE] REMOTEFILE"
+#define uuencode_full_usage \
+	"Uuencode a file.\n\n" \
+	"Options:\n" \
+	"\t-m\tuse base64 encoding per RFC1521"
+#define uuencode_example_usage \
+	"$ uuencode busybox busybox\n" \
+	"begin 755 busybox\n" \
+	"<encoded file snipped>\n" \
+	"$ uudecode busybox busybox > busybox.uu\n" \
+	"$\n"
+
+#define vconfig_trivial_usage \
+	"COMMAND [OPTIONS] ..."
+#define vconfig_full_usage \
+	"vconfig lets you create and remove virtual ethernet devices.\n\n" \
+	"Options:\n" \
+	"\tadd             [interface-name] [vlan_id]\n" \
+	"\trem             [vlan-name]\n" \
+	"\tset_flag        [interface-name] [flag-num]       [0 | 1]\n" \
+	"\tset_egress_map  [vlan-name]      [skb_priority]   [vlan_qos]\n" \
+	"\tset_ingress_map [vlan-name]      [skb_priority]   [vlan_qos]\n" \
+	"\tset_name_type   [name-type]"
+
+#define vi_trivial_usage \
+	"[OPTION] [FILE]..."
+#define vi_full_usage \
+	"edit FILE.\n\n" \
+	"Options:\n" \
+	"\t-R\tRead-only- do not write to the file"
+
+#define vlock_trivial_usage \
+	"[OPTIONS]"
+#define vlock_full_usage \
+	"Lock a virtual terminal.  A password is required to unlock\n" \
+	"Options:\n" \
+	"\t-a\tLock all VTs"
+
+#define watch_trivial_usage \
+	"[-n <seconds>] COMMAND..."
+#define watch_full_usage \
+	"Executes a program periodically.\n" \
+	"Options:\n" \
+	"\t-n\tLoop period in seconds - default is 2"
+#define watch_example_usage \
+	"$ watch date\n" \
+	"Mon Dec 17 10:31:40 GMT 2000\n" \
+	"Mon Dec 17 10:31:42 GMT 2000\n" \
+	"Mon Dec 17 10:31:44 GMT 2000"
+
+#define watchdog_trivial_usage \
+	"[-t <seconds>] [-F] DEV"
+#define watchdog_full_usage \
+	"Periodically write to watchdog device DEV.\n" \
+	"Options:\n" \
+	"\t-t\tTimer period in seconds - default is 30\n" \
+	"\t-F\tStay in the foreground and don't fork"
+
+#define wc_trivial_usage \
+	"[OPTION]... [FILE]..."
+#define wc_full_usage \
+	"Print line, word, and byte counts for each FILE, and a total line if\n" \
+	"more than one FILE is specified.  With no FILE, read standard input.\n\n" \
+	"Options:\n" \
+	"\t-c\tprint the byte counts\n" \
+	"\t-l\tprint the newline counts\n" \
+	"\t-L\tprint the length of the longest line\n" \
+	"\t-w\tprint the word counts"
+#define wc_example_usage \
+	"$ wc /etc/passwd\n" \
+	"     31      46    1365 /etc/passwd\n"
+
+#define wget_trivial_usage \
+	"[-c|--continue] [-q|--quiet] [-O|--output-document file]\n" \
+	"\t\t[--header 'header: value'] [-Y|--proxy on/off] [-P DIR] url"
+#define wget_full_usage \
+	"wget retrieves files via HTTP or FTP\n\n" \
+	"Options:\n" \
+	"\t-c\tcontinue retrieval of aborted transfers\n" \
+	"\t-q\tquiet mode - do not print\n" \
+	"\t-P\tSet directory prefix to DIR\n" \
+	"\t-O\tsave to filename ('-' for stdout)\n" \
+	"\t-Y\tuse proxy ('on' or 'off')"
+
+#define which_trivial_usage \
+	"[COMMAND ...]"
+#define which_full_usage \
+	"Locates a COMMAND."
+#define which_example_usage \
+	"$ which login\n" \
+	"/bin/login\n"
+
+#define who_trivial_usage \
+	" "
+#define who_full_usage \
+	"Prints the current user names and related information"
+
+#define whoami_trivial_usage \
+	""
+#define whoami_full_usage \
+	"Prints the user name associated with the current effective user id."
+
+#ifdef CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION
+#define USAGE_XARGS_CONFIRMATION(a) a
+#else
+#define USAGE_XARGS_CONFIRMATION(a)
+#endif
+#ifdef CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT
+#define USAGE_XARGS_TERMOPT(a) a
+#else
+#define USAGE_XARGS_TERMOPT(a)
+#endif
+#ifdef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM
+#define USAGE_XARGS_ZERO_TERM(a) a
+#else
+#define USAGE_XARGS_ZERO_TERM(a)
+#endif
+
+
+#define xargs_trivial_usage \
+	"[COMMAND] [OPTIONS] [ARGS...]"
+#define xargs_full_usage \
+	"Executes COMMAND on every item given by standard input.\n\n" \
+	"Options:\n" \
+	USAGE_XARGS_CONFIRMATION("\t-p\tPrompt the user about whether to run each command\n") \
+	"\t-r\tDo not run command for empty read lines\n" \
+	USAGE_XARGS_TERMOPT("\t-x\tExit if the size is exceeded\n") \
+	USAGE_XARGS_ZERO_TERM("\t-0\tInput filenames are terminated by a null character\n") \
+	"\t-t\tPrint the command line on stderr before executing it"
+#define xargs_example_usage \
+	"$ ls | xargs gzip\n" \
+	"$ find . -name '*.c' -print | xargs rm\n"
+
+#define yes_trivial_usage \
+	"[OPTION]... [STRING]..."
+#define yes_full_usage \
+	"Repeatedly outputs a line with all specified STRING(s), or 'y'."
+
+#define zcat_trivial_usage \
+	"FILE"
+#define zcat_full_usage \
+	"Uncompress to stdout."
+
+#define zcip_trivial_usage \
+	"[OPTIONS] ifname script"
+#define zcip_full_usage \
+	"zcip manages a ZeroConf IPv4 link-local address.\n" \
+	"Options:\n" \
+	"\t-f              foreground mode\n" \
+	"\t-q              quit after address (no daemon)\n" \
+	"\t-r 169.254.x.x  request this address first\n" \
+	"\t-v              verbose"
+
+#endif /* __BB_USAGE_H__ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/xregex.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/xregex.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/include/xregex.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,31 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Busybox xregcomp utility routine
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Based in part on code from sash, Copyright (c) 1999 by David I. Bell
+ * Permission has been granted to redistribute this code under the GPL.
+ *
+ */
+#ifndef __BB_REGEX__
+#define __BB_REGEX__
+
+#include <sys/types.h>
+#include <regex.h>
+extern void xregcomp(regex_t *preg, const char *regex, int cflags);
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,83 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Init Utilities"
+
+config CONFIG_INIT
+	bool "init"
+	default n
+	help
+	  init is the first program run when the system boots.
+
+config CONFIG_DEBUG_INIT
+	bool "debugging aid"
+	default n
+	depends on CONFIG_INIT
+	help
+	  Turn this on to disable all the dangerous
+	  rebooting stuff when debugging.
+
+config CONFIG_FEATURE_USE_INITTAB
+	bool "Support reading an inittab file"
+	default y
+	depends on CONFIG_INIT
+	help
+	  Allow init to read an inittab file when the system boot.
+
+config CONFIG_FEATURE_INIT_SCTTY
+	bool "Support running commands with a controlling-tty"
+	default n
+	depends on CONFIG_INIT
+	help
+	  If this option is enabled a command starting with hyphen (-)
+	  is run in its own session (setsid(2)) and possibly with a
+	  controlling tty (TIOCSCTTY).  This is not the traditional init
+	  behavour, but is often what you want in an embedded system where
+	  the console is only accessed during development or for maintenance.
+
+config CONFIG_FEATURE_EXTRA_QUIET
+	bool "Be _extra_ quiet on boot"
+	default y
+	depends on CONFIG_INIT
+	help
+	  Prevent init from logging some messages to the console during boot.
+
+config CONFIG_FEATURE_INIT_COREDUMPS
+	bool "Support dumping core for child processes (debugging only)"
+	default n
+	depends on CONFIG_INIT
+	help
+	  If this option is enabled and the file /.init_enable_core
+	  exists, then init will call setrlimit() to allow unlimited
+	  core file sizes.  If this option is disabled, processes
+	  will not generate any core files.
+
+
+
+config CONFIG_FEATURE_INITRD
+	bool "Support running init from within an initrd (not initramfs)"
+	default y
+	depends on CONFIG_INIT
+	help
+	  Legacy support for running init under the old-style initrd.  Allows
+	  the name linuxrc to act as init, and it doesn't assume init is PID 1.
+
+	  This does not apply to initramfs, which runs /init as PID 1 and
+	  requires no special support.
+
+config CONFIG_HALT
+	bool "poweroff, halt, and reboot"
+	default y
+	help
+	  Stop all processes and either halt, reboot, or power off the system.
+
+config CONFIG_MESG
+	bool "mesg"
+	default y
+	help
+	  Mesg controls access to your terminal by others.  It is typically
+	  used to allow or disallow other users to write to your terminal
+
+endmenu

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/init
+INIT_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include $(srcdir)/Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,43 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+INIT_AR:=init.a
+ifndef $(INIT_DIR)
+INIT_DIR:=$(top_builddir)/init/
+endif
+srcdir=$(top_srcdir)/init
+
+INIT-y:=
+INIT-$(CONFIG_HALT)			+= halt.o
+INIT-$(CONFIG_INIT)			+= init.o
+INIT-$(CONFIG_MESG)			+= mesg.o
+
+ifeq ($(strip $(CONFIG_HALT)),y)
+CONFIG_INIT_SHARED=y
+else
+ifeq ($(strip $(CONFIG_INIT)),y)
+CONFIG_INIT_SHARED=y
+else
+CONFIG_INIT_SHARED=n
+endif
+endif
+
+INIT-$(CONFIG_INIT_SHARED)        += init_shared.o
+
+ifneq ($(strip $(INIT-y)),)
+libraries-y+=$(INIT_DIR)$(INIT_AR)
+endif
+
+INIT_SRC-y:=$(patsubst %.o,$(srcdir)/%.c,$(INIT-y))
+INIT_SRC-a:=$(wildcard $(srcdir)/*.c)
+APPLET_SRC-y+=$(INIT_SRC-y)
+APPLET_SRC-a+=$(INIT_SRC-a)
+
+$(INIT_DIR)$(INIT_AR): $(patsubst %,$(INIT_DIR)%, $(INIT-y))
+	$(do_ar)
+
+$(INIT_DIR)%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/halt.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/halt.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/halt.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,55 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Poweroff reboot and halt, oh my.
+ *
+ * Copyright 2006 by Rob Landley <rob at landley.net>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <signal.h>
+#include <sys/reboot.h>
+#include <unistd.h>
+
+int halt_main(int argc, char *argv[])
+{
+	static const int magic[] = {
+#ifdef RB_HALT_SYSTEM
+RB_HALT_SYSTEM,
+#elif defined RB_HALT
+RB_HALT,
+#endif
+#ifdef RB_POWER_OFF
+RB_POWER_OFF,
+#elif defined RB_POWERDOWN
+RB_POWERDOWN,
+#endif
+RB_AUTOBOOT
+	};
+	static const int signals[] = {SIGUSR1, SIGUSR2, SIGTERM};
+
+	char *delay = "hpr";
+	int which, flags, rc = 1;
+
+	/* Figure out which applet we're running */
+	for(which=0;delay[which]!=*bb_applet_name;which++);
+
+	/* Parse and handle arguments */
+	flags = bb_getopt_ulflags(argc, argv, "d:nf", &delay);
+	if (flags&1) sleep(atoi(delay));
+	if (!(flags&2)) sync();
+
+	/* Perform action. */
+	if (ENABLE_INIT && !(flags & 4)) {
+		if (ENABLE_FEATURE_INITRD) {
+			long *pidlist=find_pid_by_name("linuxrc");
+			if (*pidlist>0) rc = kill(*pidlist,signals[which]);
+			if (ENABLE_FEATURE_CLEAN_UP) free(pidlist);
+		}
+		if (rc) rc = kill(1,signals[which]);
+	} else rc = reboot(magic[which]);
+
+	if (rc) bb_error_msg("No.");
+	return rc;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/init.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/init.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/init.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1162 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini init implementation for busybox
+ *
+ * Copyright (C) 1995, 1996 by Bruce Perens <bruce at pixar.com>.
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ * Adjusted by so many folks, it's impossible to keep track.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/reboot.h>
+
+#include "init_shared.h"
+
+
+#ifdef CONFIG_SYSLOGD
+# include <sys/syslog.h>
+#endif
+
+
+#ifdef CONFIG_SELINUX
+# include <selinux/selinux.h>
+#endif /* CONFIG_SELINUX */
+
+
+#define INIT_BUFFS_SIZE 256
+
+/* From <linux/vt.h> */
+struct vt_stat {
+	unsigned short v_active;	/* active vt */
+	unsigned short v_signal;	/* signal to send */
+	unsigned short v_state;	/* vt bitmask */
+};
+enum { VT_GETSTATE = 0x5603 };	/* get global vt state info */
+
+/* From <linux/serial.h> */
+struct serial_struct {
+	int	type;
+	int	line;
+	unsigned int	port;
+	int	irq;
+	int	flags;
+	int	xmit_fifo_size;
+	int	custom_divisor;
+	int	baud_base;
+	unsigned short	close_delay;
+	char	io_type;
+	char	reserved_char[1];
+	int	hub6;
+	unsigned short	closing_wait; /* time to wait before closing */
+	unsigned short	closing_wait2; /* no longer used... */
+	unsigned char	*iomem_base;
+	unsigned short	iomem_reg_shift;
+	unsigned int	port_high;
+	unsigned long	iomap_base;	/* cookie passed into ioremap */
+	int	reserved[1];
+};
+
+
+#ifndef _PATH_STDPATH
+#define _PATH_STDPATH	"/usr/bin:/bin:/usr/sbin:/sbin"
+#endif
+
+#if defined CONFIG_FEATURE_INIT_COREDUMPS
+/*
+ * When a file named CORE_ENABLE_FLAG_FILE exists, setrlimit is called
+ * before processes are spawned to set core file size as unlimited.
+ * This is for debugging only.  Don't use this is production, unless
+ * you want core dumps lying about....
+ */
+#define CORE_ENABLE_FLAG_FILE "/.init_enable_core"
+#include <sys/resource.h>
+#endif
+
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+
+#define INITTAB      "/etc/inittab"	/* inittab file location */
+#ifndef INIT_SCRIPT
+#define INIT_SCRIPT  "/etc/init.d/rcS"	/* Default sysinit script. */
+#endif
+
+#define MAXENV	16		/* Number of env. vars */
+
+#define CONSOLE_BUFF_SIZE 32
+
+/* Allowed init action types */
+#define SYSINIT     0x001
+#define RESPAWN     0x002
+#define ASKFIRST    0x004
+#define WAIT        0x008
+#define ONCE        0x010
+#define CTRLALTDEL  0x020
+#define SHUTDOWN    0x040
+#define RESTART     0x080
+
+/* A mapping between "inittab" action name strings and action type codes. */
+struct init_action_type {
+	const char *name;
+	int action;
+};
+
+static const struct init_action_type actions[] = {
+	{"sysinit", SYSINIT},
+	{"respawn", RESPAWN},
+	{"askfirst", ASKFIRST},
+	{"wait", WAIT},
+	{"once", ONCE},
+	{"ctrlaltdel", CTRLALTDEL},
+	{"shutdown", SHUTDOWN},
+	{"restart", RESTART},
+	{0, 0}
+};
+
+/* Set up a linked list of init_actions, to be read from inittab */
+struct init_action {
+	pid_t pid;
+	char command[INIT_BUFFS_SIZE];
+	char terminal[CONSOLE_BUFF_SIZE];
+	struct init_action *next;
+	int action;
+};
+
+/* Static variables */
+static struct init_action *init_action_list = NULL;
+static char console[CONSOLE_BUFF_SIZE] = CONSOLE_DEV;
+
+#ifndef CONFIG_SYSLOGD
+static char *log_console = VC_5;
+#endif
+#if !ENABLE_DEBUG_INIT
+static sig_atomic_t got_cont = 0;
+#endif
+
+enum {
+	LOG = 0x1,
+	CONSOLE = 0x2,
+
+#if defined CONFIG_FEATURE_EXTRA_QUIET
+	MAYBE_CONSOLE = 0x0,
+#else
+	MAYBE_CONSOLE = CONSOLE,
+#endif
+
+#ifndef RB_HALT_SYSTEM
+	RB_HALT_SYSTEM = 0xcdef0123, /* FIXME: this overflows enum */
+	RB_ENABLE_CAD = 0x89abcdef,
+	RB_DISABLE_CAD = 0,
+	RB_POWER_OFF = 0x4321fedc,
+	RB_AUTOBOOT = 0x01234567,
+#endif
+};
+
+static const char * const environment[] = {
+	"HOME=/",
+	"PATH=" _PATH_STDPATH,
+	"SHELL=/bin/sh",
+	"USER=root",
+	NULL
+};
+
+/* Function prototypes */
+static void delete_init_action(struct init_action *a);
+static int waitfor(const struct init_action *a, pid_t pid);
+#if !ENABLE_DEBUG_INIT
+static void shutdown_signal(int sig);
+#endif
+
+static void loop_forever(void)
+{
+	while (1)
+		sleep(1);
+}
+
+/* Print a message to the specified device.
+ * Device may be bitwise-or'd from LOG | CONSOLE */
+#if ENABLE_DEBUG_INIT
+#define messageD message
+#else
+static inline void messageD(int ATTRIBUTE_UNUSED device,
+				const char ATTRIBUTE_UNUSED *fmt, ...)
+{
+}
+#endif
+static void message(int device, const char *fmt, ...)
+	__attribute__ ((format(printf, 2, 3)));
+static void message(int device, const char *fmt, ...)
+{
+	va_list arguments;
+	int l;
+	RESERVE_CONFIG_BUFFER(msg, 1024);
+#ifndef CONFIG_SYSLOGD
+	static int log_fd = -1;
+#endif
+
+	msg[0] = '\r';
+		va_start(arguments, fmt);
+	l = vsnprintf(msg + 1, 1024 - 2, fmt, arguments) + 1;
+		va_end(arguments);
+
+#ifdef CONFIG_SYSLOGD
+	/* Log the message to syslogd */
+	if (device & LOG) {
+		/* don`t out "\r\n" */
+		openlog(bb_applet_name, 0, LOG_DAEMON);
+		syslog(LOG_INFO, "%s", msg + 1);
+		closelog();
+	}
+
+	msg[l++] = '\n';
+	msg[l] = 0;
+#else
+
+	msg[l++] = '\n';
+	msg[l] = 0;
+	/* Take full control of the log tty, and never close it.
+	 * It's mine, all mine!  Muhahahaha! */
+	if (log_fd < 0) {
+		if ((log_fd = device_open(log_console, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
+			log_fd = -2;
+			bb_error_msg("Bummer, can't write to log on %s!", log_console);
+			device = CONSOLE;
+		} else {
+			fcntl(log_fd, F_SETFD, FD_CLOEXEC);
+		}
+	}
+	if ((device & LOG) && (log_fd >= 0)) {
+		bb_full_write(log_fd, msg, l);
+	}
+#endif
+
+	if (device & CONSOLE) {
+		int fd = device_open(CONSOLE_DEV,
+					O_WRONLY | O_NOCTTY | O_NONBLOCK);
+		/* Always send console messages to /dev/console so people will see them. */
+		if (fd >= 0) {
+			bb_full_write(fd, msg, l);
+			close(fd);
+#if ENABLE_DEBUG_INIT
+		/* all descriptors may be closed */
+		} else {
+			bb_error_msg("Bummer, can't print: ");
+			va_start(arguments, fmt);
+			vfprintf(stderr, fmt, arguments);
+			va_end(arguments);
+#endif
+		}
+	}
+	RELEASE_CONFIG_BUFFER(msg);
+}
+
+/* Set terminal settings to reasonable defaults */
+static void set_term(void)
+{
+	struct termios tty;
+
+	tcgetattr(STDIN_FILENO, &tty);
+
+	/* set control chars */
+	tty.c_cc[VINTR] = 3;	/* C-c */
+	tty.c_cc[VQUIT] = 28;	/* C-\ */
+	tty.c_cc[VERASE] = 127;	/* C-? */
+	tty.c_cc[VKILL] = 21;	/* C-u */
+	tty.c_cc[VEOF] = 4;	/* C-d */
+	tty.c_cc[VSTART] = 17;	/* C-q */
+	tty.c_cc[VSTOP] = 19;	/* C-s */
+	tty.c_cc[VSUSP] = 26;	/* C-z */
+
+	/* use line dicipline 0 */
+	tty.c_line = 0;
+
+	/* Make it be sane */
+	tty.c_cflag &= CBAUD | CBAUDEX | CSIZE | CSTOPB | PARENB | PARODD;
+	tty.c_cflag |= CREAD | HUPCL | CLOCAL;
+
+
+	/* input modes */
+	tty.c_iflag = ICRNL | IXON | IXOFF;
+
+	/* output modes */
+	tty.c_oflag = OPOST | ONLCR;
+
+	/* local modes */
+	tty.c_lflag =
+		ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
+
+	tcsetattr(STDIN_FILENO, TCSANOW, &tty);
+}
+
+static void console_init(void)
+{
+	int fd;
+	int tried = 0;
+	struct vt_stat vt;
+	struct serial_struct sr;
+	char *s;
+
+	if ((s = getenv("CONSOLE")) != NULL || (s = getenv("console")) != NULL) {
+		safe_strncpy(console, s, sizeof(console));
+#if 0 /* #cpu(sparc) */
+	/* sparc kernel supports console=tty[ab] parameter which is also
+	 * passed to init, so catch it here */
+		/* remap tty[ab] to /dev/ttyS[01] */
+		if (strcmp(s, "ttya") == 0)
+			safe_strncpy(console, SC_0, sizeof(console));
+		else if (strcmp(s, "ttyb") == 0)
+			safe_strncpy(console, SC_1, sizeof(console));
+#endif
+	} else {
+		/* 2.2 kernels: identify the real console backend and try to use it */
+		if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
+			/* this is a serial console */
+			snprintf(console, sizeof(console) - 1, SC_FORMAT, sr.line);
+		} else if (ioctl(0, VT_GETSTATE, &vt) == 0) {
+			/* this is linux virtual tty */
+			snprintf(console, sizeof(console) - 1, VC_FORMAT, vt.v_active);
+		} else {
+			safe_strncpy(console, CONSOLE_DEV, sizeof(console));
+			tried++;
+		}
+	}
+
+	while ((fd = open(console, O_RDONLY | O_NONBLOCK)) < 0 && tried < 2) {
+		/* Can't open selected console -- try
+			logical system console and VT_MASTER */
+		safe_strncpy(console, (tried == 0 ? CONSOLE_DEV : CURRENT_VC),
+							sizeof(console));
+		tried++;
+	}
+	if (fd < 0) {
+		/* Perhaps we should panic here? */
+#ifndef CONFIG_SYSLOGD
+		log_console =
+#endif
+		safe_strncpy(console, bb_dev_null, sizeof(console));
+	} else {
+		s = getenv("TERM");
+		/* check for serial console */
+		if (ioctl(fd, TIOCGSERIAL, &sr) == 0) {
+			/* Force the TERM setting to vt102 for serial console --
+			 * if TERM is set to linux (the default) */
+			if (s == NULL || strcmp(s, "linux") == 0)
+				putenv("TERM=vt102");
+#ifndef CONFIG_SYSLOGD
+			log_console = console;
+#endif
+		} else {
+			if (s == NULL)
+				putenv("TERM=linux");
+		}
+		close(fd);
+	}
+	messageD(LOG, "console=%s", console);
+}
+
+static void fixup_argv(int argc, char **argv, char *new_argv0)
+{
+	int len;
+
+	/* Fix up argv[0] to be certain we claim to be init */
+	len = strlen(argv[0]);
+	memset(argv[0], 0, len);
+	safe_strncpy(argv[0], new_argv0, len + 1);
+
+	/* Wipe argv[1]-argv[N] so they don't clutter the ps listing */
+	len = 1;
+	while (argc > len) {
+		memset(argv[len], 0, strlen(argv[len]));
+		len++;
+	}
+}
+
+/* Open the new terminal device */
+static void open_new_terminal(const char * const device, const int fail) {
+	struct stat sb;
+
+	if ((device_open(device, O_RDWR)) < 0) {
+		if (stat(device, &sb) != 0) {
+			message(LOG | CONSOLE, "device '%s' does not exist.", device);
+		} else {
+			message(LOG | CONSOLE, "Bummer, can't open %s", device);
+		}
+		if (fail)
+			_exit(1);
+		/* else */
+#if !ENABLE_DEBUG_INIT
+		shutdown_signal(SIGUSR1);
+#else
+		_exit(2);
+#endif
+	}
+}
+
+static pid_t run(const struct init_action *a)
+{
+	int i;
+	pid_t pid;
+	char *s, *tmpCmd, *cmd[INIT_BUFFS_SIZE], *cmdpath;
+	char buf[INIT_BUFFS_SIZE + 6];	/* INIT_BUFFS_SIZE+strlen("exec ")+1 */
+	sigset_t nmask, omask;
+	static const char press_enter[] =
+#ifdef CUSTOMIZED_BANNER
+#include CUSTOMIZED_BANNER
+#endif
+		"\nPlease press Enter to activate this console. ";
+
+	/* Block sigchild while forking.  */
+	sigemptyset(&nmask);
+	sigaddset(&nmask, SIGCHLD);
+	sigprocmask(SIG_BLOCK, &nmask, &omask);
+
+	if ((pid = fork()) == 0) {
+
+		/* Clean up */
+		close(0);
+		close(1);
+		close(2);
+		sigprocmask(SIG_SETMASK, &omask, NULL);
+
+		/* Reset signal handlers that were set by the parent process */
+		signal(SIGUSR1, SIG_DFL);
+		signal(SIGUSR2, SIG_DFL);
+		signal(SIGINT, SIG_DFL);
+		signal(SIGTERM, SIG_DFL);
+		signal(SIGHUP, SIG_DFL);
+		signal(SIGQUIT, SIG_DFL);
+		signal(SIGCONT, SIG_DFL);
+		signal(SIGSTOP, SIG_DFL);
+		signal(SIGTSTP, SIG_DFL);
+
+		/* Create a new session and make ourself the process
+		 * group leader */
+		setsid();
+
+		/* Open the new terminal device */
+		open_new_terminal(a->terminal, 1);
+
+		/* Make sure the terminal will act fairly normal for us */
+		set_term();
+		/* Setup stdout, stderr for the new process so
+		 * they point to the supplied terminal */
+		dup(0);
+		dup(0);
+
+		/* If the init Action requires us to wait, then force the
+		 * supplied terminal to be the controlling tty. */
+		if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
+
+			/* Now fork off another process to just hang around */
+			if ((pid = fork()) < 0) {
+				message(LOG | CONSOLE, "Can't fork!");
+				_exit(1);
+			}
+
+			if (pid > 0) {
+
+				/* We are the parent -- wait till the child is done */
+				signal(SIGINT, SIG_IGN);
+				signal(SIGTSTP, SIG_IGN);
+				signal(SIGQUIT, SIG_IGN);
+				signal(SIGCHLD, SIG_DFL);
+
+				waitfor(NULL, pid);
+				/* See if stealing the controlling tty back is necessary */
+				if (tcgetpgrp(0) != getpid())
+					_exit(0);
+
+				/* Use a temporary process to steal the controlling tty. */
+				if ((pid = fork()) < 0) {
+					message(LOG | CONSOLE, "Can't fork!");
+					_exit(1);
+				}
+				if (pid == 0) {
+					setsid();
+					ioctl(0, TIOCSCTTY, 1);
+					_exit(0);
+				}
+				waitfor(NULL, pid);
+				_exit(0);
+			}
+
+			/* Now fall though to actually execute things */
+		}
+
+		/* See if any special /bin/sh requiring characters are present */
+		if (strpbrk(a->command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
+			cmd[0] = (char *)DEFAULT_SHELL;
+			cmd[1] = "-c";
+			cmd[2] = strcat(strcpy(buf, "exec "), a->command);
+			cmd[3] = NULL;
+		} else {
+			/* Convert command (char*) into cmd (char**, one word per string) */
+			strcpy(buf, a->command);
+			s = buf;
+			for (tmpCmd = buf, i = 0; (tmpCmd = strsep(&s, " \t")) != NULL;) {
+				if (*tmpCmd != '\0') {
+					cmd[i] = tmpCmd;
+					i++;
+				}
+			}
+			cmd[i] = NULL;
+		}
+
+		cmdpath = cmd[0];
+
+		/*
+		   Interactive shells want to see a dash in argv[0].  This
+		   typically is handled by login, argv will be setup this
+		   way if a dash appears at the front of the command path
+		   (like "-/bin/sh").
+		 */
+
+		if (*cmdpath == '-') {
+
+			/* skip over the dash */
+			++cmdpath;
+
+			/* find the last component in the command pathname */
+			s = bb_get_last_path_component(cmdpath);
+
+			/* make a new argv[0] */
+			if ((cmd[0] = malloc(strlen(s) + 2)) == NULL) {
+				message(LOG | CONSOLE, bb_msg_memory_exhausted);
+				cmd[0] = cmdpath;
+			} else {
+				cmd[0][0] = '-';
+				strcpy(cmd[0] + 1, s);
+			}
+#ifdef CONFIG_FEATURE_INIT_SCTTY
+			/* Establish this process as session leader and
+			 * (attempt) to make the tty (if any) a controlling tty.
+			 */
+			(void) setsid();
+			(void) ioctl(0, TIOCSCTTY, 0/*don't steal it*/);
+#endif
+		}
+
+#if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__)
+		if (a->action & ASKFIRST) {
+			char c;
+			/*
+			 * Save memory by not exec-ing anything large (like a shell)
+			 * before the user wants it. This is critical if swap is not
+			 * enabled and the system has low memory. Generally this will
+			 * be run on the second virtual console, and the first will
+			 * be allowed to start a shell or whatever an init script
+			 * specifies.
+			 */
+			messageD(LOG, "Waiting for enter to start '%s'"
+						"(pid %d, terminal %s)\n",
+					  cmdpath, getpid(), a->terminal);
+			bb_full_write(1, press_enter, sizeof(press_enter) - 1);
+			while(read(0, &c, 1) == 1 && c != '\n')
+				;
+		}
+#endif
+
+		/* Log the process name and args */
+		message(LOG, "Starting pid %d, console %s: '%s'",
+				  getpid(), a->terminal, cmdpath);
+
+#if defined CONFIG_FEATURE_INIT_COREDUMPS
+		{
+			struct stat sb;
+			if (stat(CORE_ENABLE_FLAG_FILE, &sb) == 0) {
+				struct rlimit limit;
+
+				limit.rlim_cur = RLIM_INFINITY;
+				limit.rlim_max = RLIM_INFINITY;
+				setrlimit(RLIMIT_CORE, &limit);
+			}
+		}
+#endif
+
+		/* Now run it.  The new program will take over this PID,
+		 * so nothing further in init.c should be run. */
+		execv(cmdpath, cmd);
+
+		/* We're still here?  Some error happened. */
+		message(LOG | CONSOLE, "Bummer, could not run '%s': %m", cmdpath);
+		_exit(-1);
+	}
+	sigprocmask(SIG_SETMASK, &omask, NULL);
+	return pid;
+}
+
+static int waitfor(const struct init_action *a, pid_t pid)
+{
+	int runpid;
+	int status, wpid;
+
+	runpid = (NULL == a)? pid : run(a);
+	while (1) {
+		wpid = waitpid(runpid,&status,0);
+		if (wpid == runpid)
+			break;
+		if (wpid == -1 && errno == ECHILD) {
+			/* we missed its termination */
+			break;
+		}
+		/* FIXME other errors should maybe trigger an error, but allow
+		 * the program to continue */
+	}
+	return wpid;
+}
+
+/* Run all commands of a particular type */
+static void run_actions(int action)
+{
+	struct init_action *a, *tmp;
+
+	for (a = init_action_list; a; a = tmp) {
+		tmp = a->next;
+		if (a->action == action) {
+			if (access(a->terminal, R_OK | W_OK)) {
+				delete_init_action(a);
+			} else if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
+				waitfor(a, 0);
+				delete_init_action(a);
+			} else if (a->action & ONCE) {
+				run(a);
+				delete_init_action(a);
+			} else if (a->action & (RESPAWN | ASKFIRST)) {
+				/* Only run stuff with pid==0.  If they have
+				 * a pid, that means it is still running */
+				if (a->pid == 0) {
+					a->pid = run(a);
+				}
+			}
+		}
+	}
+}
+
+#if !ENABLE_DEBUG_INIT
+static void init_reboot(unsigned long magic)
+{
+	pid_t pid;
+	/* We have to fork here, since the kernel calls do_exit(0) in
+	 * linux/kernel/sys.c, which can cause the machine to panic when
+	 * the init process is killed.... */
+	if ((pid = fork()) == 0) {
+		reboot(magic);
+		_exit(0);
+	}
+	waitpid (pid, NULL, 0);
+}
+
+static void shutdown_system(void)
+{
+	sigset_t block_signals;
+
+	/* run everything to be run at "shutdown".  This is done _prior_
+	 * to killing everything, in case people wish to use scripts to
+	 * shut things down gracefully... */
+	run_actions(SHUTDOWN);
+
+	/* first disable all our signals */
+	sigemptyset(&block_signals);
+	sigaddset(&block_signals, SIGHUP);
+	sigaddset(&block_signals, SIGQUIT);
+	sigaddset(&block_signals, SIGCHLD);
+	sigaddset(&block_signals, SIGUSR1);
+	sigaddset(&block_signals, SIGUSR2);
+	sigaddset(&block_signals, SIGINT);
+	sigaddset(&block_signals, SIGTERM);
+	sigaddset(&block_signals, SIGCONT);
+	sigaddset(&block_signals, SIGSTOP);
+	sigaddset(&block_signals, SIGTSTP);
+	sigprocmask(SIG_BLOCK, &block_signals, NULL);
+
+	/* Allow Ctrl-Alt-Del to reboot system. */
+	init_reboot(RB_ENABLE_CAD);
+
+	message(CONSOLE | LOG, "The system is going down NOW !!");
+	sync();
+
+	/* Send signals to every process _except_ pid 1 */
+	message(CONSOLE | LOG, init_sending_format, "TERM");
+	kill(-1, SIGTERM);
+	sleep(1);
+	sync();
+
+	message(CONSOLE | LOG, init_sending_format, "KILL");
+	kill(-1, SIGKILL);
+	sleep(1);
+
+	sync();
+}
+
+static void exec_signal(int sig ATTRIBUTE_UNUSED)
+{
+	struct init_action *a, *tmp;
+	sigset_t unblock_signals;
+
+	for (a = init_action_list; a; a = tmp) {
+		tmp = a->next;
+		if (a->action & RESTART) {
+			shutdown_system();
+
+			/* unblock all signals, blocked in shutdown_system() */
+			sigemptyset(&unblock_signals);
+			sigaddset(&unblock_signals, SIGHUP);
+			sigaddset(&unblock_signals, SIGQUIT);
+			sigaddset(&unblock_signals, SIGCHLD);
+			sigaddset(&unblock_signals, SIGUSR1);
+			sigaddset(&unblock_signals, SIGUSR2);
+			sigaddset(&unblock_signals, SIGINT);
+			sigaddset(&unblock_signals, SIGTERM);
+			sigaddset(&unblock_signals, SIGCONT);
+			sigaddset(&unblock_signals, SIGSTOP);
+			sigaddset(&unblock_signals, SIGTSTP);
+			sigprocmask(SIG_UNBLOCK, &unblock_signals, NULL);
+
+			/* Close whatever files are open. */
+			close(0);
+			close(1);
+			close(2);
+
+			/* Open the new terminal device */
+			open_new_terminal(a->terminal, 0);
+
+			/* Make sure the terminal will act fairly normal for us */
+			set_term();
+			/* Setup stdout, stderr on the supplied terminal */
+			dup(0);
+			dup(0);
+
+			messageD(CONSOLE | LOG, "Trying to re-exec %s", a->command);
+			execl(a->command, a->command, NULL);
+
+			message(CONSOLE | LOG, "exec of '%s' failed: %m",
+					a->command);
+			sync();
+			sleep(2);
+			init_reboot(RB_HALT_SYSTEM);
+			loop_forever();
+		}
+	}
+}
+
+static void shutdown_signal(int sig)
+{
+	char *m;
+	int rb;
+
+	shutdown_system();
+
+	if (sig == SIGTERM) {
+		m = "reboot";
+		rb = RB_AUTOBOOT;
+	} else if (sig == SIGUSR2) {
+		m = "poweroff";
+		rb = RB_POWER_OFF;
+	} else {
+		m = "halt";
+		rb = RB_HALT_SYSTEM;
+	}
+	message(CONSOLE | LOG, "Requesting system %s.", m);
+	sync();
+
+	/* allow time for last message to reach serial console */
+	sleep(2);
+
+	init_reboot(rb);
+
+	loop_forever();
+}
+
+static void ctrlaltdel_signal(int sig ATTRIBUTE_UNUSED)
+{
+	run_actions(CTRLALTDEL);
+}
+
+/* The SIGSTOP & SIGTSTP handler */
+static void stop_handler(int sig ATTRIBUTE_UNUSED)
+{
+	int saved_errno = errno;
+
+	got_cont = 0;
+	while (!got_cont)
+		pause();
+	got_cont = 0;
+	errno = saved_errno;
+}
+
+/* The SIGCONT handler */
+static void cont_handler(int sig ATTRIBUTE_UNUSED)
+{
+	got_cont = 1;
+}
+
+#endif							/* ! ENABLE_DEBUG_INIT */
+
+static void new_init_action(int action, const char *command, const char *cons)
+{
+	struct init_action *new_action, *a, *last;
+
+	if (*cons == '\0')
+		cons = console;
+
+	if (strcmp(cons, bb_dev_null) == 0 && (action & ASKFIRST))
+		return;
+
+	new_action = calloc((size_t) (1), sizeof(struct init_action));
+	if (!new_action) {
+		message(LOG | CONSOLE, "Memory allocation failure");
+		loop_forever();
+	}
+
+	/* Append to the end of the list */
+	for (a = last = init_action_list; a; a = a->next) {
+		/* don't enter action if it's already in the list,
+		 * but do overwrite existing actions */
+		if ((strcmp(a->command, command) == 0) &&
+		    (strcmp(a->terminal, cons) ==0)) {
+			a->action = action;
+			free(new_action);
+			return;
+		}
+		last = a;
+	}
+	if (last) {
+		last->next = new_action;
+	} else {
+		init_action_list = new_action;
+	}
+	strcpy(new_action->command, command);
+	new_action->action = action;
+	strcpy(new_action->terminal, cons);
+#if 0   /* calloc zeroed always */
+	new_action->pid = 0;
+#endif
+	messageD(LOG|CONSOLE, "command='%s' action='%d' terminal='%s'\n",
+		new_action->command, new_action->action, new_action->terminal);
+}
+
+static void delete_init_action(struct init_action *action)
+{
+	struct init_action *a, *b = NULL;
+
+	for (a = init_action_list; a; b = a, a = a->next) {
+		if (a == action) {
+			if (b == NULL) {
+				init_action_list = a->next;
+			} else {
+				b->next = a->next;
+			}
+			free(a);
+			break;
+		}
+	}
+}
+
+/* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
+ * then parse_inittab() simply adds in some default
+ * actions(i.e., runs INIT_SCRIPT and then starts a pair
+ * of "askfirst" shells).  If CONFIG_FEATURE_USE_INITTAB
+ * _is_ defined, but /etc/inittab is missing, this
+ * results in the same set of default behaviors.
+ */
+static void parse_inittab(void)
+{
+#ifdef CONFIG_FEATURE_USE_INITTAB
+	FILE *file;
+	char buf[INIT_BUFFS_SIZE], lineAsRead[INIT_BUFFS_SIZE];
+	char tmpConsole[CONSOLE_BUFF_SIZE];
+	char *id, *runlev, *action, *command, *eol;
+	const struct init_action_type *a = actions;
+
+
+	file = fopen(INITTAB, "r");
+	if (file == NULL) {
+		/* No inittab file -- set up some default behavior */
+#endif
+		/* Reboot on Ctrl-Alt-Del */
+		new_init_action(CTRLALTDEL, "/sbin/reboot", "");
+		/* Umount all filesystems on halt/reboot */
+		new_init_action(SHUTDOWN, "/bin/umount -a -r", "");
+		/* Swapoff on halt/reboot */
+		if(ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "/sbin/swapoff -a", "");
+		/* Prepare to restart init when a HUP is received */
+		new_init_action(RESTART, "/sbin/init", "");
+		/* Askfirst shell on tty1-4 */
+		new_init_action(ASKFIRST, bb_default_login_shell, "");
+		new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
+		new_init_action(ASKFIRST, bb_default_login_shell, VC_3);
+		new_init_action(ASKFIRST, bb_default_login_shell, VC_4);
+		/* sysinit */
+		new_init_action(SYSINIT, INIT_SCRIPT, "");
+
+		return;
+#ifdef CONFIG_FEATURE_USE_INITTAB
+	}
+
+	while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) {
+		/* Skip leading spaces */
+		for (id = buf; *id == ' ' || *id == '\t'; id++);
+
+		/* Skip the line if it's a comment */
+		if (*id == '#' || *id == '\n')
+			continue;
+
+		/* Trim the trailing \n */
+		eol = strrchr(id, '\n');
+		if (eol != NULL)
+			*eol = '\0';
+
+		/* Keep a copy around for posterity's sake (and error msgs) */
+		strcpy(lineAsRead, buf);
+
+		/* Separate the ID field from the runlevels */
+		runlev = strchr(id, ':');
+		if (runlev == NULL || *(runlev + 1) == '\0') {
+			message(LOG | CONSOLE, "Bad inittab entry: %s", lineAsRead);
+			continue;
+		} else {
+			*runlev = '\0';
+			++runlev;
+		}
+
+		/* Separate the runlevels from the action */
+		action = strchr(runlev, ':');
+		if (action == NULL || *(action + 1) == '\0') {
+			message(LOG | CONSOLE, "Bad inittab entry: %s", lineAsRead);
+			continue;
+		} else {
+			*action = '\0';
+			++action;
+		}
+
+		/* Separate the action from the command */
+		command = strchr(action, ':');
+		if (command == NULL || *(command + 1) == '\0') {
+			message(LOG | CONSOLE, "Bad inittab entry: %s", lineAsRead);
+			continue;
+		} else {
+			*command = '\0';
+			++command;
+		}
+
+		/* Ok, now process it */
+		for (a = actions; a->name != 0; a++) {
+			if (strcmp(a->name, action) == 0) {
+				if (*id != '\0') {
+					if(strncmp(id, "/dev/", 5) == 0)
+						id += 5;
+					strcpy(tmpConsole, "/dev/");
+					safe_strncpy(tmpConsole + 5, id,
+						CONSOLE_BUFF_SIZE - 5);
+					id = tmpConsole;
+				}
+				new_init_action(a->action, command, id);
+				break;
+			}
+		}
+		if (a->name == 0) {
+			/* Choke on an unknown action */
+			message(LOG | CONSOLE, "Bad inittab entry: %s", lineAsRead);
+		}
+	}
+	fclose(file);
+	return;
+#endif							/* CONFIG_FEATURE_USE_INITTAB */
+}
+
+#ifdef CONFIG_FEATURE_USE_INITTAB
+static void reload_signal(int sig ATTRIBUTE_UNUSED)
+{
+	struct init_action *a, *tmp;
+
+	message(LOG, "Reloading /etc/inittab");
+
+	/* disable old entrys */
+	for (a = init_action_list; a; a = a->next ) {
+		a->action = ONCE;
+	}
+
+	parse_inittab();
+
+	/* remove unused entrys */
+	for (a = init_action_list; a; a = tmp) {
+		tmp = a->next;
+		if (a->action & (ONCE | SYSINIT | WAIT ) &&
+				a->pid == 0 ) {
+			delete_init_action(a);
+		}
+	}
+	run_actions(RESPAWN);
+	return;
+}
+#endif							/* CONFIG_FEATURE_USE_INITTAB */
+
+int init_main(int argc, char **argv)
+{
+	struct init_action *a;
+	pid_t wpid;
+
+	if (argc > 1 && !strcmp(argv[1], "-q")) {
+		return kill(1,SIGHUP);
+	}
+#if !ENABLE_DEBUG_INIT
+	/* Expect to be invoked as init with PID=1 or be invoked as linuxrc */
+	if (getpid() != 1 &&
+		(!ENABLE_FEATURE_INITRD || !strstr(bb_applet_name, "linuxrc")))
+	{
+		bb_show_usage();
+	}
+	/* Set up sig handlers  -- be sure to
+	 * clear all of these in run() */
+	signal(SIGHUP, exec_signal);
+	signal(SIGQUIT, exec_signal);
+	signal(SIGUSR1, shutdown_signal);
+	signal(SIGUSR2, shutdown_signal);
+	signal(SIGINT, ctrlaltdel_signal);
+	signal(SIGTERM, shutdown_signal);
+	signal(SIGCONT, cont_handler);
+	signal(SIGSTOP, stop_handler);
+	signal(SIGTSTP, stop_handler);
+
+	/* Turn off rebooting via CTL-ALT-DEL -- we get a
+	 * SIGINT on CAD so we can shut things down gracefully... */
+	init_reboot(RB_DISABLE_CAD);
+#endif
+
+	/* Figure out where the default console should be */
+	console_init();
+
+	/* Close whatever files are open, and reset the console. */
+	close(0);
+	close(1);
+	close(2);
+
+	if (device_open(console, O_RDWR | O_NOCTTY) == 0) {
+		set_term();
+		close(0);
+	}
+
+	chdir("/");
+	setsid();
+	{
+		const char * const *e;
+		/* Make sure environs is set to something sane */
+		for(e = environment; *e; e++)
+			putenv((char *) *e);
+	}
+	/* Hello world */
+	message(MAYBE_CONSOLE | LOG, "init started:  %s", bb_msg_full_version);
+
+	/* Make sure there is enough memory to do something useful. */
+	if (ENABLE_SWAPONOFF) {
+		struct sysinfo info;
+
+		if (!sysinfo(&info) &&
+			(info.mem_unit ? : 1) * (long long)info.totalram < MEGABYTE)
+		{
+			message(CONSOLE,"Low memory: forcing swapon.");
+			/* swapon -a requires /proc typically */
+			new_init_action(SYSINIT, "/bin/mount -t proc proc /proc", "");
+			/* Try to turn on swap */
+			new_init_action(SYSINIT, "/sbin/swapon -a", "");
+			run_actions(SYSINIT);   /* wait and removing */
+		}
+	}
+
+	/* Check if we are supposed to be in single user mode */
+	if (argc > 1 && (!strcmp(argv[1], "single") ||
+					 !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) {
+		/* Start a shell on console */
+		new_init_action(RESPAWN, bb_default_login_shell, "");
+	} else {
+		/* Not in single user mode -- see what inittab says */
+
+		/* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
+		 * then parse_inittab() simply adds in some default
+		 * actions(i.e., runs INIT_SCRIPT and then starts a pair
+		 * of "askfirst" shells */
+		parse_inittab();
+	}
+
+#ifdef CONFIG_SELINUX
+	if (getenv("SELINUX_INIT") == NULL) {
+		int enforce = 0;
+
+		putenv("SELINUX_INIT=YES");
+		if (selinux_init_load_policy(&enforce) == 0) {
+			execv(argv[0], argv);
+		} else if (enforce > 0) {
+			/* SELinux in enforcing mode but load_policy failed */
+			/* At this point, we probably can't open /dev/console, so log() won't work */
+			message(CONSOLE,"Unable to load SELinux Policy. Machine is in enforcing mode. Halting now.");
+			exit(1);
+		}
+	}
+#endif /* CONFIG_SELINUX */
+
+	/* Make the command line just say "init"  -- thats all, nothing else */
+	fixup_argv(argc, argv, "init");
+
+	/* Now run everything that needs to be run */
+
+	/* First run the sysinit command */
+	run_actions(SYSINIT);
+
+	/* Next run anything that wants to block */
+	run_actions(WAIT);
+
+	/* Next run anything to be run only once */
+	run_actions(ONCE);
+
+#ifdef CONFIG_FEATURE_USE_INITTAB
+	/* Redefine SIGHUP to reread /etc/inittab */
+	signal(SIGHUP, reload_signal);
+#else
+	signal(SIGHUP, SIG_IGN);
+#endif /* CONFIG_FEATURE_USE_INITTAB */
+
+
+	/* Now run the looping stuff for the rest of forever */
+	while (1) {
+		/* run the respawn stuff */
+		run_actions(RESPAWN);
+
+		/* run the askfirst stuff */
+		run_actions(ASKFIRST);
+
+		/* Don't consume all CPU time -- sleep a bit */
+		sleep(1);
+
+		/* Wait for a child process to exit */
+		wpid = wait(NULL);
+		while (wpid > 0) {
+			/* Find out who died and clean up their corpse */
+			for (a = init_action_list; a; a = a->next) {
+				if (a->pid == wpid) {
+					/* Set the pid to 0 so that the process gets
+					 * restarted by run_actions() */
+					a->pid = 0;
+					message(LOG, "Process '%s' (pid %d) exited.  "
+							"Scheduling it for restart.",
+							a->command, wpid);
+				}
+			}
+			/* see if anyone else is waiting to be reaped */
+			wpid = waitpid (-1, NULL, WNOHANG);
+		}
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/init_shared.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/init_shared.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/init_shared.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,68 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Stuff shared between init, reboot, halt, and poweroff
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <sys/reboot.h>
+#include <sys/syslog.h>
+#include "init_shared.h"
+
+const char * const init_sending_format = "Sending SIG%s to all processes.";
+#ifndef CONFIG_INIT
+const char * const bb_shutdown_format = "\r%s\n";
+int bb_shutdown_system(unsigned long magic)
+{
+	int pri = LOG_KERN|LOG_NOTICE|LOG_FACMASK;
+	const char *message;
+
+	/* Don't kill ourself */
+	signal(SIGTERM,SIG_IGN);
+	signal(SIGHUP,SIG_IGN);
+	bb_setpgrp;
+
+	/* Allow Ctrl-Alt-Del to reboot system. */
+#ifndef RB_ENABLE_CAD
+#define RB_ENABLE_CAD	0x89abcdef
+#endif
+	reboot(RB_ENABLE_CAD);
+
+	openlog(bb_applet_name, 0, pri);
+
+	message = "\nThe system is going down NOW !!";
+	syslog(pri, "%s", message);
+	printf(bb_shutdown_format, message);
+
+	sync();
+
+	/* Send signals to every process _except_ pid 1 */
+	message = "TERM";
+	syslog(pri, init_sending_format, message);
+	printf(bb_shutdown_format, message);
+
+	kill(-1, SIGTERM);
+	sleep(1);
+	sync();
+
+	message = "KILL";
+	syslog(pri, init_sending_format, message);
+	printf(bb_shutdown_format, message);
+
+	kill(-1, SIGKILL);
+	sleep(1);
+
+	sync();
+
+	reboot(magic);
+	return 0; /* Shrug */
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/init_shared.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/init_shared.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/init_shared.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,10 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Helper functions shared by init et al.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+extern int kill_init(int sig);
+extern int bb_shutdown_system(unsigned long magic);
+extern const char * const init_sending_format;
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/mesg.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/mesg.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/init/mesg.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,47 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * mesg implementation for busybox
+ *
+ * Copyright (c) 2002 Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+#include <unistd.h>
+#include <stdlib.h>
+
+#ifdef USE_TTY_GROUP
+#define S_IWGRP_OR_S_IWOTH	S_IWGRP
+#else
+#define S_IWGRP_OR_S_IWOTH	(S_IWGRP | S_IWOTH)
+#endif
+
+int mesg_main(int argc, char *argv[])
+{
+	struct stat sb;
+	char *tty;
+	char c = 0;
+
+	if ((--argc == 0)
+		|| ((argc == 1) && (((c = **++argv) == 'y') || (c == 'n')))) {
+		if ((tty = ttyname(STDERR_FILENO)) == NULL) {
+			tty = "ttyname";
+		} else if (stat(tty, &sb) == 0) {
+			if (argc == 0) {
+				puts(((sb.st_mode & (S_IWGRP | S_IWOTH)) ==
+					  0) ? "is n" : "is y");
+				return EXIT_SUCCESS;
+			}
+			if (chmod
+				(tty,
+				 (c ==
+				  'y') ? sb.st_mode | (S_IWGRP_OR_S_IWOTH) : sb.
+				 st_mode & ~(S_IWGRP | S_IWOTH)) == 0) {
+				return EXIT_SUCCESS;
+			}
+		}
+		bb_perror_msg_and_die("%s", tty);
+	}
+	bb_show_usage();
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/install_firmware.sh
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/install_firmware.sh	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/install_firmware.sh	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+#!/bin/sh
+echo "Installing to firmware filesystem ..."
+make install PREFIX=../../../../../firmware_files/rootfs/


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/install_firmware.sh
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,22 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Busybox Library Tuning"
+
+config CONFIG_MD5_SIZE_VS_SPEED
+	int " MD5: Trade Bytes for Speed"
+	default 2
+	range 0 3
+	help
+	  Trade binary size versus speed for the md5sum algorithm.
+	  Approximate values running uClibc and hashing
+	  linux-2.4.4.tar.bz2 were:
+	                    user times (sec)  text size (386)
+	  0 (fastest)         1.1                6144
+	  1                   1.4                5392
+	  2                   3.0                5088
+	  3 (smallest)        5.1                4912
+
+endmenu

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,29 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/libbb
+LIBBB_DIR:=./
+
+# Ensure "all" is still the default target when make is run by itself in
+# libbb, even if the files we include define rules for targets.
+
+all:
+
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,147 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef $(LIBBB_DIR)
+LIBBB_DIR:=$(top_builddir)/libbb
+endif
+srcdir=$(top_srcdir)/libbb
+
+LIBBB-n:=
+LIBBB-y:= \
+	bb_asprintf.c ask_confirmation.c change_identity.c chomp.c \
+	compare_string_array.c concat_path_file.c copy_file.c copyfd.c \
+	crc32.c create_icmp_socket.c create_icmp6_socket.c \
+	device_open.c dump.c error_msg.c error_msg_and_die.c \
+	find_pid_by_name.c find_root_device.c fgets_str.c full_read.c \
+	full_write.c get_last_path_component.c get_line_from_file.c \
+	herror_msg.c herror_msg_and_die.c \
+	human_readable.c inet_common.c inode_hash.c isdirectory.c \
+	kernel_version.c last_char_is.c login.c \
+	make_directory.c md5.c mode_string.c mtab_file.c \
+	obscure.c parse_mode.c parse_number.c perror_msg.c \
+	perror_msg_and_die.c print_file.c get_console.c \
+	process_escape_sequence.c procps.c qmodule.c \
+	read_package_field.c recursive_action.c remove_file.c \
+	restricted_shell.c run_parts.c run_shell.c safe_read.c safe_write.c \
+	safe_strncpy.c setup_environment.c sha1.c simplify_path.c \
+	trim.c u_signal_names.c vdprintf.c verror_msg.c \
+	vherror_msg.c vperror_msg.c wfopen.c xconnect.c xgetcwd.c xstat.c \
+	xgethostbyname.c xgethostbyname2.c xreadlink.c xregcomp.c xgetlarg.c \
+	bb_xsocket.c bb_xdaemon.c bb_xbind.c bb_xlisten.c bb_xchdir.c \
+	get_terminal_width_height.c fclose_nonstdin.c fflush_stdout_and_exit.c \
+	getopt_ulflags.c default_error_retval.c wfopen_input.c speed_table.c \
+	perror_nomsg_and_die.c perror_nomsg.c skip_whitespace.c bb_askpass.c \
+	warn_ignoring_args.c concat_subpath_file.c vfork_daemon_rexec.c \
+	bb_do_delay.c daemon.c
+
+# conditionally compiled objects:
+LIBBB-$(CONFIG_FEATURE_SHADOWPASSWDS)+=pwd2spwd.c
+LIBBB-$(CONFIG_FEATURE_MOUNT_LOOP)+= loop.c
+LIBBB-$(CONFIG_LOSETUP)+= loop.c
+LIBBB-$(CONFIG_FEATURE_MTAB_SUPPORT)+= mtab.c
+LIBBB-$(CONFIG_PASSWD)+= pw_encrypt.c
+LIBBB-$(CONFIG_SULOGIN)+= pw_encrypt.c
+LIBBB-$(CONFIG_FEATURE_HTTPD_AUTH_MD5)+= pw_encrypt.c
+LIBBB-$(CONFIG_VLOCK)+= correct_password.c
+LIBBB-$(CONFIG_SU)+= correct_password.c
+LIBBB-$(CONFIG_LOGIN)+= correct_password.c
+LIBBB-$(CONFIG_DF)+= find_mount_point.c
+LIBBB-$(CONFIG_EJECT)+= find_mount_point.c
+
+LIBBB-y:=$(patsubst %,$(srcdir)/%,$(LIBBB-y))
+
+get-file-subparts = $(addsuffix .o,$(shell sed -n -e "s/^\#ifdef L_//p" ${1}))
+
+# 1:N objects
+LIBBB_MSRC0:=$(srcdir)/messages.c
+LIBBB_MOBJ0:=$(call get-file-subparts, ${LIBBB_MSRC0})
+LIBBB_MOBJ0:=$(patsubst %,$(LIBBB_DIR)/%, $(LIBBB_MOBJ0))
+$(LIBBB_MOBJ0):$(LIBBB_MSRC0)
+	$(compile.c) -DL_$(notdir $*)
+
+LIBBB_MSRC1:=$(srcdir)/xfuncs.c
+LIBBB_MOBJ1:=$(call get-file-subparts, ${LIBBB_MSRC1})
+LIBBB_MOBJ1:=$(patsubst %,$(LIBBB_DIR)/%, $(LIBBB_MOBJ1))
+$(LIBBB_MOBJ1):$(LIBBB_MSRC1)
+	$(compile.c) -DL_$(notdir $*)
+
+LIBBB_MSRC2:=$(srcdir)/printf.c
+LIBBB_MOBJ2:=$(call get-file-subparts, ${LIBBB_MSRC2})
+LIBBB_MOBJ2:=$(patsubst %,$(LIBBB_DIR)/%, $(LIBBB_MOBJ2))
+$(LIBBB_MOBJ2):$(LIBBB_MSRC2)
+	$(compile.c) -DL_$(notdir $*)
+
+LIBBB_MSRC3:=$(srcdir)/xgetularg.c
+LIBBB_MOBJ3:=$(call get-file-subparts, ${LIBBB_MSRC3})
+LIBBB_MOBJ3:=$(patsubst %,$(LIBBB_DIR)/%, $(LIBBB_MOBJ3))
+$(LIBBB_MOBJ3):$(LIBBB_MSRC3)
+	$(compile.c) -DL_$(notdir $*)
+
+LIBBB_MSRC4:=$(srcdir)/safe_strtol.c
+LIBBB_MOBJ4:=$(call get-file-subparts, ${LIBBB_MSRC4})
+LIBBB_MOBJ4:=$(patsubst %,$(LIBBB_DIR)/%, $(LIBBB_MOBJ4))
+$(LIBBB_MOBJ4):$(LIBBB_MSRC4)
+	$(compile.c) -DL_$(notdir $*)
+
+LIBBB_MSRC5:=$(srcdir)/bb_pwd.c
+LIBBB_MOBJ5:=$(call get-file-subparts, ${LIBBB_MSRC5})
+LIBBB_MOBJ5:=$(patsubst %,$(LIBBB_DIR)/%, $(LIBBB_MOBJ5))
+$(LIBBB_MOBJ5):$(LIBBB_MSRC5)
+	$(compile.c) -DL_$(notdir $*)
+
+LIBBB_MSRC6:=$(srcdir)/llist.c
+LIBBB_MOBJ6:=$(call get-file-subparts, ${LIBBB_MSRC6})
+LIBBB_MOBJ6:=$(patsubst %,$(LIBBB_DIR)/%, $(LIBBB_MOBJ6))
+$(LIBBB_MOBJ6):$(LIBBB_MSRC6)
+	$(compile.c) -DL_$(notdir $*)
+
+LIBBB_MSRC7:=$(srcdir)/opendir.c
+LIBBB_MOBJ7:=$(call get-file-subparts, ${LIBBB_MSRC7})
+LIBBB_MOBJ7:=$(patsubst %,$(LIBBB_DIR)/%, $(LIBBB_MOBJ7))
+$(LIBBB_MOBJ7):$(LIBBB_MSRC7)
+	$(compile.c) -DL_$(notdir $*)
+
+# We need the names of the object files built from MSRC for the L_ defines
+LIBBB_ALL_MOBJ:=$(LIBBB_MOBJ0) $(LIBBB_MOBJ1) $(LIBBB_MOBJ2) $(LIBBB_MOBJ3) \
+	$(LIBBB_MOBJ4) $(LIBBB_MOBJ5) $(LIBBB_MOBJ6) $(LIBBB_MOBJ7)
+
+LIBBB_ALL_MSRC:=$(LIBBB_MSRC0) $(LIBBB_MSRC1) $(LIBBB_MSRC2) $(LIBBB_MSRC3) \
+	$(LIBBB_MSRC4) $(LIBBB_MSRC5) $(LIBBB_MSRC6) $(LIBBB_MSRC7)
+
+LIBBB-y:=$(sort $(LIBBB-y) $(LIBBB_ALL_MSRC))
+
+LIBBB_AR:=$(LIBBB_DIR)/libbb.a
+libraries-y+=$(LIBBB_AR)
+
+needcrypt-y:=
+ifneq ($(filter $(srcdir)/pw_encrypt.c,$(LIBBB-y)),)
+needcrypt-y:=y
+else
+ifneq ($(filter $(srcdir)/correct_password.c,$(LIBBB-y)),)
+needcrypt-y:=y
+endif
+endif
+
+ifeq ($(needcrypt-y),y)
+  LIBRARIES := -lcrypt $(filter-out -lcrypt,$(LIBRARIES))
+endif
+
+# all 1:1 objects
+LIBBB_OBJS:=$(patsubst $(srcdir)/%.c,$(LIBBB_DIR)/%.o, $(LIBBB-y))
+$(LIBBB_DIR)/%.o: $(srcdir)/%.c
+	$(compile.c)
+
+LIBBB_SRC-a:=$(wildcard $(srcdir)/*.c)
+LIBRARY_SRC-y+=$(LIBBB-y)
+LIBRARY_SRC-a+=$(LIBBB_SRC-a)
+
+# all defines needed for 1:N objects
+LIBBB_DEFINE-y:=$(patsubst %,-DL_%,$(subst .o,,$(notdir $(LIBBB_ALL_MOBJ))))
+LIBRARY_DEFINE-y+=$(LIBBB_DEFINE-y)
+LIBRARY_DEFINE-a+=$(LIBBB_DEFINE-y)
+
+$(LIBBB_AR): $(LIBBB_OBJS) $(LIBBB_ALL_MOBJ)
+	$(do_ar)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/README
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/README	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/README	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,11 @@
+Please see the LICENSE file for copyright information (GPLv2)
+
+libbb is BusyBox's utility library.  All of this stuff used to be stuffed into
+a single file named utility.c.  When I split utility.c to create libbb, some of
+the very oldest stuff ended up without their original copyright and licensing
+information (which is now lost in the mists of time).  If you see something
+that you wrote that is mis-attributed, do let me know so we can fix that up.
+
+	Erik Andersen
+	<andersen at codepoet.org>
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/ask_confirmation.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/ask_confirmation.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/ask_confirmation.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,49 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bb_ask_confirmation implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* Read a line from stdin.  If the first non-whitespace char is 'y' or 'Y',
+ * return 1.  Otherwise return 0.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "libbb.h"
+
+int bb_ask_confirmation(void)
+{
+	int retval = 0;
+	int first = 1;
+	int c;
+
+	while (((c = getchar()) != EOF) && (c != '\n')) {
+		/* Make sure we get the actual function call for isspace,
+		 * as speed is not critical here. */
+		if (first && !(isspace)(c)) {
+			--first;
+			if ((c == 'y') || (c == 'Y')) {
+				++retval;
+			}
+		}
+	}
+
+	return retval;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_askpass.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_askpass.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_askpass.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,78 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Ask for a password
+ * I use a static buffer in this function.  Plan accordingly.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include "libbb.h"
+#define PWD_BUFFER_SIZE 256
+
+
+/* do nothing signal handler */
+static void askpass_timeout(int ATTRIBUTE_UNUSED ignore)
+{
+}
+
+char *bb_askpass(int timeout, const char * prompt)
+{
+	char *ret;
+	int i, size;
+	struct sigaction sa;
+	struct termios old, new;
+	static char passwd[PWD_BUFFER_SIZE];
+
+	tcgetattr(STDIN_FILENO, &old);
+	tcflush(STDIN_FILENO, TCIFLUSH);
+
+	size = sizeof(passwd);
+	ret = passwd;
+	memset(passwd, 0, size);
+
+	fputs(prompt, stdout);
+	fflush(stdout);
+
+	tcgetattr(STDIN_FILENO, &new);
+	new.c_iflag &= ~(IUCLC|IXON|IXOFF|IXANY);
+	new.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|TOSTOP);
+	tcsetattr(STDIN_FILENO, TCSANOW, &new);
+
+	if (timeout) {
+		sa.sa_flags = 0;
+		sa.sa_handler = askpass_timeout;
+		sigaction(SIGALRM, &sa, NULL);
+		alarm(timeout);
+	}
+
+	if (read(STDIN_FILENO, passwd, size-1) <= 0) {
+		ret = NULL;
+	} else {
+		for(i = 0; i < size && passwd[i]; i++) {
+			if (passwd[i]== '\r' || passwd[i] == '\n') {
+				passwd[i]= 0;
+				break;
+			}
+		}
+	}
+
+	if (timeout) {
+		alarm(0);
+	}
+
+	tcsetattr(STDIN_FILENO, TCSANOW, &old);
+	fputs("\n", stdout);
+	fflush(stdout);
+	return ret;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_asprintf.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_asprintf.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_asprintf.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,34 @@
+/*
+   Copyright (C) 2002,2005 Vladimir Oleynik <dzo at simtreas.ru>
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "libbb.h"
+
+char *bb_xasprintf(const char *format, ...)
+{
+	va_list p;
+	int r;
+	char *string_ptr;
+
+#ifdef HAVE_GNU_EXTENSIONS
+	va_start(p, format);
+	r = vasprintf(&string_ptr, format, p);
+	va_end(p);
+#else
+	va_start(p, format);
+	r = vsnprintf(NULL, 0, format, p);
+	va_end(p);
+	string_ptr = xmalloc(r+1);
+	va_start(p, format);
+	r = vsnprintf(string_ptr, r+1, format, p);
+	va_end(p);
+#endif
+
+	if (r < 0) {
+		bb_perror_msg_and_die("bb_xasprintf");
+	}
+	return string_ptr;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_do_delay.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_do_delay.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_do_delay.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,24 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Busybox utility routines.
+ *
+ * Copyright (C) 2005 by Tito Ragusa <tito-wolit at tiscali.it>
+ *
+ * Licensed under the GPL v2, see the file LICENSE in this tarball.
+ */
+
+#include <time.h>
+#include <unistd.h>
+#include "libbb.h"
+
+void bb_do_delay(int seconds)
+{
+	time_t start, now;
+
+	time(&start);
+	now = start;
+	while (difftime(now, start) < seconds) {
+		sleep(seconds);
+		time(&now);
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_pwd.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_pwd.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_pwd.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,170 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * password utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under the GPL v2, see the file LICENSE in this tarball.
+ */
+
+
+#ifdef L_bb_getgrgid
+  /* Hacked by Tito Ragusa (c) 2004 <farmatito at tiscali.it> to make it more
+  * flexible :
+  *
+  * if bufsize is > 0 char *group cannot be set to NULL.
+  *                   On success groupname is written on static allocated buffer
+  *                   group (and a pointer to it is returned).
+  *                   On failure gid as string is written to static allocated
+  *                   buffer group and NULL is returned.
+  * if bufsize is = 0 char *group can be set to NULL.
+  *                   On success groupname is returned.
+  *                   On failure NULL is returned.
+  * if bufsize is < 0 char *group can be set to NULL.
+  *                   On success groupname is returned.
+  *                   On failure an error message is printed and
+  *                   the program exits.
+  */
+
+#include "libbb.h"
+#include "grp_.h"
+
+/* gets a groupname given a gid */
+char * bb_getgrgid(char *group, long gid, int bufsize)
+{
+	struct group *mygroup = getgrgid(gid);
+
+	return  bb_getug(group, (mygroup) ?
+			mygroup->gr_name : (char *)mygroup, gid, bufsize, 'g');
+}
+#endif /* L_bb_getgrgid */
+
+#ifdef L_bb_xgetgrnam
+#include <stdio.h>
+#include <string.h>
+#include "libbb.h"
+#include "pwd_.h"
+#include "grp_.h"
+
+
+/* returns a gid given a group name */
+long bb_xgetgrnam(const char *name)
+{
+	struct group *mygroup;
+
+	mygroup  = getgrnam(name);
+	if (mygroup==NULL)
+		bb_error_msg_and_die("unknown group name: %s", name);
+
+	return (mygroup->gr_gid);
+}
+#endif /* L_bb_xgetgrnam */
+
+#ifdef L_bb_xgetpwnam
+#include <stdio.h>
+#include <string.h>
+#include "libbb.h"
+#include "pwd_.h"
+#include "grp_.h"
+
+
+/* returns a uid given a username */
+long bb_xgetpwnam(const char *name)
+{
+	struct passwd *myuser;
+
+	myuser  = getpwnam(name);
+	if (myuser==NULL)
+		bb_error_msg_and_die("unknown user name: %s", name);
+
+	return myuser->pw_uid;
+}
+#endif /* L_bb_xgetpwnam */
+
+#ifdef L_bb_getpwuid
+ /* Hacked by Tito Ragusa (c) 2004 <farmatito at tiscali.it> to make it more
+  * flexible :
+  *
+  * if bufsize is > 0 char *name can not be set to NULL.
+  *                   On success username is written on the static allocated
+  *                   buffer name (and a pointer to it is returned).
+  *                   On failure uid as string is written to the static
+  *                   allocated buffer name and NULL is returned.
+  * if bufsize is = 0 char *name can be set to NULL.
+  *                   On success username is returned.
+  *                   On failure NULL is returned.
+  * if bufsize is < 0 char *name can be set to NULL
+  *                   On success username is returned.
+  *                   On failure an error message is printed and
+  *                   the program exits.
+  */
+
+#include "libbb.h"
+#include "pwd_.h"
+
+/* gets a username given a uid */
+char * bb_getpwuid(char *name, long uid, int bufsize)
+{
+	struct passwd *myuser = getpwuid(uid);
+
+	return  bb_getug(name, (myuser) ?
+			myuser->pw_name : (char *)myuser , uid, bufsize, 'u');
+}
+#endif /* L_bb_getpwuid */
+
+#ifdef L_bb_getug
+ /*
+  * if bufsize is > 0 char *buffer can not be set to NULL.
+  *                   If idname is not NULL it is written on the static
+  *                   allocated buffer (and a pointer to it is returned).
+  *                   if idname is NULL, id as string is written to the static
+  *                   allocated buffer and NULL is returned.
+  * if bufsize is = 0 char *buffer can be set to NULL.
+  *                   If idname exists a pointer to it is returned,
+  *                   else NULL is returned.
+  * if bufsize is < 0 char *buffer can be set to NULL.
+  *                   If idname exists a pointer to it is returned,
+  *                   else an error message is printed and the program exits.
+  */
+
+#include <stdio.h>
+#include <assert.h>
+#include "libbb.h"
+
+
+/* internal function for bb_getpwuid and bb_getgrgid */
+char * bb_getug(char *buffer, char *idname, long id, int bufsize, char prefix)
+{
+	if(bufsize > 0 ) {
+		assert(buffer!=NULL);
+		if(idname) {
+			return safe_strncpy(buffer, idname, bufsize);
+		}
+		snprintf(buffer, bufsize, "%ld", id);
+	} else if(bufsize < 0 && !idname) {
+		bb_error_msg_and_die("unknown %cid %ld", prefix, id);
+	}
+	return idname;
+}
+#endif /* L_bb_getug */
+
+
+#ifdef L_get_ug_id
+/* indirect dispatcher for pwd helpers.  */
+#include <stdlib.h>
+#include "libbb.h"
+
+unsigned long get_ug_id(const char *s,
+		long (*__bb_getxxnam)(const char *))
+{
+	unsigned long r;
+	char *p;
+
+	r = strtoul(s, &p, 10);
+	if (*p || (s == p)) {
+		r = __bb_getxxnam(s);
+	}
+
+	return r;
+}
+#endif /* L_get_ug_id */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xbind.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xbind.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xbind.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,18 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bb_xbind.c - a bind() which dies on failure with error message
+ *
+ * Copyright (C) 2006 Denis Vlasenko
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include "libbb.h"
+
+void bb_xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)
+{
+	if (bind(sockfd, my_addr, addrlen))
+		bb_perror_msg_and_die("bind");
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xchdir.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xchdir.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xchdir.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,17 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bb_xchdir.c - a chdir() which dies on failure with error message
+ *
+ * Copyright (C) 2006 Denis Vlasenko
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+#include <unistd.h>
+#include "libbb.h"
+
+void bb_xchdir(const char *path)
+{
+	if (chdir(path))
+		bb_perror_msg_and_die("chdir(%s)", path);
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xdaemon.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xdaemon.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xdaemon.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,19 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bb_xdaemon.c - a daemon() which dies on failure with error message
+ *
+ * Copyright (C) 2006 Denis Vlasenko
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <unistd.h>
+#include "libbb.h"
+
+#ifndef BB_NOMMU
+void bb_xdaemon(int nochdir, int noclose)
+{
+	if (daemon(nochdir, noclose))
+		bb_perror_msg_and_die("daemon");
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xlisten.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xlisten.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xlisten.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,17 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bb_xlisten.c - a listen() which dies on failure with error message
+ *
+ * Copyright (C) 2006 Denis Vlasenko
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <sys/socket.h>
+#include "libbb.h"
+
+void bb_xlisten(int s, int backlog)
+{
+	if (listen(s, backlog))
+		bb_perror_msg_and_die("listen");
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xsocket.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xsocket.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/bb_xsocket.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,18 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bb_xsocket.c - a socket() which dies on failure with error message
+ *
+ * Copyright (C) 2006 Denis Vlasenko
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+#include <sys/socket.h>
+#include "libbb.h"
+
+int bb_xsocket(int domain, int type, int protocol)
+{
+	int r = socket(domain, type, protocol);
+	if (r < 0)
+		bb_perror_msg_and_die("socket");
+	return r;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/change_identity.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/change_identity.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/change_identity.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,62 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright 1989 - 1991, Julianne Frances Haugh <jockgrrl at austin.rr.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <ctype.h>
+
+#include "libbb.h"
+
+
+/* Become the user and group(s) specified by PW.  */
+const char *change_identity_e2str ( const struct passwd *pw )
+{
+	if ( initgroups ( pw-> pw_name, pw-> pw_gid ) == -1 )
+		return "cannot set groups";
+	endgrent ( );
+
+	if ( setgid ( pw-> pw_gid ))
+		return "cannot set group id";
+	if ( setuid ( pw->pw_uid ))
+		return "cannot set user id";
+	return NULL;
+}
+
+void change_identity ( const struct passwd *pw )
+{
+	const char *err_msg = change_identity_e2str(pw);
+
+	if(err_msg)
+		bb_perror_msg_and_die ( "%s", err_msg );
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/chomp.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/chomp.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/chomp.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,22 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) many different people.
+ * If you wrote this, please acknowledge your work.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "libbb.h"
+
+
+void chomp(char *s)
+{
+	char *lc = last_char_is(s, '\n');
+
+	if(lc)
+		*lc = 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/compare_string_array.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/compare_string_array.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/compare_string_array.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,21 @@
+/* vi:set ts=4:*/
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <string.h>
+#include "libbb.h"
+
+/* returns the array number of the string */
+int compare_string_array(const char * const string_array[], const char *key)
+{
+	int i;
+
+	for (i = 0; string_array[i] != 0; i++) {
+		if (strcmp(string_array[i], key) == 0) {
+			return i;
+		}
+	}
+	return -i;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/concat_path_file.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/concat_path_file.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/concat_path_file.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,41 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) many different people.
+ * If you wrote this, please acknowledge your work.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/* concatenate path and file name to new allocation buffer,
+ * not addition '/' if path name already have '/'
+*/
+
+#include <string.h>
+#include "libbb.h"
+
+char *concat_path_file(const char *path, const char *filename)
+{
+	char *lc;
+
+	if (!path)
+		path = "";
+	lc = last_char_is(path, '/');
+	while (*filename == '/')
+		filename++;
+	return bb_xasprintf("%s%s%s", path, (lc==NULL ? "/" : ""), filename);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/concat_subpath_file.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/concat_subpath_file.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/concat_subpath_file.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,36 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) (C) 2003  Vladimir Oleynik  <dzo at simtreas.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+   This function make special for recursive actions with usage
+   concat_path_file(path, filename)
+   and skiping "." and ".." directory entries
+*/
+
+#include "libbb.h"
+
+char *concat_subpath_file(const char *path, const char *f)
+{
+	if(f && *f == '.' && (!f[1] || (f[1] == '.' && !f[2])))
+		return NULL;
+	return concat_path_file(path, f);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/conftest.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/conftest.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/conftest.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+int i;

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/copy_file.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/copy_file.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/copy_file.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,242 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini copy_file implementation for busybox
+ *
+ * Copyright (C) 2001 by Matt Kraai <kraai at alumni.carnegiemellon.edu>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ */
+
+#include "libbb.h"
+#include <utime.h>
+#include <errno.h>
+
+int copy_file(const char *source, const char *dest, int flags)
+{
+	struct stat source_stat;
+	struct stat dest_stat;
+	int dest_exists = 0;
+	int status = 0;
+
+	if ((!(flags & FILEUTILS_DEREFERENCE) &&
+			lstat(source, &source_stat) < 0) ||
+			((flags & FILEUTILS_DEREFERENCE) &&
+			 stat(source, &source_stat) < 0)) {
+		bb_perror_msg("%s", source);
+		return -1;
+	}
+
+	if (lstat(dest, &dest_stat) < 0) {
+		if (errno != ENOENT) {
+			bb_perror_msg("unable to stat `%s'", dest);
+			return -1;
+		}
+	} else {
+		if (source_stat.st_dev == dest_stat.st_dev &&
+			source_stat.st_ino == dest_stat.st_ino)
+		{
+			bb_error_msg("`%s' and `%s' are the same file", source, dest);
+			return -1;
+		}
+		dest_exists = 1;
+	}
+
+	if (S_ISDIR(source_stat.st_mode)) {
+		DIR *dp;
+		struct dirent *d;
+		mode_t saved_umask = 0;
+
+		if (!(flags & FILEUTILS_RECUR)) {
+			bb_error_msg("%s: omitting directory", source);
+			return -1;
+		}
+
+		/* Create DEST.  */
+		if (dest_exists) {
+			if (!S_ISDIR(dest_stat.st_mode)) {
+				bb_error_msg("`%s' is not a directory", dest);
+				return -1;
+			}
+		} else {
+			mode_t mode;
+			saved_umask = umask(0);
+
+			mode = source_stat.st_mode;
+			if (!(flags & FILEUTILS_PRESERVE_STATUS))
+				mode = source_stat.st_mode & ~saved_umask;
+			mode |= S_IRWXU;
+
+			if (mkdir(dest, mode) < 0) {
+				umask(saved_umask);
+				bb_perror_msg("cannot create directory `%s'", dest);
+				return -1;
+			}
+
+			umask(saved_umask);
+		}
+
+		/* Recursively copy files in SOURCE.  */
+		if ((dp = bb_opendir(source)) == NULL) {
+			status = -1;
+			goto preserve_status;
+		}
+
+		while ((d = readdir(dp)) != NULL) {
+			char *new_source, *new_dest;
+
+			new_source = concat_subpath_file(source, d->d_name);
+			if(new_source == NULL)
+				continue;
+			new_dest = concat_path_file(dest, d->d_name);
+			if (copy_file(new_source, new_dest, flags) < 0)
+				status = -1;
+			free(new_source);
+			free(new_dest);
+		}
+		/* closedir have only EBADF error, but "dp" not changes */
+		closedir(dp);
+
+		if (!dest_exists &&
+				chmod(dest, source_stat.st_mode & ~saved_umask) < 0) {
+			bb_perror_msg("unable to change permissions of `%s'", dest);
+			status = -1;
+		}
+	} else if (S_ISREG(source_stat.st_mode) ||
+		   (S_ISLNK(source_stat.st_mode) && (flags & FILEUTILS_DEREFERENCE)))
+	{
+		int src_fd;
+		int dst_fd;
+		if (ENABLE_FEATURE_PRESERVE_HARDLINKS) {
+			char *link_name;
+
+			if (!(flags & FILEUTILS_DEREFERENCE) &&
+					is_in_ino_dev_hashtable(&source_stat, &link_name)) {
+				if (link(link_name, dest) < 0) {
+					bb_perror_msg("unable to link `%s'", dest);
+					return -1;
+				}
+
+				return 0;
+			}
+			add_to_ino_dev_hashtable(&source_stat, dest);
+		}
+		src_fd = open(source, O_RDONLY);
+		if (src_fd == -1) {
+			bb_perror_msg("unable to open `%s'", source);
+			return(-1);
+		}
+
+		if (dest_exists) {
+			if (flags & FILEUTILS_INTERACTIVE) {
+				fprintf(stderr, "%s: overwrite `%s'? ", bb_applet_name, dest);
+				if (!bb_ask_confirmation()) {
+					close (src_fd);
+					return 0;
+				}
+			}
+
+			dst_fd = open(dest, O_WRONLY|O_TRUNC);
+			if (dst_fd == -1) {
+				if (!(flags & FILEUTILS_FORCE)) {
+					bb_perror_msg("unable to open `%s'", dest);
+					close(src_fd);
+					return -1;
+				}
+
+				if (unlink(dest) < 0) {
+					bb_perror_msg("unable to remove `%s'", dest);
+					close(src_fd);
+					return -1;
+				}
+
+				goto dest_removed;
+			}
+		} else {
+dest_removed:
+			dst_fd = open(dest, O_WRONLY|O_CREAT, source_stat.st_mode);
+			if (dst_fd == -1) {
+				bb_perror_msg("unable to open `%s'", dest);
+				close(src_fd);
+				return(-1);
+			}
+		}
+
+		if (bb_copyfd_eof(src_fd, dst_fd) == -1)
+			status = -1;
+
+		if (close(dst_fd) < 0) {
+			bb_perror_msg("unable to close `%s'", dest);
+			status = -1;
+		}
+
+		if (close(src_fd) < 0) {
+			bb_perror_msg("unable to close `%s'", source);
+			status = -1;
+		}
+	} else if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode) ||
+	    S_ISSOCK(source_stat.st_mode) || S_ISFIFO(source_stat.st_mode) ||
+	    S_ISLNK(source_stat.st_mode)) {
+
+		if (dest_exists) {
+			if((flags & FILEUTILS_FORCE) == 0) {
+				fprintf(stderr, "`%s' exists\n", dest);
+				return -1;
+			}
+			if(unlink(dest) < 0) {
+				bb_perror_msg("unable to remove `%s'", dest);
+				return -1;
+			}
+		}
+		if (S_ISFIFO(source_stat.st_mode)) {
+			if (mkfifo(dest, source_stat.st_mode) < 0) {
+				bb_perror_msg("cannot create fifo `%s'", dest);
+				return -1;
+			}
+		} else if (S_ISLNK(source_stat.st_mode)) {
+			char *lpath;
+
+			lpath = xreadlink(source);
+			if (symlink(lpath, dest) < 0) {
+				bb_perror_msg("cannot create symlink `%s'", dest);
+				return -1;
+			}
+			free(lpath);
+
+			if (flags & FILEUTILS_PRESERVE_STATUS)
+				if (lchown(dest, source_stat.st_uid, source_stat.st_gid) < 0)
+					bb_perror_msg("unable to preserve ownership of `%s'", dest);
+
+			return 0;
+
+		} else {
+			if (mknod(dest, source_stat.st_mode, source_stat.st_rdev) < 0) {
+				bb_perror_msg("unable to create `%s'", dest);
+				return -1;
+			}
+		}
+	} else {
+		bb_error_msg("internal error: unrecognized file type");
+		return -1;
+	}
+
+preserve_status:
+
+	if (flags & FILEUTILS_PRESERVE_STATUS) {
+		struct utimbuf times;
+		char *msg="unable to preserve %s of `%s'";
+
+		times.actime = source_stat.st_atime;
+		times.modtime = source_stat.st_mtime;
+		if (utime(dest, &times) < 0)
+			bb_perror_msg(msg, "times", dest);
+		if (chown(dest, source_stat.st_uid, source_stat.st_gid) < 0) {
+			source_stat.st_mode &= ~(S_ISUID | S_ISGID);
+			bb_perror_msg(msg, "ownership", dest);
+		}
+		if (chmod(dest, source_stat.st_mode) < 0)
+			bb_perror_msg(msg, "permissions", dest);
+	}
+
+	return status;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/copyfd.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/copyfd.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/copyfd.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,75 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libbb.h"
+
+
+#if BUFSIZ < 4096
+#undef BUFSIZ
+#define BUFSIZ 4096
+#endif
+
+
+static ssize_t bb_full_fd_action(int src_fd, int dst_fd, size_t size)
+{
+	int status = -1;
+	size_t total = 0;
+	RESERVE_CONFIG_BUFFER(buffer,BUFSIZ);
+
+	if (src_fd < 0) goto out;
+	while (!size || total < size)
+	{
+		ssize_t wrote, xread;
+
+		xread = safe_read(src_fd, buffer,
+				(!size || size - total > BUFSIZ) ? BUFSIZ : size - total);
+
+		if (xread > 0) {
+			/* A -1 dst_fd means we need to fake it... */
+			wrote = (dst_fd < 0) ? xread : bb_full_write(dst_fd, buffer, xread);
+			if (wrote < xread) {
+				bb_perror_msg(bb_msg_write_error);
+				break;
+			}
+			total += wrote;
+			if (total == size) status = 0;
+		} else if (xread < 0) {
+			bb_perror_msg(bb_msg_read_error);
+			break;
+		} else if (xread == 0) {
+			/* All done. */
+			status = 0;
+			break;
+		}
+	}
+
+out:
+	RELEASE_CONFIG_BUFFER(buffer);
+
+	return status ? status : (ssize_t)total;
+}
+
+
+int bb_copyfd_size(int fd1, int fd2, const off_t size)
+{
+	if (size) {
+		return(bb_full_fd_action(fd1, fd2, size));
+	}
+	return(0);
+}
+
+int bb_copyfd_eof(int fd1, int fd2)
+{
+	return(bb_full_fd_action(fd1, fd2, 0));
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/correct_password.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/correct_password.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/correct_password.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,77 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright 1989 - 1991, Julianne Frances Haugh <jockgrrl at austin.rr.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <crypt.h>
+
+#include "libbb.h"
+
+
+
+/* Ask the user for a password.
+   Return 1 if the user gives the correct password for entry PW,
+   0 if not.  Return 1 without asking for a password if run by UID 0
+   or if PW has an empty password.  */
+
+int correct_password ( const struct passwd *pw )
+{
+	char *unencrypted, *encrypted, *correct;
+
+#ifdef CONFIG_FEATURE_SHADOWPASSWDS
+	if (( strcmp ( pw-> pw_passwd, "x" ) == 0 ) || ( strcmp ( pw-> pw_passwd, "*" ) == 0 )) {
+		struct spwd *sp = getspnam ( pw-> pw_name );
+
+		if ( !sp )
+			bb_error_msg_and_die ( "\nno valid shadow password" );
+
+		correct = sp-> sp_pwdp;
+	}
+	else
+#endif
+		correct = pw-> pw_passwd;
+
+	if ( correct == 0 || correct[0] == '\0' )
+		return 1;
+
+	unencrypted = bb_askpass ( 0, "Password: " );
+	if ( !unencrypted )
+	{
+		return 0;
+	}
+	encrypted = crypt ( unencrypted, correct );
+	memset ( unencrypted, 0, strlen ( unencrypted ));
+	return ( strcmp ( encrypted, correct ) == 0 ) ? 1 : 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/crc32.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/crc32.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/crc32.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,40 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * CRC32 table fill function
+ * Copyright (C) 2006 by Rob Sullivan <cogito.ergo.cogito at gmail.com>
+ * (I can't really claim much credit however, as the algorithm is
+ * very well-known)
+ *
+ * The following function creates a CRC32 table depending on whether
+ * a big-endian (0x04c11db7) or little-endian (0xedb88320) CRC32 is 
+ * required. Admittedly, there are other CRC32 polynomials floating
+ * around, but Busybox doesn't use them.
+ *
+ * endian = 1: big-endian
+ * endian = 0: little-endian
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "libbb.h"
+
+uint32_t *bb_crc32_filltable (int endian) {
+	
+	uint32_t *crc_table = xmalloc(256 * sizeof(uint32_t));
+	uint32_t polynomial = endian ? 0x04c11db7 : 0xedb88320;
+	uint32_t c;
+	int i, j;
+	
+	for (i = 0; i < 256; i++) {
+		c = endian ? (i << 24) : i;
+		for (j = 8; j; j--) {
+			if (endian)
+				c = (c&0x80000000) ? ((c << 1) ^ polynomial) : (c << 1);
+			else
+				c = (c&1) ? ((c >> 1) ^ polynomial) : (c >> 1);
+		}
+		*crc_table++ = c;
+	}
+
+	return crc_table - 256;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/create_icmp6_socket.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/create_icmp6_socket.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/create_icmp6_socket.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,39 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * create raw socket for icmp (IPv6 version) protocol test permission
+ * and drop root privileges if running setuid
+ *
+ */
+
+#include <sys/types.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <unistd.h>
+#include "libbb.h"
+
+#ifdef CONFIG_FEATURE_IPV6
+int create_icmp6_socket(void)
+{
+	struct protoent *proto;
+	int sock;
+
+	proto = getprotobyname("ipv6-icmp");
+	/* if getprotobyname failed, just silently force
+	 * proto->p_proto to have the correct value for "ipv6-icmp" */
+	if ((sock = socket(AF_INET6, SOCK_RAW,
+			(proto ? proto->p_proto : IPPROTO_ICMPV6))) < 0) {
+		if (errno == EPERM)
+			bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+		else
+			bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket);
+	}
+
+	/* drop root privs if running setuid */
+	setuid(getuid());
+
+	return sock;
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/create_icmp_socket.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/create_icmp_socket.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/create_icmp_socket.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,37 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * create raw socket for icmp protocol test permission
+ * and drop root privileges if running setuid
+ *
+ */
+
+#include <sys/types.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <unistd.h>
+#include "libbb.h"
+
+int create_icmp_socket(void)
+{
+	struct protoent *proto;
+	int sock;
+
+	proto = getprotobyname("icmp");
+	/* if getprotobyname failed, just silently force
+	 * proto->p_proto to have the correct value for "icmp" */
+	if ((sock = socket(AF_INET, SOCK_RAW,
+			(proto ? proto->p_proto : 1))) < 0) {        /* 1 == ICMP */
+		if (errno == EPERM)
+			bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+		else
+			bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket);
+	}
+
+	/* drop root privs if running setuid */
+	setuid(getuid());
+
+	return sock;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/daemon.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/daemon.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/daemon.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,165 @@
+/*
+ * daemon() function for uClinux systems without MMU and fork().
+ *
+ * Copyright (C) 2005-2006 by Jamie Lokier <jamie at shareable.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "busybox.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/file.h>
+#include <signal.h>
+#include <errno.h>
+
+#define _XDAEMON_NOMMU_HACK
+#ifdef _XDAEMON_NOMMU_HACK
+
+#define _PATH_DEVNULL "/dev/null"
+
+static inline int fork_and_exit( void )
+{
+#if defined(__linux__) && (defined(__i386__) || defined(__arm__))
+
+	/* Equivalent to fork-then-exit which allows the parent process
+	   to exit properly even when fork() isn't available.  The trick
+	   is to use clone(), and make the parent exit without
+	   clobbering any memory.  Signals must be blocked to prevent
+	   that clobbering.  Unfortunately each implementation of this
+	   is architecture-specific. */
+
+# ifndef CLONE_VM
+#  define CLONE_VM	0x00000100
+#  define CLONE_FS	0x00000200
+#  define CLONE_FILES	0x00000400
+#  define CLONE_SIGHAND	0x00000800
+# endif
+
+	int result;
+	sigset_t new_set, old_set;
+	sigfillset(&new_set);
+	sigprocmask(SIG_BLOCK, &new_set, &old_set);
+
+	{
+		int flags = (CLONE_VM | CLONE_FS | CLONE_FILES
+			     | CLONE_SIGHAND | SIGCHLD);
+
+# ifdef __i386__
+		__asm__ __volatile__ (
+#  ifdef __PIC__
+			"pushl	%%ebx\n\t"
+			"movl	%1,%%ebx\n\t"
+#  endif /* __PIC__ */
+			"movl	$120,%0\n\t"
+			"int	$0x80\n\t"
+			"testl	%0,%0\n\t"
+			"jle	0f\n\t"
+			"movl	$1,%0\n\t"
+			"int	$0x80\n"
+			"0:"
+#  ifdef __PIC__
+			"\n\tpopl	%%ebx"
+			: "=a" (result) : "ir" (flags), "c" ((int) 0)
+#  else /* not __PIC__ */
+			: "=a" (result) : "b" (flags), "c" ((int) 0)
+#  endif /* not __PIC__ */
+			);
+# endif /* __i386__ */
+# ifdef __arm__
+		register int r0 __asm__("r0"), stack __asm__("r1") = 0;
+		__asm__ __volatile__ (
+#  ifdef __thumb__
+			/* This Thumb version hasn't been tested.
+			   If you do test it, please delete this comment. */
+			"push	{r7}\n\t"
+			"mov	r7, #120\t@ clone\n\t"
+			"swi	0\n\t"
+			"cmp	r0, #0\n\t"
+			"ble	0f\n\t"
+			"mov	r0, #0\n\t"
+			"mov	r7, #1\t\t@ exit\n\t"
+			"swi	0\n"
+			"0:\t"
+			"pop	{r7}"
+#  else  /* Standard ARM, not Thumb. */
+			"swi	0x900000+120\t@ clone\n\t"
+			"cmp	r0, #0\n\t"
+			"ble	0f\n\t"
+			"mov	r0, #0\n\t"
+			"swi	0x900000+1\t@ exit\n"
+			"0:"
+#  endif /* Standard ARM, not Thumb. */
+			: "=r" (r0)
+			: "0" (flags), "r" (stack)
+			: "cc", "lr");
+		result = r0;
+# endif /* __arm__ */
+
+	}
+	sigprocmask(SIG_SETMASK, &old_set, (sigset_t *)0);
+	if (result == 0)
+		return(0);
+	errno = -result;
+	return(-1);
+
+#else /* Can't do the special thing. */
+
+	/* Half-hearted version with vfork().  The parent process won't
+	   be able to exit until the child does, so this keeps extra
+	   processes around, and requires the program to be started in
+	   the background. */
+	switch (vfork()) {
+		case -1:
+			return(-1);
+		case 0:
+			return(0);
+		default:
+			_exit(0);
+	}
+
+#endif /* Can't do the special thing. */
+}
+
+int daemon( int nochdir, int noclose )
+{
+	int fd;
+
+	if (fork_and_exit() == -1)
+		return(-1);
+
+	if (setsid() == -1)
+		return(-1);
+
+	/* Make certain we are not a session leader, or else we
+	 * might reacquire a controlling terminal */
+	if (fork_and_exit() == -1)
+		return(-1);
+
+	if (!nochdir)
+		chdir("/");
+
+	if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+		dup2(fd, STDIN_FILENO);
+		dup2(fd, STDOUT_FILENO);
+		dup2(fd, STDERR_FILENO);
+		if (fd > 2)
+			close(fd);
+	}
+	return(0);
+}
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/default_error_retval.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/default_error_retval.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/default_error_retval.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,32 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* Seems silly to copyright a global variable.  ;-)  Oh well.
+ *
+ * At least one applet (cmp) returns a value different from the typical
+ * EXIT_FAILURE values (1) when an error occurs.  So, make it configurable
+ * by the applet.  I suppose we could use a wrapper function to set it, but
+ * that too seems silly.
+ */
+
+#include <stdlib.h>
+#include "libbb.h"
+
+int bb_default_error_retval = EXIT_FAILURE;

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/device_open.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/device_open.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/device_open.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,32 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include "libbb.h"
+
+
+/* try to open up the specified device */
+int device_open(const char *device, int mode)
+{
+	int m, f, fd = -1;
+
+	m = mode | O_NONBLOCK;
+
+	/* Retry up to 5 times */
+	for (f = 0; f < 5; f++)
+		if ((fd = open(device, m, 0600)) >= 0)
+			break;
+	if (fd < 0)
+		return fd;
+	/* Reset original flags. */
+	if (m != mode)
+		fcntl(fd, F_SETFL, mode);
+	return fd;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/dump.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/dump.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/dump.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,805 @@
+/*
+ * Support code for the hexdump and od applets,
+ * based on code from util-linux v 2.11l
+ *
+ * Copyright (c) 1989
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * Original copyright notice is retained at the end of this file.
+ */
+
+#include "libbb.h"
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>		/* for isdigit() */
+#include "dump.h"
+
+enum _vflag bb_dump_vflag = FIRST;
+FS *bb_dump_fshead;				/* head of format strings */
+static FU *endfu;
+static char **_argv;
+static off_t savaddress;	/* saved address/offset in stream */
+static off_t eaddress;	/* end address */
+static off_t address;	/* address/offset in stream */
+off_t bb_dump_skip;				/* bytes to skip */
+static int exitval;			/* final exit value */
+int bb_dump_blocksize;			/* data block size */
+int bb_dump_length = -1;		/* max bytes to read */
+
+static const char index_str[] = ".#-+ 0123456789";
+
+static const char size_conv_str[] =
+"\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG";
+
+static const char lcc[] = "diouxX";
+
+int bb_dump_size(FS * fs)
+{
+	register FU *fu;
+	register int bcnt, cur_size;
+	register char *fmt;
+	const char *p;
+	int prec;
+
+	/* figure out the data block bb_dump_size needed for each format unit */
+	for (cur_size = 0, fu = fs->nextfu; fu; fu = fu->nextfu) {
+		if (fu->bcnt) {
+			cur_size += fu->bcnt * fu->reps;
+			continue;
+		}
+		for (bcnt = prec = 0, fmt = fu->fmt; *fmt; ++fmt) {
+			if (*fmt != '%')
+				continue;
+			/*
+			 * bb_dump_skip any special chars -- save precision in
+			 * case it's a %s format.
+			 */
+			while (strchr(index_str + 1, *++fmt));
+			if (*fmt == '.' && isdigit(*++fmt)) {
+				prec = atoi(fmt);
+				while (isdigit(*++fmt));
+			}
+			if (!(p = strchr(size_conv_str + 12, *fmt))) {
+				if (*fmt == 's') {
+					bcnt += prec;
+				} else if (*fmt == '_') {
+					++fmt;
+					if ((*fmt == 'c') || (*fmt == 'p') || (*fmt == 'u')) {
+						bcnt += 1;
+					}
+				}
+			} else {
+				bcnt += size_conv_str[p - (size_conv_str + 12)];
+			}
+		}
+		cur_size += bcnt * fu->reps;
+	}
+	return (cur_size);
+}
+
+static void rewrite(FS * fs)
+{
+	enum { NOTOKAY, USEBCNT, USEPREC } sokay;
+	PR *pr, **nextpr = NULL;
+	FU *fu;
+	char *p1, *p2, *p3;
+	char savech, *fmtp;
+	const char *byte_count_str;
+	int nconv, prec = 0;
+
+	for (fu = fs->nextfu; fu; fu = fu->nextfu) {
+		/*
+		 * break each format unit into print units; each
+		 * conversion character gets its own.
+		 */
+		for (nconv = 0, fmtp = fu->fmt; *fmtp; nextpr = &pr->nextpr) {
+			/* NOSTRICT */
+			/* DBU:[dvae at cray.com] calloc so that forward ptrs start out NULL*/
+			pr = xzalloc(sizeof(PR));
+			if (!fu->nextpr)
+				fu->nextpr = pr;
+			/* ignore nextpr -- its unused inside the loop and is
+			 * uninitialized 1st time thru.
+			 */
+
+			/* bb_dump_skip preceding text and up to the next % sign */
+			for (p1 = fmtp; *p1 && *p1 != '%'; ++p1);
+
+			/* only text in the string */
+			if (!*p1) {
+				pr->fmt = fmtp;
+				pr->flags = F_TEXT;
+				break;
+			}
+
+			/*
+			 * get precision for %s -- if have a byte count, don't
+			 * need it.
+			 */
+			if (fu->bcnt) {
+				sokay = USEBCNT;
+				/* bb_dump_skip to conversion character */
+				for (++p1; strchr(index_str, *p1); ++p1);
+			} else {
+				/* bb_dump_skip any special chars, field width */
+				while (strchr(index_str + 1, *++p1));
+				if (*p1 == '.' && isdigit(*++p1)) {
+					sokay = USEPREC;
+					prec = atoi(p1);
+					while (isdigit(*++p1));
+				} else
+					sokay = NOTOKAY;
+			}
+
+			p2 = p1 + 1;	/* set end pointer */
+
+			/*
+			 * figure out the byte count for each conversion;
+			 * rewrite the format as necessary, set up blank-
+			 * pbb_dump_adding for end of data.
+			 */
+
+			if (*p1 == 'c') {
+				pr->flags = F_CHAR;
+			DO_BYTE_COUNT_1:
+				byte_count_str = "\001";
+			DO_BYTE_COUNT:
+				if (fu->bcnt) {
+					do {
+						if (fu->bcnt == *byte_count_str) {
+							break;
+						}
+					} while (*++byte_count_str);
+				}
+				/* Unlike the original, output the remainder of the format string. */
+				if (!*byte_count_str) {
+					bb_error_msg_and_die("bad byte count for conversion character %s.", p1);
+				}
+				pr->bcnt = *byte_count_str;
+			} else if (*p1 == 'l') {
+				++p2;
+				++p1;
+			DO_INT_CONV:
+				{
+					const char *e;
+					if (!(e = strchr(lcc, *p1))) {
+						goto DO_BAD_CONV_CHAR;
+					}
+					pr->flags = F_INT;
+					if (e > lcc + 1) {
+						pr->flags = F_UINT;
+					}
+					byte_count_str = "\004\002\001";
+					goto DO_BYTE_COUNT;
+				}
+				/* NOTREACHED */
+			} else if (strchr(lcc, *p1)) {
+				goto DO_INT_CONV;
+			} else if (strchr("eEfgG", *p1)) {
+				pr->flags = F_DBL;
+				byte_count_str = "\010\004";
+				goto DO_BYTE_COUNT;
+			} else if (*p1 == 's') {
+				pr->flags = F_STR;
+				if (sokay == USEBCNT) {
+					pr->bcnt = fu->bcnt;
+				} else if (sokay == USEPREC) {
+					pr->bcnt = prec;
+				} else {	/* NOTOKAY */
+					bb_error_msg_and_die("%%s requires a precision or a byte count.");
+				}
+			} else if (*p1 == '_') {
+				++p2;
+				switch (p1[1]) {
+				case 'A':
+					endfu = fu;
+					fu->flags |= F_IGNORE;
+					/* FALLTHROUGH */
+				case 'a':
+					pr->flags = F_ADDRESS;
+					++p2;
+					if ((p1[2] != 'd') && (p1[2] != 'o') && (p1[2] != 'x')) {
+						goto DO_BAD_CONV_CHAR;
+					}
+					*p1 = p1[2];
+					break;
+				case 'c':
+					pr->flags = F_C;
+					/* *p1 = 'c';   set in conv_c */
+					goto DO_BYTE_COUNT_1;
+				case 'p':
+					pr->flags = F_P;
+					*p1 = 'c';
+					goto DO_BYTE_COUNT_1;
+				case 'u':
+					pr->flags = F_U;
+					/* *p1 = 'c';   set in conv_u */
+					goto DO_BYTE_COUNT_1;
+				default:
+					goto DO_BAD_CONV_CHAR;
+				}
+			} else {
+			DO_BAD_CONV_CHAR:
+				bb_error_msg_and_die("bad conversion character %%%s.\n", p1);
+			}
+
+			/*
+			 * copy to PR format string, set conversion character
+			 * pointer, update original.
+			 */
+			savech = *p2;
+			p1[1] = '\0';
+			pr->fmt = bb_xstrdup(fmtp);
+			*p2 = savech;
+			pr->cchar = pr->fmt + (p1 - fmtp);
+
+			/* DBU:[dave at cray.com] w/o this, trailing fmt text, space is lost.
+			 * Skip subsequent text and up to the next % sign and tack the
+			 * additional text onto fmt: eg. if fmt is "%x is a HEX number",
+			 * we lose the " is a HEX number" part of fmt.
+			 */
+			for (p3 = p2; *p3 && *p3 != '%'; p3++);
+			if (p3 > p2)
+			{
+				savech = *p3;
+				*p3 = '\0';
+				pr->fmt = xrealloc(pr->fmt, strlen(pr->fmt)+(p3-p2)+1);
+				strcat(pr->fmt, p2);
+				*p3 = savech;
+				p2 = p3;
+			}
+
+			fmtp = p2;
+
+			/* only one conversion character if byte count */
+			if (!(pr->flags & F_ADDRESS) && fu->bcnt && nconv++) {
+				bb_error_msg_and_die("byte count with multiple conversion characters.\n");
+			}
+		}
+		/*
+		 * if format unit byte count not specified, figure it out
+		 * so can adjust rep count later.
+		 */
+		if (!fu->bcnt)
+			for (pr = fu->nextpr; pr; pr = pr->nextpr)
+				fu->bcnt += pr->bcnt;
+	}
+	/*
+	 * if the format string interprets any data at all, and it's
+	 * not the same as the bb_dump_blocksize, and its last format unit
+	 * interprets any data at all, and has no iteration count,
+	 * repeat it as necessary.
+	 *
+	 * if, rep count is greater than 1, no trailing whitespace
+	 * gets output from the last iteration of the format unit.
+	 */
+	for (fu = fs->nextfu;; fu = fu->nextfu) {
+		if (!fu->nextfu && fs->bcnt < bb_dump_blocksize &&
+			!(fu->flags & F_SETREP) && fu->bcnt)
+			fu->reps += (bb_dump_blocksize - fs->bcnt) / fu->bcnt;
+		if (fu->reps > 1) {
+			for (pr = fu->nextpr;; pr = pr->nextpr)
+				if (!pr->nextpr)
+					break;
+			for (p1 = pr->fmt, p2 = NULL; *p1; ++p1)
+				p2 = isspace(*p1) ? p1 : NULL;
+			if (p2)
+				pr->nospace = p2;
+		}
+		if (!fu->nextfu)
+			break;
+	}
+}
+
+static void do_skip(char *fname, int statok)
+{
+	struct stat sbuf;
+
+	if (statok) {
+		if (fstat(STDIN_FILENO, &sbuf)) {
+			bb_perror_msg_and_die("%s", fname);
+		}
+		if ((!(S_ISCHR(sbuf.st_mode) ||
+			   S_ISBLK(sbuf.st_mode) ||
+			   S_ISFIFO(sbuf.st_mode))) && bb_dump_skip >= sbuf.st_size) {
+			/* If bb_dump_size valid and bb_dump_skip >= size */
+			bb_dump_skip -= sbuf.st_size;
+			address += sbuf.st_size;
+			return;
+		}
+	}
+	if (fseek(stdin, bb_dump_skip, SEEK_SET)) {
+		bb_perror_msg_and_die("%s", fname);
+	}
+	savaddress = address += bb_dump_skip;
+	bb_dump_skip = 0;
+}
+
+static int next(char **argv)
+{
+	static int done;
+	int statok;
+
+	if (argv) {
+		_argv = argv;
+		return (1);
+	}
+	for (;;) {
+		if (*_argv) {
+			if (!(freopen(*_argv, "r", stdin))) {
+				bb_perror_msg("%s", *_argv);
+				exitval = 1;
+				++_argv;
+				continue;
+			}
+			statok = done = 1;
+		} else {
+			if (done++)
+				return (0);
+			statok = 0;
+		}
+		if (bb_dump_skip)
+			do_skip(statok ? *_argv : "stdin", statok);
+		if (*_argv)
+			++_argv;
+		if (!bb_dump_skip)
+			return (1);
+	}
+	/* NOTREACHED */
+}
+
+static unsigned char *get(void)
+{
+	static int ateof = 1;
+	static unsigned char *curp=NULL, *savp; /*DBU:[dave at cray.com]initialize curp */
+	register int n;
+	int need, nread;
+	unsigned char *tmpp;
+
+	if (!curp) {
+		address = (off_t)0; /*DBU:[dave at cray.com] initialize,initialize..*/
+		curp = (unsigned char *) xmalloc(bb_dump_blocksize);
+		savp = (unsigned char *) xmalloc(bb_dump_blocksize);
+	} else {
+		tmpp = curp;
+		curp = savp;
+		savp = tmpp;
+		address = savaddress += bb_dump_blocksize;
+	}
+	for (need = bb_dump_blocksize, nread = 0;;) {
+		/*
+		 * if read the right number of bytes, or at EOF for one file,
+		 * and no other files are available, zero-pad the rest of the
+		 * block and set the end flag.
+		 */
+		if (!bb_dump_length || (ateof && !next((char **) NULL))) {
+			if (need == bb_dump_blocksize) {
+				return ((unsigned char *) NULL);
+			}
+			if (bb_dump_vflag != ALL && !memcmp(curp, savp, nread)) {
+				if (bb_dump_vflag != DUP) {
+					printf("*\n");
+				}
+				return ((unsigned char *) NULL);
+			}
+			memset((char *) curp + nread, 0, need);
+			eaddress = address + nread;
+			return (curp);
+		}
+		n = fread((char *) curp + nread, sizeof(unsigned char),
+				  bb_dump_length == -1 ? need : MIN(bb_dump_length, need), stdin);
+		if (!n) {
+			if (ferror(stdin)) {
+				bb_perror_msg("%s", _argv[-1]);
+			}
+			ateof = 1;
+			continue;
+		}
+		ateof = 0;
+		if (bb_dump_length != -1) {
+			bb_dump_length -= n;
+		}
+		if (!(need -= n)) {
+			if (bb_dump_vflag == ALL || bb_dump_vflag == FIRST
+				|| memcmp(curp, savp, bb_dump_blocksize)) {
+				if (bb_dump_vflag == DUP || bb_dump_vflag == FIRST) {
+					bb_dump_vflag = WAIT;
+				}
+				return (curp);
+			}
+			if (bb_dump_vflag == WAIT) {
+				printf("*\n");
+			}
+			bb_dump_vflag = DUP;
+			address = savaddress += bb_dump_blocksize;
+			need = bb_dump_blocksize;
+			nread = 0;
+		} else {
+			nread += n;
+		}
+	}
+}
+
+static void bpad(PR * pr)
+{
+	char *p1, *p2;
+
+	/*
+	 * remove all conversion flags; '-' is the only one valid
+	 * with %s, and it's not useful here.
+	 */
+	pr->flags = F_BPAD;
+	*pr->cchar = 's';
+	for (p1 = pr->fmt; *p1 != '%'; ++p1);
+	for (p2 = ++p1; *p1 && strchr(" -0+#", *p1); ++p1)
+		if (pr->nospace) pr->nospace--;
+	while ((*p2++ = *p1++) != 0);
+}
+
+static const char conv_str[] =
+	"\0\\0\0"
+	"\007\\a\0"				/* \a */
+	"\b\\b\0"
+	"\f\\b\0"
+	"\n\\n\0"
+	"\r\\r\0"
+	"\t\\t\0"
+	"\v\\v\0"
+	"\0";
+
+
+static void conv_c(PR * pr, unsigned char * p)
+{
+	const char *str = conv_str;
+	char buf[10];
+
+	do {
+		if (*p == *str) {
+			++str;
+			goto strpr;
+		}
+		str += 4;
+	} while (*str);
+
+	if (isprint(*p)) {
+		*pr->cchar = 'c';
+		(void) printf(pr->fmt, *p);
+	} else {
+		sprintf(buf, "%03o", (int) *p);
+		str = buf;
+	  strpr:
+		*pr->cchar = 's';
+		printf(pr->fmt, str);
+	}
+}
+
+static void conv_u(PR * pr, unsigned char * p)
+{
+	static const char list[] =
+		"nul\0soh\0stx\0etx\0eot\0enq\0ack\0bel\0"
+		"bs\0_ht\0_lf\0_vt\0_ff\0_cr\0_so\0_si\0_"
+		"dle\0dcl\0dc2\0dc3\0dc4\0nak\0syn\0etb\0"
+		"can\0em\0_sub\0esc\0fs\0_gs\0_rs\0_us";
+
+	/* od used nl, not lf */
+	if (*p <= 0x1f) {
+		*pr->cchar = 's';
+		printf(pr->fmt, list + (4 * (int)*p));
+	} else if (*p == 0x7f) {
+		*pr->cchar = 's';
+		printf(pr->fmt, "del");
+	} else if (isprint(*p)) {
+		*pr->cchar = 'c';
+		printf(pr->fmt, *p);
+	} else {
+		*pr->cchar = 'x';
+		printf(pr->fmt, (int) *p);
+	}
+}
+
+static void display(void)
+{
+/*  extern FU *endfu; */
+	register FS *fs;
+	register FU *fu;
+	register PR *pr;
+	register int cnt;
+	register unsigned char *bp;
+
+	off_t saveaddress;
+	unsigned char savech = 0, *savebp;
+
+	while ((bp = get()) != NULL) {
+		for (fs = bb_dump_fshead, savebp = bp, saveaddress = address; fs;
+			 fs = fs->nextfs, bp = savebp, address = saveaddress) {
+			for (fu = fs->nextfu; fu; fu = fu->nextfu) {
+				if (fu->flags & F_IGNORE) {
+					break;
+				}
+				for (cnt = fu->reps; cnt; --cnt) {
+					for (pr = fu->nextpr; pr; address += pr->bcnt,
+						 bp += pr->bcnt, pr = pr->nextpr) {
+						if (eaddress && address >= eaddress &&
+							!(pr->flags & (F_TEXT | F_BPAD))) {
+							bpad(pr);
+						}
+						if (cnt == 1 && pr->nospace) {
+							savech = *pr->nospace;
+							*pr->nospace = '\0';
+						}
+/*                      PRINT; */
+						switch (pr->flags) {
+						case F_ADDRESS:
+							printf(pr->fmt, (unsigned int) address);
+							break;
+						case F_BPAD:
+							printf(pr->fmt, "");
+							break;
+						case F_C:
+							conv_c(pr, bp);
+							break;
+						case F_CHAR:
+							printf(pr->fmt, *bp);
+							break;
+						case F_DBL:{
+							double dval;
+							float fval;
+
+							switch (pr->bcnt) {
+							case 4:
+								memmove((char *) &fval, (char *) bp,
+									  sizeof(fval));
+								printf(pr->fmt, fval);
+								break;
+							case 8:
+								memmove((char *) &dval, (char *) bp,
+									  sizeof(dval));
+								printf(pr->fmt, dval);
+								break;
+							}
+							break;
+						}
+						case F_INT:{
+							int ival;
+							short sval;
+
+							switch (pr->bcnt) {
+							case 1:
+								printf(pr->fmt, (int) *bp);
+								break;
+							case 2:
+								memmove((char *) &sval, (char *) bp,
+									  sizeof(sval));
+								printf(pr->fmt, (int) sval);
+								break;
+							case 4:
+								memmove((char *) &ival, (char *) bp,
+									  sizeof(ival));
+								printf(pr->fmt, ival);
+								break;
+							}
+							break;
+						}
+						case F_P:
+							printf(pr->fmt, isprint(*bp) ? *bp : '.');
+							break;
+						case F_STR:
+							printf(pr->fmt, (char *) bp);
+							break;
+						case F_TEXT:
+							printf(pr->fmt);
+							break;
+						case F_U:
+							conv_u(pr, bp);
+							break;
+						case F_UINT:{
+							unsigned int ival;
+							unsigned short sval;
+
+							switch (pr->bcnt) {
+							case 1:
+								printf(pr->fmt, (unsigned int) * bp);
+								break;
+							case 2:
+								memmove((char *) &sval, (char *) bp,
+									  sizeof(sval));
+								printf(pr->fmt, (unsigned int) sval);
+								break;
+							case 4:
+								memmove((char *) &ival, (char *) bp,
+									  sizeof(ival));
+								printf(pr->fmt, ival);
+								break;
+							}
+							break;
+						}
+						}
+						if (cnt == 1 && pr->nospace) {
+							*pr->nospace = savech;
+						}
+					}
+				}
+			}
+		}
+	}
+	if (endfu) {
+		/*
+		 * if eaddress not set, error or file bb_dump_size was multiple of
+		 * bb_dump_blocksize, and no partial block ever found.
+		 */
+		if (!eaddress) {
+			if (!address) {
+				return;
+			}
+			eaddress = address;
+		}
+		for (pr = endfu->nextpr; pr; pr = pr->nextpr) {
+			switch (pr->flags) {
+			case F_ADDRESS:
+				(void) printf(pr->fmt, (unsigned int) eaddress);
+				break;
+			case F_TEXT:
+				(void) printf(pr->fmt);
+				break;
+			}
+		}
+	}
+}
+
+int bb_dump_dump(char **argv)
+{
+	register FS *tfs;
+
+	/* figure out the data block bb_dump_size */
+	for (bb_dump_blocksize = 0, tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) {
+		tfs->bcnt = bb_dump_size(tfs);
+		if (bb_dump_blocksize < tfs->bcnt) {
+			bb_dump_blocksize = tfs->bcnt;
+		}
+	}
+	/* rewrite the rules, do syntax checking */
+	for (tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) {
+		rewrite(tfs);
+	}
+
+	next(argv);
+	display();
+
+	return (exitval);
+}
+
+void bb_dump_add(const char *fmt)
+{
+	const char *p;
+	char *p1;
+	char *p2;
+	static FS **nextfs;
+	FS *tfs;
+	FU *tfu, **nextfu;
+	const char *savep;
+
+	/* start new linked list of format units */
+	tfs = xzalloc(sizeof(FS)); /*DBU:[dave at cray.com] start out NULL */
+	if (!bb_dump_fshead) {
+		bb_dump_fshead = tfs;
+	} else {
+		*nextfs = tfs;
+	}
+	nextfs = &tfs->nextfs;
+	nextfu = &tfs->nextfu;
+
+	/* take the format string and break it up into format units */
+	for (p = fmt;;) {
+		/* bb_dump_skip leading white space */
+		p = skip_whitespace(p);
+		if (!*p) {
+			break;
+		}
+
+		/* allocate a new format unit and link it in */
+		/* NOSTRICT */
+		/* DBU:[dave at cray.com] calloc so that forward pointers start out NULL */
+		tfu = xzalloc(sizeof(FU));
+		*nextfu = tfu;
+		nextfu = &tfu->nextfu;
+		tfu->reps = 1;
+
+		/* if leading digit, repetition count */
+		if (isdigit(*p)) {
+			for (savep = p; isdigit(*p); ++p);
+			if (!isspace(*p) && *p != '/') {
+				bb_error_msg_and_die("bad format {%s}", fmt);
+			}
+			/* may overwrite either white space or slash */
+			tfu->reps = atoi(savep);
+			tfu->flags = F_SETREP;
+			/* bb_dump_skip trailing white space */
+			p = skip_whitespace(++p);
+		}
+
+		/* bb_dump_skip slash and trailing white space */
+		if (*p == '/') {
+			p = skip_whitespace(++p);
+		}
+
+		/* byte count */
+		if (isdigit(*p)) {
+			for (savep = p; isdigit(*p); ++p);
+			if (!isspace(*p)) {
+				bb_error_msg_and_die("bad format {%s}", fmt);
+			}
+			tfu->bcnt = atoi(savep);
+			/* bb_dump_skip trailing white space */
+			p = skip_whitespace(++p);
+		}
+
+		/* format */
+		if (*p != '"') {
+			bb_error_msg_and_die("bad format {%s}", fmt);
+		}
+		for (savep = ++p; *p != '"';) {
+			if (*p++ == 0) {
+				bb_error_msg_and_die("bad format {%s}", fmt);
+			}
+		}
+		tfu->fmt = xmalloc(p - savep + 1);
+		strncpy(tfu->fmt, savep, p - savep);
+		tfu->fmt[p - savep] = '\0';
+/*      escape(tfu->fmt); */
+
+		p1 = tfu->fmt;
+
+		/* alphabetic escape sequences have to be done in place */
+		for (p2 = p1;; ++p1, ++p2) {
+			if (!*p1) {
+				*p2 = *p1;
+				break;
+			}
+			if (*p1 == '\\') {
+				const char *cs = conv_str + 4;
+				++p1;
+				*p2 = *p1;
+				do {
+					if (*p1 == cs[2]) {
+						*p2 = cs[0];
+						break;
+					}
+					cs += 4;
+				} while (*cs);
+			}
+		}
+
+		p++;
+	}
+}
+
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/error_msg.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/error_msg.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/error_msg.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,24 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include "libbb.h"
+
+void bb_error_msg(const char *s, ...)
+{
+	va_list p;
+
+	va_start(p, s);
+	bb_verror_msg(s, p);
+	va_end(p);
+	putc('\n', stderr);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/error_msg_and_die.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/error_msg_and_die.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/error_msg_and_die.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,25 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include "libbb.h"
+
+void bb_error_msg_and_die(const char *s, ...)
+{
+	va_list p;
+
+	va_start(p, s);
+	bb_verror_msg(s, p);
+	va_end(p);
+	putc('\n', stderr);
+	exit(bb_default_error_retval);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/fclose_nonstdin.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/fclose_nonstdin.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/fclose_nonstdin.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,37 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * fclose_nonstdin implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* A number of standard utilities can accept multiple command line args
+ * of '-' for stdin, according to SUSv3.  So we encapsulate the check
+ * here to save a little space.
+ */
+
+#include <stdio.h>
+#include <libbb.h>
+
+int bb_fclose_nonstdin(FILE *f)
+{
+	if (f != stdin) {
+		return fclose(f);
+	}
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/fflush_stdout_and_exit.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/fflush_stdout_and_exit.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/fflush_stdout_and_exit.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,37 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * fflush_stdout_and_exit implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* Attempt to fflush(stdout), and exit with an error code if stdout is
+ * in an error state.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <libbb.h>
+
+void bb_fflush_stdout_and_exit(int retval)
+{
+	if (fflush(stdout)) {
+		retval = bb_default_error_retval;
+	}
+	exit(retval);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/fgets_str.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/fgets_str.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/fgets_str.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,67 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) many different people.
+ * If you wrote this, please acknowledge your work.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libbb.h"
+
+/* Read up to (and including) TERMINATING_STRING from FILE and return it.
+ * Return NULL on EOF.  */
+
+char *fgets_str(FILE *file, const char *terminating_string)
+{
+	char *linebuf = NULL;
+	const int term_length = strlen(terminating_string);
+	int end_string_offset;
+	int linebufsz = 0;
+	int idx = 0;
+	int ch;
+
+	while (1) {
+		ch = fgetc(file);
+		if (ch == EOF) {
+			free(linebuf);
+			return NULL;
+		}
+
+		/* grow the line buffer as necessary */
+		while (idx > linebufsz - 2) {
+			linebuf = xrealloc(linebuf, linebufsz += 1000);
+		}
+
+		linebuf[idx] = ch;
+		idx++;
+
+		/* Check for terminating string */
+		end_string_offset = idx - term_length;
+		if ((end_string_offset > 0) && (memcmp(&linebuf[end_string_offset], terminating_string, term_length) == 0)) {
+			idx -= term_length;
+			break;
+		}
+	}
+	linebuf[idx] = '\0';
+	return(linebuf);
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/find_mount_point.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/find_mount_point.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/find_mount_point.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,54 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "libbb.h"
+
+
+#include <mntent.h>
+/*
+ * Given a block device, find the mount table entry if that block device
+ * is mounted.
+ *
+ * Given any other file (or directory), find the mount table entry for its
+ * filesystem.
+ */
+struct mntent *find_mount_point(const char *name, const char *table)
+{
+	struct stat s;
+	dev_t mountDevice;
+	FILE *mountTable;
+	struct mntent *mountEntry;
+
+	if (stat(name, &s) != 0)
+		return 0;
+
+	if ((s.st_mode & S_IFMT) == S_IFBLK)
+		mountDevice = s.st_rdev;
+	else
+		mountDevice = s.st_dev;
+
+
+	if ((mountTable = setmntent(table ? table : bb_path_mtab_file, "r")) == 0)
+		return 0;
+
+	while ((mountEntry = getmntent(mountTable)) != 0) {
+
+			if(strcmp(name, mountEntry->mnt_dir) == 0
+			|| strcmp(name, mountEntry->mnt_fsname) == 0)	/* String match. */
+			break;
+		if (stat(mountEntry->mnt_fsname, &s) == 0 && s.st_rdev == mountDevice)	/* Match the device. */
+			break;
+		if (stat(mountEntry->mnt_dir, &s) == 0 && s.st_dev == mountDevice)	/* Match the directory's mount point. */
+			break;
+	}
+	endmntent(mountTable);
+	return mountEntry;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/find_pid_by_name.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/find_pid_by_name.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/find_pid_by_name.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,59 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under the GPL v2, see the file LICENSE in this tarball.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include "libbb.h"
+
+/* find_pid_by_name()
+ *
+ *  Modified by Vladimir Oleynik for use with libbb/procps.c
+ *  This finds the pid of the specified process.
+ *  Currently, it's implemented by rummaging through
+ *  the proc filesystem.
+ *
+ *  Returns a list of all matching PIDs
+ *  It is the caller's duty to free the returned pidlist.
+ */
+long* find_pid_by_name( const char* pidName)
+{
+	long* pidList;
+	int i=0;
+	procps_status_t * p;
+
+	pidList = xmalloc(sizeof(long));
+	while ((p = procps_scan(0)) != 0)
+	{
+		if (strncmp(p->short_cmd, pidName, COMM_LEN-1) == 0) {
+			pidList=xrealloc( pidList, sizeof(long) * (i+2));
+			pidList[i++]=p->pid;
+		}
+	}
+
+	pidList[i] = i==0 ? -1 : 0;
+	return pidList;
+}
+
+long *pidlist_reverse(long *pidList)
+{
+	int i=0;
+	while (pidList[i] > 0 && ++i);
+	if ( i-- > 0) {
+		long k;
+		int j;
+		for (j = 0; i > j; i--, j++) {
+			k = pidList[i];
+			pidList[i] = pidList[j];
+			pidList[j] = k;
+		}
+	}
+	return pidList;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/find_root_device.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/find_root_device.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/find_root_device.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,50 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include "libbb.h"
+
+char *find_block_device(char *path)
+{
+	DIR *dir;
+	struct dirent *entry;
+	struct stat st;
+	dev_t dev;
+	char *retpath=NULL;
+
+	if(stat(path, &st) || !(dir = opendir("/dev"))) return NULL;
+	dev = (st.st_mode & S_IFMT) == S_IFBLK ? st.st_rdev : st.st_dev;
+	while((entry = readdir(dir)) != NULL) {
+		char devpath[PATH_MAX];
+		sprintf(devpath,"/dev/%s", entry->d_name);
+		if(!stat(devpath, &st) && S_ISBLK(st.st_mode) && st.st_rdev == dev) {
+			retpath = bb_xstrdup(devpath);
+			break;
+		}
+	}
+	closedir(dir);
+
+	return retpath;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/full_read.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/full_read.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/full_read.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,42 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include "libbb.h"
+
+/*
+ * Read all of the supplied buffer from a file.
+ * This does multiple reads as necessary.
+ * Returns the amount read, or -1 on an error.
+ * A short read is returned on an end of file.
+ */
+ssize_t bb_full_read(int fd, void *buf, size_t len)
+{
+	ssize_t cc;
+	ssize_t total;
+
+	total = 0;
+
+	while (len > 0) {
+		cc = safe_read(fd, buf, len);
+
+		if (cc < 0)
+			return cc;	/* read() returns -1 on failure. */
+
+		if (cc == 0)
+			break;
+
+		buf = ((char *)buf) + cc;
+		total += cc;
+		len -= cc;
+	}
+
+	return total;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/full_write.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/full_write.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/full_write.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,38 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include "libbb.h"
+
+/*
+ * Write all of the supplied buffer out to a file.
+ * This does multiple writes as necessary.
+ * Returns the amount written, or -1 on an error.
+ */
+ssize_t bb_full_write(int fd, const void *buf, size_t len)
+{
+	ssize_t cc;
+	ssize_t total;
+
+	total = 0;
+
+	while (len > 0) {
+		cc = safe_write(fd, buf, len);
+
+		if (cc < 0)
+			return cc;		/* write() returns -1 on failure. */
+
+		total += cc;
+		buf = ((const char *)buf) + cc;
+		len -= cc;
+	}
+
+	return total;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/get_console.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/get_console.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/get_console.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,77 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) many different people.  If you wrote this, please
+ * acknowledge your work.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include "libbb.h"
+
+
+
+/* From <linux/kd.h> */
+enum { KDGKBTYPE = 0x4B33 };  /* get keyboard type */
+
+
+static int open_a_console(const char *fnam)
+{
+	int fd;
+
+	/* try read-write */
+	fd = open(fnam, O_RDWR);
+
+	/* if failed, try read-only */
+	if (fd < 0 && errno == EACCES)
+		fd = open(fnam, O_RDONLY);
+
+	/* if failed, try write-only */
+	if (fd < 0 && errno == EACCES)
+		fd = open(fnam, O_WRONLY);
+
+	return fd;
+}
+
+/*
+ * Get an fd for use with kbd/console ioctls.
+ * We try several things because opening /dev/console will fail
+ * if someone else used X (which does a chown on /dev/console).
+ */
+
+int get_console_fd(void)
+{
+	int fd;
+
+	static const char * const choise_console_names[] = {
+		CONSOLE_DEV, CURRENT_VC, CURRENT_TTY
+	};
+
+	for (fd = 2; fd >= 0; fd--) {
+		int fd4name;
+		int choise_fd;
+		char arg;
+
+		fd4name = open_a_console(choise_console_names[fd]);
+	chk_std:
+		choise_fd = fd4name >= 0 ? fd4name : fd;
+
+		arg = 0;
+		if (ioctl(choise_fd, KDGKBTYPE, &arg) == 0)
+			return choise_fd;
+		if(fd4name >= 0) {
+			close(fd4name);
+			fd4name = -1;
+			goto chk_std;
+		}
+	}
+
+	bb_error_msg("Couldn't get a file descriptor referring to the console");
+	return fd;                      /* total failure */
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/get_last_path_component.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/get_last_path_component.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/get_last_path_component.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,32 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bb_get_last_path_component implementation for busybox
+ *
+ * Copyright (C) 2001  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+
+char *bb_get_last_path_component(char *path)
+{
+	char *first = path;
+	char *last;
+
+	last = path - 1;
+
+	while (*path) {
+		if ((*path != '/') && (path > ++last)) {
+			last = first = path;
+		}
+		++path;
+	}
+
+	if (*first == '/') {
+		last = first;
+	}
+	last[1] = 0;
+
+	return first;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/get_line_from_file.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/get_line_from_file.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/get_line_from_file.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,67 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 2005, 2006 Rob Landley <rob at landley.net>
+ * Copyright (C) 2004 Erik Andersen <andersen at codepoet.org>
+ * Copyright (C) 2001 Matt Krai
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "libbb.h"
+
+/* get_line_from_file() - This function reads an entire line from a text file,
+ * up to a newline or NUL byte.  It returns a malloc'ed char * which must be
+ * stored and free'ed  by the caller.  If end is null '\n' isn't considered
+ * and of line.  If end isn't null, length of the chunk read is stored in it. */
+
+char *bb_get_chunk_from_file(FILE * file, int *end)
+{
+	int ch;
+	int idx = 0;
+	char *linebuf = NULL;
+	int linebufsz = 0;
+
+	while ((ch = getc(file)) != EOF) {
+		/* grow the line buffer as necessary */
+		if (idx > linebufsz - 2) {
+			linebuf = xrealloc(linebuf, linebufsz += 80);
+		}
+		linebuf[idx++] = (char) ch;
+		if (!ch || (end && ch == '\n'))
+			break;
+	}
+	if (end)
+		*end = idx;
+	if (linebuf) {
+		if (ferror(file)) {
+			free(linebuf);
+			return NULL;
+		}
+		linebuf[idx] = 0;
+	}
+	return linebuf;
+}
+
+/* Get line, including trailing /n if any */
+char *bb_get_line_from_file(FILE * file)
+{
+	int i;
+
+	return bb_get_chunk_from_file(file, &i);
+}
+
+/* Get line.  Remove trailing /n */
+char *bb_get_chomped_line_from_file(FILE * file)
+{
+	int i;
+	char *c = bb_get_chunk_from_file(file, &i);
+
+	if (i && c[--i] == '\n')
+		c[i] = 0;
+
+	return c;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/get_terminal_width_height.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/get_terminal_width_height.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/get_terminal_width_height.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,31 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Determine the width and height of the terminal.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <unistd.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include "libbb.h"
+
+/* It is perfectly ok to pass in a NULL for either width or for
+ * height, in which case that value will not be set.  */
+int get_terminal_width_height(int fd, int *width, int *height)
+{
+	struct winsize win = { 0, 0, 0, 0 };
+	int ret = ioctl(fd, TIOCGWINSZ, &win);
+	if (win.ws_row <= 1) win.ws_row = 24;
+	if (win.ws_col <= 1) win.ws_col = 80;
+	if (height) *height = (int) win.ws_row;
+	if (width) *width = (int) win.ws_col;
+
+	return ret;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/getopt_ulflags.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/getopt_ulflags.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/getopt_ulflags.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,530 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * universal getopt_ulflags implementation for busybox
+ *
+ * Copyright (C) 2003-2005  Vladimir Oleynik  <dzo at simtreas.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <getopt.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include "libbb.h"
+
+/*                  Documentation
+
+unsigned long
+bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...)
+
+	The command line options must be declared in const char
+	*applet_opts as a string of chars, for example:
+
+	flags = bb_getopt_ulflags(argc, argv, "rnug");
+
+	If one of the given options is found, a flag value is added to
+	the return value (an unsigned long).
+
+	The flag value is determined by the position of the char in
+	applet_opts string.  For example, in the above case:
+
+	flags = bb_getopt_ulflags(argc, argv, "rnug");
+
+	"r" will add 1    (bit 0)
+	"n" will add 2    (bit 1)
+	"u  will add 4    (bit 2)
+	"g" will add 8    (bit 3)
+
+	and so on.  You can also look at the return value as a bit
+	field and each option sets one bit.
+
+ ":"    If one of the options requires an argument, then add a ":"
+	after the char in applet_opts and provide a pointer to store
+	the argument.  For example:
+
+	char *pointer_to_arg_for_a;
+	char *pointer_to_arg_for_b;
+	char *pointer_to_arg_for_c;
+	char *pointer_to_arg_for_d;
+
+	flags = bb_getopt_ulflags(argc, argv, "a:b:c:d:",
+			&pointer_to_arg_for_a, &pointer_to_arg_for_b,
+			&pointer_to_arg_for_c, &pointer_to_arg_for_d);
+
+	The type of the pointer (char* or llist_t*) may be controlled
+	by the "::" special separator that is set in the external string
+	bb_opt_complementally (see below for more info).
+
+ "+"    If the first character in the applet_opts string is a plus,
+	then option processing will stop as soon as a non-option is
+	encountered in the argv array.  Useful for applets like env
+	which should not process arguments to subprograms:
+	env -i ls -d /
+	Here we want env to process just the '-i', not the '-d'.
+
+const struct option *bb_applet_long_options
+
+	This struct allows you to define long options.  The syntax for
+	declaring the array is just like that of getopt's longopts.
+	(see getopt(3))
+
+	static const struct option applet_long_options[] = {
+		{ "verbose", 0, 0, 'v' },
+		{ 0, 0, 0, 0 }
+	};
+	bb_applet_long_options = applet_long_options;
+
+	The last member of struct option (val) typically is set to
+	matching short option from applet_opts. If there is no matching
+	char in applet_opts, then:
+	- return bit have next position after short options
+	- if has_arg is not "no_argument", use ptr for arg also
+	- bb_opt_complementally affects it too
+
+	Note: a good applet will make long options configurable via the
+	config process and not a required feature.  The current standard
+	is to name the config option CONFIG_FEATURE_<applet>_LONG_OPTIONS.
+
+const char *bb_opt_complementally
+	this should be bb_opt_complementary, but we'll just keep it as
+	bb_opt_complementally due to the Russian origins
+
+ ":"    The colon (":") is used to separate groups of two or more chars
+	and/or groups of chars and special characters (stating some
+	conditions to be checked).
+
+ "abc"  If groups of two or more chars are specified, the first char
+	is the main option and the other chars are secondary options.
+	Their flags will be turned on if the main option is found even
+	if they are not specifed on the command line.  For example:
+
+	bb_opt_complementally = "abc";
+
+	flags = bb_getopt_ulflags(argc, argv, "abcd")
+
+	If getopt() finds "-a" on the command line, then
+	bb_getopt_ulflags's return value will be as if "-a -b -c" were
+	found.
+
+ "ww"   Adjacent double options have a counter associated which indicates
+	the number of occurences of the option.
+	For example the ps applet needs:
+	if w is given once, GNU ps sets the width to 132,
+	if w is given more than once, it is "unlimited"
+
+	int w_counter = 0;
+	bb_opt_complementally = "ww";
+	bb_getopt_ulflags(argc, argv, "w", &w_counter);
+
+	if(w_counter)
+		width = (w_counter == 1) ? 132 : INT_MAX;
+	else
+		get_terminal_width(...&width...);
+
+	w_counter is a pointer to an integer. It has to be passed to
+	bb_getopt_ulflags() after all other option argument sinks.
+	For example: accept multiple -v to indicate the level of verbosity
+	and for each -b optarg, add optarg to my_b. Finally, if b is given,
+	turn off c and vice versa:
+
+	llist_t *my_b = NULL;
+	int verbose_level = 0;
+	bb_opt_complementally = "vv:b::b-c:c-b";
+	f = bb_getopt_ulflags(argc, argv, "vb:c", &my_b, &verbose_level);
+	if((f & 2))     // -c after -b unsets -b flag
+		while(my_b) { dosomething_with(my_b->data) ; my_b = my_b->link; }
+	if(my_b)        // but llist is stored if -b is specified
+		free_llist(my_b);
+	if(verbose_level) bb_printf("verbose level is %d\n", verbose_level);
+
+Special characters:
+
+ "-"    A dash between two options causes the second of the two
+	to be unset (and ignored) if it is given on the command line.
+
+	[FIXME: what if they are the same? like "x-x"? Is it ever useful?]
+
+	For example:
+	The du applet has the options "-s" and "-d depth".  If
+	bb_getopt_ulflags finds -s, then -d is unset or if it finds -d
+	then -s is unset.  (Note:  busybox implements the GNU
+	"--max-depth" option as "-d".)  To obtain this behavior, you
+	set bb_opt_complementally = "s-d:d-s".  Only one flag value is
+	added to bb_getopt_ulflags's return value depending on the
+	position of the options on the command line.  If one of the
+	two options requires an argument pointer (":" in applet_opts
+	as in "d:") optarg is set accordingly.
+
+	char *smax_print_depth;
+
+	bb_opt_complementally = "s-d:d-s:x-x";
+	opt = bb_getopt_ulflags(argc, argv, "sd:x", &smax_print_depth);
+
+	if (opt & 2)
+		max_print_depth = atoi(smax_print_depth);
+	if (opt & 4)
+		printf("Detected odd -x usage\n");
+
+ "-"    A dash as the first char in a bb_opt_complementally group forces
+	all arguments to be treated as options, even if they have
+	no leading dashes. Next char in this case can't be a digit (0-9),
+	use ':' or end of line. For example:
+
+	bb_opt_complementally = "-:w-x:x-w";
+	bb_getopt_ulflags(argc, argv, "wx");
+
+	Allows any arguments to be given without a dash (./program w x)
+	as well as with a dash (./program -x).
+
+ "-N"   A dash as the first char in a bb_opt_complementally group followed
+	by a single digit (0-9) means that at least N non-option
+	arguments must be present on the command line
+
+ "V-"   An option with dash before colon or end-of-line results in
+	bb_show_usage being called if this option is encountered.
+	This is typically used to implement "print verbose usage message
+	and exit" option.
+
+ "--"   A double dash between two options, or between an option and a group
+	of options, means that they are mutually exclusive.  Unlike
+	the "-" case above, an error will be forced if the options
+	are used together.
+
+	For example:
+	The cut applet must have only one type of list specified, so
+	-b, -c and -f are mutally exclusive and should raise an error
+	if specified together.  In this case you must set
+	bb_opt_complementally = "b--cf:c--bf:f--bc".  If two of the
+	mutually exclusive options are found, bb_getopt_ulflags's
+	return value will have the error flag set (BB_GETOPT_ERROR) so
+	that we can check for it:
+
+	if (flags & BB_GETOPT_ERROR)
+		bb_show_usage();
+
+ "?"    A "?" as the first char in a bb_opt_complementally group means:
+	if BB_GETOPT_ERROR is detected, don't return, call bb_show_usage
+	and exit instead. Next char after '?' can't be a digit.
+
+ "?N"   A "?" as the first char in a bb_opt_complementally group followed
+	by a single digit (0-9) means that at most N arguments must be present
+	on the command line.
+
+ "::"   A double colon after a char in bb_opt_complementally means that the
+	option can occur multiple times. Each occurrence will be saved as
+	a llist_t element instead of char*.
+
+	For example:
+	The grep applet can have one or more "-e pattern" arguments.
+	In this case you should use bb_getopt_ulflags() as follows:
+
+	llist_t *patterns = NULL;
+
+	(this pointer must be initializated to NULL if the list is empty
+	as required by *llist_add_to(llist_t *old_head, char *new_item).)
+
+	bb_opt_complementally = "e::";
+
+	bb_getopt_ulflags(argc, argv, "e:", &patterns);
+	$ grep -e user -e root /etc/passwd
+	root:x:0:0:root:/root:/bin/bash
+	user:x:500:500::/home/user:/bin/bash
+
+ "--"   A double dash at the beginning of bb_opt_complementally means the
+	argv[1] string should always be treated as options, even if it isn't
+	prefixed with a "-".  This is to support the special syntax in applets
+	such as "ar" and "tar":
+	tar xvf foo.tar
+
+ "?"    An "?" between an option and a group of options means that
+	at least one of them is required to occur if the first option
+	occurs in preceding command line arguments.
+
+	For example from "id" applet:
+
+	// Don't allow -n -r -rn -ug -rug -nug -rnug
+	bb_opt_complementally = "r?ug:n?ug:?u--g:g--u";
+	flags = bb_getopt_ulflags(argc, argv, "rnug");
+
+	This example allowed only:
+	$ id; id -u; id -g; id -ru; id -nu; id -rg; id -ng; id -rnu; id -rng
+
+ "X"    A bb_opt_complementally group with just a single letter means
+	that this this option is required. If more than one such group exists,
+	at least one option is required to occur (not all of them).
+	For example from "start-stop-daemon" applet:
+
+	// Don't allow -KS -SK, but -S or -K is required
+	bb_opt_complementally = "K:S:?K--S:S--K";
+	flags = bb_getopt_ulflags(argc, argv, "KS...);
+
+
+ "x--x" give error if double or more used -x option
+
+ Don't forget to use ':'. For example "?322-22-23X-x-a" is interpreted as
+ "?3:22:-2:2-2:2-3Xa:2--x": max 3 args; count uses of '-2'; min 2 args;
+ if there is a '-2' option then unset '-3', '-X' and '-a'; if there is
+ a '-2' and after it a '-x' then error out.
+
+*/
+
+/* this should be bb_opt_complementary, but we'll just keep it as
+   bb_opt_complementally due to the Russian origins */
+const char *bb_opt_complementally;
+
+typedef struct {
+	int opt;
+	int list_flg;
+	unsigned long switch_on;
+	unsigned long switch_off;
+	unsigned long incongruously;
+	unsigned long requires;
+	void **optarg;               /* char **optarg or llist_t **optarg */
+	int *counter;
+} t_complementally;
+
+/* You can set bb_applet_long_options for parse called long options */
+#if ENABLE_GETOPT_LONG
+static const struct option bb_default_long_options[] = {
+/*      { "help", 0, NULL, '?' }, */
+	{ 0, 0, 0, 0 }
+};
+
+const struct option *bb_applet_long_options = bb_default_long_options;
+#endif
+
+unsigned long
+bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...)
+{
+	unsigned long flags = 0;
+	unsigned long requires = 0;
+	t_complementally complementally[sizeof(flags) * 8 + 1];
+	int c;
+	const unsigned char *s;
+	t_complementally *on_off;
+	va_list p;
+#if ENABLE_GETOPT_LONG
+	const struct option *l_o;
+#endif
+	unsigned long trigger;
+#ifdef CONFIG_PS
+	char **pargv = NULL;
+#endif
+	int min_arg = 0;
+	int max_arg = -1;
+
+#define SHOW_USAGE_IF_ERROR     1
+#define ALL_ARGV_IS_OPTS        2
+#define FIRST_ARGV_IS_OPT       4
+#define FREE_FIRST_ARGV_IS_OPT  8
+	int spec_flgs = 0;
+
+	va_start (p, applet_opts);
+
+	c = 0;
+	on_off = complementally;
+	memset(on_off, 0, sizeof(complementally));
+
+	/* skip GNU extension */
+	s = (const unsigned char *)applet_opts;
+	if(*s == '+' || *s == '-')
+		s++;
+	for (; *s; s++) {
+		if(c >= (int)(sizeof(flags)*8))
+			break;
+		on_off->opt = *s;
+		on_off->switch_on = (1 << c);
+		if (s[1] == ':') {
+			on_off->optarg = va_arg (p, void **);
+			do
+				s++;
+			while (s[1] == ':');
+		}
+		on_off++;
+		c++;
+	}
+
+#if ENABLE_GETOPT_LONG
+	for(l_o = bb_applet_long_options; l_o->name; l_o++) {
+		if(l_o->flag)
+			continue;
+		for(on_off = complementally; on_off->opt != 0; on_off++)
+			if(on_off->opt == l_o->val)
+				break;
+		if(on_off->opt == 0) {
+			if(c >= (int)(sizeof(flags)*8))
+				break;
+			on_off->opt = l_o->val;
+			on_off->switch_on = (1 << c);
+			if(l_o->has_arg != no_argument)
+				on_off->optarg = va_arg (p, void **);
+			c++;
+		}
+	}
+#endif /* ENABLE_GETOPT_LONG */
+	for (s = (const unsigned char *)bb_opt_complementally; s && *s; s++) {
+		t_complementally *pair;
+		unsigned long *pair_switch;
+
+		if (*s == ':')
+			continue;
+		c = s[1];
+		if(*s == '?') {
+			if(c < '0' || c > '9') {
+				spec_flgs |= SHOW_USAGE_IF_ERROR;
+			} else {
+				max_arg = c - '0';
+				s++;
+			}
+			continue;
+		}
+		if(*s == '-') {
+			if(c < '0' || c > '9') {
+				if(c == '-') {
+					spec_flgs |= FIRST_ARGV_IS_OPT;
+					s++;
+				} else
+					spec_flgs |= ALL_ARGV_IS_OPTS;
+			} else {
+				min_arg = c - '0';
+				s++;
+			}
+			continue;
+		}
+		for (on_off = complementally; on_off->opt; on_off++)
+			if (on_off->opt == *s)
+				break;
+		if(c == ':' && s[2] == ':') {
+			on_off->list_flg++;
+			continue;
+		}
+		if(c == ':' || c == '\0') {
+			requires |= on_off->switch_on;
+			continue;
+		}
+		if(c == '-' && (s[2] == ':' || s[2] == '\0')) {
+			flags |= on_off->switch_on;
+			on_off->incongruously |= on_off->switch_on;
+			s++;
+			continue;
+		}
+		if(c == *s) {
+			on_off->counter = va_arg (p, int *);
+			s++;
+		}
+		pair = on_off;
+		pair_switch = &(pair->switch_on);
+		for(s++; *s && *s != ':'; s++) {
+			if(*s == '?') {
+				pair_switch = &(pair->requires);
+			} else if (*s == '-') {
+				if(pair_switch == &(pair->switch_off))
+					pair_switch = &(pair->incongruously);
+				else
+					pair_switch = &(pair->switch_off);
+			} else {
+			    for (on_off = complementally; on_off->opt; on_off++)
+				if (on_off->opt == *s) {
+				    *pair_switch |= on_off->switch_on;
+				    break;
+				}
+			}
+		}
+		s--;
+	}
+	va_end (p);
+
+#if defined(CONFIG_AR) || defined(CONFIG_TAR)
+	if((spec_flgs & FIRST_ARGV_IS_OPT)) {
+		if(argv[1] && argv[1][0] != '-' && argv[1][0] != '\0') {
+			argv[1] = bb_xasprintf("-%s", argv[1]);
+			if(ENABLE_FEATURE_CLEAN_UP)
+				spec_flgs |= FREE_FIRST_ARGV_IS_OPT;
+		}
+	}
+#endif
+#if ENABLE_GETOPT_LONG
+	while ((c = getopt_long (argc, argv, applet_opts,
+				 bb_applet_long_options, NULL)) >= 0) {
+#else
+	while ((c = getopt (argc, argv, applet_opts)) >= 0) {
+#endif /* ENABLE_GETOPT_LONG */
+#ifdef CONFIG_PS
+loop_arg_is_opt:
+#endif
+		for (on_off = complementally; on_off->opt != c; on_off++) {
+			/* c==0 if long opt have non NULL flag */
+			if(on_off->opt == 0 && c != 0)
+				bb_show_usage ();
+		}
+		if(flags & on_off->incongruously) {
+			if((spec_flgs & SHOW_USAGE_IF_ERROR))
+				bb_show_usage ();
+			flags |= BB_GETOPT_ERROR;
+		}
+		trigger = on_off->switch_on & on_off->switch_off;
+		flags &= ~(on_off->switch_off ^ trigger);
+		flags |= on_off->switch_on ^ trigger;
+		flags ^= trigger;
+		if(on_off->counter)
+			(*(on_off->counter))++;
+		if(on_off->list_flg) {
+			llist_add_to((llist_t **)(on_off->optarg), optarg);
+		} else if (on_off->optarg) {
+			*(char **)(on_off->optarg) = optarg;
+		}
+#ifdef CONFIG_PS
+		if(pargv != NULL)
+			break;
+#endif
+	}
+
+#ifdef CONFIG_PS
+	if((spec_flgs & ALL_ARGV_IS_OPTS)) {
+		/* process argv is option, for example "ps" applet */
+		if(pargv == NULL)
+			pargv = argv + optind;
+		while(*pargv) {
+			c = **pargv;
+			if(c == '\0') {
+				pargv++;
+			} else {
+				(*pargv)++;
+				goto loop_arg_is_opt;
+			}
+		}
+	}
+#endif
+
+#if (defined(CONFIG_AR) || defined(CONFIG_TAR)) && \
+				defined(CONFIG_FEATURE_CLEAN_UP)
+	if((spec_flgs & FREE_FIRST_ARGV_IS_OPT))
+		free(argv[1]);
+#endif
+	/* check depending requires for given options */
+	for (on_off = complementally; on_off->opt; on_off++) {
+		if(on_off->requires && (flags & on_off->switch_on) &&
+					(flags & on_off->requires) == 0)
+			bb_show_usage ();
+	}
+	if(requires && (flags & requires) == 0)
+		bb_show_usage ();
+	argc -= optind;
+	if(argc < min_arg || (max_arg >= 0 && argc > max_arg))
+		bb_show_usage ();
+	return flags;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/herror_msg.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/herror_msg.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/herror_msg.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,22 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include "libbb.h"
+
+void bb_herror_msg(const char *s, ...)
+{
+	va_list p;
+
+	va_start(p, s);
+	bb_vherror_msg(s, p);
+	va_end(p);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/herror_msg_and_die.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/herror_msg_and_die.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/herror_msg_and_die.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include "libbb.h"
+
+void bb_herror_msg_and_die(const char *s, ...)
+{
+	va_list p;
+
+	va_start(p, s);
+	bb_vherror_msg(s, p);
+	va_end(p);
+	exit(bb_default_error_retval);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/human_readable.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/human_readable.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/human_readable.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,87 @@
+/*
+ * June 30, 2001                 Manuel Novoa III
+ *
+ * All-integer version (hey, not everyone has floating point) of
+ * make_human_readable_str, modified from similar code I had written
+ * for busybox several months ago.
+ *
+ * Notes:
+ *   1) I'm using an unsigned long long to hold the product size * block_size,
+ *      as df (which calls this routine) could request a representation of a
+ *      partition size in bytes > max of unsigned long.  If long longs aren't
+ *      available, it would be possible to do what's needed using polynomial
+ *      representations (say, powers of 1024) and manipulating coefficients.
+ *      The base ten "bytes" output could be handled similarly.
+ *
+ *   2) This routine always outputs a decimal point and a tenths digit when
+ *      display_unit != 0.  Hence, it isn't uncommon for the returned string
+ *      to have a length of 5 or 6.
+ *
+ *      It might be nice to add a flag to indicate no decimal digits in
+ *      that case.  This could be either an additional parameter, or a
+ *      special value of display_unit.  Such a flag would also be nice for du.
+ *
+ *      Some code to omit the decimal point and tenths digit is sketched out
+ *      and "#if 0"'d below.
+ */
+
+#include <stdio.h>
+#include "libbb.h"
+
+const char *make_human_readable_str(unsigned long long size,
+	unsigned long block_size, unsigned long display_unit)
+{
+	/* The code will adjust for additional (appended) units. */
+	static const char zero_and_units[] = { '0', 0, 'k', 'M', 'G', 'T' };
+	static const char fmt[] = "%llu";
+	static const char fmt_tenths[] = "%llu.%d%c";
+
+	static char str[21];		/* Sufficient for 64 bit unsigned integers. */
+
+	unsigned long long val;
+	int frac;
+	const char *u;
+	const char *f;
+
+	u = zero_and_units;
+	f = fmt;
+	frac = 0;
+
+	val = size * block_size;
+	if (val == 0) {
+		return u;
+	}
+
+	if (display_unit) {
+		val += display_unit/2;	/* Deal with rounding. */
+		val /= display_unit;	/* Don't combine with the line above!!! */
+	} else {
+		++u;
+		while ((val >= KILOBYTE)
+			   && (u < zero_and_units + sizeof(zero_and_units) - 1)) {
+			f = fmt_tenths;
+			++u;
+			frac = ((((int)(val % KILOBYTE)) * 10) + (KILOBYTE/2)) / KILOBYTE;
+			val /= KILOBYTE;
+		}
+		if (frac >= 10) {		/* We need to round up here. */
+			++val;
+			frac = 0;
+		}
+#if 0
+		/* Sample code to omit decimal point and tenths digit. */
+		if ( /* no_tenths */ 1 ) {
+			if ( frac >= 5 ) {
+				++val;
+			}
+			f = "%llu%*c" /* fmt_no_tenths */ ;
+			frac = 1;
+		}
+#endif
+	}
+
+	/* If f==fmt then 'frac' and 'u' are ignored. */
+	snprintf(str, sizeof(str), f, val, frac, *u);
+
+	return str;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/inet_common.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/inet_common.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/inet_common.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,247 @@
+/*
+ * stolen from net-tools-1.59 and stripped down for busybox by
+ *                      Erik Andersen <andersen at codepoet.org>
+ *
+ * Heavily modified by Manuel Novoa III       Mar 12, 2001
+ *
+ * Version:     $Id: inet_common.c,v 1.8 2004/03/10 07:42:38 mjn3 Exp $
+ *
+ */
+
+#include "libbb.h"
+#include "inet_common.h"
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef DEBUG
+# include <resolv.h>
+#endif
+
+
+const char bb_INET_default[] = "default";
+
+int INET_resolve(const char *name, struct sockaddr_in *s_in, int hostfirst)
+{
+	struct hostent *hp;
+	struct netent *np;
+
+	/* Grmpf. -FvK */
+	s_in->sin_family = AF_INET;
+	s_in->sin_port = 0;
+
+	/* Default is special, meaning 0.0.0.0. */
+	if (!strcmp(name, bb_INET_default)) {
+		s_in->sin_addr.s_addr = INADDR_ANY;
+		return (1);
+	}
+	/* Look to see if it's a dotted quad. */
+	if (inet_aton(name, &s_in->sin_addr)) {
+		return 0;
+	}
+	/* If we expect this to be a hostname, try hostname database first */
+#ifdef DEBUG
+	if (hostfirst) {
+		bb_error_msg("gethostbyname (%s)", name);
+	}
+#endif
+	if (hostfirst && (hp = gethostbyname(name)) != (struct hostent *) NULL) {
+		memcpy((char *) &s_in->sin_addr, (char *) hp->h_addr_list[0],
+			   sizeof(struct in_addr));
+		return 0;
+	}
+	/* Try the NETWORKS database to see if this is a known network. */
+#ifdef DEBUG
+	bb_error_msg("getnetbyname (%s)", name);
+#endif
+	if ((np = getnetbyname(name)) != (struct netent *) NULL) {
+		s_in->sin_addr.s_addr = htonl(np->n_net);
+		return 1;
+	}
+	if (hostfirst) {
+		/* Don't try again */
+		return -1;
+	}
+#ifdef DEBUG
+	res_init();
+	_res.options |= RES_DEBUG;
+#endif
+
+#ifdef DEBUG
+	bb_error_msg("gethostbyname (%s)", name);
+#endif
+	if ((hp = gethostbyname(name)) == (struct hostent *) NULL) {
+		return -1;
+	}
+	memcpy((char *) &s_in->sin_addr, (char *) hp->h_addr_list[0],
+		   sizeof(struct in_addr));
+
+	return 0;
+}
+
+/* cache */
+struct addr {
+	struct sockaddr_in addr;
+	char *name;
+	int host;
+	struct addr *next;
+};
+
+static struct addr *INET_nn = NULL;	/* addr-to-name cache           */
+
+/* numeric: & 0x8000: default instead of *,
+ *          & 0x4000: host instead of net,
+ *          & 0x0fff: don't resolve
+ */
+int INET_rresolve(char *name, size_t len, struct sockaddr_in *s_in,
+				  int numeric, unsigned int netmask)
+{
+	struct hostent *ent;
+	struct netent *np;
+	struct addr *pn;
+	unsigned long ad, host_ad;
+	int host = 0;
+
+	/* Grmpf. -FvK */
+	if (s_in->sin_family != AF_INET) {
+#ifdef DEBUG
+		bb_error_msg("rresolve: unsupport address family %d !",
+				  s_in->sin_family);
+#endif
+		errno = EAFNOSUPPORT;
+		return (-1);
+	}
+	ad = (unsigned long) s_in->sin_addr.s_addr;
+#ifdef DEBUG
+	bb_error_msg("rresolve: %08lx, mask %08x, num %08x", ad, netmask, numeric);
+#endif
+	if (ad == INADDR_ANY) {
+		if ((numeric & 0x0FFF) == 0) {
+			if (numeric & 0x8000)
+				safe_strncpy(name, bb_INET_default, len);
+			else
+				safe_strncpy(name, "*", len);
+			return (0);
+		}
+	}
+	if (numeric & 0x0FFF) {
+		safe_strncpy(name, inet_ntoa(s_in->sin_addr), len);
+		return (0);
+	}
+
+	if ((ad & (~netmask)) != 0 || (numeric & 0x4000))
+		host = 1;
+#if 0
+	INET_nn = NULL;
+#endif
+	pn = INET_nn;
+	while (pn != NULL) {
+		if (pn->addr.sin_addr.s_addr == ad && pn->host == host) {
+			safe_strncpy(name, pn->name, len);
+#ifdef DEBUG
+			bb_error_msg("rresolve: found %s %08lx in cache",
+					  (host ? "host" : "net"), ad);
+#endif
+			return (0);
+		}
+		pn = pn->next;
+	}
+
+	host_ad = ntohl(ad);
+	np = NULL;
+	ent = NULL;
+	if (host) {
+#ifdef DEBUG
+		bb_error_msg("gethostbyaddr (%08lx)", ad);
+#endif
+		ent = gethostbyaddr((char *) &ad, 4, AF_INET);
+		if (ent != NULL) {
+			safe_strncpy(name, ent->h_name, len);
+		}
+	} else {
+#ifdef DEBUG
+		bb_error_msg("getnetbyaddr (%08lx)", host_ad);
+#endif
+		np = getnetbyaddr(host_ad, AF_INET);
+		if (np != NULL) {
+			safe_strncpy(name, np->n_name, len);
+		}
+	}
+	if ((ent == NULL) && (np == NULL)) {
+		safe_strncpy(name, inet_ntoa(s_in->sin_addr), len);
+	}
+	pn = (struct addr *) xmalloc(sizeof(struct addr));
+	pn->addr = *s_in;
+	pn->next = INET_nn;
+	pn->host = host;
+	pn->name = bb_xstrdup(name);
+	INET_nn = pn;
+
+	return (0);
+}
+
+#ifdef CONFIG_FEATURE_IPV6
+
+int INET6_resolve(const char *name, struct sockaddr_in6 *sin6)
+{
+	struct addrinfo req, *ai;
+	int s;
+
+	memset(&req, '\0', sizeof req);
+	req.ai_family = AF_INET6;
+	if ((s = getaddrinfo(name, NULL, &req, &ai))) {
+		bb_error_msg("getaddrinfo: %s: %d", name, s);
+		return -1;
+	}
+	memcpy(sin6, ai->ai_addr, sizeof(struct sockaddr_in6));
+
+	freeaddrinfo(ai);
+
+	return (0);
+}
+
+#ifndef IN6_IS_ADDR_UNSPECIFIED
+# define IN6_IS_ADDR_UNSPECIFIED(a) \
+	(((uint32_t *) (a))[0] == 0 && ((uint32_t *) (a))[1] == 0 && \
+	 ((uint32_t *) (a))[2] == 0 && ((uint32_t *) (a))[3] == 0)
+#endif
+
+
+int INET6_rresolve(char *name, size_t len, struct sockaddr_in6 *sin6,
+				   int numeric)
+{
+	int s;
+
+	/* Grmpf. -FvK */
+	if (sin6->sin6_family != AF_INET6) {
+#ifdef DEBUG
+		bb_error_msg(_("rresolve: unsupport address family %d !\n"),
+				  sin6->sin6_family);
+#endif
+		errno = EAFNOSUPPORT;
+		return (-1);
+	}
+	if (numeric & 0x7FFF) {
+		inet_ntop(AF_INET6, &sin6->sin6_addr, name, len);
+		return (0);
+	}
+	if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+		if (numeric & 0x8000) {
+			strcpy(name, "default");
+		} else {
+			strcpy(name, "*");
+		}
+		return (0);
+	}
+
+	s = getnameinfo((struct sockaddr *) sin6, sizeof(struct sockaddr_in6), name, len, NULL, 0, 0);
+	if (s) {
+		bb_error_msg("getnameinfo failed");
+		return -1;
+	}
+	return (0);
+}
+
+#endif							/* CONFIG_FEATURE_IPV6 */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/inode_hash.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/inode_hash.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/inode_hash.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,88 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) many different people.
+ * If you wrote this, please acknowledge your work.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "libbb.h"
+
+#define HASH_SIZE	311		/* Should be prime */
+#define hash_inode(i)	((i) % HASH_SIZE)
+
+typedef struct ino_dev_hash_bucket_struct {
+  struct ino_dev_hash_bucket_struct *next;
+  ino_t ino;
+  dev_t dev;
+  char name[1];
+} ino_dev_hashtable_bucket_t;
+
+static ino_dev_hashtable_bucket_t *ino_dev_hashtable[HASH_SIZE];
+
+/*
+ * Return 1 if statbuf->st_ino && statbuf->st_dev are recorded in
+ * `ino_dev_hashtable', else return 0
+ *
+ * If NAME is a non-NULL pointer to a character pointer, and there is
+ * a match, then set *NAME to the value of the name slot in that
+ * bucket.
+ */
+int is_in_ino_dev_hashtable(const struct stat *statbuf, char **name)
+{
+	ino_dev_hashtable_bucket_t *bucket;
+
+	bucket = ino_dev_hashtable[hash_inode(statbuf->st_ino)];
+	while (bucket != NULL) {
+	  if ((bucket->ino == statbuf->st_ino) &&
+		  (bucket->dev == statbuf->st_dev))
+	  {
+		if (name) *name = bucket->name;
+		return 1;
+	  }
+	  bucket = bucket->next;
+	}
+	return 0;
+}
+
+/* Add statbuf to statbuf hash table */
+void add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name)
+{
+	int i;
+	size_t s;
+	ino_dev_hashtable_bucket_t *bucket;
+
+	i = hash_inode(statbuf->st_ino);
+	s = name ? strlen(name) : 0;
+	bucket = xmalloc(sizeof(ino_dev_hashtable_bucket_t) + s);
+	bucket->ino = statbuf->st_ino;
+	bucket->dev = statbuf->st_dev;
+	if (name)
+		strcpy(bucket->name, name);
+	else
+		bucket->name[0] = '\0';
+	bucket->next = ino_dev_hashtable[i];
+	ino_dev_hashtable[i] = bucket;
+}
+
+#ifdef CONFIG_FEATURE_CLEAN_UP
+/* Clear statbuf hash table */
+void reset_ino_dev_hashtable(void)
+{
+	int i;
+	ino_dev_hashtable_bucket_t *bucket;
+
+	for (i = 0; i < HASH_SIZE; i++) {
+		while (ino_dev_hashtable[i] != NULL) {
+			bucket = ino_dev_hashtable[i]->next;
+			free(ino_dev_hashtable[i]);
+			ino_dev_hashtable[i] = bucket;
+		}
+	}
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/isdirectory.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/isdirectory.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/isdirectory.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,39 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Based in part on code from sash, Copyright (c) 1999 by David I. Bell
+ * Permission has been granted to redistribute this code under the GPL.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <sys/stat.h>
+#include "libbb.h"
+
+/*
+ * Return TRUE if a fileName is a directory.
+ * Nonexistent files return FALSE.
+ */
+int is_directory(const char *fileName, const int followLinks, struct stat *statBuf)
+{
+	int status;
+	struct stat astatBuf;
+
+	if (statBuf == NULL) {
+	    /* set from auto stack buffer */
+	    statBuf = &astatBuf;
+	}
+
+	if (followLinks)
+		status = stat(fileName, statBuf);
+	else
+		status = lstat(fileName, statBuf);
+
+	if (status < 0 || !(S_ISDIR(statBuf->st_mode))) {
+	    status = FALSE;
+	}
+	else status = TRUE;
+
+	return status;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/kernel_version.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/kernel_version.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/kernel_version.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,40 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/utsname.h>		/* for uname(2) */
+
+#include "libbb.h"
+
+/* Returns current kernel version encoded as major*65536 + minor*256 + patch,
+ * so, for example,  to check if the kernel is greater than 2.2.11:
+ *
+ *     if (get_linux_version_code() > KERNEL_VERSION(2,2,11)) { <stuff> }
+ */
+int get_linux_version_code(void)
+{
+	struct utsname name;
+	char *s;
+	int i, r;
+
+	if (uname(&name) == -1) {
+		bb_perror_msg("cannot get system information");
+		return (0);
+	}
+
+	s = name.release;
+	r = 0;
+	for (i=0 ; i<3 ; i++) {
+		r = r * 256 + atoi(strtok(s, "."));
+		s = NULL;
+	}
+	return r;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/last_char_is.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/last_char_is.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/last_char_is.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,38 @@
+/*
+ * busybox library eXtended function
+ *
+ * Copyright (C) 2001 Larry Doolittle, <ldoolitt at recycle.lbl.gov>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <string.h>
+#include "libbb.h"
+
+/* Find out if the last character of a string matches the one given Don't
+ * underrun the buffer if the string length is 0.  Also avoids a possible
+ * space-hogging inline of strlen() per usage.
+ */
+char * last_char_is(const char *s, int c)
+{
+	char *sret = (char *)s;
+	if (sret) {
+		sret = strrchr(sret, c);
+		if(sret != NULL && *(sret+1) != 0)
+			sret = NULL;
+	}
+	return sret;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/llist.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/llist.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/llist.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,71 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * linked list helper functions.
+ *
+ * Copyright (C) 2003 Glenn McGrath
+ * Copyright (C) 2005 Vladimir Oleynik
+ * Copyright (C) 2005 Bernhard Fischer
+ * Copyright (C) 2006 Rob Landley <rob at landley.net>
+ *
+ * Licensed under the GPL v2, see the file LICENSE in this tarball.
+ */
+#include <stdlib.h>
+#include "libbb.h"
+
+#ifdef L_llist_add_to
+/* Add data to the start of the linked list.  */
+void llist_add_to(llist_t **old_head, void *data)
+{
+	llist_t *new_head = xmalloc(sizeof(llist_t));
+	new_head->data = data;
+	new_head->link = *old_head;
+	*old_head = new_head;
+}
+#endif
+
+#ifdef L_llist_add_to_end
+/* Add data to the end of the linked list.  */
+void llist_add_to_end(llist_t **list_head, void *data)
+{
+	llist_t *new_item = xmalloc(sizeof(llist_t));
+	new_item->data = data;
+	new_item->link = NULL;
+
+	if (!*list_head) *list_head = new_item;
+	else {
+		llist_t *tail = *list_head;
+		while (tail->link) tail = tail->link;
+		tail->link = new_item;
+	}
+}
+#endif
+
+#ifdef L_llist_pop
+/* Remove first element from the list and return it */
+void *llist_pop(llist_t **head)
+{
+	void *data;
+
+	if(!*head) data = *head;
+	else {
+		void *next = (*head)->link;
+		data = (*head)->data;
+		free(*head);
+		*head = next;
+	}
+
+	return data;
+}
+#endif
+
+#ifdef L_llist_free
+/* Recursively free all elements in the linked list.  If freeit != NULL
+ * call it on each datum in the list */
+void llist_free(llist_t *elm, void (*freeit)(void *data))
+{
+	while (elm) {
+		void *data = llist_pop(&elm);
+		if (freeit) freeit(data);
+	}
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/login.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/login.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/login.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,129 @@
+/*
+ * issue.c: issue printing code
+ *
+ * Copyright (C) 2003 Bastian Blank <waldi at tuxbox.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Optimize and correcting OCRNL by Vladimir Oleynik <dzo at simtreas.ru>
+ */
+
+#include <sys/param.h>  /* MAXHOSTNAMELEN */
+#include <stdio.h>
+#include <unistd.h>
+#include "libbb.h"
+
+#include <sys/utsname.h>
+#include <time.h>
+
+#define LOGIN " login: "
+
+static const char fmtstr_d[] = "%A, %d %B %Y";
+static const char fmtstr_t[] = "%H:%M:%S";
+
+void print_login_issue(const char *issue_file, const char *tty)
+{
+	FILE *fd;
+	int c;
+	char buf[256+1];
+	const char *outbuf;
+	time_t t;
+	struct utsname uts;
+
+	time(&t);
+	uname(&uts);
+
+	puts("\r");	/* start a new line */
+
+	if ((fd = fopen(issue_file, "r"))) {
+		while ((c = fgetc(fd)) != EOF) {
+			outbuf = buf;
+			buf[0] = c;
+			if(c == '\n') {
+				buf[1] = '\r';
+				buf[2] = 0;
+			} else {
+				buf[1] = 0;
+			}
+			if (c == '\\' || c == '%') {
+				c = fgetc(fd);
+				switch (c) {
+					case 's':
+						outbuf = uts.sysname;
+						break;
+
+					case 'n':
+						outbuf = uts.nodename;
+						break;
+
+					case 'r':
+						outbuf = uts.release;
+						break;
+
+					case 'v':
+						outbuf = uts.version;
+						break;
+
+					case 'm':
+						outbuf = uts.machine;
+						break;
+
+					case 'D':
+					case 'o':
+						c = getdomainname(buf, sizeof(buf) - 1);
+						buf[c >= 0 ? c : 0] = '\0'; 
+						break;
+
+					case 'd':
+						strftime(buf, sizeof(buf), fmtstr_d, localtime(&t));
+						break;
+
+					case 't':
+						strftime(buf, sizeof(buf), fmtstr_t, localtime(&t));
+						break;
+
+					case 'h':
+						gethostname(buf, sizeof(buf) - 1);
+						buf[sizeof(buf) - 1] = '\0';
+						break;
+
+					case 'l':
+						outbuf = tty;
+						break;
+
+					default:
+						buf[0] = c;
+				}
+			}
+			fputs(outbuf, stdout);
+		}
+
+		fclose(fd);
+
+		fflush(stdout);
+	}
+}
+
+void print_login_prompt(void)
+{
+	char buf[MAXHOSTNAMELEN+1];
+
+	if(gethostname(buf, MAXHOSTNAMELEN) == 0)
+		fputs(buf, stdout);
+
+	fputs(LOGIN, stdout);
+	fflush(stdout);
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/loop.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/loop.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/loop.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,142 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+
+#include <features.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include "libbb.h"
+
+/* For 2.6, use the cleaned up header to get the 64 bit API. */
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#include <linux/loop.h>
+typedef struct loop_info64 bb_loop_info;
+#define BB_LOOP_SET_STATUS LOOP_SET_STATUS64
+#define BB_LOOP_GET_STATUS LOOP_GET_STATUS64
+
+/* For 2.4 and earlier, use the 32 bit API (and don't trust the headers) */
+#else
+/* Stuff stolen from linux/loop.h for 2.4 and earlier kernels*/
+#include <linux/posix_types.h>
+#define LO_NAME_SIZE        64
+#define LO_KEY_SIZE         32
+#define LOOP_SET_FD         0x4C00
+#define LOOP_CLR_FD         0x4C01
+#define BB_LOOP_SET_STATUS  0x4C02
+#define BB_LOOP_GET_STATUS  0x4C03
+typedef struct {
+	int                lo_number;
+	__kernel_dev_t     lo_device;
+	unsigned long      lo_inode;
+	__kernel_dev_t     lo_rdevice;
+	int                lo_offset;
+	int                lo_encrypt_type;
+	int                lo_encrypt_key_size;
+	int                lo_flags;
+	char               lo_file_name[LO_NAME_SIZE];
+	unsigned char      lo_encrypt_key[LO_KEY_SIZE];
+	unsigned long      lo_init[2];
+	char               reserved[4];
+} bb_loop_info;
+#endif
+
+char *query_loop(const char *device)
+{
+	int fd;
+	bb_loop_info loopinfo;
+	char *dev=0;
+
+	if ((fd = open(device, O_RDONLY)) < 0) return 0;
+	if (!ioctl(fd, BB_LOOP_GET_STATUS, &loopinfo))
+		dev=bb_xasprintf("%ld %s", (long) loopinfo.lo_offset,
+				(char *)loopinfo.lo_file_name);
+	close(fd);
+
+	return dev;
+}
+
+
+int del_loop(const char *device)
+{
+	int fd, rc;
+
+	if ((fd = open(device, O_RDONLY)) < 0) return 1;
+	rc=ioctl(fd, LOOP_CLR_FD, 0);
+	close(fd);
+
+	return rc;
+}
+
+/* Returns 0 if mounted RW, 1 if mounted read-only, <0 for error.
+   *device is loop device to use, or if *device==NULL finds a loop device to
+   mount it on and sets *device to a strdup of that loop device name.  This
+   search will re-use an existing loop device already bound to that
+   file/offset if it finds one.
+ */
+int set_loop(char **device, const char *file, int offset)
+{
+	char dev[20], *try;
+	bb_loop_info loopinfo;
+	struct stat statbuf;
+	int i, dfd, ffd, mode, rc=-1;
+	
+	/* Open the file.  Barf if this doesn't work.  */
+	if((ffd = open(file, mode=O_RDWR))<0 && (ffd = open(file,mode=O_RDONLY))<0)
+		return -errno;
+
+	/* Find a loop device.  */
+	try=*device ? : dev;
+	for(i=0;rc;i++) {
+		sprintf(dev, LOOP_FORMAT, i);
+
+		/* Ran out of block devices, return failure.  */
+		if(stat(try, &statbuf) || !S_ISBLK(statbuf.st_mode)) {
+			rc=-ENOENT;
+			break;
+		}
+		/* Open the sucker and check its loopiness.  */
+		if((dfd=open(try, mode))<0 && errno==EROFS)
+			dfd=open(try, mode = O_RDONLY);
+		if(dfd<0) goto try_again;
+
+		rc=ioctl(dfd, BB_LOOP_GET_STATUS, &loopinfo);
+
+		/* If device free, claim it.  */
+		if(rc && errno==ENXIO) {
+			memset(&loopinfo, 0, sizeof(loopinfo));
+			safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE);
+			loopinfo.lo_offset = offset;
+			/* Associate free loop device with file.  */
+			if(!ioctl(dfd, LOOP_SET_FD, ffd)) {
+				if (!ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo)) rc=0;
+				else ioctl(dfd, LOOP_CLR_FD, 0);
+			}
+
+		/* If this block device already set up right, re-use it.
+		   (Yes this is racy, but associating two loop devices with the same
+		   file isn't pretty either.  In general, mounting the same file twice
+		   without using losetup manually is problematic.)
+		 */
+		} else if(strcmp(file,(char *)loopinfo.lo_file_name)
+					|| offset!=loopinfo.lo_offset) rc=-1;
+		close(dfd);
+try_again:
+		if(*device) break;
+	}
+	close(ffd);
+	if(!rc) {
+		if(!*device) *device=strdup(dev);
+		return mode==O_RDONLY ? 1 : 0;
+	} else return rc;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/make_directory.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/make_directory.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/make_directory.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,117 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * parse_mode implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* Mar 5, 2003    Manuel Novoa III
+ *
+ * This is the main work function for the 'mkdir' applet.  As such, it
+ * strives to be SUSv3 compliant in it's behaviour when recursively
+ * making missing parent dirs, and in it's mode setting of the final
+ * directory 'path'.
+ *
+ * To recursively build all missing intermediate directories, make
+ * sure that (flags & FILEUTILS_RECUR) is non-zero.  Newly created
+ * intermediate directories will have at least u+wx perms.
+ *
+ * To set specific permissions on 'path', pass the appropriate 'mode'
+ * val.  Otherwise, pass -1 to get default permissions.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include "libbb.h"
+
+int bb_make_directory (char *path, long mode, int flags)
+{
+	mode_t mask;
+	const char *fail_msg;
+	char *s = path;
+	char c;
+	struct stat st;
+
+	mask = umask(0);
+	if (mode == -1) {
+		umask(mask);
+		mode = (S_IXUSR | S_IXGRP | S_IXOTH |
+				S_IWUSR | S_IWGRP | S_IWOTH |
+				S_IRUSR | S_IRGRP | S_IROTH) & ~mask;
+	} else {
+		umask(mask & ~0300);
+	}
+
+	do {
+		c = 0;
+
+		if (flags & FILEUTILS_RECUR) {	/* Get the parent. */
+			/* Bypass leading non-'/'s and then subsequent '/'s. */
+			while (*s) {
+				if (*s == '/') {
+					do {
+						++s;
+					} while (*s == '/');
+					c = *s;		/* Save the current char */
+					*s = 0;		/* and replace it with nul. */
+					break;
+				}
+				++s;
+			}
+		}
+
+		if (mkdir(path, 0777) < 0) {
+			/* If we failed for any other reason than the directory
+			 * already exists, output a diagnostic and return -1.*/
+			if (errno != EEXIST
+				|| !(flags & FILEUTILS_RECUR)
+				|| (stat(path, &st) < 0 || !S_ISDIR(st.st_mode))) {
+				fail_msg = "create";
+				umask(mask);
+				break;
+			}
+			/* Since the directory exists, don't attempt to change
+			 * permissions if it was the full target.  Note that
+			 * this is not an error conditon. */
+			if (!c) {
+				umask(mask);
+				return 0;
+			}
+		}
+
+		if (!c) {
+			/* Done.  If necessary, updated perms on the newly
+			 * created directory.  Failure to update here _is_
+			 * an error.*/
+			umask(mask);
+			if ((mode != -1) && (chmod(path, mode) < 0)){
+				fail_msg = "set permissions of";
+				break;
+			}
+			return 0;
+		}
+
+		/* Remove any inserted nul from the path (recursive mode). */
+		*s = c;
+
+	} while (1);
+
+	bb_perror_msg ("Cannot %s directory `%s'", fail_msg, path);
+	return -1;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/md5.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/md5.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/md5.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,456 @@
+/*
+ *  md5.c - Compute MD5 checksum of strings according to the
+ *          definition of MD5 in RFC 1321 from April 1992.
+ *
+ *  Written by Ulrich Drepper <drepper at gnu.ai.mit.edu>, 1995.
+ *
+ *  Copyright (C) 1995-1999 Free Software Foundation, Inc.
+ *  Copyright (C) 2001 Manuel Novoa III
+ *  Copyright (C) 2003 Glenn L. McGrath
+ *  Copyright (C) 2003 Erik Andersen
+ *
+ *  Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libbb.h"
+
+# if CONFIG_MD5_SIZE_VS_SPEED < 0 || CONFIG_MD5_SIZE_VS_SPEED > 3
+# define MD5_SIZE_VS_SPEED 2
+# else
+# define MD5_SIZE_VS_SPEED CONFIG_MD5_SIZE_VS_SPEED
+# endif
+
+/* Initialize structure containing state of computation.
+ * (RFC 1321, 3.3: Step 3)
+ */
+void md5_begin(md5_ctx_t *ctx)
+{
+	ctx->A = 0x67452301;
+	ctx->B = 0xefcdab89;
+	ctx->C = 0x98badcfe;
+	ctx->D = 0x10325476;
+
+	ctx->total = 0;
+	ctx->buflen = 0;
+}
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+ * and defined in the RFC 1321.  The first function is a little bit optimized
+ * (as found in Colin Plumbs public domain implementation).
+ * #define FF(b, c, d) ((b & c) | (~b & d))
+ */
+# define FF(b, c, d) (d ^ (b & (c ^ d)))
+# define FG(b, c, d) FF (d, b, c)
+# define FH(b, c, d) (b ^ c ^ d)
+# define FI(b, c, d) (c ^ (b | ~d))
+
+/* Hash a single block, 64 bytes long and 4-byte aligned. */
+static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
+{
+	uint32_t correct_words[16];
+	const uint32_t *words = buffer;
+
+# if MD5_SIZE_VS_SPEED > 0
+	static const uint32_t C_array[] = {
+		/* round 1 */
+		0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+		0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+		0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+		0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+		/* round 2 */
+		0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+		0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
+		0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+		0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+		/* round 3 */
+		0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+		0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+		0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
+		0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+		/* round 4 */
+		0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+		0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+		0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+		0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+	};
+
+	static const char P_array[] = {
+#  if MD5_SIZE_VS_SPEED > 1
+		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,	/* 1 */
+#  endif	/* MD5_SIZE_VS_SPEED > 1 */
+		1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12,	/* 2 */
+		5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2,	/* 3 */
+		0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9	/* 4 */
+	};
+
+#  if MD5_SIZE_VS_SPEED > 1
+	static const char S_array[] = {
+		7, 12, 17, 22,
+		5, 9, 14, 20,
+		4, 11, 16, 23,
+		6, 10, 15, 21
+	};
+#  endif	/* MD5_SIZE_VS_SPEED > 1 */
+# endif
+
+	uint32_t A = ctx->A;
+	uint32_t B = ctx->B;
+	uint32_t C = ctx->C;
+	uint32_t D = ctx->D;
+
+	/* Process all bytes in the buffer with 64 bytes in each round of
+	   the loop.  */
+		uint32_t *cwp = correct_words;
+		uint32_t A_save = A;
+		uint32_t B_save = B;
+		uint32_t C_save = C;
+		uint32_t D_save = D;
+
+# if MD5_SIZE_VS_SPEED > 1
+#  define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
+
+		const uint32_t *pc;
+		const char *pp;
+		const char *ps;
+		int i;
+		uint32_t temp;
+
+		for (i = 0; i < 16; i++) {
+			cwp[i] = SWAP_LE32(words[i]);
+		}
+		words += 16;
+
+#  if MD5_SIZE_VS_SPEED > 2
+		pc = C_array;
+		pp = P_array;
+		ps = S_array - 4;
+
+		for (i = 0; i < 64; i++) {
+			if ((i & 0x0f) == 0)
+				ps += 4;
+			temp = A;
+			switch (i >> 4) {
+			case 0:
+				temp += FF(B, C, D);
+				break;
+			case 1:
+				temp += FG(B, C, D);
+				break;
+			case 2:
+				temp += FH(B, C, D);
+				break;
+			case 3:
+				temp += FI(B, C, D);
+			}
+			temp += cwp[(int) (*pp++)] + *pc++;
+			CYCLIC(temp, ps[i & 3]);
+			temp += B;
+			A = D;
+			D = C;
+			C = B;
+			B = temp;
+		}
+#  else
+		pc = C_array;
+		pp = P_array;
+		ps = S_array;
+
+		for (i = 0; i < 16; i++) {
+			temp = A + FF(B, C, D) + cwp[(int) (*pp++)] + *pc++;
+			CYCLIC(temp, ps[i & 3]);
+			temp += B;
+			A = D;
+			D = C;
+			C = B;
+			B = temp;
+		}
+
+		ps += 4;
+		for (i = 0; i < 16; i++) {
+			temp = A + FG(B, C, D) + cwp[(int) (*pp++)] + *pc++;
+			CYCLIC(temp, ps[i & 3]);
+			temp += B;
+			A = D;
+			D = C;
+			C = B;
+			B = temp;
+		}
+		ps += 4;
+		for (i = 0; i < 16; i++) {
+			temp = A + FH(B, C, D) + cwp[(int) (*pp++)] + *pc++;
+			CYCLIC(temp, ps[i & 3]);
+			temp += B;
+			A = D;
+			D = C;
+			C = B;
+			B = temp;
+		}
+		ps += 4;
+		for (i = 0; i < 16; i++) {
+			temp = A + FI(B, C, D) + cwp[(int) (*pp++)] + *pc++;
+			CYCLIC(temp, ps[i & 3]);
+			temp += B;
+			A = D;
+			D = C;
+			C = B;
+			B = temp;
+		}
+
+#  endif	/* MD5_SIZE_VS_SPEED > 2 */
+# else
+		/* First round: using the given function, the context and a constant
+		   the next context is computed.  Because the algorithms processing
+		   unit is a 32-bit word and it is determined to work on words in
+		   little endian byte order we perhaps have to change the byte order
+		   before the computation.  To reduce the work for the next steps
+		   we store the swapped words in the array CORRECT_WORDS.  */
+
+#  define OP(a, b, c, d, s, T)	\
+      do	\
+	{	\
+	  a += FF (b, c, d) + (*cwp++ = SWAP_LE32(*words)) + T; \
+	  ++words;	\
+	  CYCLIC (a, s);	\
+	  a += b;	\
+	}	\
+      while (0)
+
+		/* It is unfortunate that C does not provide an operator for
+		   cyclic rotation.  Hope the C compiler is smart enough.  */
+		/* gcc 2.95.4 seems to be --aaronl */
+#  define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
+
+		/* Before we start, one word to the strange constants.
+		   They are defined in RFC 1321 as
+
+		   T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
+		 */
+
+#  if MD5_SIZE_VS_SPEED == 1
+		const uint32_t *pc;
+		const char *pp;
+		int i;
+#  endif	/* MD5_SIZE_VS_SPEED */
+
+		/* Round 1.  */
+#  if MD5_SIZE_VS_SPEED == 1
+		pc = C_array;
+		for (i = 0; i < 4; i++) {
+			OP(A, B, C, D, 7, *pc++);
+			OP(D, A, B, C, 12, *pc++);
+			OP(C, D, A, B, 17, *pc++);
+			OP(B, C, D, A, 22, *pc++);
+		}
+#  else
+		OP(A, B, C, D, 7, 0xd76aa478);
+		OP(D, A, B, C, 12, 0xe8c7b756);
+		OP(C, D, A, B, 17, 0x242070db);
+		OP(B, C, D, A, 22, 0xc1bdceee);
+		OP(A, B, C, D, 7, 0xf57c0faf);
+		OP(D, A, B, C, 12, 0x4787c62a);
+		OP(C, D, A, B, 17, 0xa8304613);
+		OP(B, C, D, A, 22, 0xfd469501);
+		OP(A, B, C, D, 7, 0x698098d8);
+		OP(D, A, B, C, 12, 0x8b44f7af);
+		OP(C, D, A, B, 17, 0xffff5bb1);
+		OP(B, C, D, A, 22, 0x895cd7be);
+		OP(A, B, C, D, 7, 0x6b901122);
+		OP(D, A, B, C, 12, 0xfd987193);
+		OP(C, D, A, B, 17, 0xa679438e);
+		OP(B, C, D, A, 22, 0x49b40821);
+#  endif	/* MD5_SIZE_VS_SPEED == 1 */
+
+		/* For the second to fourth round we have the possibly swapped words
+		   in CORRECT_WORDS.  Redefine the macro to take an additional first
+		   argument specifying the function to use.  */
+#  undef OP
+#  define OP(f, a, b, c, d, k, s, T)	\
+      do	\
+	{	\
+	  a += f (b, c, d) + correct_words[k] + T;	\
+	  CYCLIC (a, s);	\
+	  a += b;	\
+	}	\
+      while (0)
+
+		/* Round 2.  */
+#  if MD5_SIZE_VS_SPEED == 1
+		pp = P_array;
+		for (i = 0; i < 4; i++) {
+			OP(FG, A, B, C, D, (int) (*pp++), 5, *pc++);
+			OP(FG, D, A, B, C, (int) (*pp++), 9, *pc++);
+			OP(FG, C, D, A, B, (int) (*pp++), 14, *pc++);
+			OP(FG, B, C, D, A, (int) (*pp++), 20, *pc++);
+		}
+#  else
+		OP(FG, A, B, C, D, 1, 5, 0xf61e2562);
+		OP(FG, D, A, B, C, 6, 9, 0xc040b340);
+		OP(FG, C, D, A, B, 11, 14, 0x265e5a51);
+		OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
+		OP(FG, A, B, C, D, 5, 5, 0xd62f105d);
+		OP(FG, D, A, B, C, 10, 9, 0x02441453);
+		OP(FG, C, D, A, B, 15, 14, 0xd8a1e681);
+		OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
+		OP(FG, A, B, C, D, 9, 5, 0x21e1cde6);
+		OP(FG, D, A, B, C, 14, 9, 0xc33707d6);
+		OP(FG, C, D, A, B, 3, 14, 0xf4d50d87);
+		OP(FG, B, C, D, A, 8, 20, 0x455a14ed);
+		OP(FG, A, B, C, D, 13, 5, 0xa9e3e905);
+		OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8);
+		OP(FG, C, D, A, B, 7, 14, 0x676f02d9);
+		OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+#  endif	/* MD5_SIZE_VS_SPEED == 1 */
+
+		/* Round 3.  */
+#  if MD5_SIZE_VS_SPEED == 1
+		for (i = 0; i < 4; i++) {
+			OP(FH, A, B, C, D, (int) (*pp++), 4, *pc++);
+			OP(FH, D, A, B, C, (int) (*pp++), 11, *pc++);
+			OP(FH, C, D, A, B, (int) (*pp++), 16, *pc++);
+			OP(FH, B, C, D, A, (int) (*pp++), 23, *pc++);
+		}
+#  else
+		OP(FH, A, B, C, D, 5, 4, 0xfffa3942);
+		OP(FH, D, A, B, C, 8, 11, 0x8771f681);
+		OP(FH, C, D, A, B, 11, 16, 0x6d9d6122);
+		OP(FH, B, C, D, A, 14, 23, 0xfde5380c);
+		OP(FH, A, B, C, D, 1, 4, 0xa4beea44);
+		OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9);
+		OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60);
+		OP(FH, B, C, D, A, 10, 23, 0xbebfbc70);
+		OP(FH, A, B, C, D, 13, 4, 0x289b7ec6);
+		OP(FH, D, A, B, C, 0, 11, 0xeaa127fa);
+		OP(FH, C, D, A, B, 3, 16, 0xd4ef3085);
+		OP(FH, B, C, D, A, 6, 23, 0x04881d05);
+		OP(FH, A, B, C, D, 9, 4, 0xd9d4d039);
+		OP(FH, D, A, B, C, 12, 11, 0xe6db99e5);
+		OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+		OP(FH, B, C, D, A, 2, 23, 0xc4ac5665);
+#  endif	/* MD5_SIZE_VS_SPEED == 1 */
+
+		/* Round 4.  */
+#  if MD5_SIZE_VS_SPEED == 1
+		for (i = 0; i < 4; i++) {
+			OP(FI, A, B, C, D, (int) (*pp++), 6, *pc++);
+			OP(FI, D, A, B, C, (int) (*pp++), 10, *pc++);
+			OP(FI, C, D, A, B, (int) (*pp++), 15, *pc++);
+			OP(FI, B, C, D, A, (int) (*pp++), 21, *pc++);
+		}
+#  else
+		OP(FI, A, B, C, D, 0, 6, 0xf4292244);
+		OP(FI, D, A, B, C, 7, 10, 0x432aff97);
+		OP(FI, C, D, A, B, 14, 15, 0xab9423a7);
+		OP(FI, B, C, D, A, 5, 21, 0xfc93a039);
+		OP(FI, A, B, C, D, 12, 6, 0x655b59c3);
+		OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92);
+		OP(FI, C, D, A, B, 10, 15, 0xffeff47d);
+		OP(FI, B, C, D, A, 1, 21, 0x85845dd1);
+		OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f);
+		OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+		OP(FI, C, D, A, B, 6, 15, 0xa3014314);
+		OP(FI, B, C, D, A, 13, 21, 0x4e0811a1);
+		OP(FI, A, B, C, D, 4, 6, 0xf7537e82);
+		OP(FI, D, A, B, C, 11, 10, 0xbd3af235);
+		OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
+		OP(FI, B, C, D, A, 9, 21, 0xeb86d391);
+#  endif	/* MD5_SIZE_VS_SPEED == 1 */
+# endif	/* MD5_SIZE_VS_SPEED > 1 */
+
+		/* Add the starting values of the context.  */
+		A += A_save;
+		B += B_save;
+		C += C_save;
+		D += D_save;
+
+	/* Put checksum in context given as argument.  */
+	ctx->A = A;
+	ctx->B = B;
+	ctx->C = C;
+	ctx->D = D;
+}
+
+/* Feed data through a temporary buffer to call md5_hash_aligned_block()
+ * with chunks of data that are 4-byte aligned and a multiple of 64 bytes.
+ * This function's internal buffer remembers previous data until it has 64
+ * bytes worth to pass on.  Call md5_end() to flush this buffer. */
+
+void md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx)
+{
+	char *buf=(char *)buffer;
+
+	/* RFC 1321 specifies the possible length of the file up to 2^64 bits,
+	 * Here we only track the number of bytes.  */
+
+	ctx->total += len;
+
+	// Process all input.
+
+	while (len) {
+		int i = 64 - ctx->buflen;
+
+		// Copy data into aligned buffer.
+
+		if (i > len) i = len;
+		memcpy(ctx->buffer + ctx->buflen, buf, i);
+		len -= i;
+		ctx->buflen += i;
+		buf += i;
+
+		// When buffer fills up, process it.
+
+		if (ctx->buflen == 64) {
+			md5_hash_block(ctx->buffer, ctx);
+			ctx->buflen = 0;
+		}
+	}
+}
+
+/* Process the remaining bytes in the buffer and put result from CTX
+ * in first 16 bytes following RESBUF.  The result is always in little
+ * endian byte order, so that a byte-wise output yields to the wanted
+ * ASCII representation of the message digest.
+ *
+ * IMPORTANT: On some systems it is required that RESBUF is correctly
+ * aligned for a 32 bits value.
+ */
+void *md5_end(void *resbuf, md5_ctx_t *ctx)
+{
+	char *buf = ctx->buffer;
+	int i;
+
+	/* Pad data to block size.  */
+
+	buf[ctx->buflen++] = 0x80;
+	memset(buf + ctx->buflen, 0, 128 - ctx->buflen);
+
+	/* Put the 64-bit file length in *bits* at the end of the buffer.  */
+	ctx->total <<= 3;
+	if (ctx->buflen > 56) buf += 64;
+	for (i = 0; i < 8; i++)  buf[56 + i] = ctx->total >> (i*8);
+
+	/* Process last bytes.  */
+	if (buf != ctx->buffer) md5_hash_block(ctx->buffer, ctx);
+	md5_hash_block(buf, ctx);
+	
+	/* Put result from CTX in first 16 bytes following RESBUF.  The result is
+	 * always in little endian byte order, so that a byte-wise output yields
+	 * to the wanted ASCII representation of the message digest.
+	 *
+	 * IMPORTANT: On some systems it is required that RESBUF is correctly
+	 * aligned for a 32 bits value.
+	 */
+	((uint32_t *) resbuf)[0] = SWAP_LE32(ctx->A);
+	((uint32_t *) resbuf)[1] = SWAP_LE32(ctx->B);
+	((uint32_t *) resbuf)[2] = SWAP_LE32(ctx->C);
+	((uint32_t *) resbuf)[3] = SWAP_LE32(ctx->D);
+
+	return resbuf;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/messages.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/messages.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/messages.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,118 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ */
+
+#include "libbb.h"
+
+#ifdef L_full_version
+#ifndef BB_EXTRA_VERSION
+#define LIBBB_BANNER "BusyBox's library v" BB_VER " (" BB_BT ")"
+#else
+#define LIBBB_BANNER "BusyBox's library v" BB_VER " (" BB_EXTRA_VERSION ")"
+#endif
+	const char * const libbb_msg_full_version = LIBBB_BANNER;
+#endif
+#ifdef L_memory_exhausted
+	const char * const bb_msg_memory_exhausted = "memory exhausted";
+#endif
+#ifdef L_invalid_date
+	const char * const bb_msg_invalid_date = "invalid date `%s'";
+#endif
+#ifdef L_io_error
+	const char * const bb_msg_io_error = "%s: input/output error -- %m";
+#endif
+#ifdef L_write_error
+	const char * const bb_msg_write_error = "Write Error";
+#endif
+#ifdef L_read_error
+	const char * const bb_msg_read_error = "Read Error";
+#endif
+#ifdef L_name_longer_than_foo
+	const char * const bb_msg_name_longer_than_foo = "Names longer than %d chars not supported.";
+#endif
+#ifdef L_unknown
+	const char * const bb_msg_unknown = "(unknown)";
+#endif
+#ifdef L_can_not_create_raw_socket
+	const char * const bb_msg_can_not_create_raw_socket = "can't create raw socket";
+#endif
+#ifdef L_perm_denied_are_you_root
+	const char * const bb_msg_perm_denied_are_you_root = "permission denied. (are you root?)";
+#endif
+#ifdef L_msg_requires_arg
+	const char * const bb_msg_requires_arg = "%s requires an argument";
+#endif
+#ifdef L_msg_invalid_arg
+	const char * const bb_msg_invalid_arg = "invalid argument `%s' to `%s'";
+#endif
+#ifdef L_msg_standard_input
+	const char * const bb_msg_standard_input = "standard input";
+#endif
+#ifdef L_msg_standard_output
+	const char * const bb_msg_standard_output = "standard output";
+#endif
+
+#ifdef L_passwd_file
+#define PASSWD_FILE        "/etc/passwd"
+const char * const bb_path_passwd_file = PASSWD_FILE;
+#endif
+
+#ifdef L_shadow_file
+#define SHADOW_FILE        "/etc/shadow"
+const char * const bb_path_shadow_file = SHADOW_FILE;
+#endif
+
+#ifdef L_group_file
+#define GROUP_FILE         "/etc/group"
+const char * const bb_path_group_file = GROUP_FILE;
+#endif
+
+#ifdef L_gshadow_file
+#define GSHADOW_FILE       "/etc/gshadow"
+const char * const bb_path_gshadow_file = GSHADOW_FILE;
+#endif
+
+#ifdef L_nologin_file
+#define NOLOGIN_FILE       "/etc/nologin"
+const char * const bb_path_nologin_file = NOLOGIN_FILE;
+#endif
+
+#ifdef L_securetty_file
+#define SECURETTY_FILE     "/etc/securetty"
+const char * const bb_path_securetty_file = SECURETTY_FILE;
+#endif
+
+#ifdef L_motd_file
+#define MOTD_FILE          "/etc/motd"
+const char * const bb_path_motd_file = MOTD_FILE;
+#endif
+
+#ifdef L_shell_file
+const char * const bb_default_login_shell = LIBBB_DEFAULT_LOGIN_SHELL;
+#endif
+
+#ifdef L_bb_dev_null
+const char * const bb_dev_null = "/dev/null";
+#endif
+
+#ifdef L_bb_path_wtmp_file
+#include <utmp.h>
+/* This is usually something like "/var/adm/wtmp" or "/var/log/wtmp" */
+const char * const bb_path_wtmp_file =
+#if defined _PATH_WTMP
+_PATH_WTMP;
+#elif defined WTMP_FILE
+WTMP_FILE;
+#else
+# error unknown path to wtmp file
+#endif
+#endif
+
+
+#ifdef L_bb_common_bufsiz1
+char bb_common_bufsiz1[BUFSIZ+1];
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/mode_string.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/mode_string.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/mode_string.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,129 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * mode_string implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ */
+
+/* Aug 13, 2003
+ * Fix a bug reported by junkio at cox.net involving the mode_chars index.
+ */
+
+
+#include <assert.h>
+#include <sys/stat.h>
+
+#include "libbb.h"
+
+#if ( S_ISUID != 04000 ) || ( S_ISGID != 02000 ) || ( S_ISVTX != 01000 ) \
+ || ( S_IRUSR != 00400 ) || ( S_IWUSR != 00200 ) || ( S_IXUSR != 00100 ) \
+ || ( S_IRGRP != 00040 ) || ( S_IWGRP != 00020 ) || ( S_IXGRP != 00010 ) \
+ || ( S_IROTH != 00004 ) || ( S_IWOTH != 00002 ) || ( S_IXOTH != 00001 )
+#error permission bitflag value assumption(s) violated!
+#endif
+
+#if ( S_IFSOCK!= 0140000 ) || ( S_IFLNK != 0120000 ) \
+ || ( S_IFREG != 0100000 ) || ( S_IFBLK != 0060000 ) \
+ || ( S_IFDIR != 0040000 ) || ( S_IFCHR != 0020000 ) \
+ || ( S_IFIFO != 0010000 )
+#warning mode type bitflag value assumption(s) violated! falling back to larger version
+
+#if (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX) == 07777
+#undef mode_t
+#define mode_t unsigned short
+#endif
+
+static const mode_t mode_flags[] = {
+	S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID,
+	S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID,
+	S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX
+};
+
+/* The static const char arrays below are duplicated for the two cases
+ * because moving them ahead of the mode_flags declaration cause a text
+ * size increase with the gcc version I'm using. */
+
+/* The previous version used "0pcCd?bB-?l?s???".  However, the '0', 'C',
+ * and 'B' types don't appear to be available on linux.  So I removed them. */
+static const char type_chars[16] = "?pc?d?b?-?l?s???";
+/*                                  0123456789abcdef */
+static const char mode_chars[7] = "rwxSTst";
+
+const char *bb_mode_string(int mode)
+{
+	static char buf[12];
+	char *p = buf;
+
+	int i, j, k;
+
+	*p = type_chars[ (mode >> 12) & 0xf ];
+	i = 0;
+	do {
+		j = k = 0;
+		do {
+			*++p = '-';
+			if (mode & mode_flags[i+j]) {
+				*p = mode_chars[j];
+				k = j;
+			}
+		} while (++j < 3);
+		if (mode & mode_flags[i+j]) {
+			*p = mode_chars[3 + (k & 2) + ((i&8) >> 3)];
+		}
+		i += 4;
+	} while (i < 12);
+
+	/* Note: We don't bother with nul termination because bss initialization
+	 * should have taken care of that for us.  If the user scribbled in buf
+	 * memory, they deserve whatever happens.  But we'll at least assert. */
+	assert(buf[10] == 0);
+
+	return buf;
+}
+
+#else
+
+/* The previous version used "0pcCd?bB-?l?s???".  However, the '0', 'C',
+ * and 'B' types don't appear to be available on linux.  So I removed them. */
+static const char type_chars[16] = "?pc?d?b?-?l?s???";
+/*                                  0123456789abcdef */
+static const char mode_chars[7] = "rwxSTst";
+
+const char *bb_mode_string(int mode)
+{
+	static char buf[12];
+	char *p = buf;
+
+	int i, j, k, m;
+
+	*p = type_chars[ (mode >> 12) & 0xf ];
+	i = 0;
+	m = 0400;
+	do {
+		j = k = 0;
+		do {
+			*++p = '-';
+			if (mode & m) {
+				*p = mode_chars[j];
+				k = j;
+			}
+			m >>= 1;
+		} while (++j < 3);
+		++i;
+		if (mode & (010000 >> i)) {
+			*p = mode_chars[3 + (k & 2) + (i == 3)];
+		}
+	} while (i < 3);
+
+	/* Note: We don't bother with nul termination because bss initialization
+	 * should have taken care of that for us.  If the user scribbled in buf
+	 * memory, they deserve whatever happens.  But we'll at least assert. */
+	assert(buf[10] == 0);
+
+	return buf;
+}
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/mtab.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/mtab.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/mtab.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,75 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <mntent.h>
+#include "libbb.h"
+
+#define MTAB_MAX_ENTRIES 40
+
+#ifdef CONFIG_FEATURE_MTAB_SUPPORT
+void erase_mtab(const char *name)
+{
+	struct mntent entries[MTAB_MAX_ENTRIES];
+	int count = 0;
+	FILE *mountTable = setmntent(bb_path_mtab_file, "r");
+	struct mntent *m;
+
+	/* Check if reading the mtab file failed */
+	if (mountTable == 0
+			/* Bummer.  fall back on trying the /proc filesystem */
+			&& (mountTable = setmntent("/proc/mounts", "r")) == 0) {
+		bb_perror_msg(bb_path_mtab_file);
+		return;
+	}
+
+	while (((m = getmntent(mountTable)) != 0) && (count < MTAB_MAX_ENTRIES))
+	{
+		entries[count].mnt_fsname = strdup(m->mnt_fsname);
+		entries[count].mnt_dir = strdup(m->mnt_dir);
+		entries[count].mnt_type = strdup(m->mnt_type);
+		entries[count].mnt_opts = strdup(m->mnt_opts);
+		entries[count].mnt_freq = m->mnt_freq;
+		entries[count].mnt_passno = m->mnt_passno;
+		count++;
+	}
+	endmntent(mountTable);
+	if ((mountTable = setmntent(bb_path_mtab_file, "w"))) {
+		int i;
+
+		for (i = 0; i < count; i++) {
+			int result = (strcmp(entries[i].mnt_fsname, name) == 0
+						  || strcmp(entries[i].mnt_dir, name) == 0);
+
+			if (result)
+				continue;
+			else
+				addmntent(mountTable, &entries[i]);
+		}
+		endmntent(mountTable);
+	} else if (errno != EROFS)
+		bb_perror_msg(bb_path_mtab_file);
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/mtab_file.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/mtab_file.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/mtab_file.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,20 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include "libbb.h"
+
+
+/* Busybox mount uses either /proc/mounts or /etc/mtab to
+ * get the list of currently mounted filesystems */
+#if defined(CONFIG_FEATURE_MTAB_SUPPORT)
+const char bb_path_mtab_file[] = "/etc/mtab";
+#else
+const char bb_path_mtab_file[] = "/proc/mounts";
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/obscure.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/obscure.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/obscure.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,180 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini weak password checker implementation for busybox
+ *
+ * Copyright (C) 2006 Tito Ragusa <farmatito at tiscali.it>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/*	A good password:
+	1)	should contain at least six characters (man passwd);
+	2)	empty passwords are not permitted;
+	3)	should contain a mix of four different types of characters
+		upper case letters,
+		lower case letters,
+		numbers,
+		special characters such as !@#$%^&*,;".
+	This password types should not  be permitted:
+	a)	pure numbers: birthdates, social security number, license plate, phone numbers;
+	b)	words and all letters only passwords (uppercase, lowercase or mixed)
+		as palindromes, consecutive or repetitive letters
+		or adjacent letters on your keyboard;
+	c)	username, real name, company name or (e-mail?) address
+		in any form (as-is, reversed, capitalized, doubled, etc.).
+		(we can check only against username, gecos and hostname)
+	d)	common and obvious letter-number replacements
+		(e.g. replace the letter O with number 0)
+		such as "M1cr0$0ft" or "P at ssw0rd" (CAVEAT: we cannot check for them
+		without the use of a dictionary).
+
+	For each missing type of characters an increase of password length is
+	requested.
+
+	If user is root we warn only.
+
+	CAVEAT: some older versions of crypt() truncates passwords to 8 chars,
+	so that aaaaaaaa1Q$ is equal to aaaaaaaa making it possible to fool
+	some of our checks. We don't test for this special case as newer versions
+	of crypt do not truncate passwords.
+*/
+
+#include <ctype.h>
+#include <unistd.h>
+#include <string.h>
+#include <strings.h>
+
+#include "libbb.h"
+
+
+/* passwords should consist of 6 (to 8 characters) */
+#define MINLEN 6
+
+
+static int string_checker_helper(const char *p1, const char *p2) __attribute__ ((__pure__));
+
+static int string_checker_helper(const char *p1, const char *p2)
+{
+	/* as-is or capitalized */
+	if (strcasecmp(p1, p2) == 0
+	/* as sub-string */
+	|| strcasestr(p2, p1) != NULL
+	/* invert in case haystack is shorter than needle */
+	|| strcasestr(p1, p2) != NULL)
+		return 1;
+	return 0;
+}
+
+static int string_checker(const char *p1, const char *p2)
+{
+	int size;
+	/* check string */
+	int ret = string_checker_helper(p1, p2);
+	/* Make our own copy */
+	char *p = bb_xstrdup(p1);
+	/* reverse string */
+	size = strlen(p);
+
+	while (size--) {
+		*p = p1[size];
+		p++;
+	}
+	/* restore pointer */
+	p -= strlen(p1);
+	/* check reversed string */
+	ret |= string_checker_helper(p, p2);
+	/* clean up */
+	memset(p, 0, strlen(p1));
+	free(p);
+	return ret;
+}
+
+#define LOWERCASE          1
+#define UPPERCASE          2
+#define NUMBERS            4
+#define SPECIAL            8
+
+static const char *obscure_msg(const char *old_p, const char *new_p, const struct passwd *pw)
+{
+	int i;
+	int c;
+	int length;
+	int mixed = 0;
+	/* Add 1 for each type of characters to the minlen of password */
+	int size = MINLEN + 8;
+	const char *p;
+	char hostname[255];
+
+	/* size */
+	if (!new_p || (length = strlen(new_p)) < MINLEN)
+		return("too short");
+
+	/* no username as-is, as sub-string, reversed, capitalized, doubled */
+	if (string_checker(new_p, pw->pw_name)) {
+		return "similar to username";
+	}
+	/* no gecos as-is, as sub-string, reversed, capitalized, doubled */
+	if (*pw->pw_gecos && string_checker(new_p, pw->pw_gecos)) {
+		return "similar to gecos";
+	}
+	/* hostname as-is, as sub-string, reversed, capitalized, doubled */
+	if (gethostname(hostname, 255) == 0) {
+		hostname[254] = '\0';
+		if (string_checker(new_p, hostname)) {
+			return "similar to hostname";
+		}
+	}
+
+	/* Should / Must contain a mix of: */
+	for (i = 0; i < length; i++) {
+		if (islower(new_p[i])) {        /* a-z */
+			mixed |= LOWERCASE;
+		} else if (isupper(new_p[i])) { /* A-Z */
+			mixed |= UPPERCASE;
+		} else if (isdigit(new_p[i])) { /* 0-9 */
+			mixed |= NUMBERS;
+		} else  {                       /* special characters */
+			mixed |= SPECIAL;
+		}
+		/* More than 50% similar characters ? */
+		c = 0;
+		p = new_p;
+		while (1) {
+			if ((p = strchr(p, new_p[i])) == NULL) {
+				break;
+			}
+			c++;
+			if (!++p) {
+				break; /* move past the matched char if possible */
+			}
+		}
+
+		if (c >= (length / 2)) {
+			return "too many similar characters";
+		}
+	}
+	for (i=0; i<4; i++)
+		if (mixed & (1<<i)) size -= 2;
+	if (length < size)
+		return "too weak";
+
+	if (old_p && old_p[0] != '\0') {
+		/* check vs. old password */
+		if (string_checker(new_p, old_p)) {
+			return "similar to old password";
+		}
+	}
+	return NULL;
+}
+
+int obscure(const char *old, const char *newval, const struct passwd *pwdp)
+{
+	const char *msg;
+
+	if ((msg = obscure_msg(old, newval, pwdp))) {
+		printf("Bad password: %s.\n", msg);
+		/* If user is root warn only */
+		return (getuid())? 1 : 0;
+	}
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/opendir.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/opendir.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/opendir.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,37 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * wrapper for opendir()
+ *
+ * Copyright (C) 2006 Bernhard Fischer <busybox at busybox.net>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <sys/types.h>
+#include <dirent.h>
+#include "libbb.h"
+
+#ifdef L_bb_opendir
+DIR *bb_opendir(const char *path)
+{
+	DIR *dp;
+
+	if ((dp = opendir(path)) == NULL) {
+		bb_perror_msg("unable to open `%s'", path);
+		return NULL;
+	}
+	return dp;
+}
+#endif
+
+#ifdef L_bb_xopendir
+DIR *bb_xopendir(const char *path)
+{
+	DIR *dp;
+
+	if ((dp = opendir(path)) == NULL) {
+		bb_perror_msg_and_die("unable to open `%s'", path);
+	}
+	return dp;
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/parse_mode.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/parse_mode.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/parse_mode.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,177 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * parse_mode implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/chmod.html */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/stat.h>
+#include "libbb.h"
+
+#define FILEMODEBITS    (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
+
+int bb_parse_mode(const char *s, mode_t *current_mode)
+{
+	static const mode_t who_mask[] = {
+		S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO, /* a */
+		S_ISUID | S_IRWXU,		/* u */
+		S_ISGID | S_IRWXG,		/* g */
+		S_IRWXO					/* o */
+	};
+
+	static const mode_t perm_mask[] = {
+		S_IRUSR | S_IRGRP | S_IROTH, /* r */
+		S_IWUSR | S_IWGRP | S_IWOTH, /* w */
+		S_IXUSR | S_IXGRP | S_IXOTH, /* x */
+		S_IXUSR | S_IXGRP | S_IXOTH, /* X -- special -- see below */
+		S_ISUID | S_ISGID,		/* s */
+		S_ISVTX					/* t */
+	};
+
+	static const char who_chars[] = "augo";
+	static const char perm_chars[] = "rwxXst";
+
+	const char *p;
+
+	mode_t wholist;
+	mode_t permlist;
+	mode_t mask;
+	mode_t new_mode;
+	char op;
+
+	assert(s);
+
+	if (((unsigned int)(*s - '0')) < 8) {
+		unsigned long tmp;
+		char *e;
+
+		tmp = strtol(s, &e, 8);
+		if (*e || (tmp > 07777U)) { /* Check range and trailing chars. */
+			return 0;
+		}
+		*current_mode = tmp;
+		return 1;
+	}
+
+	mask = umask(0);
+	umask(mask);
+
+	new_mode = *current_mode;
+
+	/* Note: We allow empty clauses, and hence empty modes.
+	 * We treat an empty mode as no change to perms. */
+
+	while (*s) {	/* Process clauses. */
+
+		if (*s == ',') {	/* We allow empty clauses. */
+			++s;
+			continue;
+		}
+
+		/* Get a wholist. */
+		wholist = 0;
+
+	WHO_LIST:
+		p = who_chars;
+		do {
+			if (*p == *s) {
+				wholist |= who_mask[(int)(p-who_chars)];
+				if (!*++s) {
+					return 0;
+				}
+				goto WHO_LIST;
+			}
+		} while (*++p);
+
+		do {	/* Process action list. */
+			if ((*s != '+') && (*s != '-')) {
+				if (*s != '=') {
+					return 0;
+				}
+				/* Since op is '=', clear all bits corresponding to the
+				 * wholist, of all file bits if wholist is empty. */
+				permlist = ~FILEMODEBITS;
+				if (wholist) {
+					permlist = ~wholist;
+				}
+				new_mode &= permlist;
+			}
+			op = *s++;
+
+			/* Check for permcopy. */
+			p = who_chars + 1;	/* Skip 'a' entry. */
+			do {
+				if (*p == *s) {
+					int i = 0;
+					permlist = who_mask[(int)(p-who_chars)]
+							 & (S_IRWXU | S_IRWXG | S_IRWXO)
+							 & new_mode;
+					do {
+						if (permlist & perm_mask[i]) {
+							permlist |= perm_mask[i];
+						}
+					} while (++i < 3);
+					++s;
+					goto GOT_ACTION;
+				}
+			} while (*++p);
+
+			/* It was not a permcopy, so get a permlist. */
+			permlist = 0;
+
+		PERM_LIST:
+			p = perm_chars;
+			do {
+				if (*p == *s) {
+					if ((*p != 'X')
+						|| (new_mode & (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH))
+					) {
+						permlist |= perm_mask[(int)(p-perm_chars)];
+					}
+					if (!*++s) {
+						break;
+					}
+					goto PERM_LIST;
+				}
+			} while (*++p);
+
+		GOT_ACTION:
+			if (permlist) {	/* The permlist was nonempty. */
+				mode_t tmp = ~mask;
+				if (wholist) {
+					tmp = wholist;
+				}
+				permlist &= tmp;
+
+				if (op == '-') {
+					new_mode &= ~permlist;
+				} else {
+					new_mode |= permlist;
+				}
+			}
+		} while (*s && (*s != ','));
+	}
+
+	*current_mode = new_mode;
+
+	return 1;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/parse_number.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/parse_number.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/parse_number.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,63 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bb_xparse_number implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
+#include <assert.h>
+#include "libbb.h"
+
+unsigned long bb_xparse_number(const char *numstr,
+							   const struct suffix_mult *suffixes)
+{
+	unsigned long int r;
+	char *e;
+	int old_errno;
+
+	/* Since this is a lib function, we're not allowed to reset errno to 0.
+	 * Doing so could break an app that is deferring checking of errno.
+	 * So, save the old value so that we can restore it if successful. */
+	old_errno = errno;
+	errno = 0;
+	r = strtoul(numstr, &e, 10);
+
+	if ((numstr != e) && !errno) {
+		errno = old_errno;	/* Ok.  So restore errno. */
+		if (!*e) {
+			return r;
+		}
+		if (suffixes) {
+			assert(suffixes->suffix);	/* No nul suffixes. */
+			do {
+				if (strcmp(suffixes->suffix, e) == 0) {
+					if (ULONG_MAX / suffixes->mult < r) {	/* Overflow! */
+						break;
+					}
+					return r * suffixes->mult;
+				}
+				++suffixes;
+			} while (suffixes->suffix);
+		}
+	}
+	bb_error_msg_and_die("invalid number `%s'", numstr);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/perror_msg.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/perror_msg.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/perror_msg.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include "libbb.h"
+
+void bb_perror_msg(const char *s, ...)
+{
+	va_list p;
+
+	va_start(p, s);
+	bb_vperror_msg(s, p);
+	va_end(p);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/perror_msg_and_die.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/perror_msg_and_die.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/perror_msg_and_die.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,24 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include "libbb.h"
+
+void bb_perror_msg_and_die(const char *s, ...)
+{
+	va_list p;
+
+	va_start(p, s);
+	bb_vperror_msg(s, p);
+	va_end(p);
+	exit(bb_default_error_retval);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/perror_nomsg.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/perror_nomsg.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/perror_nomsg.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,30 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bb_perror_nomsg implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stddef.h>
+#include <libbb.h>
+
+void bb_perror_nomsg(void)
+{
+	/* Ignore the gcc warning about a null format string. */
+	bb_perror_msg(NULL);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/perror_nomsg_and_die.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/perror_nomsg_and_die.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/perror_nomsg_and_die.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,30 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bb_perror_nomsg_and_die implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stddef.h>
+#include "libbb.h"
+
+void bb_perror_nomsg_and_die(void)
+{
+	/* Ignore the gcc warning about a null format string. */
+	bb_perror_msg_and_die(NULL);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/print_file.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/print_file.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/print_file.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,55 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "libbb.h"
+
+void bb_xprint_and_close_file(FILE *file)
+{
+	bb_xfflush_stdout();
+	/* Note: Do not use STDOUT_FILENO here, as this is a lib routine
+	 *       and the calling code may have reassigned stdout. */
+	if (bb_copyfd_eof(fileno(file), STDOUT_FILENO) == -1) {
+		/* bb_copyfd outputs any needed messages, so just die. */
+		exit(bb_default_error_retval);
+	}
+	/* Note: Since we're reading, don't bother checking the return value
+	 *       of fclose().  The only possible failure is EINTR which
+	 *       should already have been taken care of. */
+	fclose(file);
+}
+
+/* Returns:
+ *    0      if successful
+ *   -1      if 'filename' does not exist or is a directory
+ *  exits with default error code if an error occurs
+ */
+
+int bb_xprint_file_by_name(const char *filename)
+{
+	FILE *f;
+
+#if 0
+	/* This check shouldn't be necessary for linux, but is left
+	* here disabled just in case. */
+	struct stat statBuf;
+
+	if(is_directory(filename, TRUE, &statBuf)) {
+		bb_error_msg("%s: Is directory", filename);
+	} else
+#endif
+	if ((f = bb_wfopen(filename, "r")) != NULL) {
+		bb_xprint_and_close_file(f);
+		return 0;
+	}
+
+	return -1;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/printf.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/printf.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/printf.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,104 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * *printf implementations for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* Mar 12, 2003     Manuel Novoa III
+ *
+ * While fwrite(), fputc(), fputs(), etc. all set the stream error flag
+ * on failure, the *printf functions are unique in that they can fail
+ * for reasons not related to the actual output itself.  Among the possible
+ * reasons for failure which don't set the streams error indicator,
+ * SUSv3 lists EILSEQ, EINVAL, and ENOMEM.
+ *
+ * In some cases, it would be desirable to have a group of *printf()
+ * functions available that _always_ set the stream error indicator on
+ * failure.  That would allow us to defer error checking until applet
+ * exit.  Unfortunately, there is no standard way of setting a streams
+ * error indicator... even though we can clear it with clearerr().
+ */
+
+/* Mar 22, 2006     Rich Felker III
+ *
+ * Actually there is a portable way to set the error indicator. See below.
+ * It is not thread-safe as written due to a race condition with file
+ * descriptors but since BB is not threaded that does not matter. It can be
+ * made thread-safe at the expense of slightly more code, if this is ever
+ * needed in the future.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include "libbb.h"
+
+#ifdef L_bb_vfprintf
+int bb_vfprintf(FILE * __restrict stream,
+					   const char * __restrict format,
+					   va_list arg)
+{
+	int rv;
+
+	if ((rv = vfprintf(stream, format, arg)) < 0) {
+		/* The following sequence portably sets the error flag for
+		 * stream on any remotely POSIX-compliant implementation. */
+
+		int errno_save = errno;
+		int fd = fileno(stream);
+		int tmp = dup(fd);
+
+		fflush(stream);
+		close(fd);
+		/* Force an attempted write to nonexistant fd => EBADF */
+		fputc(0, stream);
+		fflush(stream);
+		/* Restore the stream's original fd */
+		dup2(tmp, fd);
+		close(tmp);
+		errno = errno_save;
+	}
+
+	return rv;
+}
+#endif
+
+#ifdef L_bb_vprintf
+int bb_vprintf(const char * __restrict format, va_list arg)
+{
+	return bb_vfprintf(stdout, format, arg);
+}
+#endif
+
+#ifdef L_bb_fprintf
+int bb_fprintf(FILE * __restrict stream,
+					  const char * __restrict format, ...)
+{
+	va_list arg;
+	int rv;
+
+	va_start(arg, format);
+	rv = bb_vfprintf(stream, format, arg);
+	va_end(arg);
+
+	return rv;
+}
+#endif
+
+#ifdef L_bb_printf
+int bb_printf(const char * __restrict format, ...)
+{
+	va_list arg;
+	int rv;
+
+	va_start(arg, format);
+	rv = bb_vfprintf(stdout, format, arg);
+	va_end(arg);
+
+	return rv;
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/process_escape_sequence.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/process_escape_sequence.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/process_escape_sequence.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,89 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) Manuel Novoa III <mjn3 at codepoet.org>
+ * and Vladimir Oleynik <dzo at simtreas.ru>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <limits.h>
+#include <ctype.h>
+#include "libbb.h"
+
+#define WANT_HEX_ESCAPES 1
+
+/* Usual "this only works for ascii compatible encodings" disclaimer. */
+#undef _tolower
+#define _tolower(X) ((X)|((char) 0x20))
+
+char bb_process_escape_sequence(const char **ptr)
+{
+	static const char charmap[] = {
+		'a',  'b',  'f',  'n',  'r',  't',  'v',  '\\', 0,
+		'\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\\' };
+
+	const char *p;
+	const char *q;
+	unsigned int num_digits;
+	unsigned int r;
+	unsigned int n;
+	unsigned int d;
+	unsigned int base;
+
+	num_digits = n = 0;
+	base = 8;
+	q = *ptr;
+
+#ifdef WANT_HEX_ESCAPES
+	if (*q == 'x') {
+		++q;
+		base = 16;
+		++num_digits;
+	}
+#endif
+
+	do {
+		d = (unsigned int)(*q - '0');
+#ifdef WANT_HEX_ESCAPES
+		if (d >= 10) {
+			d = ((unsigned int)(_tolower(*q) - 'a')) + 10;
+		}
+#endif
+
+		if (d >= base) {
+#ifdef WANT_HEX_ESCAPES
+			if ((base == 16) && (!--num_digits)) {
+/*				return '\\'; */
+				--q;
+			}
+#endif
+			break;
+		}
+
+		r = n * base + d;
+		if (r > UCHAR_MAX) {
+			break;
+		}
+
+		n = r;
+		++q;
+	} while (++num_digits < 3);
+
+	if (num_digits == 0) {	/* mnemonic escape sequence? */
+		p = charmap;
+		do {
+			if (*p == *q) {
+				q++;
+				break;
+			}
+		} while (*++p);
+		n = *(p+(sizeof(charmap)/2));
+	}
+
+	*ptr = q;
+
+	return (char) n;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/procps.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/procps.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/procps.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,150 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright 1998 by Albert Cahalan; all rights reserved.
+ * Copyright (C) 2002 by Vladimir Oleynik <dzo at simtreas.ru>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <dirent.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "libbb.h"
+
+
+#define PROCPS_BUFSIZE 1024
+
+static int read_to_buf(const char *filename, void *buf)
+{
+	int fd;
+	ssize_t ret;
+
+	fd = open(filename, O_RDONLY);
+	if(fd < 0)
+		return -1;
+	ret = read(fd, buf, PROCPS_BUFSIZE-1);
+	((char *)buf)[ret > 0 ? ret : 0] = 0;
+	close(fd);
+	return ret;
+}
+
+
+procps_status_t * procps_scan(int save_user_arg0)
+{
+	static DIR *dir;
+	struct dirent *entry;
+	static procps_status_t ret_status;
+	char *name;
+	int n;
+	char status[32];
+	char *status_tail;
+	char buf[PROCPS_BUFSIZE];
+	procps_status_t curstatus;
+	int pid;
+	long tasknice;
+	struct stat sb;
+
+	if (!dir) {
+		dir = bb_xopendir("/proc");
+	}
+	for(;;) {
+		if((entry = readdir(dir)) == NULL) {
+			closedir(dir);
+			dir = 0;
+			return 0;
+		}
+		name = entry->d_name;
+		if (!(*name >= '0' && *name <= '9'))
+			continue;
+
+		memset(&curstatus, 0, sizeof(procps_status_t));
+		pid = atoi(name);
+		curstatus.pid = pid;
+
+		status_tail = status + sprintf(status, "/proc/%d", pid);
+		if(stat(status, &sb))
+			continue;
+		bb_getpwuid(curstatus.user, sb.st_uid, sizeof(curstatus.user));
+
+		/* see proc(5) for some details on this */
+		strcpy(status_tail, "/stat");
+		n = read_to_buf(status, buf);
+		if(n < 0)
+			continue;
+		name = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */
+		if(name == 0 || name[1] != ' ')
+			continue;
+		*name = 0;
+		sscanf(buf, "%*s (%15c", curstatus.short_cmd);
+		n = sscanf(name+2,
+		"%c %d "
+		"%*s %*s %*s %*s "     /* pgrp, session, tty, tpgid */
+		"%*s %*s %*s %*s %*s " /* flags, min_flt, cmin_flt, maj_flt, cmaj_flt */
+#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+		"%lu %lu "             /* utime, stime */
+#else
+		"%*s %*s "             /* utime, stime */
+#endif
+		"%*s %*s %*s "         /* cutime, cstime, priority */
+		"%ld "                 /* nice */
+		"%*s %*s %*s "         /* timeout, it_real_value, start_time */
+		"%*s "                 /* vsize */
+		"%ld",                 /* rss */
+		curstatus.state, &curstatus.ppid,
+#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+		&curstatus.utime, &curstatus.stime,
+#endif
+		&tasknice,
+		&curstatus.rss);
+#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+		if(n != 6)
+#else
+		if(n != 4)
+#endif
+			continue;
+
+		if (curstatus.rss == 0 && curstatus.state[0] != 'Z')
+			curstatus.state[1] = 'W';
+		else
+			curstatus.state[1] = ' ';
+		if (tasknice < 0)
+			curstatus.state[2] = '<';
+		else if (tasknice > 0)
+			curstatus.state[2] = 'N';
+		else
+			curstatus.state[2] = ' ';
+
+#ifdef PAGE_SHIFT
+		curstatus.rss <<= (PAGE_SHIFT - 10);     /* 2**10 = 1kb */
+#else
+		curstatus.rss *= (getpagesize() >> 10);     /* 2**10 = 1kb */
+#endif
+
+		if(save_user_arg0) {
+			strcpy(status_tail, "/cmdline");
+			n = read_to_buf(status, buf);
+			if(n > 0) {
+				if(buf[n-1]=='\n')
+					buf[--n] = 0;
+				name = buf;
+				while(n) {
+					if(((unsigned char)*name) < ' ')
+						*name = ' ';
+					name++;
+					n--;
+				}
+				*name = 0;
+				if(buf[0])
+					curstatus.cmd = strdup(buf);
+				/* if NULL it work true also */
+			}
+		}
+		return memcpy(&ret_status, &curstatus, sizeof(procps_status_t));
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/pw_encrypt.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/pw_encrypt.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/pw_encrypt.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,45 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routine.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "libbb.h"
+#include <string.h>
+#include <crypt.h>
+
+
+char *pw_encrypt(const char *clear, const char *salt)
+{
+	static char cipher[128];
+	char *cp;
+
+#ifdef CONFIG_FEATURE_SHA1_PASSWORDS
+	if (strncmp(salt, "$2$", 3) == 0) {
+		return sha1_crypt(clear);
+	}
+#endif
+	cp = (char *) crypt(clear, salt);
+	/* if crypt (a nonstandard crypt) returns a string too large,
+	   truncate it so we don't overrun buffers and hope there is
+	   enough security in what's left */
+	safe_strncpy(cipher, cp, sizeof(cipher));
+	return cipher;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/pwd2spwd.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/pwd2spwd.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/pwd2spwd.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,74 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright 1989 - 1994, Julianne Frances Haugh <jockgrrl at austin.rr.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <time.h>
+#include <sys/types.h>
+#include "libbb.h"
+#include "shadow_.h"
+
+/*
+ * pwd_to_spwd - create entries for new spwd structure
+ *
+ *	pwd_to_spwd() creates a new (struct spwd) containing the
+ *	information in the pointed-to (struct passwd).
+ */
+#define DAY (24L*3600L)
+#define WEEK (7*DAY)
+#define SCALE DAY
+struct spwd *pwd_to_spwd(const struct passwd *pw)
+{
+	static struct spwd sp;
+
+	/*
+	 * Nice, easy parts first.  The name and passwd map directly
+	 * from the old password structure to the new one.
+	 */
+	sp.sp_namp = pw->pw_name;
+	sp.sp_pwdp = pw->pw_passwd;
+
+	/*
+	 * Defaults used if there is no pw_age information.
+	 */
+	sp.sp_min = 0;
+	sp.sp_max = (10000L * DAY) / SCALE;
+	sp.sp_lstchg = time((time_t *) 0) / SCALE;
+
+	/*
+	 * These fields have no corresponding information in the password
+	 * file.  They are set to uninitialized values.
+	 */
+	sp.sp_warn = -1;
+	sp.sp_expire = -1;
+	sp.sp_inact = -1;
+	sp.sp_flag = -1;
+
+	return &sp;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/qmodule.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/qmodule.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/qmodule.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,29 @@
+/*
+   Copyright (C) 2002 Tim Riker <Tim at Rikers.org>
+   everyone seems to claim it someplace. ;-)
+*/
+
+#include <errno.h>
+
+#include "libbb.h"
+
+int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret);
+
+int my_query_module(const char *name, int which, void **buf,
+		size_t *bufsize, size_t *ret)
+{
+	int my_ret;
+
+	my_ret = query_module(name, which, *buf, *bufsize, ret);
+
+	if (my_ret == -1 && errno == ENOSPC) {
+		*buf = xrealloc(*buf, *ret);
+		*bufsize = *ret;
+
+		my_ret = query_module(name, which, *buf, *bufsize, ret);
+	}
+
+	return my_ret;
+}
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/read_package_field.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/read_package_field.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/read_package_field.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,114 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) many different people.
+ * If you wrote this, please acknowledge your work.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "libbb.h"
+
+/*
+ * Gets the next package field from package_buffer, seperated into the field name
+ * and field value, it returns the int offset to the first character of the next field
+ */
+int read_package_field(const char *package_buffer, char **field_name, char **field_value)
+{
+	int offset_name_start = 0;
+	int offset_name_end = 0;
+	int offset_value_start = 0;
+	int offset_value_end = 0;
+	int offset = 0;
+	int next_offset;
+	int name_length;
+	int value_length;
+	int exit_flag = FALSE;
+
+	if (package_buffer == NULL) {
+		*field_name = NULL;
+		*field_value = NULL;
+		return(-1);
+	}
+	while (1) {
+		next_offset = offset + 1;
+		switch (package_buffer[offset]) {
+			case('\0'):
+				exit_flag = TRUE;
+				break;
+			case(':'):
+				if (offset_name_end == 0) {
+					offset_name_end = offset;
+					offset_value_start = next_offset;
+				}
+				/* TODO: Name might still have trailing spaces if ':' isnt
+				 * immediately after name */
+				break;
+			case('\n'):
+				/* TODO: The char next_offset may be out of bounds */
+				if (package_buffer[next_offset] != ' ') {
+					exit_flag = TRUE;
+					break;
+				}
+			case('\t'):
+			case(' '):
+				/* increment the value start point if its a just filler */
+				if (offset_name_start == offset) {
+					offset_name_start++;
+				}
+				if (offset_value_start == offset) {
+					offset_value_start++;
+				}
+				break;
+		}
+		if (exit_flag) {
+			/* Check that the names are valid */
+			offset_value_end = offset;
+			name_length = offset_name_end - offset_name_start;
+			value_length = offset_value_end - offset_value_start;
+			if (name_length == 0) {
+				break;
+			}
+			if ((name_length > 0) && (value_length > 0)) {
+				break;
+			}
+
+			/* If not valid, start fresh with next field */
+			exit_flag = FALSE;
+			offset_name_start = offset + 1;
+			offset_name_end = 0;
+			offset_value_start = offset + 1;
+			offset_value_end = offset + 1;
+			offset++;
+		}
+		offset++;
+	}
+	if (name_length == 0) {
+		*field_name = NULL;
+	} else {
+		*field_name = bb_xstrndup(&package_buffer[offset_name_start], name_length);
+	}
+	if (value_length > 0) {
+		*field_value = bb_xstrndup(&package_buffer[offset_value_start], value_length);
+	} else {
+		*field_value = NULL;
+	}
+	return(next_offset);
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/recursive_action.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/recursive_action.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/recursive_action.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,118 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <stdlib.h>	/* free() */
+#include "libbb.h"
+
+#undef DEBUG_RECURS_ACTION
+
+
+/*
+ * Walk down all the directories under the specified
+ * location, and do something (something specified
+ * by the fileAction and dirAction function pointers).
+ *
+ * Unfortunately, while nftw(3) could replace this and reduce
+ * code size a bit, nftw() wasn't supported before GNU libc 2.1,
+ * and so isn't sufficiently portable to take over since glibc2.1
+ * is so stinking huge.
+ */
+int recursive_action(const char *fileName,
+					int recurse, int followLinks, int depthFirst,
+					int (*fileAction) (const char *fileName,
+									   struct stat * statbuf,
+									   void* userData),
+					int (*dirAction) (const char *fileName,
+									  struct stat * statbuf,
+									  void* userData),
+					void* userData)
+{
+	int status;
+	struct stat statbuf;
+	struct dirent *next;
+
+	if (followLinks)
+		status = stat(fileName, &statbuf);
+	else
+		status = lstat(fileName, &statbuf);
+
+	if (status < 0) {
+#ifdef DEBUG_RECURS_ACTION
+		bb_error_msg("status=%d followLinks=%d TRUE=%d",
+				status, followLinks, TRUE);
+#endif
+		bb_perror_msg("%s", fileName);
+		return FALSE;
+	}
+
+	if (! followLinks && (S_ISLNK(statbuf.st_mode))) {
+		if (fileAction == NULL)
+			return TRUE;
+		else
+			return fileAction(fileName, &statbuf, userData);
+	}
+
+	if (! recurse) {
+		if (S_ISDIR(statbuf.st_mode)) {
+			if (dirAction != NULL)
+				return (dirAction(fileName, &statbuf, userData));
+			else
+				return TRUE;
+		}
+	}
+
+	if (S_ISDIR(statbuf.st_mode)) {
+		DIR *dir;
+
+		if (dirAction != NULL && ! depthFirst) {
+			status = dirAction(fileName, &statbuf, userData);
+			if (! status) {
+				bb_perror_msg("%s", fileName);
+				return FALSE;
+			} else if (status == SKIP)
+				return TRUE;
+		}
+		dir = bb_opendir(fileName);
+		if (!dir) {
+			return FALSE;
+		}
+		status = TRUE;
+		while ((next = readdir(dir)) != NULL) {
+			char *nextFile;
+
+			nextFile = concat_subpath_file(fileName, next->d_name);
+			if(nextFile == NULL)
+				continue;
+			if (! recursive_action(nextFile, TRUE, followLinks, depthFirst,
+						fileAction, dirAction, userData)) {
+				status = FALSE;
+			}
+			free(nextFile);
+		}
+		closedir(dir);
+		if (dirAction != NULL && depthFirst) {
+			if (! dirAction(fileName, &statbuf, userData)) {
+				bb_perror_msg("%s", fileName);
+				return FALSE;
+			}
+		}
+		if (! status)
+			return FALSE;
+	} else {
+		if (fileAction == NULL)
+			return TRUE;
+		else
+			return fileAction(fileName, &statbuf, userData);
+	}
+	return TRUE;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/remove_file.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/remove_file.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/remove_file.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,111 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini remove_file implementation for busybox
+ *
+ * Copyright (C) 2001 Matt Kraai <kraai at alumni.carnegiemellon.edu>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <utime.h>
+#include <dirent.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include "libbb.h"
+
+int remove_file(const char *path, int flags)
+{
+	struct stat path_stat;
+	int path_exists = 1;
+
+	if (lstat(path, &path_stat) < 0) {
+		if (errno != ENOENT) {
+			bb_perror_msg("unable to stat `%s'", path);
+			return -1;
+		}
+
+		path_exists = 0;
+	}
+
+	if (!path_exists) {
+		if (!(flags & FILEUTILS_FORCE)) {
+			bb_perror_msg("cannot remove `%s'", path);
+			return -1;
+		}
+		return 0;
+	}
+
+	if (S_ISDIR(path_stat.st_mode)) {
+		DIR *dp;
+		struct dirent *d;
+		int status = 0;
+
+		if (!(flags & FILEUTILS_RECUR)) {
+			bb_error_msg("%s: is a directory", path);
+			return -1;
+		}
+
+		if ((!(flags & FILEUTILS_FORCE) && access(path, W_OK) < 0 &&
+					isatty(0)) ||
+				(flags & FILEUTILS_INTERACTIVE)) {
+			fprintf(stderr, "%s: descend into directory `%s'? ", bb_applet_name,
+					path);
+			if (!bb_ask_confirmation())
+				return 0;
+		}
+
+		if ((dp = bb_opendir(path)) == NULL) {
+			return -1;
+		}
+
+		while ((d = readdir(dp)) != NULL) {
+			char *new_path;
+
+			new_path = concat_subpath_file(path, d->d_name);
+			if(new_path == NULL)
+				continue;
+			if (remove_file(new_path, flags) < 0)
+				status = -1;
+			free(new_path);
+		}
+
+		if (closedir(dp) < 0) {
+			bb_perror_msg("unable to close `%s'", path);
+			return -1;
+		}
+
+		if (flags & FILEUTILS_INTERACTIVE) {
+			fprintf(stderr, "%s: remove directory `%s'? ", bb_applet_name, path);
+			if (!bb_ask_confirmation())
+				return status;
+		}
+
+		if (rmdir(path) < 0) {
+			bb_perror_msg("unable to remove `%s'", path);
+			return -1;
+		}
+
+		return status;
+	} else {
+		if ((!(flags & FILEUTILS_FORCE) && access(path, W_OK) < 0 &&
+					!S_ISLNK(path_stat.st_mode) &&
+					isatty(0)) ||
+				(flags & FILEUTILS_INTERACTIVE)) {
+			fprintf(stderr, "%s: remove `%s'? ", bb_applet_name, path);
+			if (!bb_ask_confirmation())
+				return 0;
+		}
+
+		if (unlink(path) < 0) {
+			bb_perror_msg("unable to remove `%s'", path);
+			return -1;
+		}
+
+		return 0;
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/restricted_shell.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/restricted_shell.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/restricted_shell.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,57 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright 1989 - 1991, Julianne Frances Haugh <jockgrrl at austin.rr.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <ctype.h>
+#include "libbb.h"
+
+
+
+/* Return 1 if SHELL is a restricted shell (one not returned by
+   getusershell), else 0, meaning it is a standard shell.  */
+
+int restricted_shell ( const char *shell )
+{
+	char *line;
+
+	setusershell ( );
+	while (( line = getusershell ( ))) {
+		if (( *line != '#' ) && ( strcmp ( line, shell ) == 0 ))
+			break;
+	}
+	endusershell ( );
+	return line ? 0 : 1;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/run_parts.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/run_parts.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/run_parts.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,119 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * run command from specified directory
+ *
+ *
+ * Copyright (C) 2001 by Emanuele Aina <emanuele.aina at tiscali.it>
+ * rewrite to vfork usage by
+ * Copyright (C) 2002 by Vladimir Oleynik <dzo at simtreas.ru>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "libbb.h"
+
+/* valid_name */
+/* True or false? Is this a valid filename (upper/lower alpha, digits,
+ * underscores, and hyphens only?)
+ */
+static int valid_name(const struct dirent *d)
+{
+	char *c = d->d_name;
+
+	while (*c) {
+		if (!isalnum(*c) && (*c != '_') && (*c != '-')) {
+			return 0;
+		}
+		++c;
+	}
+	return 1;
+}
+
+/* test mode = 1 is the same as official run_parts
+ * test_mode = 2 means to fail silently on missing directories
+ */
+
+int run_parts(char **args, const unsigned char test_mode, char **env)
+{
+	struct dirent **namelist = 0;
+	struct stat st;
+	char *filename;
+	char *arg0 = args[0];
+	int entries;
+	int i;
+	int exitstatus = 0;
+
+#if __GNUC__
+	/* Avoid longjmp clobbering */
+	(void) &i;
+	(void) &exitstatus;
+#endif
+	/* scandir() isn't POSIX, but it makes things easy. */
+	entries = scandir(arg0, &namelist, valid_name, alphasort);
+
+	if (entries == -1) {
+		if (test_mode & 2) {
+			return(2);
+		}
+		bb_perror_msg_and_die("unable to open `%s'", arg0);
+	}
+
+	for (i = 0; i < entries; i++) {
+
+		filename = concat_path_file(arg0, namelist[i]->d_name);
+
+		xstat(filename, &st);
+		if (S_ISREG(st.st_mode) && !access(filename, X_OK)) {
+			if (test_mode) {
+				puts(filename);
+			} else {
+				/* exec_errno is common vfork variable */
+				volatile int exec_errno = 0;
+				int result;
+				int pid;
+
+				if ((pid = vfork()) < 0) {
+					bb_perror_msg_and_die("failed to fork");
+				} else if (!pid) {
+					args[0] = filename;
+					execve(filename, args, env);
+					exec_errno = errno;
+					_exit(1);
+				}
+
+				waitpid(pid, &result, 0);
+				if(exec_errno) {
+					errno = exec_errno;
+					bb_perror_msg("failed to exec %s", filename);
+					exitstatus = 1;
+				}
+				if (WIFEXITED(result) && WEXITSTATUS(result)) {
+					bb_perror_msg("%s exited with return code %d", filename, WEXITSTATUS(result));
+					exitstatus = 1;
+				} else if (WIFSIGNALED(result)) {
+					bb_perror_msg("%s exited because of uncaught signal %d", filename, WTERMSIG(result));
+					exitstatus = 1;
+				}
+			}
+		}
+		else if (!S_ISDIR(st.st_mode)) {
+			bb_error_msg("component %s is not an executable plain file", filename);
+			exitstatus = 1;
+		}
+
+		free(namelist[i]);
+		free(filename);
+	}
+	free(namelist);
+
+	return(exitstatus);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/run_shell.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/run_shell.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/run_shell.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,107 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright 1989 - 1991, Julianne Frances Haugh <jockgrrl at austin.rr.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <ctype.h>
+#include "libbb.h"
+#ifdef CONFIG_SELINUX
+#include <selinux/selinux.h>  /* for setexeccon  */
+#endif
+
+#ifdef CONFIG_SELINUX
+static security_context_t current_sid=NULL;
+
+void
+renew_current_security_context(void)
+{
+  if  (current_sid)
+    freecon(current_sid);  /* Release old context  */
+
+  getcon(&current_sid);  /* update */
+
+  return;
+}
+void
+set_current_security_context(security_context_t sid)
+{
+  if  (current_sid)
+    freecon(current_sid);  /* Release old context  */
+
+  current_sid=sid;
+
+  return;
+}
+
+#endif
+
+/* Run SHELL, or DEFAULT_SHELL if SHELL is empty.
+   If COMMAND is nonzero, pass it to the shell with the -c option.
+   If ADDITIONAL_ARGS is nonzero, pass it to the shell as more
+   arguments.  */
+
+void run_shell ( const char *shell, int loginshell, const char *command, const char **additional_args)
+{
+	const char **args;
+	int argno = 1;
+	int additional_args_cnt = 0;
+
+	for ( args = additional_args; args && *args; args++ )
+		additional_args_cnt++;
+
+		args = (const char **) xmalloc (sizeof (char *) * ( 4  + additional_args_cnt ));
+
+	args [0] = bb_get_last_path_component ( bb_xstrdup ( shell ));
+
+	if ( loginshell )
+		args [0] = bb_xasprintf ("-%s", args [0]);
+
+	if ( command ) {
+		args [argno++] = "-c";
+		args [argno++] = command;
+	}
+	if ( additional_args ) {
+		for ( ; *additional_args; ++additional_args )
+			args [argno++] = *additional_args;
+	}
+	args [argno] = 0;
+#ifdef CONFIG_SELINUX
+	if ( (current_sid) && (!setexeccon(current_sid)) ) {
+	    freecon(current_sid);
+	    execve(shell, (char **) args, environ);
+	} else
+#endif
+	  execv ( shell, (char **) args );
+	bb_perror_msg_and_die ( "cannot run %s", shell );
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/safe_read.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/safe_read.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/safe_read.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,26 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include "libbb.h"
+
+
+
+ssize_t safe_read(int fd, void *buf, size_t count)
+{
+	ssize_t n;
+
+	do {
+		n = read(fd, buf, count);
+	} while (n < 0 && errno == EINTR);
+
+	return n;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/safe_strncpy.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/safe_strncpy.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/safe_strncpy.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,20 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <string.h>
+#include "libbb.h"
+
+
+
+/* Like strncpy but make sure the resulting string is always 0 terminated. */
+char * safe_strncpy(char *dst, const char *src, size_t size)
+{
+	dst[size-1] = '\0';
+	return strncpy(dst, src, size-1);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/safe_strtol.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/safe_strtol.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/safe_strtol.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,88 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+#include "libbb.h"
+
+#ifdef L_safe_strtoi
+int safe_strtoi(char *arg, int* value)
+{
+	int error;
+	long lvalue = *value;
+	error = safe_strtol(arg, &lvalue);
+	*value = (int) lvalue;
+	return error;
+}
+#endif
+
+#ifdef L_safe_strtod
+int safe_strtod(char *arg, double* value)
+{
+	char *endptr;
+	int errno_save = errno;
+
+	assert(arg!=NULL);
+	errno = 0;
+	*value = strtod(arg, &endptr);
+	if (errno != 0 || *endptr!='\0' || endptr==arg) {
+		return 1;
+	}
+	errno = errno_save;
+	return 0;
+}
+#endif
+
+#ifdef L_safe_strtol
+int safe_strtol(char *arg, long* value)
+{
+	char *endptr;
+	int errno_save = errno;
+
+	assert(arg!=NULL);
+	errno = 0;
+	*value = strtol(arg, &endptr, 0);
+	if (errno != 0 || *endptr!='\0' || endptr==arg) {
+		return 1;
+	}
+	errno = errno_save;
+	return 0;
+}
+#endif
+
+#ifdef L_safe_strtoul
+int safe_strtoul(char *arg, unsigned long* value)
+{
+	char *endptr;
+	int errno_save = errno;
+
+	assert(arg!=NULL);
+	errno = 0;
+	*value = strtoul(arg, &endptr, 0);
+	if (errno != 0 || *endptr!='\0' || endptr==arg) {
+		return 1;
+	}
+	errno = errno_save;
+	return 0;
+}
+#endif
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/safe_write.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/safe_write.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/safe_write.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,26 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include "libbb.h"
+
+
+
+ssize_t safe_write(int fd, const void *buf, size_t count)
+{
+	ssize_t n;
+
+	do {
+		n = write(fd, buf, count);
+	} while (n < 0 && errno == EINTR);
+
+	return n;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/setup_environment.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/setup_environment.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/setup_environment.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,93 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright 1989 - 1991, Julianne Frances Haugh <jockgrrl at austin.rr.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <ctype.h>
+#include "libbb.h"
+
+
+
+#define DEFAULT_LOGIN_PATH      "/bin:/usr/bin"
+#define DEFAULT_ROOT_LOGIN_PATH "/usr/sbin:/bin:/usr/bin:/sbin"
+
+static void xsetenv ( const char *key, const char *value )
+{
+	    if ( setenv ( key, value, 1 ))
+				bb_error_msg_and_die (bb_msg_memory_exhausted);
+}
+
+void setup_environment ( const char *shell, int loginshell, int changeenv, const struct passwd *pw )
+{
+	if ( loginshell ) {
+		const char *term;
+
+		/* Change the current working directory to be the home directory
+		 * of the user.  It is a fatal error for this process to be unable
+		 * to change to that directory.  There is no "default" home
+		 * directory.
+		 * Some systems default to HOME=/
+		 */
+		if ( chdir ( pw-> pw_dir )) {
+			if ( chdir ( "/" )) {
+				syslog ( LOG_WARNING, "unable to cd to %s' for user %s'\n", pw-> pw_dir, pw-> pw_name );
+				bb_error_msg_and_die ( "cannot cd to home directory or /" );
+			}
+			fputs ( "warning: cannot change to home directory\n", stderr );
+		}
+
+		/* Leave TERM unchanged.  Set HOME, SHELL, USER, LOGNAME, PATH.
+		   Unset all other environment variables.  */
+		term = getenv ("TERM");
+		clearenv ( );
+		if ( term )
+			xsetenv ( "TERM", term );
+		xsetenv ( "HOME",    pw-> pw_dir );
+		xsetenv ( "SHELL",   shell );
+		xsetenv ( "USER",    pw-> pw_name );
+		xsetenv ( "LOGNAME", pw-> pw_name );
+		xsetenv ( "PATH",    ( pw-> pw_uid ? DEFAULT_LOGIN_PATH : DEFAULT_ROOT_LOGIN_PATH ));
+	}
+	else if ( changeenv ) {
+		/* Set HOME, SHELL, and if not becoming a super-user,
+		   USER and LOGNAME.  */
+		xsetenv ( "HOME",  pw-> pw_dir );
+		xsetenv ( "SHELL", shell );
+		if  ( pw-> pw_uid ) {
+			xsetenv ( "USER",    pw-> pw_name );
+			xsetenv ( "LOGNAME", pw-> pw_name );
+		}
+	}
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/sha1.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/sha1.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/sha1.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,200 @@
+/*
+ *  Based on shasum from http://www.netsw.org/crypto/hash/
+ *  Majorly hacked up to use Dr Brian Gladman's sha1 code
+ *
+ *  Copyright (C) 2002 Dr Brian Gladman <brg at gladman.me.uk>, Worcester, UK.
+ *  Copyright (C) 2003 Glenn L. McGrath
+ *  Copyright (C) 2003 Erik Andersen
+ *  
+ *  LICENSE TERMS
+ *
+ *  The free distribution and use of this software in both source and binary
+ *  form is allowed (with or without changes) provided that:
+ *
+ *    1. distributions of this source code include the above copyright
+ *       notice, this list of conditions and the following disclaimer;
+ *
+ *    2. distributions in binary form include the above copyright
+ *       notice, this list of conditions and the following disclaimer
+ *       in the documentation and/or other associated materials;
+ *
+ *    3. the copyright holder's name is not used to endorse products
+ *       built using this software without specific written permission.
+ *
+ *  ALTERNATIVELY, provided that this notice is retained in full, this product
+ *  may be distributed under the terms of the GNU General Public License (GPL),
+ *  in which case the provisions of the GPL apply INSTEAD OF those given above.
+ *
+ *  DISCLAIMER
+ *
+ *  This software is provided 'as is' with no explicit or implied warranties
+ *  in respect of its properties, including, but not limited to, correctness
+ *  and/or fitness for purpose.
+ *  ---------------------------------------------------------------------------
+ *  Issue Date: 10/11/2002
+ *
+ *  This is a byte oriented version of SHA1 that operates on arrays of bytes
+ *  stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor
+ */
+
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libbb.h"
+
+# define SHA1_BLOCK_SIZE  64
+# define SHA1_DIGEST_SIZE 20
+# define SHA1_HASH_SIZE   SHA1_DIGEST_SIZE
+# define SHA2_GOOD        0
+# define SHA2_BAD         1
+
+# define rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
+
+# define SHA1_MASK   (SHA1_BLOCK_SIZE - 1)
+
+/* reverse byte order in 32-bit words   */
+#define ch(x,y,z)       ((z) ^ ((x) & ((y) ^ (z))))
+#define parity(x,y,z)   ((x) ^ (y) ^ (z))
+#define maj(x,y,z)      (((x) & (y)) | ((z) & ((x) | (y))))
+
+/* A normal version as set out in the FIPS. This version uses   */
+/* partial loop unrolling and is optimised for the Pentium 4    */
+# define rnd(f,k)    \
+    t = a; a = rotl32(a,5) + f(b,c,d) + e + k + w[i]; \
+    e = d; d = c; c = rotl32(b, 30); b = t
+
+
+static void sha1_compile(sha1_ctx_t *ctx)
+{
+	uint32_t w[80], i, a, b, c, d, e, t;
+
+	/* note that words are compiled from the buffer into 32-bit */
+	/* words in big-endian order so an order reversal is needed */
+	/* here on little endian machines                           */
+	for (i = 0; i < SHA1_BLOCK_SIZE / 4; ++i)
+		w[i] = htonl(ctx->wbuf[i]);
+
+	for (i = SHA1_BLOCK_SIZE / 4; i < 80; ++i)
+		w[i] = rotl32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
+
+	a = ctx->hash[0];
+	b = ctx->hash[1];
+	c = ctx->hash[2];
+	d = ctx->hash[3];
+	e = ctx->hash[4];
+
+	for (i = 0; i < 20; ++i) {
+		rnd(ch, 0x5a827999);
+	}
+
+	for (i = 20; i < 40; ++i) {
+		rnd(parity, 0x6ed9eba1);
+	}
+
+	for (i = 40; i < 60; ++i) {
+		rnd(maj, 0x8f1bbcdc);
+	}
+
+	for (i = 60; i < 80; ++i) {
+		rnd(parity, 0xca62c1d6);
+	}
+
+	ctx->hash[0] += a;
+	ctx->hash[1] += b;
+	ctx->hash[2] += c;
+	ctx->hash[3] += d;
+	ctx->hash[4] += e;
+}
+
+void sha1_begin(sha1_ctx_t *ctx)
+{
+	ctx->count[0] = ctx->count[1] = 0;
+	ctx->hash[0] = 0x67452301;
+	ctx->hash[1] = 0xefcdab89;
+	ctx->hash[2] = 0x98badcfe;
+	ctx->hash[3] = 0x10325476;
+	ctx->hash[4] = 0xc3d2e1f0;
+}
+
+/* SHA1 hash data in an array of bytes into hash buffer and call the        */
+/* hash_compile function as required.                                       */
+void sha1_hash(const void *data, size_t length, sha1_ctx_t *ctx)
+{
+	uint32_t pos = (uint32_t) (ctx->count[0] & SHA1_MASK);
+	uint32_t freeb = SHA1_BLOCK_SIZE - pos;
+	const unsigned char *sp = data;
+
+	if ((ctx->count[0] += length) < length)
+		++(ctx->count[1]);
+
+	while (length >= freeb) {	/* tranfer whole blocks while possible  */
+		memcpy(((unsigned char *) ctx->wbuf) + pos, sp, freeb);
+		sp += freeb;
+		length -= freeb;
+		freeb = SHA1_BLOCK_SIZE;
+		pos = 0;
+		sha1_compile(ctx);
+	}
+
+	memcpy(((unsigned char *) ctx->wbuf) + pos, sp, length);
+}
+
+void *sha1_end(void *resbuf, sha1_ctx_t *ctx)
+{
+	/* SHA1 Final padding and digest calculation  */
+#if BB_BIG_ENDIAN
+	static uint32_t mask[4] = { 0x00000000, 0xff000000, 0xffff0000, 0xffffff00 };
+	static uint32_t bits[4] = { 0x80000000, 0x00800000, 0x00008000, 0x00000080 };
+#else
+	static uint32_t mask[4] = { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff };
+	static uint32_t bits[4] = { 0x00000080, 0x00008000, 0x00800000, 0x80000000 };
+#endif
+
+	uint8_t *hval = resbuf;
+	uint32_t i, cnt = (uint32_t) (ctx->count[0] & SHA1_MASK);
+
+	/* mask out the rest of any partial 32-bit word and then set    */
+	/* the next byte to 0x80. On big-endian machines any bytes in   */
+	/* the buffer will be at the top end of 32 bit words, on little */
+	/* endian machines they will be at the bottom. Hence the AND    */
+	/* and OR masks above are reversed for little endian systems    */
+	ctx->wbuf[cnt >> 2] =
+		(ctx->wbuf[cnt >> 2] & mask[cnt & 3]) | bits[cnt & 3];
+
+	/* we need 9 or more empty positions, one for the padding byte  */
+	/* (above) and eight for the length count.  If there is not     */
+	/* enough space pad and empty the buffer                        */
+	if (cnt > SHA1_BLOCK_SIZE - 9) {
+		if (cnt < 60)
+			ctx->wbuf[15] = 0;
+		sha1_compile(ctx);
+		cnt = 0;
+	} else				/* compute a word index for the empty buffer positions  */
+		cnt = (cnt >> 2) + 1;
+
+	while (cnt < 14)	/* and zero pad all but last two positions      */
+		ctx->wbuf[cnt++] = 0;
+
+	/* assemble the eight byte counter in the buffer in big-endian  */
+	/* format					               */
+
+	ctx->wbuf[14] = htonl((ctx->count[1] << 3) | (ctx->count[0] >> 29));
+	ctx->wbuf[15] = htonl(ctx->count[0] << 3);
+
+	sha1_compile(ctx);
+
+	/* extract the hash value as bytes in case the hash buffer is   */
+	/* misaligned for 32-bit words                                  */
+
+	for (i = 0; i < SHA1_DIGEST_SIZE; ++i)
+		hval[i] = (unsigned char) (ctx->hash[i >> 2] >> 8 * (~i & 3));
+	
+	return resbuf;
+}
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/simplify_path.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/simplify_path.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/simplify_path.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,64 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bb_simplify_path implementation for busybox
+ *
+ * Copyright (C) 2001  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdlib.h>
+#include "libbb.h"
+
+char *bb_simplify_path(const char *path)
+{
+	char *s, *start, *p;
+
+	if (path[0] == '/')
+		start = bb_xstrdup(path);
+	else {
+		s = xgetcwd(NULL);
+		start = concat_path_file(s, path);
+		free(s);
+	}
+	p = s = start;
+
+	do {
+		if (*p == '/') {
+			if (*s == '/') {	/* skip duplicate (or initial) slash */
+				continue;
+			} else if (*s == '.') {
+				if (s[1] == '/' || s[1] == 0) {	/* remove extra '.' */
+					continue;
+				} else if ((s[1] == '.') && (s[2] == '/' || s[2] == 0)) {
+					++s;
+					if (p > start) {
+						while (*--p != '/');	/* omit previous dir */
+					}
+					continue;
+				}
+			}
+		}
+		*++p = *s;
+	} while (*++s);
+
+	if ((p == start) || (*p != '/')) {	/* not a trailing slash */
+		++p;					/* so keep last character */
+	}
+	*p = 0;
+
+	return start;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/skip_whitespace.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/skip_whitespace.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/skip_whitespace.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,18 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * skip_whitespace implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <ctype.h>
+#include "libbb.h"
+
+char *skip_whitespace(const char *s)
+{
+	while (isspace(*s)) ++s;
+
+	return (char *) s;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/speed_table.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/speed_table.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/speed_table.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,117 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * compact speed_t <-> speed functions for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <termios.h>
+#include "libbb.h"
+
+struct speed_map {
+	unsigned short speed;
+	unsigned short value;
+};
+
+static const struct speed_map speeds[] = {
+	{B0, 0},
+	{B50, 50},
+	{B75, 75},
+	{B110, 110},
+	{B134, 134},
+	{B150, 150},
+	{B200, 200},
+	{B300, 300},
+	{B600, 600},
+	{B1200, 1200},
+	{B1800, 1800},
+	{B2400, 2400},
+	{B4800, 4800},
+	{B9600, 9600},
+#ifdef	B19200
+	{B19200, 19200},
+#elif defined(EXTA)
+	{EXTA, 19200},
+#endif
+#ifdef	B38400
+	{B38400, 38400/256 + 0x8000U},
+#elif defined(EXTB)
+	{EXTB, 38400/256 + 0x8000U},
+#endif
+#ifdef B57600
+	{B57600, 57600/256 + 0x8000U},
+#endif
+#ifdef B115200
+	{B115200, 115200/256 + 0x8000U},
+#endif
+#ifdef B230400
+	{B230400, 230400/256 + 0x8000U},
+#endif
+#ifdef B460800
+	{B460800, 460800/256 + 0x8000U},
+#endif
+};
+
+enum { NUM_SPEEDS = (sizeof(speeds) / sizeof(struct speed_map)) };
+
+unsigned int tty_baud_to_value(speed_t speed)
+{
+	int i = 0;
+
+	do {
+		if (speed == speeds[i].speed) {
+			if (speeds[i].value & 0x8000U) {
+				return ((unsigned long) (speeds[i].value) & 0x7fffU) * 256;
+			}
+			return speeds[i].value;
+		}
+	} while (++i < NUM_SPEEDS);
+
+	return 0;
+}
+
+speed_t tty_value_to_baud(unsigned int value)
+{
+	int i = 0;
+
+	do {
+		if (value == tty_baud_to_value(speeds[i].speed)) {
+			return speeds[i].speed;
+		}
+	} while (++i < NUM_SPEEDS);
+
+	return (speed_t) - 1;
+}
+
+#if 0
+/* testing code */
+#include <stdio.h>
+
+int main(void)
+{
+	unsigned long v;
+	speed_t s;
+
+	for (v = 0 ; v < 500000 ; v++) {
+		s = tty_value_to_baud(v);
+		if (s == (speed_t) -1) {
+			continue;
+		}
+		printf("v = %lu -- s = %0lo\n", v, (unsigned long) s);
+	}
+
+	printf("-------------------------------\n");
+
+	for (s = 0 ; s < 010017+1 ; s++) {
+		v = tty_baud_to_value(s);
+		if (!v) {
+			continue;
+		}
+		printf("v = %lu -- s = %0lo\n", v, (unsigned long) s);
+	}
+
+	return 0;
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/trim.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/trim.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/trim.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,31 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) many different people.
+ * If you wrote this, please acknowledge your work.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "libbb.h"
+
+
+void trim(char *s)
+{
+	size_t len = strlen(s);
+	size_t lws;
+
+	/* trim trailing whitespace */
+	while (len && isspace(s[len-1])) --len;
+
+	/* trim leading whitespace */
+	if(len) {
+		lws = strspn(s, " \n\r\t\v");
+		memmove(s, s + lws, len -= lws);
+	}
+	s[len] = 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/u_signal_names.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/u_signal_names.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/u_signal_names.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,179 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) many different people.
+ * If you wrote this, please acknowledge your work.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <signal.h>
+#include <ctype.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libbb.h"
+
+struct signal_name {
+	const char *name;
+	int number;
+};
+
+static const struct signal_name signames[] = {
+	/* POSIX signals */
+	{ "EXIT",       0 },            /* 0 */
+	{ "HUP",        SIGHUP },       /* 1 */
+	{ "INT",        SIGINT },       /* 2 */
+	{ "QUIT",       SIGQUIT },      /* 3 */
+	{ "ILL",        SIGILL },       /* 4 */
+	{ "ABRT",       SIGABRT },      /* 6 */
+	{ "FPE",        SIGFPE },       /* 8 */
+	{ "KILL",       SIGKILL },      /* 9 */
+	{ "SEGV",       SIGSEGV },      /* 11 */
+	{ "PIPE",       SIGPIPE },      /* 13 */
+	{ "ALRM",       SIGALRM },      /* 14 */
+	{ "TERM",       SIGTERM },      /* 15 */
+	{ "USR1",       SIGUSR1 },      /* 10 (arm,i386,m68k,ppc), 30 (alpha,sparc*), 16 (mips) */
+	{ "USR2",       SIGUSR2 },      /* 12 (arm,i386,m68k,ppc), 31 (alpha,sparc*), 17 (mips) */
+	{ "CHLD",       SIGCHLD },      /* 17 (arm,i386,m68k,ppc), 20 (alpha,sparc*), 18 (mips) */
+	{ "CONT",       SIGCONT },      /* 18 (arm,i386,m68k,ppc), 19 (alpha,sparc*), 25 (mips) */
+	{ "STOP",       SIGSTOP },      /* 19 (arm,i386,m68k,ppc), 17 (alpha,sparc*), 23 (mips) */
+	{ "TSTP",       SIGTSTP },      /* 20 (arm,i386,m68k,ppc), 18 (alpha,sparc*), 24 (mips) */
+	{ "TTIN",       SIGTTIN },      /* 21 (arm,i386,m68k,ppc,alpha,sparc*), 26 (mips) */
+	{ "TTOU",       SIGTTOU },      /* 22 (arm,i386,m68k,ppc,alpha,sparc*), 27 (mips) */
+	/* Miscellaneous other signals */
+#ifdef SIGTRAP
+	{ "TRAP",       SIGTRAP },      /* 5 */
+#endif
+#ifdef SIGIOT
+	{ "IOT",        SIGIOT },       /* 6, same as SIGABRT */
+#endif
+#ifdef SIGEMT
+	{ "EMT",        SIGEMT },       /* 7 (mips,alpha,sparc*) */
+#endif
+#ifdef SIGBUS
+	{ "BUS",        SIGBUS },       /* 7 (arm,i386,m68k,ppc), 10 (mips,alpha,sparc*) */
+#endif
+#ifdef SIGSYS
+	{ "SYS",        SIGSYS },       /* 12 (mips,alpha,sparc*) */
+#endif
+#ifdef SIGSTKFLT
+	{ "STKFLT",     SIGSTKFLT },    /* 16 (arm,i386,m68k,ppc) */
+#endif
+#ifdef SIGURG
+	{ "URG",        SIGURG },       /* 23 (arm,i386,m68k,ppc), 16 (alpha,sparc*), 21 (mips) */
+#endif
+#ifdef SIGIO
+	{ "IO",         SIGIO },        /* 29 (arm,i386,m68k,ppc), 23 (alpha,sparc*), 22 (mips) */
+#endif
+#ifdef SIGPOLL
+	{ "POLL",       SIGPOLL },      /* same as SIGIO */
+#endif
+#ifdef SIGCLD
+	{ "CLD",        SIGCLD },       /* same as SIGCHLD (mips) */
+#endif
+#ifdef SIGXCPU
+	{ "XCPU",       SIGXCPU },      /* 24 (arm,i386,m68k,ppc,alpha,sparc*), 30 (mips) */
+#endif
+#ifdef SIGXFSZ
+	{ "XFSZ",       SIGXFSZ },      /* 25 (arm,i386,m68k,ppc,alpha,sparc*), 31 (mips) */
+#endif
+#ifdef SIGVTALRM
+	{ "VTALRM",     SIGVTALRM },    /* 26 (arm,i386,m68k,ppc,alpha,sparc*), 28 (mips) */
+#endif
+#ifdef SIGPROF
+	{ "PROF",       SIGPROF },      /* 27 (arm,i386,m68k,ppc,alpha,sparc*), 29 (mips) */
+#endif
+#ifdef SIGPWR
+	{ "PWR",        SIGPWR },       /* 30 (arm,i386,m68k,ppc), 29 (alpha,sparc*), 19 (mips) */
+#endif
+#ifdef SIGINFO
+	{ "INFO",       SIGINFO },      /* 29 (alpha) */
+#endif
+#ifdef SIGLOST
+	{ "LOST",       SIGLOST },      /* 29 (arm,i386,m68k,ppc,sparc*) */
+#endif
+#ifdef SIGWINCH
+	{ "WINCH",      SIGWINCH },     /* 28 (arm,i386,m68k,ppc,alpha,sparc*), 20 (mips) */
+#endif
+#ifdef SIGUNUSED
+	{ "UNUSED",     SIGUNUSED },    /* 31 (arm,i386,m68k,ppc) */
+#endif
+	{0, 0}
+};
+
+/*
+	if str_sig == NULL returned signal name [*signo],
+	if str_sig != NULL - set *signo from signal_name,
+		findings with digit number or with or without SIG-prefix name
+
+	if startnum=0 flag for support finding zero signal,
+		but str_sig="0" always found, (hmm - standart or realize?)
+	if startnum<0 returned reverse signal_number  <-> signal_name
+	if found error - returned NULL
+
+*/
+
+const char *
+u_signal_names(const char *str_sig, int *signo, int startnum)
+{
+	static char retstr[16];
+	const struct signal_name *s = signames;
+	static const char prefix[] = "SIG";
+	const char *sptr;
+
+	if(startnum)
+		s++;
+	if(str_sig==NULL) {
+		while (s->name != 0) {
+			if(s->number == *signo)
+				break;
+			s++;
+		}
+	} else {
+		if (isdigit(((unsigned char)*str_sig))) {
+			char *endp;
+			long int sn = strtol(str_sig, &endp, 10);
+			/* test correct and overflow */
+			if(*endp == 0 && sn >= 0 && sn < NSIG) {
+				*signo = (int)sn;
+				/* test for unnamed */
+				sptr = u_signal_names(0, signo, 0);
+				if(sptr==NULL)
+					return NULL;
+				if(sn!=0)
+					sptr += 3;
+				return sptr;
+			}
+		} else {
+			sptr = str_sig;
+			while (s->name != 0) {
+				if (strcasecmp(s->name, sptr) == 0) {
+					*signo = s->number;
+					if(startnum<0) {
+						sprintf(retstr, "%d", *signo);
+						return retstr;
+					}
+					break;
+				}
+				if(s!=signames && sptr == str_sig &&
+						strncasecmp(sptr, prefix, 3) == 0) {
+					sptr += 3;      /* strlen(prefix) */
+					continue;
+				}
+				sptr = str_sig;
+				s++;
+			}
+		}
+	}
+	if(s->name==0)
+		return NULL;
+	if(s!=signames)
+		strcpy(retstr, prefix);
+	 else
+		retstr[0] = 0;
+	return strcat(retstr, s->name);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/vdprintf.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/vdprintf.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/vdprintf.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,25 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include "libbb.h"
+
+
+
+#if (__GLIBC__ < 2)
+int vdprintf(int d, const char *format, va_list ap)
+{
+	char buf[BUF_SIZE];
+	int len;
+
+	len = vsprintf(buf, format, ap);
+	return write(d, buf, len);
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/verror_msg.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/verror_msg.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/verror_msg.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,21 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include "libbb.h"
+
+void bb_verror_msg(const char *s, va_list p)
+{
+	fflush(stdout);
+	fprintf(stderr, "%s: ", bb_applet_name);
+	vfprintf(stderr, s, p);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/vfork_daemon_rexec.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/vfork_daemon_rexec.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/vfork_daemon_rexec.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,67 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Rexec program for system have fork() as vfork() with foreground option
+ *
+ * Copyright (C) Vladimir N. Oleynik <dzo at simtreas.ru>
+ * Copyright (C) 2003 Russ Dill <Russ.Dill at asu.edu>
+ *
+ * daemon() portion taken from uClibc:
+ *
+ * Copyright (c) 1991, 1993
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Modified for uClibc by Erik Andersen <andersee at debian.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <paths.h>
+#include "libbb.h"
+
+
+#ifdef BB_NOMMU
+void vfork_daemon_rexec(int nochdir, int noclose,
+		int argc, char **argv, char *foreground_opt)
+{
+	int fd;
+	char **vfork_args;
+	int a = 0;
+
+	setsid();
+
+	if (!nochdir)
+		chdir("/");
+
+	if (!noclose && (fd = open(bb_dev_null, O_RDWR, 0)) != -1) {
+		dup2(fd, STDIN_FILENO);
+		dup2(fd, STDOUT_FILENO);
+		dup2(fd, STDERR_FILENO);
+		if (fd > 2)
+			close(fd);
+	}
+
+	vfork_args = xcalloc(sizeof(char *), argc + 3);
+	vfork_args[a++] = "/bin/busybox";
+	while(*argv) {
+	    vfork_args[a++] = *argv;
+	    argv++;
+	}
+	vfork_args[a] = foreground_opt;
+	switch (vfork()) {
+	case 0: /* child */
+		/* Make certain we are not a session leader, or else we
+		 * might reacquire a controlling terminal */
+		if (vfork())
+			_exit(0);
+		execv(vfork_args[0], vfork_args);
+		bb_perror_msg_and_die("execv %s", vfork_args[0]);
+	case -1: /* error */
+		bb_perror_msg_and_die("vfork");
+	default: /* parent */
+		exit(0);
+	}
+}
+#endif /* BB_NOMMU */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/vherror_msg.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/vherror_msg.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/vherror_msg.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,37 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdarg.h>
+#include <netdb.h>
+#include <stdio.h>
+
+#include "libbb.h"
+
+
+void bb_vherror_msg(const char *s, va_list p)
+{
+	if(s == 0)
+		s = "";
+	bb_verror_msg(s, p);
+	if (*s)
+		fputs(": ", stderr);
+	herror("");
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/vperror_msg.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/vperror_msg.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/vperror_msg.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include "libbb.h"
+
+void bb_vperror_msg(const char *s, va_list p)
+{
+	int err=errno;
+	if(s == 0) s = "";
+	bb_verror_msg(s, p);
+	if (*s) s = ": ";
+	fprintf(stderr, "%s%s\n", s, strerror(err));
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/warn_ignoring_args.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/warn_ignoring_args.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/warn_ignoring_args.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,30 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * warn_ignoring_args implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <libbb.h>
+
+void bb_warn_ignoring_args(int n)
+{
+	if (n) {
+		bb_perror_msg("ignoring all arguments");
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/wfopen.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/wfopen.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/wfopen.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,22 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include "libbb.h"
+
+FILE *bb_wfopen(const char *path, const char *mode)
+{
+	FILE *fp;
+	if ((fp = fopen(path, mode)) == NULL) {
+		bb_perror_msg("%s", path);
+		errno = 0;
+	}
+	return fp;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/wfopen_input.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/wfopen_input.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/wfopen_input.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,45 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * wfopen_input implementation for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* A number of applets need to open a file for reading, where the filename
+ * is a command line arg.  Since often that arg is '-' (meaning stdin),
+ * we avoid testing everywhere by consolidating things in this routine.
+ *
+ * Note: We also consider "" to main stdin (for 'cmp' at least).
+ */
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <libbb.h>
+
+FILE *bb_wfopen_input(const char *filename)
+{
+	FILE *fp = stdin;
+
+	if ((filename != bb_msg_standard_input)
+		&& filename[0] && ((filename[0] != '-') || filename[1])
+	) {
+		fp = bb_wfopen(filename, "r");
+	}
+
+	return fp;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xconnect.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xconnect.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xconnect.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,72 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Connect to host at port using address resolution from getaddrinfo
+ *
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "libbb.h"
+
+/* Return network byte ordered port number for a service.
+ * If "port" is a number use it as the port.
+ * If "port" is a name it is looked up in /etc/services, if it isnt found return
+ * default_port
+ */
+unsigned short bb_lookup_port(const char *port, const char *protocol, unsigned short default_port)
+{
+	unsigned short port_nr = htons(default_port);
+	if (port) {
+		char *endptr;
+		int old_errno;
+		long port_long;
+
+		/* Since this is a lib function, we're not allowed to reset errno to 0.
+		 * Doing so could break an app that is deferring checking of errno. */
+		old_errno = errno;
+		errno = 0;
+		port_long = strtol(port, &endptr, 10);
+		if (errno != 0 || *endptr!='\0' || endptr==port || port_long < 0 || port_long > 65535) {
+			struct servent *tserv = getservbyname(port, protocol);
+			if (tserv) {
+				port_nr = tserv->s_port;
+			}
+		} else {
+			port_nr = htons(port_long);
+		}
+		errno = old_errno;
+	}
+	return port_nr;
+}
+
+void bb_lookup_host(struct sockaddr_in *s_in, const char *host)
+{
+	struct hostent *he;
+
+	memset(s_in, 0, sizeof(struct sockaddr_in));
+	s_in->sin_family = AF_INET;
+	he = xgethostbyname(host);
+	memcpy(&(s_in->sin_addr), he->h_addr_list[0], he->h_length);
+}
+
+int xconnect(struct sockaddr_in *s_addr)
+{
+	int s = bb_xsocket(AF_INET, SOCK_STREAM, 0);
+	if (connect(s, (struct sockaddr *)s_addr, sizeof(struct sockaddr_in)) < 0)
+	{
+		if (ENABLE_FEATURE_CLEAN_UP) close(s);
+		bb_perror_msg_and_die("Unable to connect to remote host (%s)",
+				inet_ntoa(s_addr->sin_addr));
+	}
+	return s;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xfuncs.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xfuncs.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xfuncs.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,244 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "busybox.h"
+
+#ifndef DMALLOC
+#ifdef L_xmalloc
+void *xmalloc(size_t size)
+{
+	void *ptr = malloc(size);
+	if (ptr == NULL && size != 0)
+		bb_error_msg_and_die(bb_msg_memory_exhausted);
+	return ptr;
+}
+#endif
+
+#ifdef L_xrealloc
+void *xrealloc(void *ptr, size_t size)
+{
+	ptr = realloc(ptr, size);
+	if (ptr == NULL && size != 0)
+		bb_error_msg_and_die(bb_msg_memory_exhausted);
+	return ptr;
+}
+#endif
+
+#ifdef L_xzalloc
+void *xzalloc(size_t size)
+{
+	void *ptr = xmalloc(size);
+	memset(ptr, 0, size);
+	return ptr;
+}
+#endif
+
+#ifdef L_xcalloc
+void *xcalloc(size_t nmemb, size_t size)
+{
+	void *ptr = calloc(nmemb, size);
+	if (ptr == NULL && nmemb != 0 && size != 0)
+		bb_error_msg_and_die(bb_msg_memory_exhausted);
+	return ptr;
+}
+#endif
+#endif /* DMALLOC */
+
+#ifdef L_xstrdup
+char * bb_xstrdup (const char *s)
+{
+	char *t;
+
+	if (s == NULL)
+		return NULL;
+
+	t = strdup (s);
+
+	if (t == NULL)
+		bb_error_msg_and_die(bb_msg_memory_exhausted);
+
+	return t;
+}
+#endif
+
+#ifdef L_xstrndup
+char * bb_xstrndup (const char *s, int n)
+{
+	char *t;
+
+	if (ENABLE_DEBUG && s == NULL)
+		bb_error_msg_and_die("bb_xstrndup bug");
+
+	t = xmalloc(++n);
+
+	return safe_strncpy(t,s,n);
+}
+#endif
+
+#ifdef L_xfopen
+FILE *bb_xfopen(const char *path, const char *mode)
+{
+	FILE *fp;
+	if ((fp = fopen(path, mode)) == NULL)
+		bb_perror_msg_and_die("%s", path);
+	return fp;
+}
+#endif
+
+#ifdef L_xopen
+int bb_xopen(const char *pathname, int flags)
+{
+	return bb_xopen3(pathname, flags, 0777);
+}
+#endif
+
+#ifdef L_xopen3
+int bb_xopen3(const char *pathname, int flags, int mode)
+{
+	int ret;
+
+	ret = open(pathname, flags, mode);
+	if (ret < 0) {
+		bb_perror_msg_and_die("%s", pathname);
+	}
+	return ret;
+}
+#endif
+
+#ifdef L_xread
+ssize_t bb_xread(int fd, void *buf, size_t count)
+{
+	ssize_t size;
+
+	size = read(fd, buf, count);
+	if (size < 0) {
+		bb_perror_msg_and_die(bb_msg_read_error);
+	}
+	return(size);
+}
+#endif
+
+#ifdef L_xread_all
+void bb_xread_all(int fd, void *buf, size_t count)
+{
+	ssize_t size;
+
+	while (count) {
+		if ((size = bb_xread(fd, buf, count)) == 0) {	/* EOF */
+			bb_error_msg_and_die("Short read");
+		}
+		count -= size;
+		buf = ((char *) buf) + size;
+	}
+	return;
+}
+#endif
+
+#ifdef L_xread_char
+unsigned char bb_xread_char(int fd)
+{
+	char tmp;
+
+	bb_xread_all(fd, &tmp, 1);
+
+	return(tmp);
+}
+#endif
+
+#ifdef L_xferror
+void bb_xferror(FILE *fp, const char *fn)
+{
+	if (ferror(fp)) {
+		bb_error_msg_and_die("%s", fn);
+	}
+}
+#endif
+
+#ifdef L_xferror_stdout
+void bb_xferror_stdout(void)
+{
+	bb_xferror(stdout, bb_msg_standard_output);
+}
+#endif
+
+#ifdef L_xfflush_stdout
+void bb_xfflush_stdout(void)
+{
+	if (fflush(stdout)) {
+		bb_perror_msg_and_die(bb_msg_standard_output);
+	}
+}
+#endif
+
+#ifdef L_spawn
+// This does a fork/exec in one call, using vfork().
+pid_t bb_spawn(char **argv)
+{
+	static int failed;
+	pid_t pid;
+	void *app = find_applet_by_name(argv[0]);
+
+	// Be nice to nommu machines.
+	failed = 0;
+	pid = vfork();
+	if (pid < 0) return pid;
+	if (!pid) {
+		execvp(app ? CONFIG_BUSYBOX_EXEC_PATH : *argv, argv);
+
+		// We're sharing a stack with blocked parent, let parent know we failed
+		// and then exit to unblock parent (but don't run atexit() stuff, which
+		// would screw up parent.)
+
+		failed = -1;
+		_exit(0);
+	}
+	return failed ? failed : pid;
+}
+#endif
+
+#ifdef L_xspawn
+pid_t bb_xspawn(char **argv)
+{
+	pid_t pid = bb_spawn(argv);
+	if (pid < 0) bb_perror_msg_and_die("%s", *argv);
+	return pid;
+}
+#endif
+
+#ifdef L_wait4
+int wait4pid(int pid)
+{
+	int status;
+
+	if (pid == -1 || waitpid(pid, &status, 0) == -1) return -1;
+	if (WIFEXITED(status)) return WEXITSTATUS(status);
+	if (WIFSIGNALED(status)) return WTERMSIG(status);
+	return 0;
+}
+#endif	
+
+#ifdef L_setuid
+void xsetgid(gid_t gid)
+{
+	if (setgid(gid)) bb_error_msg_and_die("setgid");
+}
+
+void xsetuid(uid_t uid)
+{
+	if (setuid(uid)) bb_error_msg_and_die("setuid");
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgetcwd.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgetcwd.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgetcwd.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,48 @@
+/*
+ * xgetcwd.c -- return current directory with unlimited length
+ * Copyright (C) 1992, 1996 Free Software Foundation, Inc.
+ * Written by David MacKenzie <djm at gnu.ai.mit.edu>.
+ *
+ * Special function for busybox written by Vladimir Oleynik <dzo at simtreas.ru>
+*/
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/param.h>
+#include "libbb.h"
+
+/* Amount to increase buffer size by in each try. */
+#define PATH_INCR 32
+
+/* Return the current directory, newly allocated, arbitrarily long.
+   Return NULL and set errno on error.
+   If argument is not NULL (previous usage allocate memory), call free()
+*/
+
+char *
+xgetcwd (char *cwd)
+{
+  char *ret;
+  unsigned path_max;
+
+  path_max = (unsigned) PATH_MAX;
+  path_max += 2;                /* The getcwd docs say to do this. */
+
+  if(cwd==0)
+	cwd = xmalloc (path_max);
+
+  while ((ret = getcwd (cwd, path_max)) == NULL && errno == ERANGE) {
+      path_max += PATH_INCR;
+      cwd = xrealloc (cwd, path_max);
+  }
+
+  if (ret == NULL) {
+      free (cwd);
+      bb_perror_msg("getcwd()");
+      return NULL;
+  }
+
+  return cwd;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgethostbyname.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgethostbyname.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgethostbyname.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,35 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini xgethostbyname implementation.
+ *
+ * Copyright (C) 2001 Matt Kraai <kraai at alumni.carnegiemellon.edu>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <netdb.h>
+#include "libbb.h"
+
+
+struct hostent *xgethostbyname(const char *name)
+{
+	struct hostent *retval;
+
+	if ((retval = gethostbyname(name)) == NULL)
+		bb_herror_msg_and_die("%s", name);
+
+	return retval;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgethostbyname2.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgethostbyname2.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgethostbyname2.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,37 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini xgethostbyname2 implementation.
+ *
+ * Copyright (C) 2001 Matt Kraai <kraai at alumni.carnegiemellon.edu>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <netdb.h>
+#include "libbb.h"
+
+
+#ifdef CONFIG_FEATURE_IPV6
+struct hostent *xgethostbyname2(const char *name, int af)
+{
+	struct hostent *retval;
+
+	if ((retval = gethostbyname2(name, af)) == NULL)
+		bb_herror_msg_and_die("%s", name);
+
+	return retval;
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgetlarg.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgetlarg.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgetlarg.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,39 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2003-2004 Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <errno.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "libbb.h"
+
+long bb_xgetlarg(const char *arg, int base, long lower, long upper)
+{
+	long result;
+	char *endptr;
+	int errno_save = errno;
+
+	assert(arg!=NULL);
+
+	/* Don't allow leading whitespace.
+	 * Wrap isspace in () to make sure we call the
+	 * function rather than the macro. */
+	if ((isspace)(*arg)) {
+		bb_show_usage();
+	}
+
+	errno = 0;
+	result = strtol(arg, &endptr, base);
+	if (errno != 0 || *endptr!='\0' || endptr==arg || result < lower || result > upper)
+		bb_show_usage();
+	errno = errno_save;
+	return result;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgetularg.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgetularg.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xgetularg.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,154 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * xgetularg* implementations for busybox
+ *
+ * Copyright (C) 2003  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <assert.h>
+#include "libbb.h"
+
+#ifdef L_xgetularg_bnd_sfx
+unsigned long bb_xgetularg_bnd_sfx(const char *arg, int base,
+								   unsigned long lower,
+								   unsigned long upper,
+								   const struct suffix_mult *suffixes)
+{
+	unsigned long r;
+	int old_errno;
+	char *e;
+
+	assert(arg);
+
+	/* Disallow '-' and any leading whitespace.  Speed isn't critical here
+	 * since we're parsing commandline args.  So make sure we get the
+	 * actual isspace function rather than a larger macro implementaion. */
+	if ((*arg == '-') || (isspace)(*arg)) {
+		bb_show_usage();
+	}
+
+	/* Since this is a lib function, we're not allowed to reset errno to 0.
+	 * Doing so could break an app that is deferring checking of errno.
+	 * So, save the old value so that we can restore it if successful. */
+	old_errno = errno;
+	errno = 0;
+	r = strtoul(arg, &e, base);
+	/* Do the initial validity check.  Note: The standards do not
+	 * guarantee that errno is set if no digits were found.  So we
+	 * must test for this explicitly. */
+	if (errno || (arg == e)) {	/* error or no digits */
+		bb_show_usage();
+	}
+	errno = old_errno;	/* Ok.  So restore errno. */
+
+	/* Do optional suffix parsing.  Allow 'empty' suffix tables.
+	 * Note that we also all nul suffixes with associated multipliers,
+	 * to allow for scaling of the arg by some default multiplier. */
+
+	if (suffixes) {
+		while (suffixes->suffix) {
+			if (strcmp(suffixes->suffix, e) == 0) {
+				if (ULONG_MAX / suffixes->mult < r) {	/* Overflow! */
+					bb_show_usage();
+				}
+				++e;
+				r *= suffixes->mult;
+				break;
+			}
+			++suffixes;
+		}
+	}
+
+	/* Finally, check for illegal trailing chars and range limits. */
+	/* Note: although we allow leading space (via stroul), trailing space
+	 * is an error.  It would be easy enough to allow though if desired. */
+	if (*e || (r < lower) || (r > upper)) {
+		bb_show_usage();
+	}
+
+	return r;
+}
+#endif
+
+#ifdef L_xgetlarg_bnd_sfx
+long bb_xgetlarg_bnd_sfx(const char *arg, int base,
+						 long lower,
+						 long upper,
+						 const struct suffix_mult *suffixes)
+{
+	unsigned long u = LONG_MAX;
+	long r;
+	const char *p = arg;
+
+	if ((*p == '-') && (p[1] != '+')) {
+		++p;
+#if LONG_MAX == (-(LONG_MIN + 1))
+		++u;	/* two's complement */
+#endif
+	}
+
+	r = bb_xgetularg_bnd_sfx(p, base, 0, u, suffixes);
+
+	if (*arg == '-') {
+		r = -r;
+	}
+
+	if ((r < lower) || (r > upper)) {
+		bb_show_usage();
+	}
+
+	return r;
+}
+#endif
+
+#ifdef L_getlarg10_sfx
+long bb_xgetlarg10_sfx(const char *arg, const struct suffix_mult *suffixes)
+{
+	return bb_xgetlarg_bnd_sfx(arg, 10, LONG_MIN, LONG_MAX, suffixes);
+}
+#endif
+
+#ifdef L_xgetularg_bnd
+unsigned long bb_xgetularg_bnd(const char *arg, int base,
+							   unsigned long lower,
+							   unsigned long upper)
+{
+	return bb_xgetularg_bnd_sfx(arg, base, lower, upper, NULL);
+}
+#endif
+
+#ifdef L_xgetularg10_bnd
+unsigned long bb_xgetularg10_bnd(const char *arg,
+								 unsigned long lower,
+								 unsigned long upper)
+{
+	return bb_xgetularg_bnd(arg, 10, lower, upper);
+}
+#endif
+
+#ifdef L_xgetularg10
+unsigned long bb_xgetularg10(const char *arg)
+{
+	return bb_xgetularg10_bnd(arg, 0, ULONG_MAX);
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xreadlink.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xreadlink.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xreadlink.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,37 @@
+/*
+ *  xreadlink.c - safe implementation of readlink.
+ *  Returns a NULL on failure...
+ */
+
+#include <stdio.h>
+
+/*
+ * NOTE: This function returns a malloced char* that you will have to free
+ * yourself. You have been warned.
+ */
+
+#include <unistd.h>
+#include "libbb.h"
+
+char *xreadlink(const char *path)
+{
+	enum { GROWBY = 80 }; /* how large we will grow strings by */
+
+	char *buf = NULL;
+	int bufsize = 0, readsize = 0;
+
+	do {
+		buf = xrealloc(buf, bufsize += GROWBY);
+		readsize = readlink(path, buf, bufsize); /* 1st try */
+		if (readsize == -1) {
+			bb_perror_msg("%s", path);
+			free(buf);
+			return NULL;
+		}
+	}
+	while (bufsize < readsize + 1);
+
+	buf[readsize] = '\0';
+
+	return buf;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xregcomp.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xregcomp.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xregcomp.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,26 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) many different people.
+ * If you wrote this, please acknowledge your work.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include "libbb.h"
+#include "xregex.h"
+
+
+
+void xregcomp(regex_t *preg, const char *regex, int cflags)
+{
+	int ret;
+	if ((ret = regcomp(preg, regex, cflags)) != 0) {
+		int errmsgsz = regerror(ret, preg, NULL, 0);
+		char *errmsg = xmalloc(errmsgsz);
+		regerror(ret, preg, errmsg, errmsgsz);
+		bb_error_msg_and_die("xregcomp: %s", errmsg);
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xstat.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xstat.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libbb/xstat.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,11 @@
+/*
+ * xstat.c - a stat() which dies on failure with meaningful error message
+ */
+#include <unistd.h>
+#include "libbb.h"
+
+void xstat(const char *name, struct stat *stat_buf)
+{
+	if (stat(name, stat_buf))
+		bb_perror_msg_and_die("Can't stat '%s'", name);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libc.aold
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libc.aold
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/libpwgrp
+LIBPWDGRP_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,51 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+LIBPWDGRP_AR:=libpwdgrp.a
+ifndef $(LIBPWDGRP_DIR)
+LIBPWDGRP_DIR:=$(top_builddir)/libpwdgrp
+endif
+srcdir=$(top_srcdir)/libpwdgrp
+
+LIBPWDGRP-obj:=$(LIBPWDGRP_DIR)/$(LIBPWDGRP_AR)
+
+libraries-y+=$(LIBPWDGRP_DIR)/$(LIBPWDGRP_AR)
+
+LIBPWDGRP_MSRC0:=$(srcdir)/pwd_grp.c
+LIBPWDGRP_MOBJ0-$(CONFIG_USE_BB_PWD_GRP):= fgetpwent_r.o fgetgrent_r.o \
+	fgetpwent.o fgetgrent.o getpwnam_r.o getgrnam_r.o getpwuid_r.o \
+	getgrgid_r.o getpwuid.o getgrgid.o getpwnam.o getgrnam.o getpw.o \
+	getpwent_r.o getgrent_r.o getpwent.o getgrent.o \
+	initgroups.o putpwent.o putgrent.o
+LIBPWDGRP_MOBJS0=$(patsubst %,$(LIBPWDGRP_DIR)/%, $(LIBPWDGRP_MOBJ0-y))
+
+LIBPWDGRP_MSRC1:=$(srcdir)/pwd_grp.c
+LIBPWDGRP_MOBJ1-$(CONFIG_USE_BB_PWD_GRP):= __parsepwent.o __parsegrent.o \
+	__pgsreader.o fgetspent_r.o fgetspent.o sgetspent_r.o getspnam_r.o \
+	getspnam.o getspent_r.o getspent.o sgetspent.o \
+	putspent.o __parsespent.o # getspuid_r.o getspuid.o
+LIBPWDGRP_MOBJS1=$(patsubst %,$(LIBPWDGRP_DIR)/%, $(LIBPWDGRP_MOBJ1-y))
+
+LIBPWDGRP_DEFINE0-y:=$(patsubst %,-DL_%,$(subst .o,,$(notdir $(LIBPWDGRP_MOBJS0))))
+LIBPWDGRP_DEFINE1-y:=$(patsubst %,-DL_%,$(subst .o,,$(notdir $(LIBPWDGRP_MOBJS1))))
+
+LIBPWDGRP_SRC-y:=$(LIBPWDGRP_MSRC0)
+
+LIBRARY_SRC-y+=$(LIBPWDGRP_SRC-y)
+LIBRARY_SRC-a+=$(LIBPWDGRP_SRC-y)
+
+LIBRARY_DEFINE-y+=$(LIBPWDGRP_DEFINE0-y) $(LIBPWDGRP_DEFINE1-y)
+LIBRARY_DEFINE-a+=$(LIBPWDGRP_DEFINE0-y) $(LIBPWDGRP_DEFINE1-y)
+
+
+$(LIBPWDGRP_DIR)/$(LIBPWDGRP_AR): $(LIBPWDGRP_MOBJS0) $(LIBPWDGRP_MOBJS1)
+	$(do_ar)
+
+$(LIBPWDGRP_MOBJS0): $(LIBPWDGRP_MSRC0)
+	$(compile.c) -DL_$(notdir $*)
+
+$(LIBPWDGRP_MOBJS1): $(LIBPWDGRP_MSRC1)
+	$(compile.c) -DL_$(notdir $*)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/pwd_grp.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/pwd_grp.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/pwd_grp.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1100 @@
+/*  Copyright (C) 2003     Manuel Novoa III
+ *
+ *  Licensed under GPL v2, or later.  See file LICENSE in this tarball.
+ */
+
+/*  Nov 6, 2003  Initial version.
+ *
+ *  NOTE: This implementation is quite strict about requiring all
+ *    field seperators.  It also does not allow leading whitespace
+ *    except when processing the numeric fields.  glibc is more
+ *    lenient.  See the various glibc difference comments below.
+ *
+ *  TODO:
+ *    Move to dynamic allocation of (currently statically allocated)
+ *      buffers; especially for the group-related functions since
+ *      large group member lists will cause error returns.
+ *
+ */
+
+#include "libbb.h"
+#include <features.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stddef.h>
+#include <errno.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "shadow_.h"
+
+#ifndef _PATH_SHADOW
+#define	_PATH_SHADOW	"/etc/shadow"
+#endif
+#ifndef _PATH_PASSWD
+#define	_PATH_PASSWD	"/etc/passwd"
+#endif
+#ifndef _PATH_GROUP
+#define	_PATH_GROUP	"/etc/group"
+#endif
+
+/**********************************************************************/
+/* Sizes for statically allocated buffers. */
+
+/* If you change these values, also change _SC_GETPW_R_SIZE_MAX and
+ * _SC_GETGR_R_SIZE_MAX in libc/unistd/sysconf.c to match */
+#define PWD_BUFFER_SIZE 256
+#define GRP_BUFFER_SIZE 256
+
+/**********************************************************************/
+/* Prototypes for internal functions. */
+
+extern int __parsepwent(void *pw, char *line);
+extern int __parsegrent(void *gr, char *line);
+extern int __parsespent(void *sp, char *line);
+
+extern int __pgsreader(int (*__parserfunc)(void *d, char *line), void *data,
+					   char *__restrict line_buff, size_t buflen, FILE *f);
+
+/**********************************************************************/
+/* For the various fget??ent_r funcs, return
+ *
+ *  0: success
+ *  ENOENT: end-of-file encountered
+ *  ERANGE: buflen too small
+ *  other error values possible. See __pgsreader.
+ *
+ * Also, *result == resultbuf on success and NULL on failure.
+ *
+ * NOTE: glibc difference - For the ENOENT case, glibc also sets errno.
+ *   We do not, as it really isn't an error if we reach the end-of-file.
+ *   Doing so is analogous to having fgetc() set errno on EOF.
+ */
+/**********************************************************************/
+
+#ifdef L_fgetpwent_r
+
+int fgetpwent_r(FILE *__restrict stream, struct passwd *__restrict resultbuf,
+				char *__restrict buffer, size_t buflen,
+				struct passwd **__restrict result)
+{
+	int rv;
+
+	*result = NULL;
+
+	if (!(rv = __pgsreader(__parsepwent, resultbuf, buffer, buflen, stream))) {
+		*result = resultbuf;
+	}
+
+	return rv;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_fgetgrent_r
+
+int fgetgrent_r(FILE *__restrict stream, struct group *__restrict resultbuf,
+				char *__restrict buffer, size_t buflen,
+				struct group **__restrict result)
+{
+	int rv;
+
+	*result = NULL;
+
+	if (!(rv = __pgsreader(__parsegrent, resultbuf, buffer, buflen, stream))) {
+		*result = resultbuf;
+	}
+
+	return rv;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_fgetspent_r
+
+int fgetspent_r(FILE *__restrict stream, struct spwd *__restrict resultbuf,
+				char *__restrict buffer, size_t buflen,
+				struct spwd **__restrict result)
+{
+	int rv;
+
+	*result = NULL;
+
+	if (!(rv = __pgsreader(__parsespent, resultbuf, buffer, buflen, stream))) {
+		*result = resultbuf;
+	}
+
+	return rv;
+}
+
+#endif
+/**********************************************************************/
+/* For the various fget??ent funcs, return NULL on failure and a
+ * pointer to the appropriate struct (statically allocated) on success.
+ */
+/**********************************************************************/
+#ifdef L_fgetpwent
+
+struct passwd *fgetpwent(FILE *stream)
+{
+	static char buffer[PWD_BUFFER_SIZE];
+	static struct passwd resultbuf;
+	struct passwd *result;
+
+	fgetpwent_r(stream, &resultbuf, buffer, sizeof(buffer), &result);
+	return result;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_fgetgrent
+
+struct group *fgetgrent(FILE *stream)
+{
+	static char buffer[GRP_BUFFER_SIZE];
+	static struct group resultbuf;
+	struct group *result;
+
+	fgetgrent_r(stream, &resultbuf, buffer, sizeof(buffer), &result);
+	return result;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_fgetspent
+
+extern int fgetspent_r(FILE *__restrict stream, struct spwd *__restrict resultbuf,
+				char *__restrict buffer, size_t buflen,
+				struct spwd **__restrict result);
+struct spwd *fgetspent(FILE *stream)
+{
+	static char buffer[PWD_BUFFER_SIZE];
+	static struct spwd resultbuf;
+	struct spwd *result;
+
+	fgetspent_r(stream, &resultbuf, buffer, sizeof(buffer), &result);
+	return result;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_sgetspent_r
+
+int sgetspent_r(const char *string, struct spwd *result_buf,
+				char *buffer, size_t buflen, struct spwd **result)
+{
+	int rv = ERANGE;
+
+	*result = NULL;
+
+	if (buflen < PWD_BUFFER_SIZE) {
+	DO_ERANGE:
+		errno=rv;
+		goto DONE;
+	}
+
+	if (string != buffer) {
+		if (strlen(string) >= buflen) {
+			goto DO_ERANGE;
+		}
+		strcpy(buffer, string);
+	}
+
+	if (!(rv = __parsespent(result_buf, buffer))) {
+		*result = result_buf;
+	}
+
+ DONE:
+	return rv;
+}
+
+#endif
+/**********************************************************************/
+
+#ifdef GETXXKEY_R_FUNC
+#error GETXXKEY_R_FUNC is already defined!
+#endif
+
+#ifdef L_getpwnam_r
+#define GETXXKEY_R_FUNC			getpwnam_r
+#define GETXXKEY_R_PARSER		__parsepwent
+#define GETXXKEY_R_ENTTYPE		struct passwd
+#define GETXXKEY_R_TEST(ENT)	(!strcmp((ENT)->pw_name, key))
+#define DO_GETXXKEY_R_KEYTYPE	const char *__restrict
+#define DO_GETXXKEY_R_PATHNAME  _PATH_PASSWD
+#include "pwd_grp_internal.c"
+#endif
+
+#ifdef L_getgrnam_r
+#define GETXXKEY_R_FUNC			getgrnam_r
+#define GETXXKEY_R_PARSER		__parsegrent
+#define GETXXKEY_R_ENTTYPE		struct group
+#define GETXXKEY_R_TEST(ENT)	(!strcmp((ENT)->gr_name, key))
+#define DO_GETXXKEY_R_KEYTYPE	const char *__restrict
+#define DO_GETXXKEY_R_PATHNAME  _PATH_GROUP
+#include "pwd_grp_internal.c"
+#endif
+
+#ifdef L_getspnam_r
+#define GETXXKEY_R_FUNC			getspnam_r
+#define GETXXKEY_R_PARSER		__parsespent
+#define GETXXKEY_R_ENTTYPE		struct spwd
+#define GETXXKEY_R_TEST(ENT)	(!strcmp((ENT)->sp_namp, key))
+#define DO_GETXXKEY_R_KEYTYPE	const char *__restrict
+#define DO_GETXXKEY_R_PATHNAME  _PATH_SHADOW
+#include "pwd_grp_internal.c"
+#endif
+
+#ifdef L_getpwuid_r
+#define GETXXKEY_R_FUNC			getpwuid_r
+#define GETXXKEY_R_PARSER		__parsepwent
+#define GETXXKEY_R_ENTTYPE		struct passwd
+#define GETXXKEY_R_TEST(ENT)	((ENT)->pw_uid == key)
+#define DO_GETXXKEY_R_KEYTYPE	uid_t
+#define DO_GETXXKEY_R_PATHNAME  _PATH_PASSWD
+#include "pwd_grp_internal.c"
+#endif
+
+#ifdef L_getgrgid_r
+#define GETXXKEY_R_FUNC			getgrgid_r
+#define GETXXKEY_R_PARSER		__parsegrent
+#define GETXXKEY_R_ENTTYPE		struct group
+#define GETXXKEY_R_TEST(ENT)	((ENT)->gr_gid == key)
+#define DO_GETXXKEY_R_KEYTYPE	gid_t
+#define DO_GETXXKEY_R_PATHNAME  _PATH_GROUP
+#include "pwd_grp_internal.c"
+#endif
+
+/**********************************************************************/
+#ifdef L_getpwuid
+
+struct passwd *getpwuid(uid_t uid)
+{
+	static char buffer[PWD_BUFFER_SIZE];
+	static struct passwd resultbuf;
+	struct passwd *result;
+
+	getpwuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result);
+	return result;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_getgrgid
+
+struct group *getgrgid(gid_t gid)
+{
+	static char buffer[GRP_BUFFER_SIZE];
+	static struct group resultbuf;
+	struct group *result;
+
+	getgrgid_r(gid, &resultbuf, buffer, sizeof(buffer), &result);
+	return result;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_getspuid_r
+
+/* This function is non-standard and is currently not built.  It seems
+ * to have been created as a reentrant version of the non-standard
+ * functions getspuid.  Why getspuid was added, I do not know. */
+
+int getspuid_r(uid_t uid, struct spwd *__restrict resultbuf,
+		       char *__restrict buffer, size_t buflen,
+		       struct spwd **__restrict result)
+{
+	int rv;
+	struct passwd *pp;
+	struct passwd password;
+	char pwd_buff[PWD_BUFFER_SIZE];
+
+	*result = NULL;
+	if (!(rv = getpwuid_r(uid, &password, pwd_buff, sizeof(pwd_buff), &pp))) {
+		rv = getspnam_r(password.pw_name, resultbuf, buffer, buflen, result);
+	}
+
+	return rv;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_getspuid
+
+/* This function is non-standard and is currently not built.
+ * Why it was added, I do not know. */
+
+struct spwd *getspuid(uid_t uid)
+{
+	static char buffer[PWD_BUFFER_SIZE];
+	static struct spwd resultbuf;
+	struct spwd *result;
+
+	getspuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result);
+	return result;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_getpwnam
+
+struct passwd *getpwnam(const char *name)
+{
+	static char buffer[PWD_BUFFER_SIZE];
+	static struct passwd resultbuf;
+	struct passwd *result;
+
+	getpwnam_r(name, &resultbuf, buffer, sizeof(buffer), &result);
+	return result;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_getgrnam
+
+struct group *getgrnam(const char *name)
+{
+	static char buffer[GRP_BUFFER_SIZE];
+	static struct group resultbuf;
+	struct group *result;
+
+	getgrnam_r(name, &resultbuf, buffer, sizeof(buffer), &result);
+	return result;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_getspnam
+
+struct spwd *getspnam(const char *name)
+{
+	static char buffer[PWD_BUFFER_SIZE];
+	static struct spwd resultbuf;
+	struct spwd *result;
+
+	getspnam_r(name, &resultbuf, buffer, sizeof(buffer), &result);
+	return result;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_getpw
+
+int getpw(uid_t uid, char *buf)
+{
+	struct passwd resultbuf;
+	struct passwd *result;
+	char buffer[PWD_BUFFER_SIZE];
+
+	if (!buf) {
+		errno=EINVAL;
+	} else if (!getpwuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result)) {
+		if (sprintf(buf, "%s:%s:%lu:%lu:%s:%s:%s\n",
+					resultbuf.pw_name, resultbuf.pw_passwd,
+					(unsigned long)(resultbuf.pw_uid),
+					(unsigned long)(resultbuf.pw_gid),
+					resultbuf.pw_gecos, resultbuf.pw_dir,
+					resultbuf.pw_shell) >= 0
+			) {
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
+#endif
+/**********************************************************************/
+
+#if defined(L_getpwent_r) || defined(L_getgrent_r) || defined(L_getspent_r)
+#if defined CONFIG_USE_BB_THREADSAFE_SHADOW && defined PTHREAD_MUTEX_INITIALIZER
+static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
+# define LOCK		pthread_mutex_lock(&mylock)
+# define UNLOCK		pthread_mutex_unlock(&mylock);
+#else
+# define LOCK		((void) 0)
+# define UNLOCK		((void) 0)
+#endif
+#endif
+
+#ifdef L_getpwent_r
+static FILE *pwf /*= NULL*/;
+void setpwent(void)
+{
+	LOCK;
+	if (pwf) {
+		rewind(pwf);
+	}
+	UNLOCK;
+}
+
+void endpwent(void)
+{
+	LOCK;
+	if (pwf) {
+		fclose(pwf);
+		pwf = NULL;
+	}
+	UNLOCK;
+}
+
+
+int getpwent_r(struct passwd *__restrict resultbuf,
+			   char *__restrict buffer, size_t buflen,
+			   struct passwd **__restrict result)
+{
+	int rv;
+
+	LOCK;
+	*result = NULL;				/* In case of error... */
+
+	if (!pwf) {
+		if (!(pwf = fopen(_PATH_PASSWD, "r"))) {
+			rv = errno;
+			goto ERR;
+		}
+	}
+
+	if (!(rv = __pgsreader(__parsepwent, resultbuf,
+						   buffer, buflen, pwf))) {
+		*result = resultbuf;
+	}
+
+ ERR:
+	UNLOCK;
+	return rv;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_getgrent_r
+
+static FILE *grf /*= NULL*/;
+void setgrent(void)
+{
+	LOCK;
+	if (grf) {
+		rewind(grf);
+	}
+	UNLOCK;
+}
+
+void endgrent(void)
+{
+	LOCK;
+	if (grf) {
+		fclose(grf);
+		grf = NULL;
+	}
+	UNLOCK;
+}
+
+int getgrent_r(struct group *__restrict resultbuf,
+			   char *__restrict buffer, size_t buflen,
+			   struct group **__restrict result)
+{
+	int rv;
+
+	LOCK;
+	*result = NULL;				/* In case of error... */
+
+	if (!grf) {
+		if (!(grf = fopen(_PATH_GROUP, "r"))) {
+			rv = errno;
+			goto ERR;
+		}
+	}
+
+	if (!(rv = __pgsreader(__parsegrent, resultbuf,
+						   buffer, buflen, grf))) {
+		*result = resultbuf;
+	}
+
+ ERR:
+	UNLOCK;
+	return rv;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_getspent_r
+
+static FILE *spf /*= NULL*/;
+void setspent(void)
+{
+	LOCK;
+	if (spf) {
+		rewind(spf);
+	}
+	UNLOCK;
+}
+
+void endspent(void)
+{
+	LOCK;
+	if (spf) {
+		fclose(spf);
+		spf = NULL;
+	}
+	UNLOCK;
+}
+
+int getspent_r(struct spwd *resultbuf, char *buffer,
+			   size_t buflen, struct spwd **result)
+{
+	int rv;
+
+	LOCK;
+	*result = NULL;				/* In case of error... */
+
+	if (!spf) {
+		if (!(spf = fopen(_PATH_SHADOW, "r"))) {
+			rv = errno;
+			goto ERR;
+		}
+	}
+
+	if (!(rv = __pgsreader(__parsespent, resultbuf,
+						   buffer, buflen, spf))) {
+		*result = resultbuf;
+	}
+
+ ERR:
+	UNLOCK;
+	return rv;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_getpwent
+
+struct passwd *getpwent(void)
+{
+	static char line_buff[PWD_BUFFER_SIZE];
+	static struct passwd pwd;
+	struct passwd *result;
+
+	getpwent_r(&pwd, line_buff, sizeof(line_buff), &result);
+	return result;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_getgrent
+
+struct group *getgrent(void)
+{
+	static char line_buff[GRP_BUFFER_SIZE];
+	static struct group gr;
+	struct group *result;
+
+	getgrent_r(&gr, line_buff, sizeof(line_buff), &result);
+	return result;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_getspent
+
+struct spwd *getspent(void)
+{
+	static char line_buff[PWD_BUFFER_SIZE];
+	static struct spwd spwd;
+	struct spwd *result;
+
+	getspent_r(&spwd, line_buff, sizeof(line_buff), &result);
+	return result;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_sgetspent
+
+struct spwd *sgetspent(const char *string)
+{
+	static char line_buff[PWD_BUFFER_SIZE];
+	static struct spwd spwd;
+	struct spwd *result;
+
+	sgetspent_r(string, &spwd, line_buff, sizeof(line_buff), &result);
+	return result;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_initgroups
+
+int initgroups(const char *user, gid_t gid)
+{
+	FILE *grfile;
+	gid_t *group_list;
+	int num_groups, rv;
+	char **m;
+	struct group group;
+	char buff[PWD_BUFFER_SIZE];
+
+	rv = -1;
+
+	/* We alloc space for 8 gids at a time. */
+	if (((group_list = (gid_t *) malloc(8*sizeof(gid_t *))) != NULL)
+		&& ((grfile = fopen(_PATH_GROUP, "r")) != NULL)
+		) {
+
+		*group_list = gid;
+		num_groups = 1;
+
+		while (!__pgsreader(__parsegrent, &group, buff, sizeof(buff), grfile)) {
+			assert(group.gr_mem); /* Must have at least a NULL terminator. */
+			if (group.gr_gid != gid) {
+				for (m=group.gr_mem ; *m ; m++) {
+					if (!strcmp(*m, user)) {
+						if (!(num_groups & 7)) {
+							gid_t *tmp = (gid_t *)
+								realloc(group_list,
+										(num_groups+8) * sizeof(gid_t *));
+							if (!tmp) {
+								rv = -1;
+								goto DO_CLOSE;
+							}
+							group_list = tmp;
+						}
+						group_list[num_groups++] = group.gr_gid;
+						break;
+					}
+				}
+			}
+		}
+
+		rv = setgroups(num_groups, group_list);
+	DO_CLOSE:
+		fclose(grfile);
+	}
+
+	/* group_list will be NULL if initial malloc failed, which may trigger
+	 * warnings from various malloc debuggers. */
+	free(group_list);
+	return rv;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_putpwent
+
+int putpwent(const struct passwd *__restrict p, FILE *__restrict f)
+{
+	int rv = -1;
+
+	if (!p || !f) {
+		errno=EINVAL;
+	} else {
+		/* No extra thread locking is needed above what fprintf does. */
+		if (fprintf(f, "%s:%s:%lu:%lu:%s:%s:%s\n",
+					p->pw_name, p->pw_passwd,
+					(unsigned long)(p->pw_uid),
+					(unsigned long)(p->pw_gid),
+					p->pw_gecos, p->pw_dir, p->pw_shell) >= 0
+			) {
+			rv = 0;
+		}
+	}
+
+	return rv;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_putgrent
+
+int putgrent(const struct group *__restrict p, FILE *__restrict f)
+{
+	static const char format[] = ",%s";
+	char **m;
+	const char *fmt;
+	int rv = -1;
+
+	if (!p || !f) {				/* Sigh... glibc checks. */
+		errno=EINVAL;
+	} else {
+		if (fprintf(f, "%s:%s:%lu:",
+					p->gr_name, p->gr_passwd,
+					(unsigned long)(p->gr_gid)) >= 0
+			) {
+
+			fmt = format + 1;
+
+			assert(p->gr_mem);
+			m = p->gr_mem;
+
+			do {
+				if (!*m) {
+					if (fputc('\n', f) >= 0) {
+						rv = 0;
+					}
+					break;
+				}
+				if (fprintf(f, fmt, *m) < 0) {
+					break;
+				}
+				++m;
+				fmt = format;
+			} while (1);
+
+		}
+
+	}
+
+	return rv;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_putspent
+
+static const unsigned char _sp_off[] = {
+	offsetof(struct spwd, sp_lstchg),	/* 2 - not a char ptr */
+	offsetof(struct spwd, sp_min),		/* 3 - not a char ptr */
+	offsetof(struct spwd, sp_max),		/* 4 - not a char ptr */
+	offsetof(struct spwd, sp_warn),		/* 5 - not a char ptr */
+	offsetof(struct spwd, sp_inact),	/* 6 - not a char ptr */
+	offsetof(struct spwd, sp_expire),	/* 7 - not a char ptr */
+};
+
+int putspent(const struct spwd *p, FILE *stream)
+{
+	static const char ld_format[] = "%ld:";
+	const char *f;
+	long int x;
+	int i;
+	int rv = -1;
+
+	/* Unlike putpwent and putgrent, glibc does not check the args. */
+	if (fprintf(stream, "%s:%s:", p->sp_namp,
+				(p->sp_pwdp ? p->sp_pwdp : "")) < 0
+		) {
+		goto DO_UNLOCK;
+	}
+
+	for (i=0 ; i < sizeof(_sp_off) ; i++) {
+		f = ld_format;
+		if ((x = *(const long int *)(((const char *) p) + _sp_off[i])) == -1) {
+			f += 3;
+		}
+		if (fprintf(stream, f, x) < 0) {
+			goto DO_UNLOCK;
+		}
+	}
+
+	if ((p->sp_flag != ~0UL) && (fprintf(stream, "%lu", p->sp_flag) < 0)) {
+		goto DO_UNLOCK;
+	}
+
+	if (fputc('\n', stream) > 0) {
+		rv = 0;
+	}
+
+DO_UNLOCK:
+	return rv;
+}
+
+#endif
+/**********************************************************************/
+/* Internal uClibc functions.					 */
+/**********************************************************************/
+#ifdef L___parsepwent
+
+static const unsigned char pw_off[] = {
+	offsetof(struct passwd, pw_name),	/* 0 */
+	offsetof(struct passwd, pw_passwd),	/* 1 */
+	offsetof(struct passwd, pw_uid),	/* 2 - not a char ptr */
+	offsetof(struct passwd, pw_gid),	/* 3 - not a char ptr */
+	offsetof(struct passwd, pw_gecos),	/* 4 */
+	offsetof(struct passwd, pw_dir),	/* 5 */
+	offsetof(struct passwd, pw_shell)	/* 6 */
+};
+
+int __parsepwent(void *data, char *line)
+{
+	char *endptr;
+	char *p;
+	int i;
+
+	i = 0;
+	do {
+		p = ((char *) ((struct passwd *) data)) + pw_off[i];
+
+		if ((i & 6) ^ 2) {	/* i!=2 and i!=3 */
+			*((char **) p) = line;
+			if (i==6) {
+				return 0;
+			}
+			/* NOTE: glibc difference - glibc allows omission of
+			 * ':' seperators after the gid field if all remaining
+			 * entries are empty.  We require all separators. */
+			if (!(line = strchr(line, ':'))) {
+				break;
+			}
+		} else {
+			unsigned long t = strtoul(line, &endptr, 10);
+			/* Make sure we had at least one digit, and that the
+			 * failing char is the next field seperator ':'.  See
+			 * glibc difference note above. */
+			/* TODO: Also check for leading whitespace? */
+			if ((endptr == line) || (*endptr != ':')) {
+				break;
+			}
+			line = endptr;
+			if (i & 1) {		/* i == 3 -- gid */
+				*((gid_t *) p) = t;
+			} else {			/* i == 2 -- uid */
+				*((uid_t *) p) = t;
+			}
+		}
+
+		*line++ = 0;
+		++i;
+	} while (1);
+
+	return -1;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L___parsegrent
+
+static const unsigned char gr_off[] = {
+	offsetof(struct group, gr_name),	/* 0 */
+	offsetof(struct group, gr_passwd),	/* 1 */
+	offsetof(struct group, gr_gid)		/* 2 - not a char ptr */
+};
+
+int __parsegrent(void *data, char *line)
+{
+	char *endptr;
+	char *p;
+	int i;
+	char **members;
+	char *end_of_buf;
+
+	end_of_buf = ((struct group *) data)->gr_name; /* Evil hack! */
+	i = 0;
+	do {
+		p = ((char *) ((struct group *) data)) + gr_off[i];
+
+		if (i < 2) {
+			*((char **) p) = line;
+			if (!(line = strchr(line, ':'))) {
+				break;
+			}
+			*line++ = 0;
+			++i;
+		} else {
+			*((gid_t *) p) = strtoul(line, &endptr, 10);
+
+			/* NOTE: glibc difference - glibc allows omission of the
+			 * trailing colon when there is no member list.  We treat
+			 * this as an error. */
+
+			/* Make sure we had at least one digit, and that the
+			 * failing char is the next field seperator ':'.  See
+			 * glibc difference note above. */
+			if ((endptr == line) || (*endptr != ':')) {
+				break;
+			}
+
+			i = 1;				/* Count terminating NULL ptr. */
+			p = endptr;
+
+			if (p[1]) { /* We have a member list to process. */
+				/* Overwrite the last ':' with a ',' before counting.
+				 * This allows us to test for initial ',' and adds
+				 * one ',' so that the ',' count equals the member
+				 * count. */
+				*p = ',';
+				do {
+					/* NOTE: glibc difference - glibc allows and trims leading
+					 * (but not trailing) space.  We treat this as an error. */
+					/* NOTE: glibc difference - glibc allows consecutive and
+					 * trailing commas, and ignores "empty string" users.  We
+					 * treat this as an error. */
+					if (*p == ',') {
+						++i;
+						*p = 0;	/* nul-terminate each member string. */
+						if (!*++p || (*p == ',') || isspace(*p)) {
+							goto ERR;
+						}
+					}
+				} while (*++p);
+			}
+
+			/* Now align (p+1), rounding up. */
+			/* Assumes sizeof(char **) is a power of 2. */
+			members = (char **)( (((intptr_t) p) + sizeof(char **))
+								 & ~((intptr_t)(sizeof(char **) - 1)) );
+
+			if (((char *)(members + i)) > end_of_buf) {	/* No space. */
+				break;
+			}
+
+			((struct group *) data)->gr_mem = members;
+
+			if (--i) {
+				p = endptr;	/* Pointing to char prior to first member. */
+				do {
+					*members++ = ++p;
+					if (!--i) break;
+					while (*++p) {}
+				} while (1);
+			}
+			*members = NULL;
+
+			return 0;
+		}
+	} while (1);
+
+ ERR:
+	return -1;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L___parsespent
+
+static const unsigned char sp_off[] = {
+	offsetof(struct spwd, sp_namp),		/* 0 */
+	offsetof(struct spwd, sp_pwdp),		/* 1 */
+	offsetof(struct spwd, sp_lstchg),	/* 2 - not a char ptr */
+	offsetof(struct spwd, sp_min),		/* 3 - not a char ptr */
+	offsetof(struct spwd, sp_max),		/* 4 - not a char ptr */
+	offsetof(struct spwd, sp_warn),		/* 5 - not a char ptr */
+	offsetof(struct spwd, sp_inact),	/* 6 - not a char ptr */
+	offsetof(struct spwd, sp_expire),	/* 7 - not a char ptr */
+	offsetof(struct spwd, sp_flag)		/* 8 - not a char ptr */
+};
+
+int __parsespent(void *data, char * line)
+{
+	char *endptr;
+	char *p;
+	int i;
+
+	i = 0;
+	do {
+		p = ((char *) ((struct spwd *) data)) + sp_off[i];
+		if (i < 2) {
+			*((char **) p) = line;
+			if (!(line = strchr(line, ':'))) {
+				break;
+			}
+		} else {
+#if 0
+			if (i==5) {			/* Support for old format. */
+				while (isspace(*line)) ++line; /* glibc eats space here. */
+				if (!*line) {
+					((struct spwd *) data)->sp_warn = -1;
+					((struct spwd *) data)->sp_inact = -1;
+					((struct spwd *) data)->sp_expire = -1;
+					((struct spwd *) data)->sp_flag = ~0UL;
+					return 0;
+				}
+			}
+#endif
+
+			*((long *) p) = (long) strtoul(line, &endptr, 10);
+
+			if (endptr == line) {
+				*((long *) p) = ((i != 8) ? -1L : ((long)(~0UL)));
+			}
+
+			line = endptr;
+
+			if (i == 8) {
+				if (!*endptr) {
+					return 0;
+				}
+				break;
+			}
+
+			if (*endptr != ':') {
+				break;
+			}
+
+		}
+
+		*line++ = 0;
+		++i;
+	} while (1);
+
+	return EINVAL;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L___pgsreader
+
+/* Reads until if EOF, or until if finds a line which fits in the buffer
+ * and for which the parser function succeeds.
+ *
+ * Returns 0 on success and ENOENT for end-of-file (glibc concession).
+ */
+
+int __pgsreader(int (*__parserfunc)(void *d, char *line), void *data,
+				char *__restrict line_buff, size_t buflen, FILE *f)
+{
+	int line_len;
+	int skip;
+	int rv = ERANGE;
+
+	if (buflen < PWD_BUFFER_SIZE) {
+		errno=rv;
+	} else {
+		skip = 0;
+		do {
+			if (!fgets(line_buff, buflen, f)) {
+				if (feof(f)) {
+					rv = ENOENT;
+				}
+				break;
+			}
+
+			line_len = strlen(line_buff) - 1; /* strlen() must be > 0. */
+			if (line_buff[line_len] == '\n') {
+				line_buff[line_len] = 0;
+			} else if (line_len + 2 == buflen) { /* line too long */
+				++skip;
+				continue;
+			}
+
+			if (skip) {
+				--skip;
+				continue;
+			}
+
+			/* NOTE: glibc difference - glibc strips leading whitespace from
+			 * records.  We do not allow leading whitespace. */
+
+			/* Skip empty lines, comment lines, and lines with leading
+			 * whitespace. */
+			if (*line_buff && (*line_buff != '#') && !isspace(*line_buff)) {
+				if (__parserfunc == __parsegrent) {	/* Do evil group hack. */
+					/* The group entry parsing function needs to know where
+					 * the end of the buffer is so that it can construct the
+					 * group member ptr table. */
+					((struct group *) data)->gr_name = line_buff + buflen;
+				}
+
+				if (!__parserfunc(data, line_buff)) {
+					rv = 0;
+					break;
+				}
+			}
+		} while (1);
+
+	}
+
+	return rv;
+}
+
+#endif
+/**********************************************************************/

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/pwd_grp_internal.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/pwd_grp_internal.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/libpwdgrp/pwd_grp_internal.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,112 @@
+/*  Copyright (C) 2003     Manuel Novoa III
+ *
+ *  Licensed under GPL v2, or later.  See file LICENSE in this tarball.
+ */
+
+/*  Nov 6, 2003  Initial version.
+ *
+ *  NOTE: This implementation is quite strict about requiring all
+ *    field seperators.  It also does not allow leading whitespace
+ *    except when processing the numeric fields.  glibc is more
+ *    lenient.  See the various glibc difference comments below.
+ *
+ *  TODO:
+ *    Move to dynamic allocation of (currently statically allocated)
+ *      buffers; especially for the group-related functions since
+ *      large group member lists will cause error returns.
+ *
+ */
+
+#include <features.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stddef.h>
+#include <errno.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "pwd_.h"
+#include "grp_.h"
+#include "shadow_.h"
+#include "libbb.h"
+
+#ifndef _PATH_SHADOW
+#define	_PATH_SHADOW	"/etc/shadow"
+#endif
+#ifndef _PATH_PASSWD
+#define	_PATH_PASSWD	"/etc/passwd"
+#endif
+#ifndef _PATH_GROUP
+#define	_PATH_GROUP	"/etc/group"
+#endif
+
+/**********************************************************************/
+/* Sizes for statically allocated buffers. */
+
+/* If you change these values, also change _SC_GETPW_R_SIZE_MAX and
+ * _SC_GETGR_R_SIZE_MAX in libc/unistd/sysconf.c to match */
+#define PWD_BUFFER_SIZE 256
+#define GRP_BUFFER_SIZE 256
+
+/**********************************************************************/
+/* Prototypes for internal functions. */
+
+extern int __parsepwent(void *pw, char *line);
+extern int __parsegrent(void *gr, char *line);
+extern int __parsespent(void *sp, char *line);
+
+extern int __pgsreader(int (*__parserfunc)(void *d, char *line), void *data,
+					   char *__restrict line_buff, size_t buflen, FILE *f);
+
+
+#ifndef GETXXKEY_R_FUNC
+#error GETXXKEY_R_FUNC is not defined!
+#endif
+/**********************************************************************/
+#ifdef GETXXKEY_R_FUNC
+
+int GETXXKEY_R_FUNC(DO_GETXXKEY_R_KEYTYPE key,
+					GETXXKEY_R_ENTTYPE *__restrict resultbuf,
+					char *__restrict buffer, size_t buflen,
+					GETXXKEY_R_ENTTYPE **__restrict result)
+{
+	FILE *stream;
+	int rv;
+
+	*result = NULL;
+
+	if (!(stream = fopen(DO_GETXXKEY_R_PATHNAME, "r"))) {
+		rv = errno;
+	} else {
+		do {
+			if (!(rv = __pgsreader(GETXXKEY_R_PARSER, resultbuf,
+								   buffer, buflen, stream))
+				) {
+				if (GETXXKEY_R_TEST(resultbuf)) { /* Found key? */
+					*result = resultbuf;
+					break;
+				}
+			} else {
+				if (rv == ENOENT) {	/* end-of-file encountered. */
+					rv = 0;
+				}
+				break;
+			}
+		} while (1);
+		fclose(stream);
+	}
+
+	return rv;
+}
+
+#endif
+/**********************************************************************/
+#undef GETXXKEY_R_FUNC
+#undef GETXXKEY_R_PARSER
+#undef GETXXKEY_R_ENTTYPE
+#undef GETXXKEY_R_TEST
+#undef DO_GETXXKEY_R_KEYTYPE
+#undef DO_GETXXKEY_R_PATHNAME
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,163 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Login/Password Management Utilities"
+
+config CONFIG_FEATURE_SHADOWPASSWDS
+	bool "Support for shadow passwords"
+	default n
+	help
+	  Build support for shadow password in /etc/shadow.  This file is only
+	  readable by root and thus the encrypted passwords are no longer
+	  publicly readable.
+
+config CONFIG_USE_BB_SHADOW
+	bool #"  Use busybox shadow password functions"
+	default y
+	depends on CONFIG_USE_BB_PWD_GRP && CONFIG_FEATURE_SHADOWPASSWDS
+	help
+	    If you leave this disabled, busybox will use the system's shadow
+	    password handling functions.  And if you are using the GNU C library
+	    (glibc), you will then need to install the /etc/nsswitch.conf
+	    configuration file and the required /lib/libnss_* libraries in
+	    order for the shadow password functions to work.  This generally
+	    makes your embedded system quite a bit larger.
+
+	    Enabling this option will cause busybox to directly access the
+	    system's /etc/shadow file when handling shadow passwords.  This
+	    makes your system smaller and I will get fewer emails asking about
+	    how glibc NSS works).  When this option is enabled, you will not be
+	    able to use PAM to access shadow passwords from remote LDAP
+	    password servers and whatnot.
+
+config CONFIG_USE_BB_PWD_GRP
+	bool "Use internal password and group functions rather than system functions"
+	default n
+	help
+	    If you leave this disabled, busybox will use the system's password
+	    and group functions.  And if you are using the GNU C library
+	    (glibc), you will then need to install the /etc/nsswitch.conf
+	    configuration file and the required /lib/libnss_* libraries in
+	    order for the password and group functions to work.  This generally
+	    makes your embedded system quite a bit larger.
+
+	    Enabling this option will cause busybox to directly access the
+	    system's /etc/password, /etc/group files (and your system will be
+	    smaller, and I will get fewer emails asking about how glibc NSS
+	    works).  When this option is enabled, you will not be able to use
+	    PAM to access remote LDAP password servers and whatnot.  And if you
+	    want hostname resolution to work with glibc, you still need the
+	    /lib/libnss_* libraries.
+
+	    If you enable this option, it will add about 1.5k to busybox.
+
+config CONFIG_ADDGROUP
+	bool "addgroup"
+	default n
+	help
+	  Utility for creating a new group account.
+
+config CONFIG_DELGROUP
+	bool "delgroup"
+	default n
+	help
+	  Utility for deleting a group account.
+
+config CONFIG_ADDUSER
+	bool "adduser"
+	default n
+	help
+	  Utility for creating a new user account.
+
+config CONFIG_DELUSER
+	bool "deluser"
+	default n
+	help
+	  Utility for deleting a user account.
+
+config CONFIG_GETTY
+	bool "getty"
+	default n
+	help
+	  getty lets you log in on a tty, it is normally invoked by init.
+
+config CONFIG_FEATURE_UTMP
+	bool "Support utmp file"
+	depends on CONFIG_GETTY || CONFIG_LOGIN || CONFIG_SU || CONFIG_WHO
+	default n
+	help
+	  The file /var/run/utmp is used to track who is currently logged in.
+
+config CONFIG_FEATURE_WTMP
+	bool "Support wtmp file"
+	depends on CONFIG_GETTY || CONFIG_LOGIN || CONFIG_SU || CONFIG_LAST
+	default n
+	select CONFIG_FEATURE_UTMP
+	help
+	  The file /var/run/wtmp is used to track when user's have logged into
+	  and logged out of the system.
+
+config CONFIG_LOGIN
+	bool "login"
+	default n
+	select CONFIG_FEATURE_SUID
+	help
+	  login is used when signing onto a system.
+
+	  Note that Busybox binary must be setuid root for this applet to
+	  work properly.
+
+config CONFIG_FEATURE_SECURETTY
+	bool "Support for /etc/securetty"
+	default y
+	depends on CONFIG_LOGIN
+	help
+	  The file  /etc/securetty  is used by (some versions of) login(1).
+	  The file contains the device names of tty lines (one per line,
+	  without leading /dev/) on which root is allowed to login.
+
+config CONFIG_PASSWD
+	bool "passwd"
+	default n
+	select CONFIG_FEATURE_SUID
+	help
+	  passwd changes passwords for user and group accounts.  A normal user
+	  may only change the password for his/her own account, the super user
+	  may change the password for any account.  The administrator of a group
+	  may change the password for the group.
+
+	  Note that Busybox binary must be setuid root for this applet to
+	  work properly.
+
+config CONFIG_SU
+	bool "su"
+	default n
+	select CONFIG_FEATURE_SUID
+	help
+	  su is used to become another user during a login session.
+	  Invoked without a username, su defaults to becoming the super user.
+
+	  Note that Busybox binary must be setuid root for this applet to
+	  work properly.
+
+config CONFIG_SULOGIN
+	bool "sulogin"
+	default n
+	help
+	  sulogin is invoked when the system goes into single user
+	  mode (this is done through an entry in inittab).
+
+config CONFIG_VLOCK
+	bool "vlock"
+	default n
+	select CONFIG_FEATURE_SUID
+	help
+	  Build the "vlock" applet which allows you to lock (virtual) terminals.
+
+	  Note that Busybox binary must be setuid root for this applet to
+	  work properly.
+
+endmenu
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/loginutils
+LOGINUTILS_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,52 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+LOGINUTILS_AR:=loginutils.a
+ifndef LOGINUTILS_DIR
+LOGINUTILS_DIR:=$(top_builddir)/loginutils/
+endif
+srcdir=$(top_srcdir)/loginutils
+
+LOGINUTILS-y:=
+LOGINUTILS-$(CONFIG_ADDGROUP)	+= addgroup.o
+LOGINUTILS-$(CONFIG_ADDUSER)	+= adduser.o
+LOGINUTILS-$(CONFIG_GETTY)	+= getty.o
+LOGINUTILS-$(CONFIG_LOGIN)	+= login.o
+LOGINUTILS-$(CONFIG_PASSWD)	+= passwd.o
+LOGINUTILS-$(CONFIG_SU)		+= su.o
+LOGINUTILS-$(CONFIG_SULOGIN)	+= sulogin.o
+LOGINUTILS-$(CONFIG_VLOCK)	+= vlock.o
+LOGINUTILS-$(CONFIG_DELUSER)	+= deluser.o
+LOGINUTILS-$(CONFIG_DELGROUP)	+= deluser.o
+
+LOGINUTILS-y:=$(sort $(LOGINUTILS-y))
+
+ifneq ($(strip $(LOGINUTILS-y)),)
+libraries-y+=$(LOGINUTILS_DIR)$(LOGINUTILS_AR)
+endif
+
+LOGINUTILS_SRC-y:=$(patsubst %.o,$(srcdir)/%.c,$(LOGINUTILS-y))
+LOGINUTILS_SRC-a:=$(wildcard $(srcdir)/*.c)
+APPLET_SRC-y+=$(LOGINUTILS_SRC-y)
+APPLET_SRC-a+=$(LOGINUTILS_SRC-a)
+
+needcrypt-y:=
+needcrypt-$(CONFIG_LOGIN)	:= y
+needcrypt-$(CONFIG_PASSWD)	:= y
+needcrypt-$(CONFIG_SU)		:= y
+needcrypt-$(CONFIG_SULOGIN)	:= y
+needcrypt-$(CONFIG_VLOCK)	:= y
+
+
+ifeq ($(needcrypt-y),y)
+  LIBRARIES := -lcrypt $(filter-out -lcrypt,$(LIBRARIES))
+endif
+
+$(LOGINUTILS_DIR)$(LOGINUTILS_AR): $(patsubst %,$(LOGINUTILS_DIR)%, $(LOGINUTILS-y))
+	$(do_ar)
+
+$(LOGINUTILS_DIR)%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/addgroup.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/addgroup.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/addgroup.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,113 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * addgroup - add users to /etc/passwd and /etc/shadow
+ *
+ * Copyright (C) 1999 by Lineo, inc. and John Beppu
+ * Copyright (C) 1999,2000,2001 by John Beppu <beppu at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "busybox.h"
+
+/* make sure gr_name isn't taken, make sure gid is kosher
+ * return 1 on failure */
+static int group_study(struct group *g)
+{
+	FILE *etc_group;
+	gid_t desired;
+
+	struct group *grp;
+	const int max = 65000;
+
+	etc_group = bb_xfopen(bb_path_group_file, "r");
+
+	/* make sure gr_name isn't taken, make sure gid is kosher */
+	desired = g->gr_gid;
+	while ((grp = fgetgrent(etc_group))) {
+		if ((strcmp(grp->gr_name, g->gr_name)) == 0) {
+			bb_error_msg_and_die("%s: group already in use", g->gr_name);
+		}
+		if ((desired) && grp->gr_gid == desired) {
+			bb_error_msg_and_die("%d: gid already in use",
+							  desired);
+		}
+		if ((grp->gr_gid > g->gr_gid) && (grp->gr_gid < max)) {
+			g->gr_gid = grp->gr_gid;
+		}
+	}
+	fclose(etc_group);
+
+	/* gid */
+	if (desired) {
+		g->gr_gid = desired;
+	} else {
+		g->gr_gid++;
+	}
+	/* return 1; */
+	return 0;
+}
+
+/* append a new user to the passwd file */
+static int addgroup(char *group, gid_t gid, const char *user)
+{
+	FILE *file;
+	struct group gr;
+
+	/* make sure gid and group haven't already been allocated */
+	gr.gr_gid = gid;
+	gr.gr_name = group;
+	if (group_study(&gr))
+		return 1;
+
+	/* add entry to group */
+	file = bb_xfopen(bb_path_group_file, "a");
+	/* group:passwd:gid:userlist */
+	fprintf(file, "%s:%s:%d:%s\n", group, "x", gr.gr_gid, user);
+	fclose(file);
+
+#if ENABLE_FEATURE_SHADOWPASSWDS
+	file = bb_xfopen(bb_path_gshadow_file, "a");
+	fprintf(file, "%s:!::\n", group);
+	fclose(file);
+#endif
+
+	/* return 1; */
+	return 0;
+}
+
+/*
+ * addgroup will take a login_name as its first parameter.
+ *
+ * gid
+ *
+ * can be customized via command-line parameters.
+ * ________________________________________________________________________ */
+int addgroup_main(int argc, char **argv)
+{
+	char *group;
+	gid_t gid = 0;
+	
+	/* check for min, max and missing args and exit on error */
+	bb_opt_complementally = "-1:?2:?";
+
+	if (bb_getopt_ulflags(argc, argv, "g:", &group)) {
+		gid = bb_xgetlarg(group, 10, 0, LONG_MAX);
+	}
+	/* move past the commandline options */
+	argv += optind;
+
+	/* need to be root */
+	if(geteuid()) {
+		bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+	}
+
+	/* werk */
+	return addgroup(argv[0], gid, (argv[1]) ? argv[1] : "");
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/adduser.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/adduser.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/adduser.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,202 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * adduser - add users to /etc/passwd and /etc/shadow
+ *
+ * Copyright (C) 1999 by Lineo, inc. and John Beppu
+ * Copyright (C) 1999,2000,2001 by John Beppu <beppu at codepoet.org>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <getopt.h>
+#include <sys/stat.h>
+
+#include "busybox.h"
+
+#define DONT_SET_PASS			(1 << 4)
+#define DONT_MAKE_HOME			(1 << 6)
+
+
+/* remix */
+/* EDR recoded such that the uid may be passed in *p */
+static int passwd_study(const char *filename, struct passwd *p)
+{
+	struct passwd *pw;
+	FILE *passwd;
+
+	const int min = 500;
+	const int max = 65000;
+
+	passwd = bb_xfopen(filename, "r");
+
+	/* EDR if uid is out of bounds, set to min */
+	if ((p->pw_uid > max) || (p->pw_uid < min))
+		p->pw_uid = min;
+
+	/* stuff to do:
+	 * make sure login isn't taken;
+	 * find free uid and gid;
+	 */
+	while ((pw = fgetpwent(passwd))) {
+		if (strcmp(pw->pw_name, p->pw_name) == 0) {
+			/* return 0; */
+			return 1;
+		}
+		if ((pw->pw_uid >= p->pw_uid) && (pw->pw_uid < max)
+			&& (pw->pw_uid >= min)) {
+			p->pw_uid = pw->pw_uid + 1;
+		}
+	}
+
+	if (p->pw_gid == 0) {
+		/* EDR check for an already existing gid */
+		while (getgrgid(p->pw_uid) != NULL)
+			p->pw_uid++;
+
+		/* EDR also check for an existing group definition */
+		if (getgrnam(p->pw_name) != NULL)
+			return 3;
+
+		/* EDR create new gid always = uid */
+		p->pw_gid = p->pw_uid;
+	}
+
+	/* EDR bounds check */
+	if ((p->pw_uid > max) || (p->pw_uid < min))
+		return 2;
+
+	/* return 1; */
+	return 0;
+}
+
+static void addgroup_wrapper(struct passwd *p)
+{
+	char *cmd;
+
+	cmd = bb_xasprintf("addgroup -g %d \"%s\"", p->pw_gid, p->pw_name);
+	system(cmd);
+	free(cmd);
+}
+
+static void passwd_wrapper(const char *login) ATTRIBUTE_NORETURN;
+
+static void passwd_wrapper(const char *login)
+{
+	static const char prog[] = "passwd";
+	execlp(prog, prog, login, NULL);
+	bb_error_msg_and_die("Failed to execute '%s', you must set the password for '%s' manually", prog, login);
+}
+
+/* putpwent(3) remix */
+static int adduser(struct passwd *p, unsigned long flags)
+{
+	FILE *file;
+	int addgroup = !p->pw_gid;
+
+	/* make sure everything is kosher and setup uid && gid */
+	file = bb_xfopen(bb_path_passwd_file, "a");
+	fseek(file, 0, SEEK_END);
+
+	switch (passwd_study(bb_path_passwd_file, p)) {
+		case 1:
+			bb_error_msg_and_die("%s: login already in use", p->pw_name);
+		case 2:
+			bb_error_msg_and_die("illegal uid or no uids left");
+		case 3:
+			bb_error_msg_and_die("%s: group name already in use", p->pw_name);
+ 	}
+
+	/* add to passwd */
+	if (putpwent(p, file) == -1) {
+		bb_perror_nomsg_and_die();
+	}
+	fclose(file);
+
+#if ENABLE_FEATURE_SHADOWPASSWDS
+	/* add to shadow if necessary */
+	file = bb_xfopen(bb_path_shadow_file, "a");
+	fseek(file, 0, SEEK_END);
+	fprintf(file, "%s:!:%ld:%d:%d:%d:::\n",
+					p->pw_name,				/* username */
+					time(NULL) / 86400,		/* sp->sp_lstchg */ 
+					0,						/* sp->sp_min */
+					99999,					/* sp->sp_max */
+					7);						/* sp->sp_warn */
+	fclose(file);
+#endif
+
+	/* add to group */
+	/* addgroup should be responsible for dealing w/ gshadow */
+	/* if using a pre-existing group, don't create one */
+	if (addgroup) addgroup_wrapper(p);
+
+	/* Clear the umask for this process so it doesn't
+	 * * screw up the permissions on the mkdir and chown. */
+	umask(0);
+	if (!(flags & DONT_MAKE_HOME)) {
+		/* Set the owner and group so it is owned by the new user,
+		   then fix up the permissions to 2755. Can't do it before
+		   since chown will clear the setgid bit */
+		if (mkdir(p->pw_dir, 0755)
+		|| chown(p->pw_dir, p->pw_uid, p->pw_gid)
+		|| chmod(p->pw_dir, 02755)) {
+ 			bb_perror_msg("%s", p->pw_dir);
+ 		}
+	}
+
+	if (!(flags & DONT_SET_PASS)) {
+		/* interactively set passwd */
+		passwd_wrapper(p->pw_name);
+	}
+
+	return 0;
+}
+
+/*
+ * adduser will take a login_name as its first parameter.
+ *
+ * home
+ * shell
+ * gecos
+ *
+ * can be customized via command-line parameters.
+ * ________________________________________________________________________ */
+int adduser_main(int argc, char **argv)
+{
+	struct passwd pw;
+	const char *usegroup = NULL;
+	unsigned long flags;
+
+	pw.pw_gecos = "Linux User,,,";
+	pw.pw_shell = (char *)DEFAULT_SHELL;
+	pw.pw_dir = NULL;
+
+	/* check for min, max and missing args and exit on error */
+	bb_opt_complementally = "-1:?1:?";
+	flags = bb_getopt_ulflags(argc, argv, "h:g:s:G:DSH", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup);
+
+	/* got root? */
+	if(geteuid()) {
+		bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+ 	}
+
+	/* create string for $HOME if not specified already */
+	if (!pw.pw_dir) {
+		snprintf(bb_common_bufsiz1, BUFSIZ, "/home/%s", argv[optind]);
+		pw.pw_dir =  &bb_common_bufsiz1[0];
+	}
+
+	/* create a passwd struct */
+	pw.pw_name = argv[optind];
+	pw.pw_passwd = "x";
+	pw.pw_uid = 0;
+	pw.pw_gid = (usegroup) ? bb_xgetgrnam(usegroup) : 0; /* exits on failure */
+
+	/* grand finale */
+	return adduser(&pw, flags);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/deluser.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/deluser.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/deluser.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,100 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * deluser (remove lusers from the system ;) for TinyLogin
+ *
+ * Copyright (C) 1999 by Lineo, inc. and John Beppu
+ * Copyright (C) 1999,2000,2001 by John Beppu <beppu at codepoet.org>
+ * Unified with delgroup by Tito Ragusa <farmatito at tiscali.it>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ */
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "busybox.h"
+
+/* where to start and stop deletion */
+typedef struct {
+	size_t start;
+	size_t stop;
+} Bounds;
+
+/* An interesting side-effect of boundary()'s
+ * implementation is that the first user (typically root)
+ * cannot be removed.  Let's call it a feature. */
+static inline Bounds boundary(const char *buffer, const char *login)
+{
+	char needle[256];
+	char *start;
+	char *stop;
+	Bounds b;
+
+	snprintf(needle, 256, "\n%s:", login);
+	needle[255] = 0;
+	start = strstr(buffer, needle);
+	if (!start) {
+		b.start = 0;
+		b.stop = 0;
+		return b;
+	}
+	start++;
+
+	stop = strchr(start, '\n');
+	b.start = start - buffer;
+	b.stop = stop - buffer;
+	return b;
+}
+
+/* grep -v ^login (except it only deletes the first match) */
+/* ...in fact, I think I'm going to simplify this later */
+static void del_line_matching(const char *login, const char *filename)
+{
+	char *buffer;
+	FILE *passwd;
+	Bounds b;
+	struct stat statbuf;
+
+
+	if ((passwd = bb_wfopen(filename, "r"))) {
+		xstat(filename, &statbuf);
+		buffer = (char *) xmalloc(statbuf.st_size * sizeof(char));
+		fread(buffer, statbuf.st_size, sizeof(char), passwd);
+		fclose(passwd);
+		/* find the user to remove */
+		b = boundary(buffer, login);
+		if (b.stop != 0) {
+			/* write the file w/o the user */
+			if ((passwd = bb_wfopen(filename, "w"))) {
+				fwrite(buffer, (b.start - 1), sizeof(char), passwd);
+				fwrite(&buffer[b.stop], (statbuf.st_size - b.stop), sizeof(char), passwd);
+				fclose(passwd);
+			}
+		} else {
+			bb_error_msg("Can't find '%s' in '%s'", login, filename);
+		}
+		free(buffer);
+	}
+}
+
+int deluser_main(int argc, char **argv)
+{
+	if (argc != 2) {
+		bb_show_usage();
+	} else {
+		if (ENABLE_DELUSER && bb_applet_name[3] == 'u') {
+			del_line_matching(argv[1], bb_path_passwd_file);
+			if (ENABLE_FEATURE_SHADOWPASSWDS)
+				del_line_matching(argv[1], bb_path_shadow_file);
+		}
+		del_line_matching(argv[1], bb_path_group_file);
+		if (ENABLE_FEATURE_SHADOWPASSWDS)
+			del_line_matching(argv[1], bb_path_gshadow_file);
+	}
+	return (EXIT_SUCCESS);
+}
+
+/* $Id: deluser.c,v 1.4 2003/07/14 20:20:45 andersen Exp $ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/getty.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/getty.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/getty.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,966 @@
+/* vi: set sw=4 ts=4: */
+/* agetty.c - another getty program for Linux. By W. Z. Venema 1989
+   Ported to Linux by Peter Orbaek <poe at daimi.aau.dk>
+   This program is freely distributable. The entire man-page used to
+   be here. Now read the real man-page agetty.8 instead.
+
+   -f option added by Eric Rasmussen <ear at usfirst.org> - 12/28/95
+
+   1999-02-22 Arkadiusz Mi¶kiewicz <misiek at misiek.eu.org>
+   - added Native Language Support
+
+   1999-05-05 Thorsten Kranzkowski <dl8bcu at gmx.net>
+   - enable hardware flow control before displaying /etc/issue
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <termios.h>
+#include "busybox.h"
+
+#ifdef CONFIG_FEATURE_UTMP
+#include <utmp.h>
+#endif
+
+#define _PATH_LOGIN     "/bin/login"
+
+ /* If USE_SYSLOG is undefined all diagnostics go directly to /dev/console. */
+#ifdef CONFIG_SYSLOGD
+#include <sys/param.h>
+#include <syslog.h>
+#endif
+
+
+ /*
+  * Some heuristics to find out what environment we are in: if it is not
+  * System V, assume it is SunOS 4.
+  */
+
+#ifdef LOGIN_PROCESS                    /* defined in System V utmp.h */
+#define SYSV_STYLE                      /* select System V style getty */
+#ifdef CONFIG_FEATURE_WTMP
+extern void updwtmp(const char *filename, const struct utmp *ut);
+#endif
+#endif  /* LOGIN_PROCESS */
+
+ /*
+  * Things you may want to modify.
+  *
+  * You may disagree with the default line-editing etc. characters defined
+  * below. Note, however, that DEL cannot be used for interrupt generation
+  * and for line editing at the same time.
+  */
+
+#ifdef  SYSV_STYLE
+#include <sys/utsname.h>
+#include <time.h>
+#endif
+
+ /* If ISSUE is not defined, agetty will never display the contents of the
+  * /etc/issue file. You will not want to spit out large "issue" files at the
+  * wrong baud rate.
+  */
+#define ISSUE "/etc/issue"              /* displayed before the login prompt */
+
+/* Some shorthands for control characters. */
+
+#define CTL(x)          (x ^ 0100)      /* Assumes ASCII dialect */
+#define CR              CTL('M')        /* carriage return */
+#define NL              CTL('J')        /* line feed */
+#define BS              CTL('H')        /* back space */
+#define DEL             CTL('?')        /* delete */
+
+/* Defaults for line-editing etc. characters; you may want to change this. */
+
+#define DEF_ERASE       DEL             /* default erase character */
+#define DEF_INTR        CTL('C')        /* default interrupt character */
+#define DEF_QUIT        CTL('\\')       /* default quit char */
+#define DEF_KILL        CTL('U')        /* default kill char */
+#define DEF_EOF         CTL('D')        /* default EOF char */
+#define DEF_EOL         '\n'
+#define DEF_SWITCH      0               /* default switch char */
+
+ /*
+  * SunOS 4.1.1 termio is broken. We must use the termios stuff instead,
+  * because the termio -> termios translation does not clear the termios
+  * CIBAUD bits. Therefore, the tty driver would sometimes report that input
+  * baud rate != output baud rate. I did not notice that problem with SunOS
+  * 4.1. We will use termios where available, and termio otherwise.
+  */
+
+/* linux 0.12 termio is broken too, if we use it c_cc[VERASE] isn't set
+   properly, but all is well if we use termios?! */
+
+#ifdef  TCGETS
+#undef  TCGETA
+#undef  TCSETA
+#undef  TCSETAW
+#define termio  termios
+#define TCGETA  TCGETS
+#define TCSETA  TCSETS
+#define TCSETAW TCSETSW
+#endif
+
+ /*
+  * When multiple baud rates are specified on the command line, the first one
+  * we will try is the first one specified.
+  */
+
+#define FIRST_SPEED     0
+
+/* Storage for command-line options. */
+
+#define MAX_SPEED       10              /* max. nr. of baud rates */
+
+struct options {
+	int flags;                      /* toggle switches, see below */
+	int timeout;                    /* time-out period */
+	char *login;                    /* login program */
+	char *tty;                      /* name of tty */
+	char *initstring;               /* modem init string */
+	char *issue;                    /* alternative issue file */
+	int numspeed;                   /* number of baud rates to try */
+	int speeds[MAX_SPEED];          /* baud rates to be tried */
+};
+
+static const char opt_string[] = "I:LH:f:hil:mt:wn";
+#define F_INITSTRING    (1<<0)          /* initstring is set */
+#define F_LOCAL         (1<<1)          /* force local */
+#define F_FAKEHOST      (1<<2)          /* force fakehost */
+#define F_CUSTISSUE     (1<<3)          /* give alternative issue file */
+#define F_RTSCTS        (1<<4)          /* enable RTS/CTS flow control */
+#define F_ISSUE         (1<<5)          /* display /etc/issue */
+#define F_LOGIN         (1<<6)          /* non-default login program */
+#define F_PARSE         (1<<7)          /* process modem status messages */
+#define F_TIMEOUT       (1<<8)          /* time out */
+#define F_WAITCRLF      (1<<9)          /* wait for CR or LF */
+#define F_NOPROMPT      (1<<10)         /* don't ask for login name! */
+
+/* Storage for things detected while the login name was read. */
+
+struct chardata {
+	int erase;                      /* erase character */
+	int kill;                       /* kill character */
+	int eol;                        /* end-of-line character */
+	int parity;                     /* what parity did we see */
+	int capslock;                   /* upper case without lower case */
+};
+
+/* Initial values for the above. */
+
+static struct chardata init_chardata = {
+	DEF_ERASE,                              /* default erase character */
+	DEF_KILL,                               /* default kill character */
+	13,                                     /* default eol char */
+	0,                                      /* space parity */
+	0,                                      /* no capslock */
+};
+
+#if 0
+struct Speedtab {
+	long speed;
+	int code;
+};
+
+static struct Speedtab speedtab[] = {
+	{50, B50},
+	{75, B75},
+	{110, B110},
+	{134, B134},
+	{150, B150},
+	{200, B200},
+	{300, B300},
+	{600, B600},
+	{1200, B1200},
+	{1800, B1800},
+	{2400, B2400},
+	{4800, B4800},
+	{9600, B9600},
+#ifdef  B19200
+	{19200, B19200},
+#endif
+#ifdef  B38400
+	{38400, B38400},
+#endif
+#ifdef  EXTA
+	{19200, EXTA},
+#endif
+#ifdef  EXTB
+	{38400, EXTB},
+#endif
+#ifdef B57600
+	{57600, B57600},
+#endif
+#ifdef B115200
+	{115200, B115200},
+#endif
+#ifdef B230400
+	{230400, B230400},
+#endif
+	{0, 0},
+};
+#endif
+
+
+#ifdef  SYSV_STYLE
+#ifdef CONFIG_FEATURE_UTMP
+static void update_utmp(char *line);
+#endif
+#endif
+
+/* The following is used for understandable diagnostics. */
+
+/* Fake hostname for ut_host specified on command line. */
+static char *fakehost = NULL;
+
+/* ... */
+#ifdef DEBUGGING
+#define debug(s) fprintf(dbf,s); fflush(dbf)
+#define DEBUGTERM "/dev/ttyp0"
+FILE *dbf;
+#else
+#define debug(s)                                /* nothing */
+#endif
+
+
+/*
+ * output error messages
+ */
+static void error(const char *fmt, ...) ATTRIBUTE_NORETURN;
+static void error(const char *fmt, ...)
+{
+	va_list va_alist;
+	char buf[256];
+
+#ifdef CONFIG_SYSLOGD
+	va_start(va_alist, fmt);
+	vsnprintf(buf, sizeof(buf), fmt, va_alist);
+	openlog(bb_applet_name, 0, LOG_AUTH);
+	syslog(LOG_ERR, "%s", buf);
+	closelog();
+#else
+	int fd;
+	size_t l;
+
+	snprintf(buf, sizeof(buf), "%s: ", bb_applet_name);
+	l = strlen(buf);
+	va_start(va_alist, fmt);
+	vsnprintf(buf + l, sizeof(buf) - l, fmt, va_alist);
+	l = strlen(buf);
+	/* truncate if need */
+	if((l + 3) > sizeof(buf))
+		l = sizeof(buf) - 3;
+	/* add \r\n always */
+	buf[l++] = '\r';
+	buf[l++] = '\n';
+	buf[l] = 0;
+	if ((fd = open("/dev/console", 1)) >= 0) {
+		write(fd, buf, l);
+		close(fd);
+	}
+#endif
+
+	va_end(va_alist);
+
+	(void) sleep((unsigned) 10);    /* be kind to init(8) */
+	exit(1);
+}
+
+
+
+/* bcode - convert speed string to speed code; return 0 on failure */
+static int bcode(const char *s)
+{
+	int r;
+	unsigned long value;
+	if (safe_strtoul((char *)s, &value)) {
+		return -1;
+	}
+	if ((r = tty_value_to_baud(value)) > 0) {
+		return r;
+	}
+	return 0;
+}
+
+
+/* parse_speeds - parse alternate baud rates */
+static void parse_speeds(struct options *op, char *arg)
+{
+	char *cp;
+
+	debug("entered parse_speeds\n");
+	for (cp = strtok(arg, ","); cp != 0; cp = strtok((char *) 0, ",")) {
+		if ((op->speeds[op->numspeed++] = bcode(cp)) <= 0)
+			error("bad speed: %s", cp);
+		if (op->numspeed > MAX_SPEED)
+			error("too many alternate speeds");
+	}
+	debug("exiting parsespeeds\n");
+}
+
+
+/* parse-args - parse command-line arguments */
+static void parse_args(int argc, char **argv, struct options *op)
+{
+	char *ts;
+
+	op->flags = bb_getopt_ulflags(argc, argv, opt_string,
+		&(op->initstring), &fakehost, &(op->issue),
+		&(op->login), &ts);
+	if(op->flags & F_INITSTRING) {
+		const char *p = op->initstring;
+		char *q;
+
+		q = op->initstring = bb_xstrdup(op->initstring);
+		/* copy optarg into op->initstring decoding \ddd
+		   octal codes into chars */
+		while (*p) {
+			if (*p == '\\') {
+				p++;
+				*q++ = bb_process_escape_sequence(&p);
+			} else {
+				*q++ = *p++;
+			}
+		}
+		*q = '\0';
+	}
+	op->flags ^= F_ISSUE;           /* revert flag show /etc/issue */
+	if(op->flags & F_TIMEOUT) {
+		if ((op->timeout = atoi(ts)) <= 0)
+			error("bad timeout value: %s", ts);
+	}
+	debug("after getopt loop\n");
+	if (argc < optind + 2)          /* check parameter count */
+		bb_show_usage();
+
+	/* we loosen up a bit and accept both "baudrate tty" and "tty baudrate" */
+	if ('0' <= argv[optind][0] && argv[optind][0] <= '9') {
+		/* a number first, assume it's a speed (BSD style) */
+		parse_speeds(op, argv[optind++]);       /* baud rate(s) */
+		op->tty = argv[optind]; /* tty name */
+	} else {
+		op->tty = argv[optind++];       /* tty name */
+		parse_speeds(op, argv[optind]); /* baud rate(s) */
+	}
+
+	optind++;
+	if (argc > optind && argv[optind])
+		setenv("TERM", argv[optind], 1);
+
+	debug("exiting parseargs\n");
+}
+
+/* open_tty - set up tty as standard { input, output, error } */
+static void open_tty(char *tty, struct termio *tp, int local)
+{
+	int chdir_to_root = 0;
+
+	/* Set up new standard input, unless we are given an already opened port. */
+
+	if (strcmp(tty, "-")) {
+		struct stat st;
+		int fd;
+
+		/* Sanity checks... */
+
+		if (chdir("/dev"))
+			error("/dev: chdir() failed: %m");
+		chdir_to_root = 1;
+		if (stat(tty, &st) < 0)
+			error("/dev/%s: %m", tty);
+		if ((st.st_mode & S_IFMT) != S_IFCHR)
+			error("/dev/%s: not a character device", tty);
+
+		/* Open the tty as standard input. */
+
+		close(0);
+		debug("open(2)\n");
+		fd = open(tty, O_RDWR | O_NONBLOCK, 0);
+		if (fd != 0)
+			error("/dev/%s: cannot open as standard input: %m", tty);
+	} else {
+
+		/*
+		 * Standard input should already be connected to an open port. Make
+		 * sure it is open for read/write.
+		 */
+
+		if ((fcntl(0, F_GETFL, 0) & O_RDWR) != O_RDWR)
+			error("%s: not open for read/write", tty);
+	}
+
+	/* Replace current standard output/error fd's with new ones */
+	debug("duping\n");
+	if (dup2(STDIN_FILENO, STDOUT_FILENO) == -1 ||
+	    dup2(STDIN_FILENO, STDERR_FILENO) == -1)
+		error("%s: dup problem: %m", tty);      /* we have a problem */
+
+	/*
+	 * The following ioctl will fail if stdin is not a tty, but also when
+	 * there is noise on the modem control lines. In the latter case, the
+	 * common course of action is (1) fix your cables (2) give the modem more
+	 * time to properly reset after hanging up. SunOS users can achieve (2)
+	 * by patching the SunOS kernel variable "zsadtrlow" to a larger value;
+	 * 5 seconds seems to be a good value.
+	 */
+
+	if (ioctl(0, TCGETA, tp) < 0)
+		error("%s: ioctl: %m", tty);
+
+	/*
+	 * It seems to be a terminal. Set proper protections and ownership. Mode
+	 * 0622 is suitable for SYSV <4 because /bin/login does not change
+	 * protections. SunOS 4 login will change the protections to 0620 (write
+	 * access for group tty) after the login has succeeded.
+	 */
+
+#ifdef DEBIAN
+	{
+		/* tty to root.dialout 660 */
+		struct group *gr;
+		int id;
+
+		id = (gr = getgrnam("dialout")) ? gr->gr_gid : 0;
+		chown(tty, 0, id);
+		chmod(tty, 0660);
+
+		/* vcs,vcsa to root.sys 600 */
+		if (!strncmp(tty, "tty", 3) && isdigit(tty[3])) {
+			char *vcs, *vcsa;
+
+			if (!(vcs = strdup(tty)))
+				error("Can't malloc for vcs");
+			if (!(vcsa = malloc(strlen(tty) + 2)))
+				error("Can't malloc for vcsa");
+			strcpy(vcs, "vcs");
+			strcpy(vcs + 3, tty + 3);
+			strcpy(vcsa, "vcsa");
+			strcpy(vcsa + 4, tty + 3);
+
+			id = (gr = getgrnam("sys")) ? gr->gr_gid : 0;
+			chown(vcs, 0, id);
+			chmod(vcs, 0600);
+			chown(vcsa, 0, id);
+			chmod(vcs, 0600);
+
+			free(vcs);
+			free(vcsa);
+		}
+	}
+#else
+	(void) chown(tty, 0, 0);        /* root, sys */
+	(void) chmod(tty, 0622);        /* crw--w--w- */
+#endif
+	if(chdir_to_root && chdir("/"))
+		error("chdir to / failed: %m");
+}
+
+/* termio_init - initialize termio settings */
+static void termio_init(struct termio *tp, int speed, struct options *op)
+{
+	/*
+	 * Initial termio settings: 8-bit characters, raw-mode, blocking i/o.
+	 * Special characters are set after we have read the login name; all
+	 * reads will be done in raw mode anyway. Errors will be dealt with
+	 * lateron.
+	 */
+#ifdef __linux__
+	/* flush input and output queues, important for modems! */
+	(void) ioctl(0, TCFLSH, TCIOFLUSH);
+#endif
+
+	tp->c_cflag = CS8 | HUPCL | CREAD | speed;
+	if (op->flags & F_LOCAL) {
+		tp->c_cflag |= CLOCAL;
+	}
+
+	tp->c_iflag = tp->c_lflag = tp->c_oflag = tp->c_line = 0;
+	tp->c_cc[VMIN] = 1;
+	tp->c_cc[VTIME] = 0;
+
+	/* Optionally enable hardware flow control */
+
+#ifdef  CRTSCTS
+	if (op->flags & F_RTSCTS)
+		tp->c_cflag |= CRTSCTS;
+#endif
+
+	(void) ioctl(0, TCSETA, tp);
+
+	/* go to blocking input even in local mode */
+	fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NONBLOCK);
+
+	debug("term_io 2\n");
+}
+
+/* auto_baud - extract baud rate from modem status message */
+static void auto_baud(struct termio *tp)
+{
+	int speed;
+	int vmin;
+	unsigned iflag;
+	char buf[BUFSIZ];
+	char *bp;
+	int nread;
+
+	/*
+	 * This works only if the modem produces its status code AFTER raising
+	 * the DCD line, and if the computer is fast enough to set the proper
+	 * baud rate before the message has gone by. We expect a message of the
+	 * following format:
+	 *
+	 * <junk><number><junk>
+	 *
+	 * The number is interpreted as the baud rate of the incoming call. If the
+	 * modem does not tell us the baud rate within one second, we will keep
+	 * using the current baud rate. It is advisable to enable BREAK
+	 * processing (comma-separated list of baud rates) if the processing of
+	 * modem status messages is enabled.
+	 */
+
+	/*
+	 * Use 7-bit characters, don't block if input queue is empty. Errors will
+	 * be dealt with lateron.
+	 */
+
+	iflag = tp->c_iflag;
+	tp->c_iflag |= ISTRIP;          /* enable 8th-bit stripping */
+	vmin = tp->c_cc[VMIN];
+	tp->c_cc[VMIN] = 0;                     /* don't block if queue empty */
+	(void) ioctl(0, TCSETA, tp);
+
+	/*
+	 * Wait for a while, then read everything the modem has said so far and
+	 * try to extract the speed of the dial-in call.
+	 */
+
+	(void) sleep(1);
+	if ((nread = read(0, buf, sizeof(buf) - 1)) > 0) {
+		buf[nread] = '\0';
+		for (bp = buf; bp < buf + nread; bp++) {
+			if (isascii(*bp) && isdigit(*bp)) {
+				if ((speed = bcode(bp))) {
+					tp->c_cflag &= ~CBAUD;
+					tp->c_cflag |= speed;
+				}
+				break;
+			}
+		}
+	}
+	/* Restore terminal settings. Errors will be dealt with lateron. */
+
+	tp->c_iflag = iflag;
+	tp->c_cc[VMIN] = vmin;
+	(void) ioctl(0, TCSETA, tp);
+}
+
+/* next_speed - select next baud rate */
+static void next_speed(struct termio *tp, struct options *op)
+{
+	static int baud_index = FIRST_SPEED;    /* current speed index */
+
+	baud_index = (baud_index + 1) % op->numspeed;
+	tp->c_cflag &= ~CBAUD;
+	tp->c_cflag |= op->speeds[baud_index];
+	(void) ioctl(0, TCSETA, tp);
+}
+
+
+/* do_prompt - show login prompt, optionally preceded by /etc/issue contents */
+static void do_prompt(struct options *op, struct termio *tp)
+{
+#ifdef  ISSUE                                   /* optional: show /etc/issue */
+	print_login_issue(op->issue, op->tty);
+#endif
+	print_login_prompt();
+}
+
+/* caps_lock - string contains upper case without lower case */
+/* returns 1 if true, 0 if false */
+static int caps_lock(const char *s)
+{
+	int capslock;
+
+	for (capslock = 0; *s; s++) {
+		if (islower(*s))
+			return (0);
+		if (capslock == 0)
+			capslock = isupper(*s);
+	}
+	return (capslock);
+}
+
+#define logname bb_common_bufsiz1
+/* get_logname - get user name, establish parity, speed, erase, kill, eol */
+/* return NULL on failure, logname on success */
+static char *get_logname(struct options *op, struct chardata *cp, struct termio *tp)
+{
+	char *bp;
+	char c;				/* input character, full eight bits */
+	char ascval;                    /* low 7 bits of input character */
+	int bits;                       /* # of "1" bits per character */
+	int mask;                       /* mask with 1 bit up */
+	static char *erase[] = {        /* backspace-space-backspace */
+		"\010\040\010",                 /* space parity */
+		"\010\040\010",                 /* odd parity */
+		"\210\240\210",                 /* even parity */
+		"\210\240\210",                 /* no parity */
+	};
+
+	/* Initialize kill, erase, parity etc. (also after switching speeds). */
+
+	*cp = init_chardata;
+
+	/* Flush pending input (esp. after parsing or switching the baud rate). */
+
+	(void) sleep(1);
+	(void) ioctl(0, TCFLSH, TCIFLUSH);
+
+	/* Prompt for and read a login name. */
+
+	for (*logname = 0; *logname == 0; /* void */ ) {
+
+		/* Write issue file and prompt, with "parity" bit == 0. */
+
+		do_prompt(op, tp);
+
+		/* Read name, watch for break, parity, erase, kill, end-of-line. */
+
+		for (bp = logname, cp->eol = 0; cp->eol == 0; /* void */ ) {
+
+			/* Do not report trivial EINTR/EIO errors. */
+
+			if (read(0, &c, 1) < 1) {
+				if (errno == EINTR || errno == EIO)
+					exit(0);
+				error("%s: read: %m", op->tty);
+			}
+			/* Do BREAK handling elsewhere. */
+
+			if ((c == 0) && op->numspeed > 1)
+				/* return (0); */
+				return NULL;
+
+			/* Do parity bit handling. */
+
+			if (c != (ascval = (c & 0177))) {       /* "parity" bit on ? */
+				for (bits = 1, mask = 1; mask & 0177; mask <<= 1)
+					if (mask & ascval)
+						bits++; /* count "1" bits */
+				cp->parity |= ((bits & 1) ? 1 : 2);
+			}
+			/* Do erase, kill and end-of-line processing. */
+
+			switch (ascval) {
+			case CR:
+			case NL:
+				*bp = 0;                /* terminate logname */
+				cp->eol = ascval;       /* set end-of-line char */
+				break;
+			case BS:
+			case DEL:
+			case '#':
+				cp->erase = ascval;     /* set erase character */
+				if (bp > logname) {
+					(void) write(1, erase[cp->parity], 3);
+					bp--;
+				}
+				break;
+			case CTL('U'):
+			case '@':
+				cp->kill = ascval;      /* set kill character */
+				while (bp > logname) {
+					(void) write(1, erase[cp->parity], 3);
+					bp--;
+				}
+				break;
+			case CTL('D'):
+				exit(0);
+			default:
+				if (!isascii(ascval) || !isprint(ascval)) {
+					/* ignore garbage characters */ ;
+				} else if (bp - logname >= sizeof(logname) - 1) {
+					error("%s: input overrun", op->tty);
+				} else {
+					(void) write(1, &c, 1); /* echo the character */
+					*bp++ = ascval; /* and store it */
+				}
+				break;
+			}
+		}
+	}
+	/* Handle names with upper case and no lower case. */
+
+	if ((cp->capslock = caps_lock(logname))) {
+		for (bp = logname; *bp; bp++)
+			if (isupper(*bp))
+				*bp = tolower(*bp);     /* map name to lower case */
+	}
+	return (logname);
+}
+
+/* termio_final - set the final tty mode bits */
+static void termio_final(struct options *op, struct termio *tp, struct chardata *cp)
+{
+	/* General terminal-independent stuff. */
+
+	tp->c_iflag |= IXON | IXOFF;    /* 2-way flow control */
+	tp->c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE;
+	/* no longer| ECHOCTL | ECHOPRT */
+	tp->c_oflag |= OPOST;
+	/* tp->c_cflag = 0; */
+	tp->c_cc[VINTR] = DEF_INTR;     /* default interrupt */
+	tp->c_cc[VQUIT] = DEF_QUIT;     /* default quit */
+	tp->c_cc[VEOF] = DEF_EOF;       /* default EOF character */
+	tp->c_cc[VEOL] = DEF_EOL;
+	tp->c_cc[VSWTC] = DEF_SWITCH;   /* default switch character */
+
+	/* Account for special characters seen in input. */
+
+	if (cp->eol == CR) {
+		tp->c_iflag |= ICRNL;   /* map CR in input to NL */
+		tp->c_oflag |= ONLCR;   /* map NL in output to CR-NL */
+	}
+	tp->c_cc[VERASE] = cp->erase;   /* set erase character */
+	tp->c_cc[VKILL] = cp->kill;     /* set kill character */
+
+	/* Account for the presence or absence of parity bits in input. */
+
+	switch (cp->parity) {
+	case 0:                                 /* space (always 0) parity */
+		break;
+	case 1:                                 /* odd parity */
+		tp->c_cflag |= PARODD;
+		/* FALLTHROUGH */
+	case 2:                                 /* even parity */
+		tp->c_cflag |= PARENB;
+		tp->c_iflag |= INPCK | ISTRIP;
+		/* FALLTHROUGH */
+	case (1 | 2):                           /* no parity bit */
+		tp->c_cflag &= ~CSIZE;
+		tp->c_cflag |= CS7;
+		break;
+	}
+	/* Account for upper case without lower case. */
+
+	if (cp->capslock) {
+		tp->c_iflag |= IUCLC;
+		tp->c_lflag |= XCASE;
+		tp->c_oflag |= OLCUC;
+	}
+	/* Optionally enable hardware flow control */
+
+#ifdef  CRTSCTS
+	if (op->flags & F_RTSCTS)
+		tp->c_cflag |= CRTSCTS;
+#endif
+
+	/* Finally, make the new settings effective */
+
+	if (ioctl(0, TCSETA, tp) < 0)
+		error("%s: ioctl: TCSETA: %m", op->tty);
+}
+
+
+#ifdef  SYSV_STYLE
+#ifdef CONFIG_FEATURE_UTMP
+/* update_utmp - update our utmp entry */
+static void update_utmp(char *line)
+{
+	struct utmp ut;
+	struct utmp *utp;
+	time_t t;
+	int mypid = getpid();
+#if ! (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1))
+	struct flock lock;
+#endif
+
+	/*
+	 * The utmp file holds miscellaneous information about things started by
+	 * /sbin/init and other system-related events. Our purpose is to update
+	 * the utmp entry for the current process, in particular the process type
+	 * and the tty line we are listening to. Return successfully only if the
+	 * utmp file can be opened for update, and if we are able to find our
+	 * entry in the utmp file.
+	 */
+	if (access(_PATH_UTMP, R_OK|W_OK) == -1) {
+		close(creat(_PATH_UTMP, 0664));
+	}
+	utmpname(_PATH_UTMP);
+	setutent();
+	while ((utp = getutent())
+		   && !(utp->ut_type == INIT_PROCESS && utp->ut_pid == mypid))  /* nothing */
+		;
+
+	if (utp) {
+		memcpy(&ut, utp, sizeof(ut));
+	} else {
+		/* some inits don't initialize utmp... */
+		memset(&ut, 0, sizeof(ut));
+		safe_strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
+	}
+	/*endutent(); */
+
+	strcpy(ut.ut_user, "LOGIN");
+	safe_strncpy(ut.ut_line, line, sizeof(ut.ut_line));
+	if (fakehost)
+		safe_strncpy(ut.ut_host, fakehost, sizeof(ut.ut_host));
+	time(&t);
+	ut.ut_time = t;
+	ut.ut_type = LOGIN_PROCESS;
+	ut.ut_pid = mypid;
+
+	pututline(&ut);
+	endutent();
+
+#ifdef CONFIG_FEATURE_WTMP
+	if (access(bb_path_wtmp_file, R_OK|W_OK) == -1)
+		close(creat(bb_path_wtmp_file, 0664));
+	updwtmp(bb_path_wtmp_file, &ut);
+#endif
+}
+
+#endif /* CONFIG_FEATURE_UTMP */
+#endif /* SYSV_STYLE */
+
+
+#undef logname
+int getty_main(int argc, char **argv)
+{
+	char *logname = NULL;           /* login name, given to /bin/login */
+	struct chardata chardata;       /* set by get_logname() */
+	struct termio termio;           /* terminal mode bits */
+	static struct options options = {
+		0,                      /* show /etc/issue (SYSV_STYLE) */
+		0,                      /* no timeout */
+		_PATH_LOGIN,            /* default login program */
+		"tty1",                 /* default tty line */
+		"",                     /* modem init string */
+#ifdef ISSUE
+		ISSUE,                  /* default issue file */
+#else
+		NULL,
+#endif
+		0,                      /* no baud rates known yet */
+	};
+
+#ifdef DEBUGGING
+	dbf = bb_xfopen(DEBUGTERM, "w");
+
+	{
+		int i;
+
+		for (i = 1; i < argc; i++) {
+			debug(argv[i]);
+			debug("\n");
+		}
+	}
+#endif
+
+	/* Parse command-line arguments. */
+
+	parse_args(argc, argv, &options);
+
+#ifdef __linux__
+	setsid();
+#endif
+
+	/* Update the utmp file. */
+
+
+#ifdef  SYSV_STYLE
+#ifdef CONFIG_FEATURE_UTMP
+	update_utmp(options.tty);
+#endif
+#endif
+
+	debug("calling open_tty\n");
+	/* Open the tty as standard { input, output, error }. */
+	open_tty(options.tty, &termio, options.flags & F_LOCAL);
+
+#ifdef __linux__
+	{
+		int iv;
+
+		iv = getpid();
+		ioctl(0, TIOCSPGRP, &iv);
+	}
+#endif
+	/* Initialize the termio settings (raw mode, eight-bit, blocking i/o). */
+	debug("calling termio_init\n");
+	termio_init(&termio, options.speeds[FIRST_SPEED], &options);
+
+	/* write the modem init string and DON'T flush the buffers */
+	if (options.flags & F_INITSTRING) {
+		debug("writing init string\n");
+		write(1, options.initstring, strlen(options.initstring));
+	}
+
+	if (!(options.flags & F_LOCAL)) {
+		/* go to blocking write mode unless -L is specified */
+		fcntl(1, F_SETFL, fcntl(1, F_GETFL, 0) & ~O_NONBLOCK);
+	}
+
+	/* Optionally detect the baud rate from the modem status message. */
+	debug("before autobaud\n");
+	if (options.flags & F_PARSE)
+		auto_baud(&termio);
+
+	/* Set the optional timer. */
+	if (options.timeout)
+		(void) alarm((unsigned) options.timeout);
+
+	/* optionally wait for CR or LF before writing /etc/issue */
+	if (options.flags & F_WAITCRLF) {
+		char ch;
+
+		debug("waiting for cr-lf\n");
+		while (read(0, &ch, 1) == 1) {
+			ch &= 0x7f;                     /* strip "parity bit" */
+#ifdef DEBUGGING
+			fprintf(dbf, "read %c\n", ch);
+#endif
+			if (ch == '\n' || ch == '\r')
+				break;
+		}
+	}
+
+	chardata = init_chardata;
+	if (!(options.flags & F_NOPROMPT)) {
+		/* Read the login name. */
+		debug("reading login name\n");
+		/* while ((logname = get_logname(&options, &chardata, &termio)) == 0) */
+		while ((logname = get_logname(&options, &chardata, &termio)) ==
+			   NULL) next_speed(&termio, &options);
+	}
+
+	/* Disable timer. */
+
+	if (options.timeout)
+		(void) alarm(0);
+
+	/* Finalize the termio settings. */
+
+	termio_final(&options, &termio, &chardata);
+
+	/* Now the newline character should be properly written. */
+
+	(void) write(1, "\n", 1);
+
+	/* Let the login program take care of password validation. */
+
+	(void) execl(options.login, options.login, "--", logname, (char *) 0);
+	error("%s: can't exec %s: %m", options.tty, options.login);
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/login.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/login.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/login.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,480 @@
+/* vi: set sw=4 ts=4: */
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <termios.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "busybox.h"
+#ifdef CONFIG_SELINUX
+#include <selinux/selinux.h>  /* for is_selinux_enabled()  */
+#include <selinux/get_context_list.h> /* for get_default_context() */
+#include <selinux/flask.h> /* for security class definitions  */
+#include <errno.h>
+#endif
+
+#ifdef CONFIG_FEATURE_UTMP
+// import from utmp.c
+static void checkutmp(int picky);
+static void setutmp(const char *name, const char *line);
+/* Stuff global to this file */
+static struct utmp utent;
+#endif
+
+// login defines
+#define TIMEOUT       60
+#define EMPTY_USERNAME_COUNT    10
+#define USERNAME_SIZE 32
+
+
+static int check_nologin ( int amroot );
+
+#if defined CONFIG_FEATURE_SECURETTY
+static int check_tty ( const char *tty );
+
+#else
+static inline int check_tty ( const char *tty )  { return 1; }
+
+#endif
+
+static int is_my_tty ( const char *tty );
+static int login_prompt ( char *buf_name );
+static void motd ( void );
+
+
+static void alarm_handler ( int sig ATTRIBUTE_UNUSED)
+{
+	fprintf (stderr, "\nLogin timed out after %d seconds.\n", TIMEOUT );
+	exit ( EXIT_SUCCESS );
+}
+
+
+int login_main(int argc, char **argv)
+{
+	char tty[BUFSIZ];
+	char full_tty[200];
+	char fromhost[512];
+	char username[USERNAME_SIZE];
+	const char *tmp;
+	int amroot;
+	int flag;
+	int failed;
+	int count=0;
+	struct passwd *pw, pw_copy;
+#ifdef CONFIG_WHEEL_GROUP
+	struct group *grp;
+#endif
+	int opt_preserve = 0;
+	int opt_fflag = 0;
+	char *opt_host = 0;
+	int alarmstarted = 0;
+#ifdef CONFIG_SELINUX
+	security_context_t user_sid = NULL;
+#endif
+
+	username[0]=0;
+	amroot = ( getuid ( ) == 0 );
+	signal ( SIGALRM, alarm_handler );
+	alarm ( TIMEOUT );
+	alarmstarted = 1;
+
+	while (( flag = getopt(argc, argv, "f:h:p")) != EOF ) {
+		switch ( flag ) {
+		case 'p':
+			opt_preserve = 1;
+			break;
+		case 'f':
+			/*
+			 * username must be a separate token
+			 * (-f root, *NOT* -froot). --marekm
+			 */
+			if ( optarg != argv[optind-1] )
+				bb_show_usage( );
+
+			if ( !amroot )		/* Auth bypass only if real UID is zero */
+				bb_error_msg_and_die ( "-f permission denied" );
+
+			safe_strncpy(username, optarg, USERNAME_SIZE);
+			opt_fflag = 1;
+			break;
+		case 'h':
+			opt_host = optarg;
+			break;
+		default:
+			bb_show_usage( );
+		}
+	}
+
+	if (optind < argc)             // user from command line (getty)
+		safe_strncpy(username, argv[optind], USERNAME_SIZE);
+
+	if ( !isatty ( 0 ) || !isatty ( 1 ) || !isatty ( 2 ))
+		return EXIT_FAILURE;		/* Must be a terminal */
+
+#ifdef CONFIG_FEATURE_UTMP
+	checkutmp ( !amroot );
+#endif
+
+	tmp = ttyname ( 0 );
+	if ( tmp && ( strncmp ( tmp, "/dev/", 5 ) == 0 ))
+		safe_strncpy ( tty, tmp + 5, sizeof( tty ));
+	else if ( tmp && *tmp == '/' )
+		safe_strncpy ( tty, tmp, sizeof( tty ));
+	else
+		safe_strncpy ( tty, "UNKNOWN", sizeof( tty ));
+
+#ifdef CONFIG_FEATURE_UTMP
+	if ( amroot )
+		memset ( utent.ut_host, 0, sizeof utent.ut_host );
+#endif
+
+	if ( opt_host ) {
+#ifdef CONFIG_FEATURE_UTMP
+		safe_strncpy ( utent.ut_host, opt_host, sizeof( utent. ut_host ));
+#endif
+		snprintf ( fromhost, sizeof( fromhost ) - 1, " on `%.100s' from `%.200s'", tty, opt_host );
+	}
+	else
+		snprintf ( fromhost, sizeof( fromhost ) - 1, " on `%.100s'", tty );
+
+	bb_setpgrp;
+
+	openlog ( "login", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH );
+
+	while ( 1 ) {
+		failed = 0;
+
+		if ( !username[0] )
+			if(!login_prompt ( username ))
+				return EXIT_FAILURE;
+
+		if ( !alarmstarted && ( TIMEOUT > 0 )) {
+			alarm ( TIMEOUT );
+			alarmstarted = 1;
+		}
+
+		if (!( pw = getpwnam ( username ))) {
+			pw_copy.pw_name   = "UNKNOWN";
+			pw_copy.pw_passwd = "!";
+			opt_fflag = 0;
+			failed = 1;
+		} else
+			pw_copy = *pw;
+
+		pw = &pw_copy;
+
+		if (( pw-> pw_passwd [0] == '!' ) || ( pw-> pw_passwd[0] == '*' ))
+			failed = 1;
+
+		if ( opt_fflag ) {
+			opt_fflag = 0;
+			goto auth_ok;
+		}
+
+		if (!failed && ( pw-> pw_uid == 0 ) && ( !check_tty ( tty )))
+			failed = 1;
+
+		/* Don't check the password if password entry is empty (!) */
+		if ( !pw-> pw_passwd[0] )
+			goto auth_ok;
+
+		/* authorization takes place here */
+		if ( correct_password ( pw ))
+			goto auth_ok;
+
+		failed = 1;
+
+auth_ok:
+		if ( !failed)
+			break;
+
+		bb_do_delay(FAIL_DELAY);
+		puts("Login incorrect");
+		username[0] = 0;
+		if ( ++count == 3 ) {
+			syslog ( LOG_WARNING, "invalid password for `%s'%s\n", pw->pw_name, fromhost);
+			return EXIT_FAILURE;
+	}
+	}
+
+	alarm ( 0 );
+	if ( check_nologin ( pw-> pw_uid == 0 ))
+		return EXIT_FAILURE;
+
+#ifdef CONFIG_FEATURE_UTMP
+	setutmp ( username, tty );
+#endif
+
+	if ( *tty != '/' )
+		snprintf ( full_tty, sizeof( full_tty ) - 1, "/dev/%s", tty);
+	else
+		safe_strncpy ( full_tty, tty, sizeof( full_tty ) - 1 );
+
+#ifdef CONFIG_SELINUX
+	if (is_selinux_enabled())
+	{
+		security_context_t old_tty_sid, new_tty_sid;
+
+		if (get_default_context(username, NULL, &user_sid))
+		{
+			fprintf(stderr, "Unable to get SID for %s\n", username);
+			exit(1);
+		}
+		if (getfilecon(full_tty, &old_tty_sid) < 0)
+		{
+			fprintf(stderr, "getfilecon(%.100s) failed: %.100s\n", full_tty, strerror(errno));
+			return EXIT_FAILURE;
+		}
+		if (security_compute_relabel(user_sid, old_tty_sid, SECCLASS_CHR_FILE, &new_tty_sid) != 0)
+		{
+			fprintf(stderr, "security_change_sid(%.100s) failed: %.100s\n", full_tty, strerror(errno));
+			return EXIT_FAILURE;
+		}
+		if(setfilecon(full_tty, new_tty_sid) != 0)
+		{
+			fprintf(stderr, "chsid(%.100s, %s) failed: %.100s\n", full_tty, new_tty_sid, strerror(errno));
+			return EXIT_FAILURE;
+		}
+	}
+#endif
+	if ( !is_my_tty ( full_tty ))
+		syslog ( LOG_ERR, "unable to determine TTY name, got %s\n", full_tty );
+
+	/* Try these, but don't complain if they fail
+	 * (for example when the root fs is read only) */
+	chown ( full_tty, pw-> pw_uid, pw-> pw_gid );
+	chmod ( full_tty, 0600 );
+
+	change_identity ( pw );
+	tmp = pw-> pw_shell;
+	if(!tmp || !*tmp)
+		tmp = DEFAULT_SHELL;
+	setup_environment ( tmp, 1, !opt_preserve, pw );
+
+	motd ( );
+	signal ( SIGALRM, SIG_DFL );	/* default alarm signal */
+
+	if ( pw-> pw_uid == 0 )
+		syslog ( LOG_INFO, "root login %s\n", fromhost );
+#ifdef CONFIG_SELINUX
+	/* well, a simple setexeccon() here would do the job as well,
+	 * but let's play the game for now */
+	set_current_security_context(user_sid);
+#endif
+	run_shell ( tmp, 1, 0, 0);	/* exec the shell finally. */
+
+	return EXIT_FAILURE;
+}
+
+
+
+static int login_prompt ( char *buf_name )
+{
+	char buf [1024];
+	char *sp, *ep;
+	int i;
+
+	for(i=0; i<EMPTY_USERNAME_COUNT; i++) {
+		print_login_prompt();
+
+		if ( !fgets ( buf, sizeof( buf ) - 1, stdin ))
+			return 0;
+
+		if ( !strchr ( buf, '\n' ))
+			return 0;
+
+		for ( sp = buf; isspace ( *sp ); sp++ ) { }
+		for ( ep = sp; isgraph ( *ep ); ep++ ) { }
+
+		*ep = 0;
+		safe_strncpy(buf_name, sp, USERNAME_SIZE);
+		if(buf_name[0])
+			return 1;
+	}
+	return 0;
+}
+
+
+static int check_nologin ( int amroot )
+{
+	if ( access ( bb_path_nologin_file, F_OK ) == 0 ) {
+		FILE *fp;
+		int c;
+
+		if (( fp = fopen ( bb_path_nologin_file, "r" ))) {
+			while (( c = getc ( fp )) != EOF )
+				putchar (( c == '\n' ) ? '\r' : c );
+
+			fflush ( stdout );
+			fclose ( fp );
+		} else {
+			puts ( "\r\nSystem closed for routine maintenance.\r" );
+		}
+		if ( !amroot )
+			return 1;
+
+		puts ( "\r\n[Disconnect bypassed -- root login allowed.]\r" );
+	}
+	return 0;
+}
+
+#ifdef CONFIG_FEATURE_SECURETTY
+
+static int check_tty ( const char *tty )
+{
+	FILE *fp;
+	int i;
+	char buf[BUFSIZ];
+
+	if (( fp = fopen ( bb_path_securetty_file, "r" ))) {
+		while ( fgets ( buf, sizeof( buf ) - 1, fp )) {
+			for ( i = strlen( buf ) - 1; i >= 0; --i ) {
+				if ( !isspace ( buf[i] ))
+					break;
+			}
+			buf[++i] = '\0';
+			if (( buf [0] == '\0' ) || ( buf [0] == '#' ))
+				continue;
+
+			if ( strcmp ( buf, tty ) == 0 ) {
+				fclose ( fp );
+				return 1;
+			}
+		}
+		fclose(fp);
+		return 0;
+	}
+	/* A missing securetty file is not an error. */
+	return 1;
+}
+
+#endif
+
+/* returns 1 if true */
+static int is_my_tty ( const char *tty )
+{
+	struct stat by_name, by_fd;
+
+	if ( stat ( tty, &by_name ) || fstat ( 0, &by_fd ))
+		return 0;
+
+	if ( by_name. st_rdev != by_fd. st_rdev )
+		return 0;
+	else
+		return 1;
+}
+
+
+static void motd (void)
+{
+	FILE *fp;
+	register int c;
+
+	if (( fp = fopen ( bb_path_motd_file, "r" ))) {
+		while (( c = getc ( fp )) != EOF )
+			putchar ( c );
+		fclose ( fp );
+	}
+}
+
+
+#ifdef CONFIG_FEATURE_UTMP
+// vv  Taken from tinylogin utmp.c  vv
+
+#define	NO_UTENT \
+	"No utmp entry.  You must exec \"login\" from the lowest level \"sh\""
+#define	NO_TTY \
+	"Unable to determine your tty name."
+
+/*
+ * checkutmp - see if utmp file is correct for this process
+ *
+ *	System V is very picky about the contents of the utmp file
+ *	and requires that a slot for the current process exist.
+ *	The utmp file is scanned for an entry with the same process
+ *	ID.  If no entry exists the process exits with a message.
+ *
+ *	The "picky" flag is for network and other logins that may
+ *	use special flags.  It allows the pid checks to be overridden.
+ *	This means that getty should never invoke login with any
+ *	command line flags.
+ */
+
+static void checkutmp(int picky)
+{
+	char *line;
+	struct utmp *ut;
+	pid_t pid = getpid();
+
+	setutent();
+
+	/* First, try to find a valid utmp entry for this process.  */
+	while ((ut = getutent()))
+		if (ut->ut_pid == pid && ut->ut_line[0] && ut->ut_id[0] &&
+			(ut->ut_type == LOGIN_PROCESS || ut->ut_type == USER_PROCESS))
+			break;
+
+	/* If there is one, just use it, otherwise create a new one.  */
+	if (ut) {
+		utent = *ut;
+	} else {
+		time_t t_tmp;
+		
+		if (picky) {
+			puts(NO_UTENT);
+			exit(1);
+		}
+		line = ttyname(0);
+		if (!line) {
+			puts(NO_TTY);
+			exit(1);
+		}
+		if (strncmp(line, "/dev/", 5) == 0)
+			line += 5;
+		memset((void *) &utent, 0, sizeof utent);
+		utent.ut_type = LOGIN_PROCESS;
+		utent.ut_pid = pid;
+		strncpy(utent.ut_line, line, sizeof utent.ut_line);
+		/* XXX - assumes /dev/tty?? */
+		strncpy(utent.ut_id, utent.ut_line + 3, sizeof utent.ut_id);
+		strncpy(utent.ut_user, "LOGIN", sizeof utent.ut_user);
+		t_tmp = (time_t)utent.ut_time;
+		time(&t_tmp);
+	}
+}
+
+/*
+ * setutmp - put a USER_PROCESS entry in the utmp file
+ *
+ *	setutmp changes the type of the current utmp entry to
+ *	USER_PROCESS.  the wtmp file will be updated as well.
+ */
+
+static void setutmp(const char *name, const char *line ATTRIBUTE_UNUSED)
+{
+	time_t t_tmp = (time_t)utent.ut_time;
+
+	utent.ut_type = USER_PROCESS;
+	strncpy(utent.ut_user, name, sizeof utent.ut_user);
+	time(&t_tmp);
+	/* other fields already filled in by checkutmp above */
+	setutent();
+	pututline(&utent);
+	endutent();
+#ifdef CONFIG_FEATURE_WTMP
+	if (access(bb_path_wtmp_file, R_OK|W_OK) == -1) {
+		close(creat(bb_path_wtmp_file, 0664));
+	}
+	updwtmp(bb_path_wtmp_file, &utent);
+#endif
+}
+#endif /* CONFIG_FEATURE_UTMP */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/passwd.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/passwd.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/passwd.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,400 @@
+/* vi: set sw=4 ts=4: */
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <utime.h>
+#include <syslog.h>
+#include <time.h>
+#include <sys/resource.h>
+#include <errno.h>
+
+#include "busybox.h"
+
+static char crypt_passwd[128];
+
+static int create_backup(const char *backup, FILE * fp);
+static int new_password(const struct passwd *pw, int amroot, int algo);
+static void set_filesize_limit(int blocks);
+
+
+static int get_algo(char *a)
+{
+	int x = 1;					/* standard: MD5 */
+
+	if (strcasecmp(a, "des") == 0)
+		x = 0;
+	return x;
+}
+
+
+static int update_passwd(const struct passwd *pw, const char *crypt_pw)
+{
+	char filename[1024];
+	char buf[1025];
+	char buffer[80];
+	char username[32];
+	char *pw_rest;
+	int mask;
+	int continued;
+	FILE *fp;
+	FILE *out_fp;
+	struct stat sb;
+	struct flock lock;
+
+#if ENABLE_FEATURE_SHADOWPASSWDS
+	if (access(bb_path_shadow_file, F_OK) == 0) {
+		snprintf(filename, sizeof filename, "%s", bb_path_shadow_file);
+	} else
+#endif
+	{
+		snprintf(filename, sizeof filename, "%s", bb_path_passwd_file);
+	}
+
+	if (((fp = fopen(filename, "r+")) == 0) || (fstat(fileno(fp), &sb))) {
+		/* return 0; */
+		return 1;
+	}
+
+	/* Lock the password file before updating */
+	lock.l_type = F_WRLCK;
+	lock.l_whence = SEEK_SET;
+	lock.l_start = 0;
+	lock.l_len = 0;
+	if (fcntl(fileno(fp), F_SETLK, &lock) < 0) {
+		fprintf(stderr, "%s: %s\n", filename, strerror(errno));
+		return 1;
+	}
+	lock.l_type = F_UNLCK;
+
+	snprintf(buf, sizeof buf, "%s-", filename);
+	if (create_backup(buf, fp)) {
+		fcntl(fileno(fp), F_SETLK, &lock);
+		fclose(fp);
+		return 1;
+	}
+	snprintf(buf, sizeof buf, "%s+", filename);
+	mask = umask(0777);
+	out_fp = fopen(buf, "w");
+	umask(mask);
+	if ((!out_fp) || (fchmod(fileno(out_fp), sb.st_mode & 0777))
+		|| (fchown(fileno(out_fp), sb.st_uid, sb.st_gid))) {
+		fcntl(fileno(fp), F_SETLK, &lock);
+		fclose(fp);
+		fclose(out_fp);
+		return 1;
+	}
+
+	continued = 0;
+	snprintf(username, sizeof username, "%s:", pw->pw_name);
+	rewind(fp);
+	while (!feof(fp)) {
+		fgets(buffer, sizeof buffer, fp);
+		if (!continued) { /* Check to see if we're updating this line.  */
+			if (strncmp(username, buffer, strlen(username)) == 0) {
+				/* we have a match. */
+				pw_rest = strchr(buffer, ':');
+				*pw_rest++ = '\0';
+				pw_rest = strchr(pw_rest, ':');
+				fprintf(out_fp, "%s:%s%s", buffer, crypt_pw, pw_rest);
+			} else {
+				fputs(buffer, out_fp);
+			}
+		} else {
+			fputs(buffer, out_fp);
+		}
+		if (buffer[strlen(buffer) - 1] == '\n') {
+			continued = 0;
+		} else {
+			continued = 1;
+		}
+		memset(buffer, 0, sizeof buffer);
+	}
+
+	if (fflush(out_fp) || fsync(fileno(out_fp)) || fclose(out_fp)) {
+		unlink(buf);
+		fcntl(fileno(fp), F_SETLK, &lock);
+		fclose(fp);
+		return 1;
+	}
+	if (rename(buf, filename) < 0) {
+		fcntl(fileno(fp), F_SETLK, &lock);
+		fclose(fp);
+		return 1;
+	} else {
+		fcntl(fileno(fp), F_SETLK, &lock);
+		fclose(fp);
+		return 0;
+	}
+}
+
+
+int passwd_main(int argc, char **argv)
+{
+	int amroot;
+	char *cp;
+	char *np;
+	char *name;
+	char *myname;
+	int flag;
+	int algo = 1;				/* -a - password algorithm */
+	int lflg = 0;				/* -l - lock account */
+	int uflg = 0;				/* -u - unlock account */
+	int dflg = 0;				/* -d - delete password */
+	const struct passwd *pw;
+
+#if ENABLE_FEATURE_SHADOWPASSWDS
+	const struct spwd *sp;
+#endif
+	amroot = (getuid() == 0);
+	openlog("passwd", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH);
+	while ((flag = getopt(argc, argv, "a:dlu")) != EOF) {
+		switch (flag) {
+		case 'a':
+			algo = get_algo(optarg);
+			break;
+		case 'd':
+			dflg++;
+			break;
+		case 'l':
+			lflg++;
+			break;
+		case 'u':
+			uflg++;
+			break;
+		default:
+			bb_show_usage();
+		}
+	}
+	myname = (char *) bb_xstrdup(bb_getpwuid(NULL, getuid(), -1));
+	/* exits on error */
+	if (optind < argc) {
+		name = argv[optind];
+	} else {
+		name = myname;
+	}
+	if ((lflg || uflg || dflg) && (optind >= argc || !amroot)) {
+		bb_show_usage();
+	}
+	pw = getpwnam(name);
+	if (!pw) {
+		bb_error_msg_and_die("Unknown user %s\n", name);
+	}
+	if (!amroot && pw->pw_uid != getuid()) {
+		syslog(LOG_WARNING, "can't change pwd for `%s'", name);
+		bb_error_msg_and_die("Permission denied.\n");
+	}
+#if ENABLE_FEATURE_SHADOWPASSWDS
+	sp = getspnam(name);
+	if (!sp) {
+		sp = (struct spwd *) pwd_to_spwd(pw);
+	}
+	cp = sp->sp_pwdp;
+	np = sp->sp_namp;
+#else
+	cp = pw->pw_passwd;
+	np = name;
+#endif
+
+	safe_strncpy(crypt_passwd, cp, sizeof(crypt_passwd));
+	if (!(dflg || lflg || uflg)) {
+		if (!amroot) {
+			if (cp[0] == '!') {
+				syslog(LOG_WARNING, "password locked for `%s'", np);
+				bb_error_msg_and_die( "The password for `%s' cannot be changed.\n", np);
+			}
+		}
+		printf("Changing password for %s\n", name);
+		if (new_password(pw, amroot, algo)) {
+			bb_error_msg_and_die( "The password for %s is unchanged.\n", name);
+		}
+	} else if (lflg) {
+		if (crypt_passwd[0] != '!') {
+			memmove(&crypt_passwd[1], crypt_passwd,
+					sizeof crypt_passwd - 1);
+			crypt_passwd[sizeof crypt_passwd - 1] = '\0';
+			crypt_passwd[0] = '!';
+		}
+	} else if (uflg) {
+		if (crypt_passwd[0] == '!') {
+			memmove(crypt_passwd, &crypt_passwd[1],
+					sizeof crypt_passwd - 1);
+		}
+	} else if (dflg) {
+		crypt_passwd[0] = '\0';
+	}
+	set_filesize_limit(30000);
+	signal(SIGHUP, SIG_IGN);
+	signal(SIGINT, SIG_IGN);
+	signal(SIGQUIT, SIG_IGN);
+	umask(077);
+	xsetuid(0);
+	if (!update_passwd(pw, crypt_passwd)) {
+		syslog(LOG_INFO, "password for `%s' changed by user `%s'", name,
+			   myname);
+		printf("Password changed.\n");
+	} else {
+		syslog(LOG_WARNING, "an error occurred updating the password file");
+		bb_error_msg_and_die("An error occurred updating the password file.\n");
+	}
+	return (0);
+}
+
+
+
+static int create_backup(const char *backup, FILE * fp)
+{
+	struct stat sb;
+	struct utimbuf ub;
+	FILE *bkfp;
+	int c, mask;
+
+	if (fstat(fileno(fp), &sb))
+		/* return -1; */
+		return 1;
+
+	mask = umask(077);
+	bkfp = fopen(backup, "w");
+	umask(mask);
+	if (!bkfp)
+		/* return -1; */
+		return 1;
+
+	/* TODO: faster copy, not one-char-at-a-time.  --marekm */
+	rewind(fp);
+	while ((c = getc(fp)) != EOF) {
+		if (putc(c, bkfp) == EOF)
+			break;
+	}
+	if (c != EOF || fflush(bkfp)) {
+		fclose(bkfp);
+		/* return -1; */
+		return 1;
+	}
+	if (fclose(bkfp))
+		/* return -1; */
+		return 1;
+
+	ub.actime = sb.st_atime;
+	ub.modtime = sb.st_mtime;
+	utime(backup, &ub);
+	return 0;
+}
+
+static int i64c(int i)
+{
+	if (i <= 0)
+		return ('.');
+	if (i == 1)
+		return ('/');
+	if (i >= 2 && i < 12)
+		return ('0' - 2 + i);
+	if (i >= 12 && i < 38)
+		return ('A' - 12 + i);
+	if (i >= 38 && i < 63)
+		return ('a' - 38 + i);
+	return ('z');
+}
+
+static char *crypt_make_salt(void)
+{
+	time_t now;
+	static unsigned long x;
+	static char result[3];
+
+	time(&now);
+	x += now + getpid() + clock();
+	result[0] = i64c(((x >> 18) ^ (x >> 6)) & 077);
+	result[1] = i64c(((x >> 12) ^ x) & 077);
+	result[2] = '\0';
+	return result;
+}
+
+
+static int new_password(const struct passwd *pw, int amroot, int algo)
+{
+	char *clear;
+	char *cipher;
+	char *cp;
+	char salt[12]; /* "$N$XXXXXXXX" or "XX" */
+	char orig[200];
+	char pass[200];
+
+	if (!amroot && crypt_passwd[0]) {
+		if (!(clear = bb_askpass(0, "Old password:"))) {
+			/* return -1; */
+			return 1;
+		}
+		cipher = pw_encrypt(clear, crypt_passwd);
+		if (strcmp(cipher, crypt_passwd) != 0) {
+			syslog(LOG_WARNING, "incorrect password for `%s'",
+				   pw->pw_name);
+			bb_do_delay(FAIL_DELAY);
+			fprintf(stderr, "Incorrect password.\n");
+			/* return -1; */
+			return 1;
+		}
+		safe_strncpy(orig, clear, sizeof(orig));
+		memset(clear, 0, strlen(clear));
+		memset(cipher, 0, strlen(cipher));
+	} else {
+		orig[0] = '\0';
+	}
+	if (! (cp=bb_askpass(0, "Enter the new password (minimum of 5, maximum of 8 characters)\n"
+					  "Please use a combination of upper and lower case letters and numbers.\n"
+					  "Enter new password: ")))
+	{
+		memset(orig, 0, sizeof orig);
+		/* return -1; */
+		return 1;
+	}
+	safe_strncpy(pass, cp, sizeof(pass));
+	memset(cp, 0, strlen(cp));
+	/* if (!obscure(orig, pass, pw)) { */
+	if (obscure(orig, pass, pw)) {
+		if (amroot) {
+			printf("\nWarning: weak password (continuing).\n");
+		} else {
+			/* return -1; */
+			return 1;
+		}
+	}
+	if (!(cp = bb_askpass(0, "Re-enter new password: "))) {
+		memset(orig, 0, sizeof orig);
+		/* return -1; */
+		return 1;
+	}
+	if (strcmp(cp, pass)) {
+		fprintf(stderr, "Passwords do not match.\n");
+		/* return -1; */
+		return 1;
+	}
+	memset(cp, 0, strlen(cp));
+	memset(orig, 0, sizeof(orig));
+	memset(salt, 0, sizeof(salt));
+
+	if (algo == 1) {
+		strcpy(salt, "$1$");
+		strcat(salt, crypt_make_salt());
+		strcat(salt, crypt_make_salt());
+		strcat(salt, crypt_make_salt());
+	}
+
+	strcat(salt, crypt_make_salt());
+	cp = pw_encrypt(pass, salt);
+
+	memset(pass, 0, sizeof pass);
+	safe_strncpy(crypt_passwd, cp, sizeof(crypt_passwd));
+	return 0;
+}
+
+static void set_filesize_limit(int blocks)
+{
+	struct rlimit rlimit_fsize;
+
+	rlimit_fsize.rlim_cur = rlimit_fsize.rlim_max = 512L * blocks;
+	setrlimit(RLIMIT_FSIZE, &rlimit_fsize);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/su.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/su.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/su.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,162 @@
+/* vi: set sw=4 ts=4: */
+/*
+   Licensed under the GPL v2, see the file LICENSE in this tarball.
+*/
+
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <termios.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "busybox.h"
+
+/* The shell to run if none is given in the user's passwd entry.  */
+#ifndef DEFAULT_SHELL
+#define DEFAULT_SHELL "/bin/sh"
+#endif
+
+/* Default user.  */
+#define DEFAULT_USER  "root"
+
+/* #define SYSLOG_SUCCESS */
+#define SYSLOG_FAILURE
+
+
+#if defined( SYSLOG_SUCCESS ) || defined( SYSLOG_FAILURE )
+/* Log the fact that someone has run su */
+
+# if defined( SYSLOG_SUCCESS ) && defined( SYSLOG_FAILURE )
+static void log_su (const char *successful, const char *old_user,
+					const char *tty)
+{
+	syslog ( LOG_NOTICE, "%s%s on %s", successful, old_user, tty);
+}
+#  define log_su_successful(cu, u, tty) if(!cu) log_su("", u, tty)
+#  define log_su_failure(cu, u, tty)    if(!cu) log_su("FAILED SU ", u, tty)
+# else
+	/* partial logging */
+#  if !defined( SYSLOG_SUCESS )
+#   define log_su_successful(cu, u, tty)
+#   define log_su_failure(cu, u, t) if(!cu) \
+			syslog(LOG_NOTICE, "FAILED SU %s on %s", u, t)
+#  else
+#   define log_su_successful(cu, u, t) if(!cu) \
+			syslog(LOG_NOTICE, "%s on %s", u, t)
+#   define log_su_failure(cu, u, tty)
+#  endif
+# endif
+#else
+	/* logging not used */
+# define log_su_successful(cu, u, tty)
+# define log_su_failure(cu, u, tty)
+#endif
+
+
+int su_main ( int argc, char **argv )
+{
+	unsigned long flags;
+	char *opt_shell = 0;
+	char *opt_command = 0;
+	char *opt_username = DEFAULT_USER;
+	char **opt_args = 0;
+	struct passwd *pw;
+	uid_t cur_uid = getuid();
+
+#if defined( SYSLOG_SUCCESS ) || defined( SYSLOG_FAILURE )
+	const char *tty;
+	const char *old_user;
+#endif
+
+	flags = bb_getopt_ulflags(argc, argv, "mplc:s:",
+						  &opt_command, &opt_shell);
+#define SU_OPT_m (3)
+#define SU_OPT_p (3)
+#define SU_OPT_l (4)
+
+	if (optind < argc  && argv[optind][0] == '-' && argv[optind][1] == 0) {
+		flags |= SU_OPT_l;
+		++optind;
+    }
+
+	/* get user if specified */
+	if ( optind < argc )
+		opt_username = argv [optind++];
+
+	if ( optind < argc )
+		opt_args = argv + optind;
+
+#if defined( SYSLOG_SUCCESS ) || defined( SYSLOG_FAILURE )
+#ifdef CONFIG_FEATURE_UTMP
+	/* The utmp entry (via getlogin) is probably the best way to identify
+	   the user, especially if someone su's from a su-shell.  */
+	old_user = getlogin ( );
+	if ( !old_user )
+#endif
+		{
+		/* getlogin can fail -- usually due to lack of utmp entry.
+		   Resort to getpwuid.  */
+		pw = getpwuid ( cur_uid );
+		old_user = ( pw ? pw->pw_name : "" );
+	}
+	tty = ttyname ( 2 );
+	if(!tty)
+		tty = "none";
+
+	openlog ( bb_applet_name, 0, LOG_AUTH );
+#endif
+
+	pw = getpwnam ( opt_username );
+	if ( !pw )
+		bb_error_msg_and_die ( "user %s does not exist", opt_username );
+
+	/* Make sure pw->pw_shell is non-NULL.  It may be NULL when NEW_USER
+	   is a username that is retrieved via NIS (YP), but that doesn't have
+	   a default shell listed.  */
+	if ( !pw->pw_shell || !pw->pw_shell [0] )
+		pw->pw_shell = (char *) DEFAULT_SHELL;
+
+	if ((( cur_uid == 0 ) || correct_password ( pw ))) {
+		log_su_successful(pw->pw_uid, old_user, tty );
+	} else {
+		log_su_failure (pw->pw_uid, old_user, tty );
+		bb_error_msg_and_die ( "incorrect password" );
+	}
+
+#if defined( SYSLOG_SUCCESS ) || defined( SYSLOG_FAILURE )
+	closelog();
+#endif
+
+	if ( !opt_shell && (flags & SU_OPT_p))
+		opt_shell = getenv ( "SHELL" );
+
+	if ( opt_shell && cur_uid && restricted_shell ( pw->pw_shell )) {
+		/* The user being su'd to has a nonstandard shell, and so is
+		   probably a uucp account or has restricted access.  Don't
+		   compromise the account by allowing access with a standard
+		   shell.  */
+		fputs ( "using restricted shell\n", stderr );
+		opt_shell = 0;
+	}
+
+	if ( !opt_shell )
+		opt_shell = pw->pw_shell;
+
+	change_identity ( pw );
+	setup_environment(opt_shell, flags & SU_OPT_l, !(flags & SU_OPT_p), pw);
+#if ENABLE_SELINUX
+       set_current_security_context(NULL);
+#endif
+	run_shell(opt_shell, flags & SU_OPT_l, opt_command, (const char**)opt_args);
+
+	return EXIT_FAILURE;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/sulogin.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/sulogin.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/sulogin.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,158 @@
+/* vi: set sw=4 ts=4: */
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <utmp.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "busybox.h"
+
+
+#define SULOGIN_PROMPT "\nGive root password for system maintenance\n" \
+	"(or type Control-D for normal startup):"
+
+static const char * const forbid[] = {
+	"ENV",
+	"BASH_ENV",
+	"HOME",
+	"IFS",
+	"PATH",
+	"SHELL",
+	"LD_LIBRARY_PATH",
+	"LD_PRELOAD",
+	"LD_TRACE_LOADED_OBJECTS",
+	"LD_BIND_NOW",
+	"LD_AOUT_LIBRARY_PATH",
+	"LD_AOUT_PRELOAD",
+	"LD_NOWARN",
+	"LD_KEEPDIR",
+	(char *) 0
+};
+
+
+
+static void catchalarm(int ATTRIBUTE_UNUSED junk)
+{
+	exit(EXIT_FAILURE);
+}
+
+
+int sulogin_main(int argc, char **argv)
+{
+	char *cp;
+	char *device = (char *) 0;
+	const char *name = "root";
+	int timeout = 0;
+
+#define pass bb_common_bufsiz1
+
+	struct passwd pwent;
+	struct passwd *pwd;
+	const char * const *p;
+#if ENABLE_FEATURE_SHADOWPASSWDS
+	struct spwd *spwd = NULL;
+#endif
+
+	openlog("sulogin", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH);
+	if (argc > 1) {
+		if (strncmp(argv[1], "-t", 2) == 0) {
+			if (strcmp(argv[1], "-t") == 0) {
+				if (argc > 2) {
+					timeout = atoi(argv[2]);
+					if (argc > 3) {
+						device = argv[3];
+					}
+				}
+			} else {
+				if (argc > 2) {
+					device = argv[2];
+				}
+			}
+		} else {
+			device = argv[1];
+		}
+		if (device) {
+			close(0);
+			close(1);
+			close(2);
+			if (open(device, O_RDWR) >= 0) {
+				dup(0);
+				dup(0);
+			} else {
+				syslog(LOG_WARNING, "cannot open %s\n", device);
+				exit(EXIT_FAILURE);
+			}
+		}
+	}
+	if (access(bb_path_passwd_file, 0) == -1) {
+		syslog(LOG_WARNING, "No password file\n");
+		bb_error_msg_and_die("No password file\n");
+	}
+	if (!isatty(0) || !isatty(1) || !isatty(2)) {
+		exit(EXIT_FAILURE);
+	}
+
+
+	/* Clear out anything dangerous from the environment */
+	for (p = forbid; *p; p++)
+		unsetenv(*p);
+
+
+	signal(SIGALRM, catchalarm);
+	if (!(pwd = getpwnam(name))) {
+		syslog(LOG_WARNING, "No password entry for `root'\n");
+		bb_error_msg_and_die("No password entry for `root'\n");
+	}
+	pwent = *pwd;
+#if ENABLE_FEATURE_SHADOWPASSWDS
+	spwd = NULL;
+	if (pwd && ((strcmp(pwd->pw_passwd, "x") == 0)
+				|| (strcmp(pwd->pw_passwd, "*") == 0))) {
+		endspent();
+		spwd = getspnam(name);
+		if (spwd) {
+			pwent.pw_passwd = spwd->sp_pwdp;
+		}
+	}
+#endif
+	while (1) {
+		cp = bb_askpass(timeout, SULOGIN_PROMPT);
+		if (!cp || !*cp) {
+			puts("\n");
+			fflush(stdout);
+			syslog(LOG_INFO, "Normal startup\n");
+			exit(EXIT_SUCCESS);
+		} else {
+			safe_strncpy(pass, cp, sizeof(pass));
+			memset(cp, 0, strlen(cp));
+		}
+		if (strcmp(pw_encrypt(pass, pwent.pw_passwd), pwent.pw_passwd) == 0) {
+			break;
+		}
+		bb_do_delay(FAIL_DELAY);
+		puts("Login incorrect");
+		fflush(stdout);
+		syslog(LOG_WARNING, "Incorrect root password\n");
+	}
+	memset(pass, 0, strlen(pass));
+	signal(SIGALRM, SIG_DFL);
+	puts("Entering System Maintenance Mode\n");
+	fflush(stdout);
+	syslog(LOG_INFO, "System Maintenance Mode\n");
+
+#if ENABLE_SELINUX
+	renew_current_security_context();
+#endif
+
+	run_shell(pwent.pw_shell, 1, 0, 0);
+
+	return (0);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/vlock.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/vlock.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/loginutils/vlock.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,130 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * vlock implementation for busybox
+ *
+ * Copyright (C) 2000 by spoon <spoon at ix.netcom.com>
+ * Written by spoon <spon at ix.netcom.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* Shoutz to Michael K. Johnson <johnsonm at redhat.com>, author of the
+ * original vlock.  I snagged a bunch of his code to write this
+ * minimalistic vlock.
+ */
+/* Fixed by Erik Andersen to do passwords the tinylogin way...
+ * It now works with md5, sha1, etc passwords. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/vt.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+
+#include "busybox.h"
+
+static struct passwd *pw;
+static struct vt_mode ovtm;
+static struct termios oterm;
+static int vfd;
+static unsigned long o_lock_all;
+
+static void release_vt(int signo)
+{
+	if (!o_lock_all)
+		ioctl(vfd, VT_RELDISP, 1);
+	else
+		ioctl(vfd, VT_RELDISP, 0);
+}
+
+static void acquire_vt(int signo)
+{
+	ioctl(vfd, VT_RELDISP, VT_ACKACQ);
+}
+
+static void restore_terminal(void)
+{
+	ioctl(vfd, VT_SETMODE, &ovtm);
+	tcsetattr(STDIN_FILENO, TCSANOW, &oterm);
+}
+
+int vlock_main(int argc, char **argv)
+{
+	sigset_t sig;
+	struct sigaction sa;
+	struct vt_mode vtm;
+	struct termios term;
+
+	if (argc > 2) {
+		bb_show_usage();
+	}
+
+	o_lock_all = bb_getopt_ulflags (argc, argv, "a");
+
+	if((pw = getpwuid(getuid())) == NULL) {
+		bb_error_msg_and_die("Unknown uid %d", getuid());
+	}
+
+	vfd = bb_xopen(CURRENT_TTY, O_RDWR);
+
+	if (ioctl(vfd, VT_GETMODE, &vtm) < 0) {
+		bb_perror_msg_and_die("VT_GETMODE");
+	}
+
+	/* mask a bunch of signals */
+	sigprocmask(SIG_SETMASK, NULL, &sig);
+	sigdelset(&sig, SIGUSR1);
+	sigdelset(&sig, SIGUSR2);
+	sigaddset(&sig, SIGTSTP);
+	sigaddset(&sig, SIGTTIN);
+	sigaddset(&sig, SIGTTOU);
+	sigaddset(&sig, SIGHUP);
+	sigaddset(&sig, SIGCHLD);
+	sigaddset(&sig, SIGQUIT);
+	sigaddset(&sig, SIGINT);
+
+	sigemptyset(&(sa.sa_mask));
+	sa.sa_flags = SA_RESTART;
+	sa.sa_handler = release_vt;
+	sigaction(SIGUSR1, &sa, NULL);
+	sa.sa_handler = acquire_vt;
+	sigaction(SIGUSR2, &sa, NULL);
+
+	/* need to handle some signals so that we don't get killed by them */
+	sa.sa_handler = SIG_IGN;
+	sigaction(SIGHUP, &sa, NULL);
+	sigaction(SIGQUIT, &sa, NULL);
+	sigaction(SIGINT, &sa, NULL);
+	sigaction(SIGTSTP, &sa, NULL);
+
+	ovtm = vtm;
+	vtm.mode = VT_PROCESS;
+	vtm.relsig = SIGUSR1;
+	vtm.acqsig = SIGUSR2;
+	ioctl(vfd, VT_SETMODE, &vtm);
+
+	tcgetattr(STDIN_FILENO, &oterm);
+	term = oterm;
+	term.c_iflag &= ~BRKINT;
+	term.c_iflag |= IGNBRK;
+	term.c_lflag &= ~ISIG;
+	term.c_lflag &= ~(ECHO | ECHOCTL);
+	tcsetattr(STDIN_FILENO, TCSANOW, &term);
+
+	do {
+		printf("Virtual Console%s locked.\n%s's ", (o_lock_all) ? "s" : "", pw->pw_name);
+		fflush(stdout);
+		if (correct_password (pw)) {
+			break;
+		}
+		bb_do_delay(FAIL_DELAY);
+		puts("Password incorrect.");
+	} while (1);
+	restore_terminal();
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,340 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Miscellaneous Utilities"
+
+config CONFIG_ADJTIMEX
+	bool "adjtimex"
+	default n
+	help
+	  Adjtimex reads and optionally sets adjustment parameters for
+	  the Linux clock adjustment algorithm.
+
+config CONFIG_BBCONFIG
+	bool "bbconfig"
+	default n
+	help
+	  The bbconfig applet will print the config file with which
+	  busybox was built.
+
+config CONFIG_CROND
+	bool "crond"
+	default n
+	select CONFIG_FEATURE_SUID
+	help
+	  Crond is a background daemon that parses individual crontab
+	  files and executes commands on behalf of the users in question.
+	  This is a port of dcron from slackware.  It uses files of the
+	  format /var/spool/cron/crontabs/<username> files, for example:
+	      $ cat /var/spool/cron/crontabs/root
+	      # Run daily cron jobs at 4:40 every day:
+	      40 4 * * * /etc/cron/daily > /dev/null 2>&1
+	  Note that Busybox binary must be setuid root for this applet to
+	  work properly.
+
+config CONFIG_DEBUG_CROND_OPTION
+	bool "Support debug option -d"
+	depends on CONFIG_CROND
+	default n
+	help
+	  Support option -d to enter debug mode.
+
+config CONFIG_FEATURE_CROND_CALL_SENDMAIL
+	bool "Using /usr/sbin/sendmail?"
+	default n
+	depends on CONFIG_CROND
+	help
+	  Support calling /usr/sbin/sendmail for send cmd outputs.
+
+config CONFIG_CRONTAB
+	bool "crontab"
+	default n
+	select CONFIG_FEATURE_SUID
+	help
+	  Crontab manipulates the crontab for a particular user.  Only
+	  the superuser may specify a different user and/or crontab directory.
+
+config CONFIG_DC
+	bool "dc"
+	default n
+	help
+	  Dc is a reverse-polish desk calculator which supports unlimited
+	  precision arithmetic.
+
+config CONFIG_DEVFSD
+	bool "devfsd (obsolete)"
+	default n
+	help
+	  This is deprecated, and will be going away in a future release.
+
+	  Provides compatibility with old device names on a devfs systems.
+	  You should set it to true if you have devfs enabled.
+	  The following keywords in devsfd.conf are supported:
+	  "CLEAR_CONFIG", "INCLUDE", "OPTIONAL_INCLUDE", "RESTORE",
+	  "PERMISSIONS", "EXECUTE", "COPY", "IGNORE",
+	  "MKOLDCOMPAT", "MKNEWCOMPAT","RMOLDCOMPAT", "RMNEWCOMPAT".
+
+	   But only if they are written UPPERCASE!!!!!!!!
+
+config CONFIG_DEVFSD_MODLOAD
+	bool "Adds support for MODLOAD keyword in devsfd.conf"
+	default n
+	depends on CONFIG_DEVFSD
+	help
+	  This actually doesn't work with busybox modutils but needs
+	  the external modutils.
+
+config CONFIG_DEVFSD_FG_NP
+	bool "Enables the -fg and -np options"
+	default n
+	depends on CONFIG_DEVFSD
+	help
+		-fg	Run the daemon in the foreground.
+		-np	Exit  after  parsing  the configuration file. Do not poll for events.
+
+config CONFIG_DEVFSD_VERBOSE
+	bool "Increases logging (and size)"
+	default n
+	depends on CONFIG_DEVFSD
+	help
+	  Increases logging to stderr or syslog.
+
+config CONFIG_FEATURE_DEVFS
+	bool "  Use devfs names for all devices (obsolete)"
+	default n
+	help
+	  This tells busybox to look for names like /dev/loop/0 instead of
+	  /dev/loop0.  If your /dev directory has normal names instead of
+	  devfs names, you don't want this.
+
+	  This is obsolete and will be going away someday.  Consider it
+	  deprecated.
+
+config CONFIG_EJECT
+	bool "eject"
+	default n
+	help
+	  Used to eject cdroms.  (defaults to /dev/cdrom)
+
+config CONFIG_LAST
+	bool "last"
+	default n
+	select CONFIG_FEATURE_WTMP
+	help
+	  'last' displays a list of the last users that logged into the system.
+
+config CONFIG_LESS
+	bool "less"
+	default n
+	help
+	  'less' is a pager, meaning that it displays text files. It possesses
+	  a wide array of features, and is an improvement over 'more'.
+
+config CONFIG_FEATURE_LESS_BRACKETS
+	bool "Enable bracket searching"
+	default y
+	depends on CONFIG_LESS
+	help
+	  This option adds the capability to search for matching left and right
+	  brackets, facilitating programming.
+
+config CONFIG_FEATURE_LESS_FLAGS
+	bool "Enable extra flags"
+	default y
+	depends on CONFIG_LESS
+	help
+	  The extra flags provided do the following:
+
+	  The -M flag enables a more sophisticated status line.
+	  The -m flag enables a simpler status line with a percentage.
+
+config CONFIG_FEATURE_LESS_FLAGCS
+	bool "Enable flag changes"
+	default n
+	depends on CONFIG_LESS
+	help
+	  This enables the ability to change command-line flags within
+	  less itself.
+
+config CONFIG_FEATURE_LESS_MARKS
+	bool "Enable marks"
+	default n
+	depends on CONFIG_LESS
+	help
+	  Marks enable positions in a file to be stored for easy reference.
+
+config CONFIG_FEATURE_LESS_REGEXP
+	bool "Enable regular expressions"
+	default n
+	depends on CONFIG_LESS
+	help
+	  Enable regular expressions, allowing complex file searches.
+
+config CONFIG_HDPARM
+	bool "hdparm"
+	default n
+	help
+	  Get/Set hard drive parameters.  Primarily intended for ATA
+	  drives.  Adds about 13k (or around 30k if you enable the
+	  CONFIG_FEATURE_HDPARM_GET_IDENTITY option)....
+
+config CONFIG_FEATURE_HDPARM_GET_IDENTITY
+	bool "Support obtaining detailed information directly from drives"
+	default y
+	depends on CONFIG_HDPARM
+	help
+	  Enables the -I and -i options to obtain detailed information
+	  directly from drives about their capabilities and supported ATA
+	  feature set. If no device name is specified, hdparm will read
+	  identify data from stdin. Enabling this option will add about 16k...
+
+config CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF
+	bool "Register an IDE interface (DANGEROUS)"
+	default n
+	depends on CONFIG_HDPARM
+	help
+	  Enables the 'hdparm -R' option to register an IDE interface.
+	  This is dangerous stuff, so you should probably say N.
+
+config CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
+	bool "Un-register an IDE interface (DANGEROUS)"
+	default n
+	depends on CONFIG_HDPARM
+	help
+	  Enables the 'hdparm -U' option to un-register an IDE interface.
+	  This is dangerous stuff, so you should probably say N.
+
+config CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET
+	bool "perform device reset (DANGEROUS)"
+	default n
+	depends on CONFIG_HDPARM
+	help
+	  Enables the 'hdparm -w' option to perform a device reset.
+	  This is dangerous stuff, so you should probably say N.
+
+config CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
+	bool "tristate device for hotswap (DANGEROUS)"
+	default n
+	depends on CONFIG_HDPARM
+	help
+	  Enables the 'hdparm -x' option to tristate device for hotswap,
+	  and the '-b' option to get/set bus state.  This is dangerous
+	  stuff, so you should probably say N.
+
+config CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA
+	bool "get/set using_dma flag (DANGEROUS)"
+	default n
+	depends on CONFIG_HDPARM
+	help
+	  Enables the 'hdparm -d' option to get/set using_dma flag.
+	  This is dangerous stuff, so you should probably say N.
+
+config CONFIG_MAKEDEVS
+	bool "makedevs"
+	default n
+	help
+	  'makedevs' is a utility used to create a batch of devices with
+	  one command.
+	  .
+	  There are two choices for command line behaviour, the interface
+	  as used by LEAF/Linux Router Project, or a device table file.
+	  .
+	  'leaf' is traditionally what busybox follows, it allows multiple
+	  devices of a particluar type to be created per command.
+	  e.g. /dev/hda[0-9]
+          Device properties are passed as command line arguments.
+	  .
+	  'table' reads device properties from a file or stdin, allowing
+	  a batch of unrelated devices to be made with one command.
+          User/group names are allowed as an alternative to uid/gid.
+
+choice
+	prompt "Choose makedevs behaviour"
+	depends CONFIG_MAKEDEVS
+	default CONFIG_FEATURE_MAKEDEVS_TABLE
+
+config CONFIG_FEATURE_MAKEDEVS_LEAF
+        bool "leaf"
+
+config CONFIG_FEATURE_MAKEDEVS_TABLE
+	bool "table"
+
+endchoice
+
+config CONFIG_MOUNTPOINT
+	bool "mountpoint"
+	default n
+	help
+	  mountpoint checks if the directory is a mountpoint.
+
+config CONFIG_MT
+	bool "mt"
+	default n
+	help
+	  mt is used to control tape devices.  You can use the mt utility
+	  to advance or rewind a tape past a specified number of archive
+	  files on the tape.
+
+config CONFIG_RUNLEVEL
+        bool "runlevel"
+	default n
+	help
+ 	  find the current and previous system runlevel.
+
+	  This applet uses utmp but does not rely on busybox supporing
+	  utmp on purpose. It is used by e.g. emdebian via /etc/init.d/rc.
+
+config CONFIG_RX
+        bool "rx"
+	default n
+	help
+ 	  Receive files using the Xmodem protocol.
+
+config CONFIG_STRINGS
+	bool "strings"
+	default n
+	help
+	  strings prints the printable character sequences for each file
+	  specified.
+
+config CONFIG_SETSID
+	bool "setsid"
+	default n
+	help
+	  setsid runs a program in a new session
+
+config CONFIG_TASKSET
+	bool "taskset"
+	default n
+	help
+	  Retrieve or set a processes's CPU affinity
+
+config CONFIG_TASKSET
+	bool "taskset"
+	default n
+	help
+	  Retrieve or set a processes's CPU affinity (on linux)
+
+config CONFIG_TIME
+	bool "time"
+	default n
+	help
+	  The time command runs the specified program with the given arguments.
+	  When the command finishes, time writes a message to standard output
+	  giving timing statistics about this program run.
+
+config CONFIG_WATCHDOG
+	bool "watchdog"
+	default n
+	help
+	  The watchdog utility is used with hardware or software watchdog
+	  device drivers.  It opens the specified watchdog device special file
+	  and periodically writes a magic character to the device.  If the
+	  watchdog applet ever fails to write the magic character within a
+	  certain amount of time, the watchdog device assumes the system has
+	  hung, and will cause the hardware to reboot.
+
+endmenu
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/miscutils
+MISCUTILS_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,54 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+MISCUTILS_AR:=miscutils.a
+ifndef $(MISCUTILS_DIR)
+MISCUTILS_DIR:=$(top_builddir)/miscutils/
+endif
+srcdir=$(top_srcdir)/miscutils
+
+MISCUTILS-y:=
+MISCUTILS-$(CONFIG_ADJTIMEX)    += adjtimex.o
+MISCUTILS-$(CONFIG_CROND)       += crond.o
+MISCUTILS-$(CONFIG_CRONTAB)     += crontab.o
+MISCUTILS-$(CONFIG_BBCONFIG)    += bbconfig.o
+MISCUTILS-$(CONFIG_DC)          += dc.o
+MISCUTILS-$(CONFIG_DEVFSD)      += devfsd.o
+MISCUTILS-$(CONFIG_EJECT)       += eject.o
+MISCUTILS-$(CONFIG_HDPARM)      += hdparm.o
+MISCUTILS-$(CONFIG_LAST)        += last.o
+MISCUTILS-${CONFIG_LESS}        += less.o
+MISCUTILS-$(CONFIG_MAKEDEVS)    += makedevs.o
+MISCUTILS-$(CONFIG_MOUNTPOINT)  += mountpoint.o
+MISCUTILS-$(CONFIG_MT)          += mt.o
+MISCUTILS-$(CONFIG_RUNLEVEL)    += runlevel.o
+MISCUTILS-$(CONFIG_RX)          += rx.o
+MISCUTILS-$(CONFIG_SETSID)      += setsid.o
+MISCUTILS-$(CONFIG_STRINGS)     += strings.o
+MISCUTILS-$(CONFIG_TIME)        += time.o
+MISCUTILS-$(CONFIG_WATCHDOG)    += watchdog.o
+
+ifneq ($(strip $(MISCUTILS-y)),)
+libraries-y+=$(MISCUTILS_DIR)$(MISCUTILS_AR)
+endif
+
+MISCUTILS_SRC-y:=$(patsubst %.o,$(srcdir)/%.c,$(MISCUTILS-y))
+MISCUTILS_SRC-a:=$(wildcard $(srcdir)/*.c)
+APPLET_SRC-y+=$(MISCUTILS_SRC-y)
+APPLET_SRC-a+=$(MISCUTILS_SRC-a)
+
+needlibm-y:=
+needlibm-$(CONFIG_DC) := y
+
+ifeq ($(needlibm-y),y)
+  LIBRARIES := -lm $(filter-out -lm,$(LIBRARIES))
+endif
+
+$(MISCUTILS_DIR)$(MISCUTILS_AR): $(patsubst %,$(MISCUTILS_DIR)%, $(MISCUTILS-y))
+	$(do_ar)
+
+$(MISCUTILS_DIR)%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/adjtimex.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/adjtimex.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/adjtimex.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,126 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * adjtimex.c - read, and possibly modify, the Linux kernel `timex' variables.
+ *
+ * Originally written: October 1997
+ * Last hack: March 2001
+ * Copyright 1997, 2000, 2001 Larry Doolittle <LRDoolittle at lbl.gov>
+ *
+ * busyboxed 20 March 2001, Larry Doolittle <ldoolitt at recycle.lbl.gov>
+ *
+ * Licensed under GPLv2 or later, see file License in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/timex.h>
+
+static const struct {int bit; const char *name;} statlist[] = {
+	{ STA_PLL,       "PLL"       },
+	{ STA_PPSFREQ,   "PPSFREQ"   },
+	{ STA_PPSTIME,   "PPSTIME"   },
+	{ STA_FLL,       "FFL"       },
+	{ STA_INS,       "INS"       },
+	{ STA_DEL,       "DEL"       },
+	{ STA_UNSYNC,    "UNSYNC"    },
+	{ STA_FREQHOLD,  "FREQHOLD"  },
+	{ STA_PPSSIGNAL, "PPSSIGNAL" },
+	{ STA_PPSJITTER, "PPSJITTER" },
+	{ STA_PPSWANDER, "PPSWANDER" },
+	{ STA_PPSERROR,  "PPSERROR"  },
+	{ STA_CLOCKERR,  "CLOCKERR"  },
+	{ 0, NULL } };
+
+static const char * const ret_code_descript[] = {
+	"clock synchronized",
+	"insert leap second",
+	"delete leap second",
+	"leap second in progress",
+	"leap second has occurred",
+	"clock not synchronized" };
+
+int adjtimex_main(int argc, char **argv)
+{
+	struct timex txc;
+	int quiet=0;
+	int c, i, ret, sep;
+	const char *descript;
+	txc.modes=0;
+	for (;;) {
+		c = getopt( argc, argv, "qo:f:p:t:");
+		if (c == EOF) break;
+		switch (c) {
+			case 'q':
+				quiet=1;
+				break;
+			case 'o':
+				txc.offset = atoi(optarg);
+				txc.modes |= ADJ_OFFSET_SINGLESHOT;
+				break;
+			case 'f':
+				txc.freq = atoi(optarg);
+				txc.modes |= ADJ_FREQUENCY;
+				break;
+			case 'p':
+				txc.constant = atoi(optarg);
+				txc.modes |= ADJ_TIMECONST;
+				break;
+			case 't':
+				txc.tick = atoi(optarg);
+				txc.modes |= ADJ_TICK;
+				break;
+			default:
+				bb_show_usage();
+				exit(1);
+		}
+	}
+	if (argc != optind) { /* no valid non-option parameters */
+		bb_show_usage();
+		exit(1);
+	}
+
+	ret = adjtimex(&txc);
+
+	if (ret < 0) perror("adjtimex");
+
+	if (!quiet && ret>=0) {
+		printf(
+			"    mode:         %d\n"
+			"-o  offset:       %ld\n"
+			"-f  frequency:    %ld\n"
+			"    maxerror:     %ld\n"
+			"    esterror:     %ld\n"
+			"    status:       %d ( ",
+		txc.modes, txc.offset, txc.freq, txc.maxerror,
+		txc.esterror, txc.status);
+
+		/* representative output of next code fragment:
+		   "PLL | PPSTIME" */
+		sep=0;
+		for (i=0; statlist[i].name; i++) {
+			if (txc.status & statlist[i].bit) {
+				if (sep) fputs(" | ",stdout);
+				fputs(statlist[i].name,stdout);
+				sep=1;
+			}
+		}
+
+		descript = "error";
+		if (ret >= 0 && ret <= 5) descript = ret_code_descript[ret];
+		printf(" )\n"
+			"-p  timeconstant: %ld\n"
+			"    precision:    %ld\n"
+			"    tolerance:    %ld\n"
+			"-t  tick:         %ld\n"
+			"    time.tv_sec:  %ld\n"
+			"    time.tv_usec: %ld\n"
+			"    return value: %d (%s)\n",
+		txc.constant,
+		txc.precision, txc.tolerance, txc.tick,
+		(long)txc.time.tv_sec, (long)txc.time.tv_usec, ret, descript);
+	}
+	return (ret<0);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/bbconfig.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/bbconfig.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/bbconfig.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,11 @@
+/* vi: set sw=4 ts=4: */
+/* This file was released into the public domain by Paul Fox.
+ */
+#include "busybox.h"
+#include "bbconfigopts.h"
+
+int bbconfig_main(int argc, char **argv)
+{
+	printf(bbconfig_config);
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/crond.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/crond.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/crond.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1031 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * crond -d[#] -c <crondir> -f -b
+ *
+ * run as root, but NOT setuid root
+ *
+ * Copyright 1994 Matthew Dillon (dillon at apollo.west.oic.com)
+ * Vladimir Oleynik <dzo at simtreas.ru> (C) 2002
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#define VERSION "2.3.2"
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <signal.h>
+#include <getopt.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+
+#define arysize(ary)    (sizeof(ary)/sizeof((ary)[0]))
+
+#ifndef CRONTABS
+#define CRONTABS        "/var/spool/cron/crontabs"
+#endif
+#ifndef TMPDIR
+#define TMPDIR          "/var/spool/cron"
+#endif
+#ifndef SENDMAIL
+#define SENDMAIL        "/usr/sbin/sendmail"
+#endif
+#ifndef SENDMAIL_ARGS
+#define SENDMAIL_ARGS   "-ti", "oem"
+#endif
+#ifndef CRONUPDATE
+#define CRONUPDATE      "cron.update"
+#endif
+#ifndef MAXLINES
+#define MAXLINES        256	/* max lines in non-root crontabs */
+#endif
+
+typedef struct CronFile {
+	struct CronFile *cf_Next;
+	struct CronLine *cf_LineBase;
+	char *cf_User;		/* username                     */
+	int cf_Ready;		/* bool: one or more jobs ready */
+	int cf_Running;		/* bool: one or more jobs running */
+	int cf_Deleted;		/* marked for deletion, ignore  */
+} CronFile;
+
+typedef struct CronLine {
+	struct CronLine *cl_Next;
+	char *cl_Shell;		/* shell command                        */
+	pid_t cl_Pid;		/* running pid, 0, or armed (-1)        */
+	int cl_MailFlag;	/* running pid is for mail              */
+	int cl_MailPos;		/* 'empty file' size                    */
+	char cl_Mins[60];	/* 0-59                                 */
+	char cl_Hrs[24];	/* 0-23                                 */
+	char cl_Days[32];	/* 1-31                                 */
+	char cl_Mons[12];	/* 0-11                                 */
+	char cl_Dow[7];		/* 0-6, beginning sunday                */
+} CronLine;
+
+#define RUN_RANOUT      1
+#define RUN_RUNNING     2
+#define RUN_FAILED      3
+
+#define DaemonUid 0
+
+#if ENABLE_DEBUG_CROND_OPTION
+static short DebugOpt;
+#endif
+
+static short LogLevel = 8;
+static const char *LogFile;
+static const char *CDir = CRONTABS;
+
+static void startlogger(void);
+
+static void CheckUpdates(void);
+static void SynchronizeDir(void);
+static int TestJobs(time_t t1, time_t t2);
+static void RunJobs(void);
+static int CheckJobs(void);
+
+static void RunJob(const char *user, CronLine * line);
+
+#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
+static void EndJob(const char *user, CronLine * line);
+#else
+#define EndJob(user, line)  line->cl_Pid = 0
+#endif
+
+static void DeleteFile(const char *userName);
+
+static CronFile *FileBase;
+
+
+static void crondlog(const char *ctl, ...)
+{
+	va_list va;
+	const char *fmt;
+	int level = (int) (ctl[0] & 0xf);
+	int type = level == 20 ?
+		LOG_ERR : ((ctl[0] & 0100) ? LOG_WARNING : LOG_NOTICE);
+
+
+	va_start(va, ctl);
+	fmt = ctl + 1;
+	if (level >= LogLevel) {
+
+#if ENABLE_DEBUG_CROND_OPTION
+		if (DebugOpt) {
+			vfprintf(stderr, fmt, va);
+		} else
+#endif
+		if (LogFile == 0) {
+			vsyslog(type, fmt, va);
+		} else {
+			int logfd = open(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0600);
+			if (logfd >= 0) {
+				vdprintf(logfd, fmt, va);
+				close(logfd);
+#if ENABLE_DEBUG_CROND_OPTION
+			} else {
+				bb_perror_msg("Can't open log file");
+#endif
+			}
+		}
+	}
+	va_end(va);
+	if (ctl[0] & 0200) {
+		exit(20);
+	}
+}
+
+int crond_main(int ac, char **av)
+{
+	unsigned long opt;
+	char *lopt, *Lopt, *copt;
+
+#if ENABLE_DEBUG_CROND_OPTION
+	char *dopt;
+
+	bb_opt_complementally = "f-b:b-f:S-L:L-S:d-l";
+#else
+	bb_opt_complementally = "f-b:b-f:S-L:L-S";
+#endif
+
+	opterr = 0;			/* disable getopt 'errors' message. */
+	opt = bb_getopt_ulflags(ac, av, "l:L:fbSc:"
+#if ENABLE_DEBUG_CROND_OPTION
+							"d:"
+#endif
+							, &lopt, &Lopt, &copt
+#if ENABLE_DEBUG_CROND_OPTION
+							, &dopt
+#endif
+		);
+	if (opt & 1) {
+		LogLevel = atoi(lopt);
+	}
+	if (opt & 2) {
+		if (*Lopt != 0) {
+			LogFile = Lopt;
+		}
+	}
+	if (opt & 32) {
+		if (*copt != 0) {
+			CDir = copt;
+		}
+	}
+#if ENABLE_DEBUG_CROND_OPTION
+	if (opt & 64) {
+		DebugOpt = atoi(dopt);
+		LogLevel = 0;
+	}
+#endif
+
+	/*
+	 * change directory
+	 */
+
+	bb_xchdir(CDir);
+	signal(SIGHUP, SIG_IGN);	/* hmm.. but, if kill -HUP original
+								 * version - his died. ;(
+								 */
+	/*
+	 * close stdin and stdout, stderr.
+	 * close unused descriptors -  don't need.
+	 * optional detach from controlling terminal
+	 */
+
+	if (!(opt & 4)) {
+#ifdef BB_NOMMU
+		/* reexec for vfork() do continue parent */
+		vfork_daemon_rexec(1, 0, ac, av, "-f");
+#else
+		bb_xdaemon(1, 0);
+#endif
+	}
+
+	(void) startlogger();	/* need if syslog mode selected */
+
+	/*
+	 * main loop - synchronize to 1 second after the minute, minimum sleep
+	 *             of 1 second.
+	 */
+
+	crondlog("\011%s " VERSION " dillon, started, log level %d\n",
+			 bb_applet_name, LogLevel);
+
+	SynchronizeDir();
+
+	{
+		time_t t1 = time(NULL);
+		time_t t2;
+		long dt;
+		int rescan = 60;
+		short sleep_time = 60;
+
+		for (;;) {
+			sleep((sleep_time + 1) - (short) (time(NULL) % sleep_time));
+
+			t2 = time(NULL);
+			dt = t2 - t1;
+
+			/*
+			 * The file 'cron.update' is checked to determine new cron
+			 * jobs.  The directory is rescanned once an hour to deal
+			 * with any screwups.
+			 *
+			 * check for disparity.  Disparities over an hour either way
+			 * result in resynchronization.  A reverse-indexed disparity
+			 * less then an hour causes us to effectively sleep until we
+			 * match the original time (i.e. no re-execution of jobs that
+			 * have just been run).  A forward-indexed disparity less then
+			 * an hour causes intermediate jobs to be run, but only once
+			 * in the worst case.
+			 *
+			 * when running jobs, the inequality used is greater but not
+			 * equal to t1, and less then or equal to t2.
+			 */
+
+			if (--rescan == 0) {
+				rescan = 60;
+				SynchronizeDir();
+			}
+			CheckUpdates();
+#if ENABLE_DEBUG_CROND_OPTION
+			if (DebugOpt)
+				crondlog("\005Wakeup dt=%d\n", dt);
+#endif
+			if (dt < -60 * 60 || dt > 60 * 60) {
+				t1 = t2;
+				crondlog("\111time disparity of %d minutes detected\n", dt / 60);
+			} else if (dt > 0) {
+				TestJobs(t1, t2);
+				RunJobs();
+				sleep(5);
+				if (CheckJobs() > 0) {
+					sleep_time = 10;
+				} else {
+					sleep_time = 60;
+				}
+				t1 = t2;
+			}
+		}
+	}
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS); /* not reached */
+}
+
+static int ChangeUser(const char *user)
+{
+	struct passwd *pas;
+	const char *err_msg;
+
+	/*
+	 * Obtain password entry and change privileges
+	 */
+	pas = getpwnam(user);
+	if (pas == 0) {
+		crondlog("\011failed to get uid for %s", user);
+		return (-1);
+	}
+	setenv("USER", pas->pw_name, 1);
+	setenv("HOME", pas->pw_dir, 1);
+	setenv("SHELL", DEFAULT_SHELL, 1);
+
+	/*
+	 * Change running state to the user in question
+	 */
+	err_msg = change_identity_e2str(pas);
+	if (err_msg) {
+		crondlog("\011%s for user %s", err_msg, user);
+		return (-1);
+	}
+	if (chdir(pas->pw_dir) < 0) {
+		crondlog("\011chdir failed: %s: %m", pas->pw_dir);
+		if (chdir(TMPDIR) < 0) {
+			crondlog("\011chdir failed: %s: %m", TMPDIR);
+			return (-1);
+		}
+	}
+	return (pas->pw_uid);
+}
+
+static void startlogger(void)
+{
+	if (LogFile == 0) {
+		openlog(bb_applet_name, LOG_CONS | LOG_PID, LOG_CRON);
+	}
+#if ENABLE_DEBUG_CROND_OPTION
+	else {				/* test logfile */
+		int logfd;
+
+		if ((logfd = open(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0600)) >= 0) {
+			close(logfd);
+		} else {
+			bb_perror_msg("Failed to open log file '%s' reason", LogFile);
+		}
+	}
+#endif
+}
+
+
+static const char *const DowAry[] = {
+	"sun",
+	"mon",
+	"tue",
+	"wed",
+	"thu",
+	"fri",
+	"sat",
+
+	"Sun",
+	"Mon",
+	"Tue",
+	"Wed",
+	"Thu",
+	"Fri",
+	"Sat",
+	NULL
+};
+
+static const char *const MonAry[] = {
+	"jan",
+	"feb",
+	"mar",
+	"apr",
+	"may",
+	"jun",
+	"jul",
+	"aug",
+	"sep",
+	"oct",
+	"nov",
+	"dec",
+
+	"Jan",
+	"Feb",
+	"Mar",
+	"Apr",
+	"May",
+	"Jun",
+	"Jul",
+	"Aug",
+	"Sep",
+	"Oct",
+	"Nov",
+	"Dec",
+	NULL
+};
+
+static char *ParseField(char *user, char *ary, int modvalue, int off,
+						const char *const *names, char *ptr)
+{
+	char *base = ptr;
+	int n1 = -1;
+	int n2 = -1;
+
+	if (base == NULL) {
+		return (NULL);
+	}
+
+	while (*ptr != ' ' && *ptr != '\t' && *ptr != '\n') {
+		int skip = 0;
+
+		/* Handle numeric digit or symbol or '*' */
+
+		if (*ptr == '*') {
+			n1 = 0;		/* everything will be filled */
+			n2 = modvalue - 1;
+			skip = 1;
+			++ptr;
+		} else if (*ptr >= '0' && *ptr <= '9') {
+			if (n1 < 0) {
+				n1 = strtol(ptr, &ptr, 10) + off;
+			} else {
+				n2 = strtol(ptr, &ptr, 10) + off;
+			}
+			skip = 1;
+		} else if (names) {
+			int i;
+
+			for (i = 0; names[i]; ++i) {
+				if (strncmp(ptr, names[i], strlen(names[i])) == 0) {
+					break;
+				}
+			}
+			if (names[i]) {
+				ptr += strlen(names[i]);
+				if (n1 < 0) {
+					n1 = i;
+				} else {
+					n2 = i;
+				}
+				skip = 1;
+			}
+		}
+
+		/* handle optional range '-' */
+
+		if (skip == 0) {
+			crondlog("\111failed user %s parsing %s\n", user, base);
+			return (NULL);
+		}
+		if (*ptr == '-' && n2 < 0) {
+			++ptr;
+			continue;
+		}
+
+		/*
+		 * collapse single-value ranges, handle skipmark, and fill
+		 * in the character array appropriately.
+		 */
+
+		if (n2 < 0) {
+			n2 = n1;
+		}
+		if (*ptr == '/') {
+			skip = strtol(ptr + 1, &ptr, 10);
+		}
+		/*
+		 * fill array, using a failsafe is the easiest way to prevent
+		 * an endless loop
+		 */
+
+		{
+			int s0 = 1;
+			int failsafe = 1024;
+
+			--n1;
+			do {
+				n1 = (n1 + 1) % modvalue;
+
+				if (--s0 == 0) {
+					ary[n1 % modvalue] = 1;
+					s0 = skip;
+				}
+			}
+			while (n1 != n2 && --failsafe);
+
+			if (failsafe == 0) {
+				crondlog("\111failed user %s parsing %s\n", user, base);
+				return (NULL);
+			}
+		}
+		if (*ptr != ',') {
+			break;
+		}
+		++ptr;
+		n1 = -1;
+		n2 = -1;
+	}
+
+	if (*ptr != ' ' && *ptr != '\t' && *ptr != '\n') {
+		crondlog("\111failed user %s parsing %s\n", user, base);
+		return (NULL);
+	}
+
+	while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n') {
+		++ptr;
+	}
+#if ENABLE_DEBUG_CROND_OPTION
+	if (DebugOpt) {
+		int i;
+
+		for (i = 0; i < modvalue; ++i) {
+			crondlog("\005%d", ary[i]);
+		}
+		crondlog("\005\n");
+	}
+#endif
+
+	return (ptr);
+}
+
+static void FixDayDow(CronLine * line)
+{
+	int i;
+	int weekUsed = 0;
+	int daysUsed = 0;
+
+	for (i = 0; i < (int)(arysize(line->cl_Dow)); ++i) {
+		if (line->cl_Dow[i] == 0) {
+			weekUsed = 1;
+			break;
+		}
+	}
+	for (i = 0; i < (int)(arysize(line->cl_Days)); ++i) {
+		if (line->cl_Days[i] == 0) {
+			daysUsed = 1;
+			break;
+		}
+	}
+	if (weekUsed && !daysUsed) {
+		memset(line->cl_Days, 0, sizeof(line->cl_Days));
+	}
+	if (daysUsed && !weekUsed) {
+		memset(line->cl_Dow, 0, sizeof(line->cl_Dow));
+	}
+}
+
+
+
+static void SynchronizeFile(const char *fileName)
+{
+	int maxEntries = MAXLINES;
+	int maxLines;
+	char buf[1024];
+
+	if (strcmp(fileName, "root") == 0) {
+		maxEntries = 65535;
+	}
+	maxLines = maxEntries * 10;
+
+	if (fileName) {
+		FILE *fi;
+
+		DeleteFile(fileName);
+
+		fi = fopen(fileName, "r");
+		if (fi != NULL) {
+			struct stat sbuf;
+
+			if (fstat(fileno(fi), &sbuf) == 0 && sbuf.st_uid == DaemonUid) {
+				CronFile *file = calloc(1, sizeof(CronFile));
+				CronLine **pline;
+
+				file->cf_User = strdup(fileName);
+				pline = &file->cf_LineBase;
+
+				while (fgets(buf, sizeof(buf), fi) != NULL && --maxLines) {
+					CronLine line;
+					char *ptr;
+
+					trim(buf);
+					if (buf[0] == 0 || buf[0] == '#') {
+						continue;
+					}
+					if (--maxEntries == 0) {
+						break;
+					}
+					memset(&line, 0, sizeof(line));
+
+#if ENABLE_DEBUG_CROND_OPTION
+					if (DebugOpt) {
+						crondlog("\111User %s Entry %s\n", fileName, buf);
+					}
+#endif
+
+					/* parse date ranges */
+					ptr = ParseField(file->cf_User, line.cl_Mins, 60, 0, NULL, buf);
+					ptr = ParseField(file->cf_User, line.cl_Hrs, 24, 0, NULL, ptr);
+					ptr = ParseField(file->cf_User, line.cl_Days, 32, 0, NULL, ptr);
+					ptr = ParseField(file->cf_User, line.cl_Mons, 12, -1, MonAry, ptr);
+					ptr = ParseField(file->cf_User, line.cl_Dow, 7, 0, DowAry, ptr);
+
+					/* check failure */
+					if (ptr == NULL) {
+						continue;
+					}
+
+					/*
+					 * fix days and dow - if one is not * and the other
+					 * is *, the other is set to 0, and vise-versa
+					 */
+
+					FixDayDow(&line);
+
+					*pline = calloc(1, sizeof(CronLine));
+					**pline = line;
+
+					/* copy command */
+					(*pline)->cl_Shell = strdup(ptr);
+
+#if ENABLE_DEBUG_CROND_OPTION
+					if (DebugOpt) {
+						crondlog("\111    Command %s\n", ptr);
+					}
+#endif
+
+					pline = &((*pline)->cl_Next);
+				}
+				*pline = NULL;
+
+				file->cf_Next = FileBase;
+				FileBase = file;
+
+				if (maxLines == 0 || maxEntries == 0) {
+					crondlog("\111Maximum number of lines reached for user %s\n", fileName);
+				}
+			}
+			fclose(fi);
+		}
+	}
+}
+
+static void CheckUpdates(void)
+{
+	FILE *fi;
+	char buf[256];
+
+	fi = fopen(CRONUPDATE, "r");
+	if (fi != NULL) {
+		remove(CRONUPDATE);
+		while (fgets(buf, sizeof(buf), fi) != NULL) {
+			SynchronizeFile(strtok(buf, " \t\r\n"));
+		}
+		fclose(fi);
+	}
+}
+
+static void SynchronizeDir(void)
+{
+	/* Attempt to delete the database. */
+
+	for (;;) {
+		CronFile *file;
+
+		for (file = FileBase; file && file->cf_Deleted; file = file->cf_Next);
+		if (file == NULL) {
+			break;
+		}
+		DeleteFile(file->cf_User);
+	}
+
+	/*
+	 * Remove cron update file
+	 *
+	 * Re-chdir, in case directory was renamed & deleted, or otherwise
+	 * screwed up.
+	 *
+	 * scan directory and add associated users
+	 */
+
+	remove(CRONUPDATE);
+	if (chdir(CDir) < 0) {
+		crondlog("\311unable to find %s\n", CDir);
+	}
+	{
+		DIR *dir = opendir(".");
+		struct dirent *den;
+
+		if (dir) {
+			while ((den = readdir(dir))) {
+				if (strchr(den->d_name, '.') != NULL) {
+					continue;
+				}
+				if (getpwnam(den->d_name)) {
+					SynchronizeFile(den->d_name);
+				} else {
+					crondlog("\007ignoring %s\n", den->d_name);
+				}
+			}
+			closedir(dir);
+		} else {
+			crondlog("\311Unable to open current dir!\n");
+		}
+	}
+}
+
+
+/*
+ *  DeleteFile() - delete user database
+ *
+ *  Note: multiple entries for same user may exist if we were unable to
+ *  completely delete a database due to running processes.
+ */
+
+static void DeleteFile(const char *userName)
+{
+	CronFile **pfile = &FileBase;
+	CronFile *file;
+
+	while ((file = *pfile) != NULL) {
+		if (strcmp(userName, file->cf_User) == 0) {
+			CronLine **pline = &file->cf_LineBase;
+			CronLine *line;
+
+			file->cf_Running = 0;
+			file->cf_Deleted = 1;
+
+			while ((line = *pline) != NULL) {
+				if (line->cl_Pid > 0) {
+					file->cf_Running = 1;
+					pline = &line->cl_Next;
+				} else {
+					*pline = line->cl_Next;
+					free(line->cl_Shell);
+					free(line);
+				}
+			}
+			if (file->cf_Running == 0) {
+				*pfile = file->cf_Next;
+				free(file->cf_User);
+				free(file);
+			} else {
+				pfile = &file->cf_Next;
+			}
+		} else {
+			pfile = &file->cf_Next;
+		}
+	}
+}
+
+/*
+ * TestJobs()
+ *
+ * determine which jobs need to be run.  Under normal conditions, the
+ * period is about a minute (one scan).  Worst case it will be one
+ * hour (60 scans).
+ */
+
+static int TestJobs(time_t t1, time_t t2)
+{
+	int nJobs = 0;
+	time_t t;
+
+	/* Find jobs > t1 and <= t2 */
+
+	for (t = t1 - t1 % 60; t <= t2; t += 60) {
+		if (t > t1) {
+			struct tm *tp = localtime(&t);
+			CronFile *file;
+			CronLine *line;
+
+			for (file = FileBase; file; file = file->cf_Next) {
+#if ENABLE_DEBUG_CROND_OPTION
+				if (DebugOpt)
+					crondlog("\005FILE %s:\n", file->cf_User);
+#endif
+				if (file->cf_Deleted)
+					continue;
+				for (line = file->cf_LineBase; line; line = line->cl_Next) {
+#if ENABLE_DEBUG_CROND_OPTION
+					if (DebugOpt)
+						crondlog("\005    LINE %s\n", line->cl_Shell);
+#endif
+					if (line->cl_Mins[tp->tm_min] && line->cl_Hrs[tp->tm_hour] &&
+						(line->cl_Days[tp->tm_mday] || line->cl_Dow[tp->tm_wday])
+						&& line->cl_Mons[tp->tm_mon]) {
+#if ENABLE_DEBUG_CROND_OPTION
+						if (DebugOpt) {
+							crondlog("\005    JobToDo: %d %s\n",
+								line->cl_Pid, line->cl_Shell);
+						}
+#endif
+						if (line->cl_Pid > 0) {
+							crondlog("\010    process already running: %s %s\n",
+								file->cf_User, line->cl_Shell);
+						} else if (line->cl_Pid == 0) {
+							line->cl_Pid = -1;
+							file->cf_Ready = 1;
+							++nJobs;
+						}
+					}
+				}
+			}
+		}
+	}
+	return (nJobs);
+}
+
+static void RunJobs(void)
+{
+	CronFile *file;
+	CronLine *line;
+
+	for (file = FileBase; file; file = file->cf_Next) {
+		if (file->cf_Ready) {
+			file->cf_Ready = 0;
+
+			for (line = file->cf_LineBase; line; line = line->cl_Next) {
+				if (line->cl_Pid < 0) {
+
+					RunJob(file->cf_User, line);
+
+					crondlog("\010USER %s pid %3d cmd %s\n",
+						file->cf_User, line->cl_Pid, line->cl_Shell);
+					if (line->cl_Pid < 0) {
+						file->cf_Ready = 1;
+					}
+					else if (line->cl_Pid > 0) {
+						file->cf_Running = 1;
+					}
+				}
+			}
+		}
+	}
+}
+
+/*
+ * CheckJobs() - check for job completion
+ *
+ * Check for job completion, return number of jobs still running after
+ * all done.
+ */
+
+static int CheckJobs(void)
+{
+	CronFile *file;
+	CronLine *line;
+	int nStillRunning = 0;
+
+	for (file = FileBase; file; file = file->cf_Next) {
+		if (file->cf_Running) {
+			file->cf_Running = 0;
+
+			for (line = file->cf_LineBase; line; line = line->cl_Next) {
+				if (line->cl_Pid > 0) {
+					int status;
+					int r = wait4(line->cl_Pid, &status, WNOHANG, NULL);
+
+					if (r < 0 || r == line->cl_Pid) {
+						EndJob(file->cf_User, line);
+						if (line->cl_Pid) {
+							file->cf_Running = 1;
+						}
+					} else if (r == 0) {
+						file->cf_Running = 1;
+					}
+				}
+			}
+		}
+		nStillRunning += file->cf_Running;
+	}
+	return (nStillRunning);
+}
+
+
+#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
+static void
+ForkJob(const char *user, CronLine * line, int mailFd,
+		const char *prog, const char *cmd, const char *arg, const char *mailf)
+{
+	/* Fork as the user in question and run program */
+	pid_t pid = fork();
+
+	line->cl_Pid = pid;
+	if (pid == 0) {
+		/* CHILD */
+
+		/* Change running state to the user in question */
+
+		if (ChangeUser(user) < 0) {
+			exit(0);
+		}
+#if ENABLE_DEBUG_CROND_OPTION
+		if (DebugOpt) {
+			crondlog("\005Child Running %s\n", prog);
+		}
+#endif
+
+		if (mailFd >= 0) {
+			dup2(mailFd, mailf != NULL);
+			dup2((mailf ? mailFd : 1), 2);
+			close(mailFd);
+		}
+		execl(prog, prog, cmd, arg, NULL);
+		crondlog("\024unable to exec, user %s cmd %s %s %s\n", user, prog, cmd, arg);
+		if (mailf) {
+			fdprintf(1, "Exec failed: %s -c %s\n", prog, arg);
+		}
+		exit(0);
+	} else if (pid < 0) {
+		/* FORK FAILED */
+		crondlog("\024couldn't fork, user %s\n", user);
+		line->cl_Pid = 0;
+		if (mailf) {
+			remove(mailf);
+		}
+	} else if (mailf) {
+		/* PARENT, FORK SUCCESS
+		 * rename mail-file based on pid of process
+		 */
+		char mailFile2[128];
+
+		snprintf(mailFile2, sizeof(mailFile2), TMPDIR "/cron.%s.%d", user, pid);
+		rename(mailf, mailFile2);
+	}
+	/*
+	 * Close the mail file descriptor.. we can't just leave it open in
+	 * a structure, closing it later, because we might run out of descriptors
+	 */
+
+	if (mailFd >= 0) {
+		close(mailFd);
+	}
+}
+
+static void RunJob(const char *user, CronLine * line)
+{
+	char mailFile[128];
+	int mailFd;
+
+	line->cl_Pid = 0;
+	line->cl_MailFlag = 0;
+
+	/* open mail file - owner root so nobody can screw with it. */
+
+	snprintf(mailFile, sizeof(mailFile), TMPDIR "/cron.%s.%d", user, getpid());
+	mailFd = open(mailFile, O_CREAT | O_TRUNC | O_WRONLY | O_EXCL | O_APPEND, 0600);
+
+	if (mailFd >= 0) {
+		line->cl_MailFlag = 1;
+		fdprintf(mailFd, "To: %s\nSubject: cron: %s\n\n", user,
+			line->cl_Shell);
+		line->cl_MailPos = lseek(mailFd, 0, 1);
+	} else {
+		crondlog("\024unable to create mail file user %s file %s, output to /dev/null\n", user, mailFile);
+	}
+
+	ForkJob(user, line, mailFd, DEFAULT_SHELL, "-c", line->cl_Shell, mailFile);
+}
+
+/*
+ * EndJob - called when job terminates and when mail terminates
+ */
+
+static void EndJob(const char *user, CronLine * line)
+{
+	int mailFd;
+	char mailFile[128];
+	struct stat sbuf;
+
+	/* No job */
+
+	if (line->cl_Pid <= 0) {
+		line->cl_Pid = 0;
+		return;
+	}
+
+	/*
+	 * End of job and no mail file
+	 * End of sendmail job
+	 */
+
+	snprintf(mailFile, sizeof(mailFile), TMPDIR "/cron.%s.%d", user, line->cl_Pid);
+	line->cl_Pid = 0;
+
+	if (line->cl_MailFlag != 1) {
+		return;
+	}
+	line->cl_MailFlag = 0;
+
+	/*
+	 * End of primary job - check for mail file.  If size has increased and
+	 * the file is still valid, we sendmail it.
+	 */
+
+	mailFd = open(mailFile, O_RDONLY);
+	remove(mailFile);
+	if (mailFd < 0) {
+		return;
+	}
+
+	if (fstat(mailFd, &sbuf) < 0 || sbuf.st_uid != DaemonUid ||	sbuf.st_nlink != 0 ||
+		sbuf.st_size == line->cl_MailPos || !S_ISREG(sbuf.st_mode)) {
+		close(mailFd);
+		return;
+	}
+	ForkJob(user, line, mailFd, SENDMAIL, SENDMAIL_ARGS, NULL);
+}
+#else
+/* crond without sendmail */
+
+static void RunJob(const char *user, CronLine * line)
+{
+	/* Fork as the user in question and run program */
+	pid_t pid = fork();
+
+	if (pid == 0) {
+		/* CHILD */
+
+		/* Change running state to the user in question */
+
+		if (ChangeUser(user) < 0) {
+			exit(0);
+		}
+#if ENABLE_DEBUG_CROND_OPTION
+		if (DebugOpt) {
+			crondlog("\005Child Running %s\n", DEFAULT_SHELL);
+		}
+#endif
+
+		execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_Shell, NULL);
+		crondlog("\024unable to exec, user %s cmd %s -c %s\n", user,
+				 DEFAULT_SHELL, line->cl_Shell);
+		exit(0);
+	} else if (pid < 0) {
+		/* FORK FAILED */
+		crondlog("\024couldn't fork, user %s\n", user);
+		pid = 0;
+	}
+	line->cl_Pid = pid;
+}
+#endif /* ENABLE_FEATURE_CROND_CALL_SENDMAIL */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/crontab.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/crontab.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/crontab.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,356 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * CRONTAB
+ *
+ * usually setuid root, -c option only works if getuid() == geteuid()
+ *
+ * Copyright 1994 Matthew Dillon (dillon at apollo.west.oic.com)
+ * Vladimir Oleynik <dzo at simtreas.ru> (C) 2002
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <signal.h>
+#include <getopt.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+
+#ifndef CRONTABS
+#define CRONTABS        "/var/spool/cron/crontabs"
+#endif
+#ifndef TMPDIR
+#define TMPDIR          "/var/spool/cron"
+#endif
+#ifndef CRONUPDATE
+#define CRONUPDATE      "cron.update"
+#endif
+#ifndef PATH_VI
+#define PATH_VI         "/bin/vi"   /* location of vi       */
+#endif
+
+static const char  *CDir = CRONTABS;
+
+static void EditFile(const char *user, const char *file);
+static int GetReplaceStream(const char *user, const char *file);
+static int  ChangeUser(const char *user, short dochdir);
+
+int
+crontab_main(int ac, char **av)
+{
+    enum { NONE, EDIT, LIST, REPLACE, DELETE } option = NONE;
+    const struct passwd *pas;
+    const char *repFile = NULL;
+    int repFd = 0;
+    int i;
+    char caller[256];           /* user that ran program */
+    int   UserId;
+
+    UserId = getuid();
+    if ((pas = getpwuid(UserId)) == NULL)
+	bb_perror_msg_and_die("getpwuid");
+
+    safe_strncpy(caller, pas->pw_name, sizeof(caller));
+
+    i = 1;
+    if (ac > 1) {
+	if (av[1][0] == '-' && av[1][1] == 0) {
+	    option = REPLACE;
+	    ++i;
+	} else if (av[1][0] != '-') {
+	    option = REPLACE;
+	    ++i;
+	    repFile = av[1];
+	}
+    }
+
+    for (; i < ac; ++i) {
+	char *ptr = av[i];
+
+	if (*ptr != '-')
+	    break;
+	ptr += 2;
+
+	switch(ptr[-1]) {
+	case 'l':
+	    if (ptr[-1] == 'l')
+		option = LIST;
+	    /* fall through */
+	case 'e':
+	    if (ptr[-1] == 'e')
+		option = EDIT;
+	    /* fall through */
+	case 'd':
+	    if (ptr[-1] == 'd')
+		option = DELETE;
+	    /* fall through */
+	case 'u':
+	    if (i + 1 < ac && av[i+1][0] != '-') {
+		++i;
+		if (getuid() == geteuid()) {
+		    pas = getpwnam(av[i]);
+		    if (pas) {
+			UserId = pas->pw_uid;
+		    } else {
+			bb_error_msg_and_die("user %s unknown", av[i]);
+		    }
+		} else {
+		    bb_error_msg_and_die("only the superuser may specify a user");
+		}
+	    }
+	    break;
+	case 'c':
+	    if (getuid() == geteuid()) {
+		CDir = (*ptr) ? ptr : av[++i];
+	    } else {
+		bb_error_msg_and_die("-c option: superuser only");
+	    }
+	    break;
+	default:
+	    i = ac;
+	    break;
+	}
+    }
+    if (i != ac || option == NONE)
+	bb_show_usage();
+
+    /*
+     * Get password entry
+     */
+
+    if ((pas = getpwuid(UserId)) == NULL)
+	bb_perror_msg_and_die("getpwuid");
+
+    /*
+     * If there is a replacement file, obtain a secure descriptor to it.
+     */
+
+    if (repFile) {
+	repFd = GetReplaceStream(caller, repFile);
+	if (repFd < 0)
+	    bb_error_msg_and_die("unable to read replacement file");
+    }
+
+    /*
+     * Change directory to our crontab directory
+     */
+
+    bb_xchdir(CDir);
+
+    /*
+     * Handle options as appropriate
+     */
+
+    switch(option) {
+    case LIST:
+	{
+	    FILE *fi;
+	    char buf[1024];
+
+	    if ((fi = fopen(pas->pw_name, "r"))) {
+		while (fgets(buf, sizeof(buf), fi) != NULL)
+		    fputs(buf, stdout);
+		fclose(fi);
+	    } else {
+		bb_error_msg("no crontab for %s", pas->pw_name);
+	    }
+	}
+	break;
+    case EDIT:
+	{
+	    FILE *fi;
+	    int fd;
+	    int n;
+	    char tmp[128];
+	    char buf[1024];
+
+	    snprintf(tmp, sizeof(tmp), TMPDIR "/crontab.%d", getpid());
+	    fd = bb_xopen3(tmp, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600);
+	    chown(tmp, getuid(), getgid());
+	    if ((fi = fopen(pas->pw_name, "r"))) {
+		while ((n = fread(buf, 1, sizeof(buf), fi)) > 0)
+		    write(fd, buf, n);
+	    }
+	    EditFile(caller, tmp);
+	    remove(tmp);
+	    lseek(fd, 0L, 0);
+	    repFd = fd;
+	}
+	option = REPLACE;
+	/* fall through */
+    case REPLACE:
+	{
+	    char buf[1024];
+	    char path[1024];
+	    int fd;
+	    int n;
+
+	    snprintf(path, sizeof(path), "%s.new", pas->pw_name);
+	    if ((fd = open(path, O_CREAT|O_TRUNC|O_APPEND|O_WRONLY, 0600)) >= 0) {
+		while ((n = read(repFd, buf, sizeof(buf))) > 0) {
+		    write(fd, buf, n);
+		}
+		close(fd);
+		rename(path, pas->pw_name);
+	    } else {
+		bb_error_msg("unable to create %s/%s", CDir, path);
+	    }
+	    close(repFd);
+	}
+	break;
+    case DELETE:
+	remove(pas->pw_name);
+	break;
+    case NONE:
+    default:
+	break;
+    }
+
+    /*
+     *  Bump notification file.  Handle window where crond picks file up
+     *  before we can write our entry out.
+     */
+
+    if (option == REPLACE || option == DELETE) {
+	FILE *fo;
+	struct stat st;
+
+	while ((fo = fopen(CRONUPDATE, "a"))) {
+	    fprintf(fo, "%s\n", pas->pw_name);
+	    fflush(fo);
+	    if (fstat(fileno(fo), &st) != 0 || st.st_nlink != 0) {
+		fclose(fo);
+		break;
+	    }
+	    fclose(fo);
+	    /* loop */
+	}
+	if (fo == NULL) {
+	    bb_error_msg("unable to append to %s/%s", CDir, CRONUPDATE);
+	}
+    }
+    return 0;
+}
+
+static int
+GetReplaceStream(const char *user, const char *file)
+{
+    int filedes[2];
+    int pid;
+    int fd;
+    int n;
+    char buf[1024];
+
+    if (pipe(filedes) < 0) {
+	perror("pipe");
+	return(-1);
+    }
+    if ((pid = fork()) < 0) {
+	perror("fork");
+	return(-1);
+    }
+    if (pid > 0) {
+	/*
+	 * PARENT
+	 */
+
+	close(filedes[1]);
+	if (read(filedes[0], buf, 1) != 1) {
+	    close(filedes[0]);
+	    filedes[0] = -1;
+	}
+	return(filedes[0]);
+    }
+
+    /*
+     * CHILD
+     */
+
+    close(filedes[0]);
+
+    if (ChangeUser(user, 0) < 0)
+	exit(0);
+
+    bb_default_error_retval = 0;
+    fd = bb_xopen3(file, O_RDONLY, 0);
+    buf[0] = 0;
+    write(filedes[1], buf, 1);
+    while ((n = read(fd, buf, sizeof(buf))) > 0) {
+	write(filedes[1], buf, n);
+    }
+    exit(0);
+}
+
+static void
+EditFile(const char *user, const char *file)
+{
+    int pid;
+
+    if ((pid = fork()) == 0) {
+	/*
+	 * CHILD - change user and run editor
+	 */
+	char *ptr;
+	char visual[1024];
+
+	if (ChangeUser(user, 1) < 0)
+	    exit(0);
+	if ((ptr = getenv("VISUAL")) == NULL || strlen(ptr) > 256)
+	    ptr = PATH_VI;
+
+	snprintf(visual, sizeof(visual), "%s %s", ptr, file);
+	execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", visual, NULL);
+	perror("exec");
+	exit(0);
+    }
+    if (pid < 0) {
+	/*
+	 * PARENT - failure
+	 */
+	bb_perror_msg_and_die("fork");
+    }
+    wait4(pid, NULL, 0, NULL);
+}
+
+static int
+ChangeUser(const char *user, short dochdir)
+{
+    struct passwd *pas;
+
+    /*
+     * Obtain password entry and change privileges
+     */
+
+    if ((pas = getpwnam(user)) == NULL) {
+	bb_perror_msg_and_die("failed to get uid for %s", user);
+	return(-1);
+    }
+    setenv("USER", pas->pw_name, 1);
+    setenv("HOME", pas->pw_dir, 1);
+    setenv("SHELL", DEFAULT_SHELL, 1);
+
+    /*
+     * Change running state to the user in question
+     */
+    change_identity(pas);
+
+    if (dochdir) {
+	if (chdir(pas->pw_dir) < 0) {
+	    bb_perror_msg("chdir failed: %s %s", user, pas->pw_dir);
+	    bb_xchdir(TMPDIR);
+	}
+    }
+    return(pas->pw_uid);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/dc.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/dc.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/dc.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,227 @@
+/* vi: set sw=4 ts=4: */
+#include "busybox.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+
+/* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */
+
+static double stack[100];
+static unsigned int pointer;
+static unsigned char base;
+
+static void push(double a)
+{
+	if (pointer >= (sizeof(stack) / sizeof(*stack)))
+		bb_error_msg_and_die("stack overflow");
+	stack[pointer++] = a;
+}
+
+static double pop(void)
+{
+	if (pointer == 0)
+		bb_error_msg_and_die("stack underflow");
+	return stack[--pointer];
+}
+
+static void add(void)
+{
+	push(pop() + pop());
+}
+
+static void sub(void)
+{
+	double subtrahend = pop();
+
+	push(pop() - subtrahend);
+}
+
+static void mul(void)
+{
+	push(pop() * pop());
+}
+
+static void power(void)
+{
+	double topower = pop();
+
+	push(pow(pop(), topower));
+}
+
+static void divide(void)
+{
+	double divisor = pop();
+
+	push(pop() / divisor);
+}
+
+static void mod(void)
+{
+	unsigned int d = pop();
+
+	push((unsigned int) pop() % d);
+}
+
+static void and(void)
+{
+	push((unsigned int) pop() & (unsigned int) pop());
+}
+
+static void or(void)
+{
+	push((unsigned int) pop() | (unsigned int) pop());
+}
+
+static void eor(void)
+{
+	push((unsigned int) pop() ^ (unsigned int) pop());
+}
+
+static void not(void)
+{
+	push(~(unsigned int) pop());
+}
+
+static void set_output_base(void)
+{
+	base=(unsigned char)pop();
+	if ((base != 10) && (base != 16)) {
+		fprintf(stderr, "Error: base = %d is not supported.\n", base);
+		base=10;
+	}
+}
+
+static void print_base(double print)
+{
+	if (base == 16)
+		printf("%x\n", (unsigned int)print);
+	else
+	printf("%g\n", print);
+}
+
+static void print_stack_no_pop(void)
+{
+	unsigned int i=pointer;
+	while (i)
+		print_base(stack[--i]);
+}
+
+static void print_no_pop(void)
+{
+	print_base(stack[pointer-1]);
+}
+
+struct op {
+	const char *name;
+	void (*function) (void);
+};
+
+static const struct op operators[] = {
+	{"+",   add},
+	{"add", add},
+	{"-",   sub},
+	{"sub", sub},
+	{"*",   mul},
+	{"mul", mul},
+	{"/",   divide},
+	{"div", divide},
+	{"**",  power},
+	{"exp", power},
+	{"pow", power},
+	{"%",   mod},
+	{"mod", mod},
+	{"and", and},
+	{"or",  or},
+	{"not", not},
+	{"eor", eor},
+	{"xor", eor},
+	{"p", print_no_pop},
+	{"f", print_stack_no_pop},
+	{"o", set_output_base},
+	{0,     0}
+};
+
+static void stack_machine(const char *argument)
+{
+	char *endPointer = 0;
+	double d;
+	const struct op *o = operators;
+
+	if (argument == 0)
+		return;
+
+	d = strtod(argument, &endPointer);
+
+	if (endPointer != argument) {
+		push(d);
+		return;
+	}
+
+	while (o->name != 0) {
+		if (strcmp(o->name, argument) == 0) {
+			(*(o->function)) ();
+			return;
+		}
+		o++;
+	}
+	bb_error_msg_and_die("%s: syntax error.", argument);
+}
+
+/* return pointer to next token in buffer and set *buffer to one char
+ * past the end of the above mentioned token
+ */
+static char *get_token(char **buffer)
+{
+	char *start   = NULL;
+	char *current = *buffer;
+
+	while (isspace(*current)) { current++; }
+	if (*current != 0) {
+		start = current;
+		while (!isspace(*current) && *current != 0) { current++; }
+		*buffer = current;
+	}
+	return start;
+}
+
+/* In Perl one might say, scalar m|\s*(\S+)\s*|g */
+static int number_of_tokens(char *buffer)
+{
+	int   i = 0;
+	char *b = buffer;
+	while (get_token(&b)) { i++; }
+	return i;
+}
+
+int dc_main(int argc, char **argv)
+{
+	/* take stuff from stdin if no args are given */
+	if (argc <= 1) {
+		int i, len;
+		char *line   = NULL;
+		char *cursor = NULL;
+		char *token  = NULL;
+		while ((line = bb_get_chomped_line_from_file(stdin))) {
+			cursor = line;
+			len = number_of_tokens(line);
+			for (i = 0; i < len; i++) {
+				token = get_token(&cursor);
+				*cursor++ = 0;
+				stack_machine(token);
+			}
+			free(line);
+		}
+	} else {
+		if (*argv[1]=='-')
+			bb_show_usage();
+		while (argc >= 2) {
+			stack_machine(argv[1]);
+			argv++;
+			argc--;
+		}
+	}
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/devfsd.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/devfsd.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/devfsd.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2039 @@
+/*
+	devfsd implementation for busybox
+
+	Copyright (C) 2003 by Tito Ragusa <farmatito at tiscali.it>
+
+	Busybox version is based on some previous work and ideas
+	Copyright (C) [2003] by [Matteo Croce] <3297627799 at wind.it>
+
+	devfsd.c
+
+	Main file for  devfsd  (devfs daemon for Linux).
+
+    Copyright (C) 1998-2002  Richard Gooch
+
+	devfsd.h
+
+    Header file for  devfsd  (devfs daemon for Linux).
+
+    Copyright (C) 1998-2000  Richard Gooch
+
+	compat_name.c
+
+    Compatibility name file for  devfsd  (build compatibility names).
+
+    Copyright (C) 1998-2002  Richard Gooch
+
+	expression.c
+
+    This code provides Borne Shell-like expression expansion.
+
+    Copyright (C) 1997-1999  Richard Gooch
+
+	This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    Richard Gooch may be reached by email at  rgooch at atnf.csiro.au
+    The postal address is:
+      Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
+*/
+
+#include "busybox.h"
+#include "xregex.h"
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/sysmacros.h>
+
+
+/* Various defines taken from linux/major.h */
+#define IDE0_MAJOR	3
+#define IDE1_MAJOR	22
+#define IDE2_MAJOR	33
+#define IDE3_MAJOR	34
+#define IDE4_MAJOR	56
+#define IDE5_MAJOR	57
+#define IDE6_MAJOR	88
+#define IDE7_MAJOR	89
+#define IDE8_MAJOR	90
+#define IDE9_MAJOR	91
+
+
+/* Various defines taken from linux/devfs_fs.h */
+#define DEVFSD_PROTOCOL_REVISION_KERNEL  5
+#define	DEVFSD_IOCTL_BASE	'd'
+/*  These are the various ioctls  */
+#define DEVFSDIOC_GET_PROTO_REV         _IOR(DEVFSD_IOCTL_BASE, 0, int)
+#define DEVFSDIOC_SET_EVENT_MASK        _IOW(DEVFSD_IOCTL_BASE, 2, int)
+#define DEVFSDIOC_RELEASE_EVENT_QUEUE   _IOW(DEVFSD_IOCTL_BASE, 3, int)
+#define DEVFSDIOC_SET_CONFIG_DEBUG_MASK _IOW(DEVFSD_IOCTL_BASE, 4, int)
+#define DEVFSD_NOTIFY_REGISTERED    0
+#define DEVFSD_NOTIFY_UNREGISTERED  1
+#define DEVFSD_NOTIFY_ASYNC_OPEN    2
+#define DEVFSD_NOTIFY_CLOSE         3
+#define DEVFSD_NOTIFY_LOOKUP        4
+#define DEVFSD_NOTIFY_CHANGE        5
+#define DEVFSD_NOTIFY_CREATE        6
+#define DEVFSD_NOTIFY_DELETE        7
+#define DEVFS_PATHLEN               1024
+/*  Never change this otherwise the binary interface will change   */
+
+struct devfsd_notify_struct
+{   /*  Use native C types to ensure same types in kernel and user space     */
+    unsigned int type;           /*  DEVFSD_NOTIFY_* value                   */
+    unsigned int mode;           /*  Mode of the inode or device entry       */
+    unsigned int major;          /*  Major number of device entry            */
+    unsigned int minor;          /*  Minor number of device entry            */
+    unsigned int uid;            /*  Uid of process, inode or device entry   */
+    unsigned int gid;            /*  Gid of process, inode or device entry   */
+    unsigned int overrun_count;  /*  Number of lost events                   */
+    unsigned int namelen;        /*  Number of characters not including '\0' */
+    /*  The device name MUST come last                                       */
+    char devname[DEVFS_PATHLEN]; /*  This will be '\0' terminated            */
+};
+
+#define BUFFER_SIZE 16384
+#define DEVFSD_VERSION "1.3.25"
+#define CONFIG_FILE  "/etc/devfsd.conf"
+#define MODPROBE		"/sbin/modprobe"
+#define MODPROBE_SWITCH_1 "-k"
+#define MODPROBE_SWITCH_2 "-C"
+#define CONFIG_MODULES_DEVFS "/etc/modules.devfs"
+#define MAX_ARGS     (6 + 1)
+#define MAX_SUBEXPR  10
+#define STRING_LENGTH 255
+
+/* for get_uid_gid() */
+#define UID			0
+#define GID			1
+
+/* fork_and_execute() */
+# define DIE			1
+# define NO_DIE			0
+
+/* for dir_operation() */
+#define RESTORE		0
+#define SERVICE		1
+#define READ_CONFIG 2
+
+/*  Update only after changing code to reflect new protocol  */
+#define DEVFSD_PROTOCOL_REVISION_DAEMON  5
+
+/*  Compile-time check  */
+#if DEVFSD_PROTOCOL_REVISION_KERNEL != DEVFSD_PROTOCOL_REVISION_DAEMON
+#error protocol version mismatch. Update your kernel headers
+#endif
+
+#define AC_PERMISSIONS				0
+#define AC_MODLOAD					1
+#define AC_EXECUTE					2
+#define AC_MFUNCTION				3	/* not supported by busybox */
+#define AC_CFUNCTION				4	/* not supported by busybox */
+#define AC_COPY						5
+#define AC_IGNORE					6
+#define AC_MKOLDCOMPAT				7
+#define AC_MKNEWCOMPAT				8
+#define AC_RMOLDCOMPAT				9
+#define AC_RMNEWCOMPAT				10
+#define AC_RESTORE					11
+
+struct permissions_type
+{
+    mode_t mode;
+    uid_t uid;
+    gid_t gid;
+};
+
+struct execute_type
+{
+    char *argv[MAX_ARGS + 1];  /*  argv[0] must always be the programme  */
+};
+
+struct copy_type
+{
+    const char *source;
+    const char *destination;
+};
+
+struct action_type
+{
+    unsigned int what;
+    unsigned int when;
+};
+
+struct config_entry_struct
+{
+    struct action_type action;
+    regex_t preg;
+    union
+    {
+	struct permissions_type permissions;
+	struct execute_type execute;
+	struct copy_type copy;
+    }
+    u;
+    struct config_entry_struct *next;
+};
+
+struct get_variable_info
+{
+    const struct devfsd_notify_struct *info;
+    const char *devname;
+    char devpath[STRING_LENGTH];
+};
+
+static void dir_operation(int , const char * , int,  unsigned long* );
+static void service(struct stat statbuf, char *path);
+static int st_expr_expand(char *, unsigned, const char *, const char *(*) (const char *, void *), void *);
+static const char *get_old_name(const char *, unsigned, char *, unsigned, unsigned);
+static int mksymlink (const char *oldpath, const char *newpath);
+static void read_config_file (char *path, int optional, unsigned long *event_mask);
+static void process_config_line (const char *, unsigned long *);
+static int  do_servicing (int, unsigned long);
+static void service_name (const struct devfsd_notify_struct *);
+static void action_permissions (const struct devfsd_notify_struct *, const struct config_entry_struct *);
+static void action_execute (const struct devfsd_notify_struct *, const struct config_entry_struct *,
+							const regmatch_t *, unsigned);
+static void action_modload (const struct devfsd_notify_struct *info, const struct config_entry_struct *entry);
+static void action_copy (const struct devfsd_notify_struct *, const struct config_entry_struct *,
+						 const regmatch_t *, unsigned);
+static void action_compat (const struct devfsd_notify_struct *, unsigned);
+static void free_config (void);
+static void restore(char *spath, struct stat source_stat, int rootlen);
+static int copy_inode (const char *, const struct stat *, mode_t, const char *, const struct stat *);
+static mode_t get_mode (const char *);
+static void signal_handler (int);
+static const char *get_variable (const char *, void *);
+static int make_dir_tree (const char *);
+static int expand_expression(char *, unsigned, const char *, const char *(*)(const char *, void *), void *,
+							 const char *, const regmatch_t *, unsigned );
+static void expand_regexp (char *, size_t, const char *, const char *, const regmatch_t *, unsigned );
+static const char *expand_variable(	char *, unsigned, unsigned *, const char *,
+									const char *(*) (const char *, void *), void * );
+static const char *get_variable_v2(const char *, const char *(*) (const char *, void *), void *);
+static char get_old_ide_name (unsigned , unsigned);
+static char *write_old_sd_name (char *, unsigned, unsigned, char *);
+
+/* busybox functions */
+static void msg_logger(int pri, const char * fmt, ... )__attribute__ ((format (printf, 2, 3)));
+static void msg_logger_and_die(int pri, const char * fmt, ... )__attribute__ ((noreturn, format (printf, 2, 3)));
+static void do_ioctl_and_die(int fd, int request, unsigned long event_mask_flag);
+static void fork_and_execute(int die, char *arg0, char **arg );
+static int get_uid_gid ( int, const char *);
+static void safe_memcpy( char * dest, const char * src, int len);
+static unsigned int scan_dev_name_common(const char *d, unsigned int n, int addendum, char *ptr);
+static unsigned int scan_dev_name(const char *d, unsigned int n, char *ptr);
+
+/* Structs and vars */
+static struct config_entry_struct *first_config = NULL;
+static struct config_entry_struct *last_config = NULL;
+static const char *mount_point = NULL;
+static volatile int caught_signal = FALSE;
+static volatile int caught_sighup = FALSE;
+static struct initial_symlink_struct
+{
+    char *dest;
+    char *name;
+} initial_symlinks[] =
+{
+    {"/proc/self/fd", "fd"},
+    {"fd/0", "stdin"},
+    {"fd/1", "stdout"},
+    {"fd/2", "stderr"},
+    {NULL, NULL},
+};
+
+static struct event_type
+{
+    unsigned int type;        /*  The DEVFSD_NOTIFY_* value                  */
+    const char *config_name;  /*  The name used in the config file           */
+} event_types[] =
+{
+    {DEVFSD_NOTIFY_REGISTERED,   "REGISTER"},
+    {DEVFSD_NOTIFY_UNREGISTERED, "UNREGISTER"},
+    {DEVFSD_NOTIFY_ASYNC_OPEN,   "ASYNC_OPEN"},
+    {DEVFSD_NOTIFY_CLOSE,        "CLOSE"},
+    {DEVFSD_NOTIFY_LOOKUP,       "LOOKUP"},
+    {DEVFSD_NOTIFY_CHANGE,       "CHANGE"},
+    {DEVFSD_NOTIFY_CREATE,       "CREATE"},
+    {DEVFSD_NOTIFY_DELETE,       "DELETE"},
+    {0xffffffff,                 NULL}
+};
+
+/* Busybox messages */
+
+static const char * const bb_msg_proto_rev			= "protocol revision";
+static const char * const bb_msg_bad_config		= "bad %s config file: %s";
+static const char * const bb_msg_small_buffer		= "buffer too small";
+static const char * const bb_msg_variable_not_found = "variable: %s not found";
+
+/* Busybox functions  */
+static void msg_logger(int pri, const char * fmt, ... )
+{
+	va_list ap;
+	int ret;
+
+	va_start(ap, fmt);
+	ret = access ("/dev/log", F_OK);
+	if (ret == 0) {
+		openlog(bb_applet_name, 0, LOG_DAEMON);
+		vsyslog( pri , fmt, ap);
+		/* Man: A trailing newline is added when needed. */
+		closelog();
+	}
+	/* ENABLE_DEVFSD_VERBOSE is always enabled if msg_logger is used */
+	if ((ENABLE_DEVFSD_VERBOSE && ret) || ENABLE_DEBUG) {
+		bb_error_msg(fmt, ap);
+	}
+	va_end(ap);
+}
+
+static void msg_logger_and_die(int pri, const char* fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	msg_logger(pri, fmt, ap);
+	va_end(ap);
+	exit(EXIT_FAILURE);
+}
+
+/* Busybox stuff */
+#if defined(CONFIG_DEVFSD_VERBOSE) || defined(CONFIG_DEBUG)
+#define devfsd_error_msg(fmt, args...)                bb_error_msg(fmt, ## args)
+#define devfsd_perror_msg_and_die(fmt, args...)       bb_perror_msg_and_die(fmt, ## args)
+#define devfsd_error_msg_and_die(fmt, args...)        bb_error_msg_and_die(fmt, ## args)
+#if defined(CONFIG_DEBUG)
+#define debug_msg_logger(x, fmt, args...)             msg_logger(x, fmt, ## args)
+#else
+#define debug_msg_logger(x, fmt, args...)
+#endif
+#else
+#define debug_msg_logger(x, fmt, args...)
+#define msg_logger(p, fmt, args...)
+#define msg_logger_and_die(p, fmt, args...)           exit(1)
+#define devfsd_perror_msg_and_die(fmt, args...)       exit(1)
+#define devfsd_error_msg_and_die(fmt, args...)        exit(1)
+#define devfsd_error_msg(fmt, args...)
+#endif
+
+static void do_ioctl_and_die(int fd, int request, unsigned long event_mask_flag)
+{
+	if (ioctl (fd, request, event_mask_flag) == -1)
+		msg_logger_and_die(LOG_ERR, "ioctl");
+}
+
+static void fork_and_execute(int die, char *arg0, char **arg )
+{
+	switch ( fork () )
+	{
+	case 0:
+		/*  Child  */
+		break;
+	case -1:
+		/*  Parent: Error  : die or return */
+		msg_logger(LOG_ERR,(char *) bb_msg_memory_exhausted);
+		if(die)
+			exit(EXIT_FAILURE);
+		return;
+	default:
+		/*  Parent : ok : return or exit  */
+		if(arg0 != NULL)
+		{
+			wait (NULL);
+			return;
+		}
+		exit (EXIT_SUCCESS);
+	}
+	 /* Child : if arg0 != NULL do execvp */
+	if(arg0 != NULL )
+	{
+		execvp (arg0, arg);
+		msg_logger_and_die(LOG_ERR, "execvp");
+	}
+}
+
+static void safe_memcpy( char *dest, const char *src, int len)
+{
+	memcpy (dest , src , len );
+	dest[len] = '\0';
+}
+
+static unsigned int scan_dev_name_common(const char *d, unsigned int n, int addendum, char *ptr)
+{
+	if( d[n - 4]=='d' && d[n - 3]=='i' && d[n - 2]=='s' && d[n - 1]=='c')
+		return (2 + addendum);
+	else if( d[n - 2]=='c' && d[n - 1]=='d')
+		return (3 + addendum);
+	else if(ptr[0]=='p' && ptr[1]=='a' && ptr[2]=='r' && ptr[3]=='t')
+		return (4 + addendum);
+	else if( ptr[n - 2]=='m' && ptr[n - 1]=='t')
+		return (5 + addendum);
+	else
+		return 0;
+}
+
+static unsigned int scan_dev_name(const char *d, unsigned int n, char *ptr)
+{
+	if(d[0]=='s' && d[1]=='c' && d[2]=='s' && d[3]=='i' && d[4]=='/')
+	{
+		if( d[n - 7]=='g' && d[n - 6]=='e' && d[n - 5]=='n' &&
+			d[n - 4]=='e' && d[n - 3]=='r' && d[n - 2]=='i' &&
+			d[n - 1]=='c' )
+			return 1;
+		return scan_dev_name_common(d, n, 0, ptr);
+	}
+	else if(d[0]=='i' && d[1]=='d' && d[2]=='e' && d[3]=='/' &&
+			d[4]=='h' && d[5]=='o' && d[6]=='s' && d[7]=='t')
+	{
+		return scan_dev_name_common(d, n, 4, ptr);
+	}
+	else if(d[0]=='s' && d[1]=='b' && d[2]=='p' && d[3]=='/')
+	{
+		return 10;
+	}
+	else if(d[0]=='v' && d[1]=='c' && d[2]=='c' && d[3]=='/')
+	{
+		return 11;
+	}
+	else if(d[0]=='p' && d[1]=='t' && d[2]=='y' && d[3]=='/')
+	{
+		return 12;
+	}
+	return 0;
+}
+
+/*  Public functions follow  */
+
+int devfsd_main (int argc, char **argv)
+{
+	int print_version = FALSE;
+	int do_daemon = TRUE;
+	int no_polling = FALSE;
+	int do_scan;
+	int fd, proto_rev, count;
+	unsigned long event_mask = 0;
+	struct sigaction new_action;
+	struct initial_symlink_struct *curr;
+
+	if (argc < 2)
+		bb_show_usage();
+
+	for (count = 2; count < argc; ++count)
+	{
+		if(argv[count][0] == '-')
+		{
+			if(argv[count][1]=='v' && !argv[count][2]) /* -v */
+					print_version = TRUE;
+			else if(ENABLE_DEVFSD_FG_NP && argv[count][1]=='f'
+					&& argv[count][2]=='g' && !argv[count][3]) /* -fg */
+					do_daemon = FALSE;
+			else if(ENABLE_DEVFSD_FG_NP && argv[count][1]=='n'
+					&& argv[count][2]=='p' && !argv[count][3]) /* -np */
+					no_polling = TRUE;
+			else
+				bb_show_usage();
+		}
+	}
+
+	/* strip last / from mount point, so we don't need to check for it later */
+	while( argv[1][1]!='\0' && argv[1][strlen(argv[1])-1] == '/' )
+		argv[1][strlen(argv[1]) -1] = '\0';
+
+	mount_point = argv[1];
+
+	if (chdir (mount_point) != 0)
+		devfsd_perror_msg_and_die(mount_point);
+
+	fd = bb_xopen (".devfsd", O_RDONLY);
+
+	if (fcntl (fd, F_SETFD, FD_CLOEXEC) != 0)
+		devfsd_perror_msg_and_die("FD_CLOEXEC");
+
+	if (ioctl (fd, DEVFSDIOC_GET_PROTO_REV, &proto_rev) == -1)
+		msg_logger_and_die(LOG_ERR, "ioctl");
+
+	/*setup initial entries */
+    for (curr = initial_symlinks; curr->dest != NULL; ++curr)
+		symlink (curr->dest, curr->name);
+
+	/* NB: The check for CONFIG_FILE is done in read_config_file() */
+
+	if ( print_version  || (DEVFSD_PROTOCOL_REVISION_DAEMON != proto_rev) )
+	{
+		bb_printf( "%s v%s\nDaemon %s:\t%d\nKernel-side %s:\t%d\n",
+					 bb_applet_name,DEVFSD_VERSION,bb_msg_proto_rev,
+					 DEVFSD_PROTOCOL_REVISION_DAEMON,bb_msg_proto_rev, proto_rev);
+		if (DEVFSD_PROTOCOL_REVISION_DAEMON != proto_rev)
+			bb_error_msg_and_die( "%s mismatch!",bb_msg_proto_rev);
+		exit(EXIT_SUCCESS); /* -v */
+	}
+	/*  Tell kernel we are special (i.e. we get to see hidden entries)  */
+	do_ioctl_and_die(fd, DEVFSDIOC_SET_EVENT_MASK, 0);
+
+	sigemptyset (&new_action.sa_mask);
+	new_action.sa_flags = 0;
+
+	/*  Set up SIGHUP and SIGUSR1 handlers  */
+	new_action.sa_handler = signal_handler;
+	if (sigaction (SIGHUP, &new_action, NULL) != 0 || sigaction (SIGUSR1, &new_action, NULL) != 0 )
+		devfsd_error_msg_and_die( "sigaction");
+
+	bb_printf("%s v%s  started for %s\n",bb_applet_name, DEVFSD_VERSION, mount_point);
+
+	/*  Set umask so that mknod(2), open(2) and mkdir(2) have complete control over permissions  */
+	umask (0);
+	read_config_file (CONFIG_FILE, FALSE, &event_mask);
+	/*  Do the scan before forking, so that boot scripts see the finished product  */
+	dir_operation(SERVICE,mount_point,0,NULL);
+
+	if (ENABLE_DEVFSD_FG_NP && no_polling)
+		exit (0);
+	if (do_daemon)
+	{
+		/*  Release so that the child can grab it  */
+		do_ioctl_and_die(fd, DEVFSDIOC_RELEASE_EVENT_QUEUE, 0);
+		fork_and_execute(DIE, NULL, NULL);
+		setsid ();        /*  Prevent hangups and become pgrp leader         */
+	} else if(ENABLE_DEVFSD_FG_NP) {
+		setpgid (0, 0);  /*  Become process group leader                    */
+	}
+
+	while (TRUE)
+	{
+		do_scan = do_servicing (fd, event_mask);
+
+		free_config ();
+		read_config_file (CONFIG_FILE, FALSE, &event_mask);
+		if (do_scan)
+			dir_operation(SERVICE,mount_point,0,NULL);
+	}
+}   /*  End Function main  */
+
+
+/*  Private functions follow  */
+
+static void read_config_file (char *path, int optional, unsigned long *event_mask)
+/*  [SUMMARY] Read a configuration database.
+    <path> The path to read the database from. If this is a directory, all
+    entries in that directory will be read (except hidden entries).
+    <optional> If TRUE, the routine will silently ignore a missing config file.
+    <event_mask> The event mask is written here. This is not initialised.
+    [RETURNS] Nothing.
+*/
+{
+	struct stat statbuf;
+	FILE *fp;
+	char buf[STRING_LENGTH];
+	char *line=NULL;
+
+	debug_msg_logger(LOG_INFO, "%s: %s", __FUNCTION__, path);
+
+	if (stat (path, &statbuf) == 0 )
+	{
+		/* Don't read 0 length files: ignored */
+		/*if( statbuf.st_size == 0 )
+				return;*/
+		if ( S_ISDIR (statbuf.st_mode) )
+		{
+			/* strip last / from dirname so we don't need to check for it later */
+			while( path  && path[1]!='\0' && path[strlen(path)-1] == '/')
+				path[strlen(path) -1] = '\0';
+
+			dir_operation(READ_CONFIG, path, 0, event_mask);
+			return;
+		}
+		if ( ( fp = fopen (path, "r") ) != NULL )
+		{
+			while (fgets (buf, STRING_LENGTH, fp) != NULL)
+			{
+				/*  Skip whitespace  */
+				for (line = buf; isspace (*line); ++line)
+					/*VOID*/;
+				if (line[0] == '\0' || line[0] == '#' )
+					continue;
+				process_config_line (line, event_mask);
+			}
+			fclose (fp);
+		} else {
+			goto read_config_file_err;
+		}
+	} else {
+read_config_file_err:
+	if(optional ==  0  && errno == ENOENT)
+		msg_logger_and_die(LOG_ERR, "read config file: %s: %m", path);
+	}
+	return;
+}   /*  End Function read_config_file   */
+
+static void process_config_line (const char *line, unsigned long *event_mask)
+/*  [SUMMARY] Process a line from a configuration file.
+    <line> The configuration line.
+    <event_mask> The event mask is written here. This is not initialised.
+    [RETURNS] Nothing.
+*/
+{
+	int  num_args, count;
+	struct config_entry_struct *new;
+	char p[MAX_ARGS][STRING_LENGTH];
+	char when[STRING_LENGTH], what[STRING_LENGTH];
+	char name[STRING_LENGTH];
+	char * msg="";
+	char *ptr;
+	int i;
+
+	/* !!!! Only Uppercase Keywords in devsfd.conf */
+	static const char *const options[] = {
+		"CLEAR_CONFIG", "INCLUDE", "OPTIONAL_INCLUDE",
+		"RESTORE", "PERMISSIONS", "MODLOAD", "EXECUTE",
+		"COPY", "IGNORE", "MKOLDCOMPAT", "MKNEWCOMPAT",
+		"RMOLDCOMPAT", "RMNEWCOMPAT", 0
+	};
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	for (count = 0; count < MAX_ARGS; ++count) p[count][0] = '\0';
+	num_args = sscanf (line, "%s %s %s %s %s %s %s %s %s %s",
+			when, name, what,
+			p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
+
+	i = compare_string_array(options, when );
+
+	/*"CLEAR_CONFIG"*/
+	if( i == 0)
+	{
+		free_config ();
+		*event_mask = 0;
+		return;
+	}
+
+	if ( num_args < 2)
+		goto process_config_line_err;
+
+	/* "INCLUDE" & "OPTIONAL_INCLUDE" */
+	if( i == 1 || i == 2 )
+	{
+		st_expr_expand (name, STRING_LENGTH, name, get_variable, NULL );
+		msg_logger(LOG_INFO, "%sinclude: %s",(toupper (when[0]) == 'I') ? "": "optional_", name);
+		read_config_file (name, (toupper (when[0]) == 'I') ? FALSE : TRUE, event_mask);
+		return;
+	}
+	/* "RESTORE" */
+	if( i == 3)
+	{
+		dir_operation(RESTORE,name, strlen (name),NULL);
+		return;
+	}
+	if (num_args < 3)
+		goto process_config_line_err;
+
+	new = xmalloc (sizeof *new);
+	memset (new, 0, sizeof *new);
+
+	for (count = 0; event_types[count].config_name != NULL; ++count)
+	{
+		if (strcasecmp (when, event_types[count].config_name) != 0)
+			continue;
+		new->action.when = event_types[count].type;
+		break;
+	}
+	if (event_types[count].config_name == NULL)
+	{
+		msg="WHEN in";
+		goto process_config_line_err;
+	}
+
+	i = compare_string_array(options, what );
+
+	switch(i)
+	{
+		case 4:	/* "PERMISSIONS" */
+			new->action.what = AC_PERMISSIONS;
+			/*  Get user and group  */
+			if ( ( ptr = strchr (p[0], '.') ) == NULL )
+			{
+				msg="UID.GID";
+				goto process_config_line_err; /*"missing '.' in UID.GID"*/
+			}
+
+			*ptr++ = '\0';
+			new->u.permissions.uid = get_uid_gid (UID, p[0]);
+			new->u.permissions.gid = get_uid_gid (GID, ptr);
+			/*  Get mode  */
+			new->u.permissions.mode = get_mode (p[1]);
+			break;
+		case 5:	/*  MODLOAD */
+			/*This  action will pass "/dev/$devname" (i.e. "/dev/" prefixed to
+			the device name) to the module loading  facility.  In  addition,
+			the /etc/modules.devfs configuration file is used.*/
+			 if (ENABLE_DEVFSD_MODLOAD)
+				new->action.what = AC_MODLOAD;
+			 break;
+		case 6: /* EXECUTE */
+			new->action.what = AC_EXECUTE;
+			num_args -= 3;
+
+			for (count = 0; count < num_args; ++count)
+				new->u.execute.argv[count] = bb_xstrdup (p[count]);
+
+			new->u.execute.argv[num_args] = NULL;
+			break;
+		case 7: /* COPY */
+			new->action.what = AC_COPY;
+			num_args -= 3;
+			if (num_args != 2)
+				goto process_config_line_err; /* missing path and function in line */
+
+			new->u.copy.source = bb_xstrdup (p[0]);
+			new->u.copy.destination = bb_xstrdup (p[1]);
+			break;
+		case 8: /* IGNORE */
+		/* FALLTROUGH */
+		case 9: /* MKOLDCOMPAT */
+		/* FALLTROUGH */
+		case 10: /* MKNEWCOMPAT */
+		/* FALLTROUGH */
+		case 11:/* RMOLDCOMPAT */
+		/* FALLTROUGH */
+		case 12: /* RMNEWCOMPAT */
+		/*	AC_IGNORE					6
+			AC_MKOLDCOMPAT				7
+			AC_MKNEWCOMPAT				8
+			AC_RMOLDCOMPAT				9
+			AC_RMNEWCOMPAT				10*/
+			new->action.what = i - 2;
+			break;
+		default:
+			msg ="WHAT in";
+			goto process_config_line_err;
+		/*esac*/
+	} /* switch (i) */
+
+	xregcomp( &new->preg, name, REG_EXTENDED);
+
+	*event_mask |= 1 << new->action.when;
+	new->next = NULL;
+	if (first_config == NULL)
+		first_config = new;
+	else
+		last_config->next = new;
+	last_config = new;
+	return;
+process_config_line_err:
+	msg_logger_and_die(LOG_ERR, bb_msg_bad_config, msg , line);
+}  /*  End Function process_config_line   */
+
+static int do_servicing (int fd, unsigned long event_mask)
+/*  [SUMMARY] Service devfs changes until a signal is received.
+    <fd> The open control file.
+    <event_mask> The event mask.
+    [RETURNS] TRUE if SIGHUP was caught, else FALSE.
+*/
+{
+	ssize_t bytes;
+	struct devfsd_notify_struct info;
+	unsigned long tmp_event_mask;
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	/*  Tell devfs what events we care about  */
+	tmp_event_mask = event_mask;
+	do_ioctl_and_die(fd, DEVFSDIOC_SET_EVENT_MASK, tmp_event_mask);
+	while (!caught_signal)
+	{
+		errno = 0;
+		bytes = read (fd, (char *) &info, sizeof info);
+		if (caught_signal)
+			break;      /*  Must test for this first     */
+		if (errno == EINTR)
+			continue;  /*  Yes, the order is important  */
+		if (bytes < 1)
+			break;
+		service_name (&info);
+	}
+	if (caught_signal)
+	{
+		int c_sighup = caught_sighup;
+
+		caught_signal = FALSE;
+		caught_sighup = FALSE;
+		return (c_sighup);
+	}
+	msg_logger_and_die(LOG_ERR, "read error on control file");
+}   /*  End Function do_servicing  */
+
+static void service_name (const struct devfsd_notify_struct *info)
+/*  [SUMMARY] Service a single devfs change.
+    <info> The devfs change.
+    [RETURNS] Nothing.
+*/
+{
+	unsigned int n;
+	regmatch_t mbuf[MAX_SUBEXPR];
+	struct config_entry_struct *entry;
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+	if (ENABLE_DEBUG && info->overrun_count > 0)
+		debug_msg_logger(LOG_ERR, "lost %u events", info->overrun_count);
+
+	/*  Discard lookups on "/dev/log" and "/dev/initctl"  */
+	if(   info->type == DEVFSD_NOTIFY_LOOKUP &&
+		((info->devname[0]=='l' && info->devname[1]=='o' &&
+		  info->devname[2]=='g' && !info->devname[3]) ||
+		( info->devname[0]=='i' && info->devname[1]=='n' &&
+		  info->devname[2]=='i' && info->devname[3]=='t' &&
+		  info->devname[4]=='c' && info->devname[5]=='t' &&
+		  info->devname[6]=='l' && !info->devname[7])))
+			return;
+	for (entry = first_config; entry != NULL; entry = entry->next)
+	{
+		/*  First check if action matches the type, then check if name matches */
+		if (info->type != entry->action.when || regexec (&entry->preg, info->devname, MAX_SUBEXPR, mbuf, 0) != 0 )
+			continue;
+		for (n = 0; (n < MAX_SUBEXPR) && (mbuf[n].rm_so != -1); ++n)
+			/* VOID */;
+
+		debug_msg_logger(LOG_INFO, "%s: action.what %d", __FUNCTION__, entry->action.what);
+
+		switch (entry->action.what)
+		{
+			case AC_PERMISSIONS:
+				action_permissions (info, entry);
+				break;
+			case AC_MODLOAD:
+				if(ENABLE_DEVFSD_MODLOAD)
+					action_modload (info, entry);
+				break;
+			case AC_EXECUTE:
+				action_execute (info, entry, mbuf, n);
+				break;
+			case AC_COPY:
+				action_copy (info, entry, mbuf, n);
+				break;
+			case AC_IGNORE:
+				return;
+				/*break;*/
+			case AC_MKOLDCOMPAT:
+			case AC_MKNEWCOMPAT:
+			case AC_RMOLDCOMPAT:
+			case AC_RMNEWCOMPAT:
+				action_compat (info, entry->action.what);
+				break;
+			default:
+				msg_logger_and_die(LOG_ERR, "Unknown action");
+		}
+	}
+}   /*  End Function service_name  */
+
+static void action_permissions (const struct devfsd_notify_struct *info,
+				const struct config_entry_struct *entry)
+/*  [SUMMARY] Update permissions for a device entry.
+    <info> The devfs change.
+    <entry> The config file entry.
+    [RETURNS] Nothing.
+*/
+{
+	struct stat statbuf;
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	if ( stat (info->devname, &statbuf) != 0	||
+		 chmod (info->devname,(statbuf.st_mode & S_IFMT) | (entry->u.permissions.mode & ~S_IFMT)) != 0 ||
+		 chown (info->devname, entry->u.permissions.uid, entry->u.permissions.gid) != 0)
+	{
+		msg_logger(LOG_ERR, "Can't chmod or chown: %s: %m",info->devname);
+	}
+}   /*  End Function action_permissions  */
+
+static void action_modload (const struct devfsd_notify_struct *info,
+			    const struct config_entry_struct *entry ATTRIBUTE_UNUSED)
+/*  [SUMMARY] Load a module.
+    <info> The devfs change.
+    <entry> The config file entry.
+    [RETURNS] Nothing.
+*/
+{
+	char *argv[6];
+	char device[STRING_LENGTH];
+
+	argv[0] = MODPROBE;
+	argv[1] = MODPROBE_SWITCH_1; /* "-k" */
+	argv[2] = MODPROBE_SWITCH_2; /* "-C" */
+	argv[3] = CONFIG_MODULES_DEVFS;
+	argv[4] = device;
+	argv[5] = NULL;
+
+	snprintf (device, sizeof (device), "/dev/%s", info->devname);
+	debug_msg_logger(LOG_INFO, "%s: %s %s %s %s %s",__FUNCTION__, argv[0],argv[1],argv[2],argv[3],argv[4]);
+	fork_and_execute(DIE, argv[0], argv);
+}  /*  End Function action_modload  */
+
+static void action_execute (const struct devfsd_notify_struct *info,
+			    const struct config_entry_struct *entry,
+			    const regmatch_t *regexpr, unsigned int numexpr)
+/*  [SUMMARY] Execute a programme.
+    <info> The devfs change.
+    <entry> The config file entry.
+    <regexpr> The number of subexpression (start, end) offsets within the
+    device name.
+    <numexpr> The number of elements within <<regexpr>>.
+    [RETURNS] Nothing.
+*/
+{
+	unsigned int count;
+	struct get_variable_info gv_info;
+	char *argv[MAX_ARGS + 1];
+	char largv[MAX_ARGS + 1][STRING_LENGTH];
+
+	debug_msg_logger(LOG_INFO ,__FUNCTION__);
+	gv_info.info = info;
+	gv_info.devname = info->devname;
+	snprintf (gv_info.devpath, sizeof (gv_info.devpath), "%s/%s", mount_point, info->devname);
+	for (count = 0; entry->u.execute.argv[count] != NULL; ++count)
+	{
+		expand_expression (largv[count], STRING_LENGTH,
+				entry->u.execute.argv[count],
+				get_variable, &gv_info,
+				gv_info.devname, regexpr, numexpr );
+		argv[count] = largv[count];
+	}
+	argv[count] = NULL;
+	fork_and_execute(NO_DIE, argv[0], argv);
+}   /*  End Function action_execute  */
+
+
+static void action_copy (const struct devfsd_notify_struct *info,
+			 const struct config_entry_struct *entry,
+			 const regmatch_t *regexpr, unsigned int numexpr)
+/*  [SUMMARY] Copy permissions.
+    <info> The devfs change.
+    <entry> The config file entry.
+    <regexpr> This list of subexpression (start, end) offsets within the
+    device name.
+    <numexpr> The number of elements in <<regexpr>>.
+    [RETURNS] Nothing.
+*/
+{
+	mode_t new_mode;
+	struct get_variable_info gv_info;
+	struct stat source_stat, dest_stat;
+	char source[STRING_LENGTH], destination[STRING_LENGTH];
+	int ret = 0;
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	dest_stat.st_mode = 0;
+
+	if ( (info->type == DEVFSD_NOTIFY_CHANGE) && S_ISLNK (info->mode) )
+		return;
+	gv_info.info = info;
+	gv_info.devname = info->devname;
+
+	snprintf (gv_info.devpath, sizeof (gv_info.devpath), "%s/%s", mount_point, info->devname);
+	expand_expression (source, STRING_LENGTH, entry->u.copy.source,
+				get_variable, &gv_info, gv_info.devname,
+				regexpr, numexpr);
+
+	expand_expression (destination, STRING_LENGTH, entry->u.copy.destination,
+				get_variable, &gv_info, gv_info.devname,
+				regexpr, numexpr);
+
+	if ( !make_dir_tree (destination) || lstat (source, &source_stat) != 0)
+			return;
+	lstat (destination, &dest_stat);
+	new_mode = source_stat.st_mode & ~S_ISVTX;
+	if (info->type == DEVFSD_NOTIFY_CREATE)
+		new_mode |= S_ISVTX;
+	else if ( (info->type == DEVFSD_NOTIFY_CHANGE) && (dest_stat.st_mode & S_ISVTX) )
+		new_mode |= S_ISVTX;
+	ret = copy_inode (destination, &dest_stat, new_mode, source, &source_stat);
+	if (ENABLE_DEBUG && ret && (errno != EEXIST))
+		debug_msg_logger(LOG_ERR, "copy_inode: %s to %s: %m", source, destination);
+	return;
+}   /*  End Function action_copy  */
+
+static void action_compat (const struct devfsd_notify_struct *info, unsigned int action)
+/*  [SUMMARY] Process a compatibility request.
+    <info> The devfs change.
+    <action> The action to take.
+    [RETURNS] Nothing.
+*/
+{
+	int ret;
+	const char *compat_name = NULL;
+	const char *dest_name = info->devname;
+	char *ptr=NULL;
+	char compat_buf[STRING_LENGTH], dest_buf[STRING_LENGTH];
+	int mode, host, bus, target, lun;
+	unsigned int i;
+	char rewind_;
+	/* 1 to 5  "scsi/" , 6 to 9 "ide/host" */
+	static const char *const fmt[] = {
+		NULL ,
+		"sg/c%db%dt%du%d",		/* scsi/generic */
+		"sd/c%db%dt%du%d",		/* scsi/disc */
+		"sr/c%db%dt%du%d",		/* scsi/cd */
+		"sd/c%db%dt%du%dp%d",		/* scsi/part */
+		"st/c%db%dt%du%dm%d%c",		/* scsi/mt */
+		"ide/hd/c%db%dt%du%d",		/* ide/host/disc */
+		"ide/cd/c%db%dt%du%d",		/* ide/host/cd */
+		"ide/hd/c%db%dt%du%dp%d",	/* ide/host/part */
+		"ide/mt/c%db%dt%du%d%s",	/* ide/host/mt */
+		NULL
+	};
+
+	/*  First construct compatibility name  */
+	switch (action)
+	{
+		case AC_MKOLDCOMPAT:
+		case AC_RMOLDCOMPAT:
+			compat_name = get_old_name (info->devname, info->namelen, compat_buf, info->major, info->minor);
+			break;
+		case AC_MKNEWCOMPAT:
+		case AC_RMNEWCOMPAT:
+			ptr = strrchr (info->devname, '/') + 1;
+			i=scan_dev_name(info->devname, info->namelen, ptr);
+
+			debug_msg_logger(LOG_INFO, "%s: scan_dev_name = %d", __FUNCTION__, i);
+
+			/* nothing found */
+			if(i==0 || i > 9)
+				return;
+
+			sscanf (info->devname +((i<6)?5:4), "host%d/bus%d/target%d/lun%d/", &host, &bus, &target, &lun);
+			snprintf (dest_buf, sizeof (dest_buf), "../%s", info->devname + ((i>5)?4:0));
+			dest_name = dest_buf;
+			compat_name = compat_buf;
+
+
+			/* 1 == scsi/generic  2 == scsi/disc 3 == scsi/cd 6 == ide/host/disc 7 == ide/host/cd */
+			if( i == 1 || i == 2 || i == 3 || i == 6 || i ==7 )
+				sprintf ( compat_buf, fmt[i], host, bus, target, lun);
+
+			/* 4 == scsi/part 8 == ide/host/part */
+			if( i == 4 || i == 8)
+				sprintf ( compat_buf, fmt[i], host, bus, target, lun, atoi (ptr + 4) );
+
+			/* 5 == scsi/mt */
+			if( i == 5)
+			{
+				rewind_ = info->devname[info->namelen - 1];
+				if (rewind_ != 'n')
+					rewind_ = '\0';
+				mode=0;
+				if(ptr[2] ==  'l' /*108*/ || ptr[2] == 'm'/*109*/)
+					mode = ptr[2] - 107; /* 1 or 2 */
+				if(ptr[2] ==  'a')
+					mode = 3;
+				sprintf (compat_buf, fmt [i], host, bus, target, lun, mode, rewind_);
+			}
+
+			/* 9 == ide/host/mt */
+			if( i ==  9 )
+				snprintf (compat_buf, sizeof (compat_buf), fmt[i], host, bus, target, lun, ptr + 2);
+		/* esac */
+	} /* switch(action) */
+
+	if(compat_name == NULL )
+		return;
+
+	debug_msg_logger( LOG_INFO, "%s: %s", __FUNCTION__, compat_name);
+
+	/*  Now decide what to do with it  */
+	switch (action)
+	{
+		case AC_MKOLDCOMPAT:
+		case AC_MKNEWCOMPAT:
+			mksymlink (dest_name, compat_name);
+			break;
+		case AC_RMOLDCOMPAT:
+		case AC_RMNEWCOMPAT:
+			ret = unlink (compat_name);
+			if (ENABLE_DEBUG && ret)
+				debug_msg_logger(LOG_ERR, "unlink: %s: %m", compat_name);
+			break;
+		/*esac*/
+	} /* switch(action) */
+}   /*  End Function action_compat  */
+
+static void restore(char *spath, struct stat source_stat, int rootlen)
+{
+	char dpath[STRING_LENGTH];
+	struct stat dest_stat;
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	dest_stat.st_mode = 0;
+	snprintf (dpath, sizeof dpath, "%s%s", mount_point, spath + rootlen);
+	lstat (dpath, &dest_stat);
+
+	if ( S_ISLNK (source_stat.st_mode) || (source_stat.st_mode & S_ISVTX) )
+		copy_inode (dpath, &dest_stat, (source_stat.st_mode & ~S_ISVTX) , spath, &source_stat);
+
+	if ( S_ISDIR (source_stat.st_mode) )
+		dir_operation(RESTORE, spath, rootlen,NULL);
+}
+
+
+static int copy_inode (const char *destpath, const struct stat *dest_stat,
+			mode_t new_mode,
+			const char *sourcepath, const struct stat *source_stat)
+/*  [SUMMARY] Copy an inode.
+    <destpath> The destination path. An existing inode may be deleted.
+    <dest_stat> The destination stat(2) information.
+    <new_mode> The desired new mode for the destination.
+    <sourcepath> The source path.
+    <source_stat> The source stat(2) information.
+    [RETURNS] TRUE on success, else FALSE.
+*/
+{
+	int source_len, dest_len;
+	char source_link[STRING_LENGTH], dest_link[STRING_LENGTH];
+	int fd, val;
+	struct sockaddr_un un_addr;
+	char symlink_val[STRING_LENGTH];
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	if ( (source_stat->st_mode & S_IFMT) == (dest_stat->st_mode & S_IFMT) )
+	{
+		/*  Same type  */
+		if ( S_ISLNK (source_stat->st_mode) )
+		{
+			if (( source_len = readlink (sourcepath, source_link, STRING_LENGTH - 1) ) < 0 ||
+				( dest_len   = readlink (destpath  , dest_link  , STRING_LENGTH - 1) ) < 0 )
+				return (FALSE);
+			source_link[source_len]	= '\0';
+			dest_link[dest_len]	= '\0';
+			if ( (source_len != dest_len) || (strcmp (source_link, dest_link) != 0) )
+			{
+				unlink (destpath);
+				symlink (source_link, destpath);
+			}
+			return (TRUE);
+		}   /*  Else not a symlink  */
+		chmod (destpath, new_mode & ~S_IFMT);
+		chown (destpath, source_stat->st_uid, source_stat->st_gid);
+		return (TRUE);
+	}
+	/*  Different types: unlink and create  */
+	unlink (destpath);
+	switch (source_stat->st_mode & S_IFMT)
+	{
+		case S_IFSOCK:
+			if ( ( fd = socket (AF_UNIX, SOCK_STREAM, 0) ) < 0 )
+				break;
+			un_addr.sun_family = AF_UNIX;
+			snprintf (un_addr.sun_path, sizeof (un_addr.sun_path), "%s", destpath);
+			val = bind (fd, (struct sockaddr *) &un_addr, (int) sizeof un_addr);
+			close (fd);
+			if (val != 0 || chmod (destpath, new_mode & ~S_IFMT) != 0)
+				break;
+			goto do_chown;
+		case S_IFLNK:
+			if ( ( val = readlink (sourcepath, symlink_val, STRING_LENGTH - 1) ) < 0 )
+				break;
+			symlink_val[val] = '\0';
+			if (symlink (symlink_val, destpath) == 0)
+				return (TRUE);
+			break;
+		case S_IFREG:
+			if ( ( fd = open (destpath, O_RDONLY | O_CREAT, new_mode & ~S_IFMT) ) < 0 )
+				break;
+			close (fd);
+			if (chmod (destpath, new_mode & ~S_IFMT) != 0)
+				break;
+			goto do_chown;
+		case S_IFBLK:
+		case S_IFCHR:
+		case S_IFIFO:
+			if (mknod (destpath, new_mode, source_stat->st_rdev) != 0)
+				break;
+			goto do_chown;
+		case S_IFDIR:
+			if (mkdir (destpath, new_mode & ~S_IFMT) != 0)
+				break;
+do_chown:
+			if (chown (destpath, source_stat->st_uid, source_stat->st_gid) == 0)
+				return (TRUE);
+		/*break;*/
+	}
+	return (FALSE);
+}   /*  End Function copy_inode  */
+
+static void free_config (void)
+/*  [SUMMARY] Free the configuration information.
+    [RETURNS] Nothing.
+*/
+{
+	struct config_entry_struct *c_entry;
+	void *next;
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	for (c_entry = first_config; c_entry != NULL; c_entry = next)
+	{
+		unsigned int count;
+
+		next = c_entry->next;
+		regfree (&c_entry->preg);
+		if (c_entry->action.what == AC_EXECUTE)
+		{
+			for (count = 0; count < MAX_ARGS; ++count)
+			{
+				if (c_entry->u.execute.argv[count] == NULL)
+					break;
+				free (c_entry->u.execute.argv[count]);
+			}
+		}
+		free (c_entry);
+	}
+	first_config = NULL;
+	last_config = NULL;
+}   /*  End Function free_config  */
+
+static int get_uid_gid (int flag, const char *string)
+/*  [SUMMARY] Convert a string to a UID or GID value.
+	<flag> "UID" or "GID".
+	<string> The string.
+    [RETURNS] The UID or GID value.
+*/
+{
+	struct passwd *pw_ent;
+	struct group *grp_ent;
+	static char *msg;
+
+	if (ENABLE_DEVFSD_VERBOSE)
+		msg="user";
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	if(ENABLE_DEBUG && flag != UID && flag != GID)
+		msg_logger_and_die(LOG_ERR,"%s: flag != UID && flag != GID", __FUNCTION__);
+
+	if ( isdigit (string[0]) || ( (string[0] == '-') && isdigit (string[1]) ) )
+		return atoi (string);
+
+	if ( flag == UID && ( pw_ent  = getpwnam (string) ) != NULL )
+		return (pw_ent->pw_uid);
+
+	if ( flag == GID && ( grp_ent = getgrnam (string) ) != NULL )
+		return (grp_ent->gr_gid);
+	else if(ENABLE_DEVFSD_VERBOSE)
+		msg="group";
+
+	if(ENABLE_DEVFSD_VERBOSE)
+		msg_logger(LOG_ERR,"unknown %s: %s, defaulting to %cid=0",  msg, string, msg[0]);
+	return (0);
+}/*  End Function get_uid_gid  */
+
+static mode_t get_mode (const char *string)
+/*  [SUMMARY] Convert a string to a mode value.
+    <string> The string.
+    [RETURNS] The mode value.
+*/
+{
+	mode_t mode;
+	int i;
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	if ( isdigit (string[0]) )
+		return strtoul (string, NULL, 8);
+	if (strlen (string) != 9)
+		msg_logger_and_die(LOG_ERR, "bad mode: %s", string);
+
+	mode = 0;
+	i= S_IRUSR;
+	while(i>0)
+	{
+		if(string[0]=='r'||string[0]=='w'||string[0]=='x')
+			mode+=i;
+		i=i/2;
+		string++;
+	}
+	return (mode);
+}   /*  End Function get_mode  */
+
+static void signal_handler (int sig)
+{
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	caught_signal = TRUE;
+	if (sig == SIGHUP)
+		caught_sighup = TRUE;
+
+	msg_logger(LOG_INFO, "Caught signal %d", sig);
+}   /*  End Function signal_handler  */
+
+static const char *get_variable (const char *variable, void *info)
+{
+	struct get_variable_info *gv_info = info;
+	static char hostname[STRING_LENGTH], sbuf[STRING_LENGTH];
+	const char *field_names[] = { "hostname", "mntpt", "devpath", "devname",
+								   "uid", "gid", "mode", hostname, mount_point,
+								   gv_info->devpath, gv_info->devname, 0 };
+	int i;
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	if (gethostname (hostname, STRING_LENGTH - 1) != 0)
+		msg_logger_and_die(LOG_ERR, "gethostname: %m");
+
+		/* Here on error we should do exit(RV_SYS_ERROR), instead we do exit(EXIT_FAILURE) */
+		hostname[STRING_LENGTH - 1] = '\0';
+
+	/* compare_string_array returns i>=0  */
+	i=compare_string_array(field_names, variable);
+
+	if ( i > 6 || i < 0 || (i > 1 && gv_info == NULL))
+			return (NULL);
+	if( i >= 0 && i <= 3)
+	{
+		debug_msg_logger(LOG_INFO, "%s: i=%d %s", __FUNCTION__, i ,field_names[i+7]);
+		return(field_names[i+7]);
+	}
+
+	if(i == 4 )
+		sprintf (sbuf, "%u", gv_info->info->uid);
+	else if(i == 5)
+		sprintf (sbuf, "%u", gv_info->info->gid);
+	else if(i == 6)
+		sprintf (sbuf, "%o", gv_info->info->mode);
+
+	debug_msg_logger(LOG_INFO, "%s: %s", __FUNCTION__, sbuf);
+
+	return (sbuf);
+}   /*  End Function get_variable  */
+
+static void service(struct stat statbuf, char *path)
+{
+	struct devfsd_notify_struct info;
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	memset (&info, 0, sizeof info);
+	info.type = DEVFSD_NOTIFY_REGISTERED;
+	info.mode = statbuf.st_mode;
+	info.major = major (statbuf.st_rdev);
+	info.minor = minor (statbuf.st_rdev);
+	info.uid = statbuf.st_uid;
+	info.gid = statbuf.st_gid;
+	snprintf (info.devname, sizeof (info.devname), "%s", path + strlen (mount_point) + 1);
+	info.namelen = strlen (info.devname);
+	service_name (&info);
+	if ( S_ISDIR (statbuf.st_mode) )
+		dir_operation(SERVICE,path,0,NULL);
+}
+
+static void dir_operation(int type, const char * dir_name, int var, unsigned long *event_mask)
+/*  [SUMMARY] Scan a directory tree and generate register events on leaf nodes.
+	<flag> To choose which function to perform
+	<dp> The directory pointer. This is closed upon completion.
+    <dir_name> The name of the directory.
+	<rootlen> string length parameter.
+    [RETURNS] Nothing.
+*/
+{
+	struct stat statbuf;
+	DIR *dp;
+	struct dirent *de;
+	char path[STRING_LENGTH];
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	if((dp = opendir( dir_name))==NULL)
+	{
+		debug_msg_logger(LOG_ERR, "opendir: %s: %m", dir_name);
+		return;
+	}
+
+	while ( (de = readdir (dp) ) != NULL )
+	{
+
+		if(de->d_name && *de->d_name == '.' && (!de->d_name[1] || (de->d_name[1] == '.' && !de->d_name[2])))
+			continue;
+		snprintf (path, sizeof (path), "%s/%s", dir_name, de->d_name);
+		debug_msg_logger(LOG_ERR, "%s: %s", __FUNCTION__, path);
+
+		if (lstat (path, &statbuf) != 0)
+		{
+			debug_msg_logger(LOG_ERR, "%s: %s: %m", __FUNCTION__, path);
+			continue;
+		}
+		switch(type)
+		{
+			case SERVICE:
+				service(statbuf,path);
+				break;
+			case RESTORE:
+				restore(path, statbuf, var);
+				break;
+			case READ_CONFIG:
+				read_config_file (path, var, event_mask);
+				break;
+		}
+	}
+	closedir (dp);
+}   /*  End Function do_scan_and_service  */
+
+static int mksymlink (const char *oldpath, const char *newpath)
+/*  [SUMMARY] Create a symlink, creating intervening directories as required.
+    <oldpath> The string contained in the symlink.
+    <newpath> The name of the new symlink.
+    [RETURNS] 0 on success, else -1.
+*/
+{
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	if ( !make_dir_tree (newpath) )
+		return (-1);
+
+	if (symlink (oldpath, newpath) != 0)
+    {
+		if (errno != EEXIST)
+		{
+			debug_msg_logger(LOG_ERR, "%s: %s to %s: %m", __FUNCTION__, oldpath, newpath);
+			return (-1);
+		}
+	}
+    return (0);
+}   /*  End Function mksymlink  */
+
+
+static int make_dir_tree (const char *path)
+/*  [SUMMARY] Creating intervening directories for a path as required.
+    <path> The full pathname (including the leaf node).
+    [RETURNS] TRUE on success, else FALSE.
+*/
+{
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	if (bb_make_directory( dirname((char *)path), -1, FILEUTILS_RECUR )==-1)
+	{
+		debug_msg_logger(LOG_ERR, "%s: %s: %m",__FUNCTION__, path);
+		return (FALSE);
+	}
+	return(TRUE);
+} /*  End Function make_dir_tree  */
+
+static int expand_expression(char *output, unsigned int outsize,
+			      const char *input,
+			      const char *(*get_variable_func)(const char *variable, void *info),
+			      void *info,
+			      const char *devname,
+			      const regmatch_t *ex, unsigned int numexp)
+/*  [SUMMARY] Expand environment variables and regular subexpressions in string.
+    <output> The output expanded expression is written here.
+    <length> The size of the output buffer.
+    <input> The input expression. This may equal <<output>>.
+    <get_variable> A function which will be used to get variable values. If
+    this returns NULL, the environment is searched instead. If this is NULL,
+    only the environment is searched.
+    <info> An arbitrary pointer passed to <<get_variable>>.
+    <devname> Device name; specifically, this is the string that contains all
+    of the regular subexpressions.
+    <ex> Array of start / end offsets into info->devname for each subexpression
+    <numexp> Number of regular subexpressions found in <<devname>>.
+    [RETURNS] TRUE on success, else FALSE.
+*/
+{
+	char temp[STRING_LENGTH];
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	if ( !st_expr_expand (temp, STRING_LENGTH, input, get_variable_func, info) )
+		return (FALSE);
+	expand_regexp (output, outsize, temp, devname, ex, numexp);
+	return (TRUE);
+}   /*  End Function expand_expression  */
+
+static void expand_regexp (char *output, size_t outsize, const char *input,
+			   const char *devname,
+			   const regmatch_t *ex, unsigned int numex )
+/*  [SUMMARY] Expand all occurrences of the regular subexpressions \0 to \9.
+    <output> The output expanded expression is written here.
+    <outsize> The size of the output buffer.
+    <input> The input expression. This may NOT equal <<output>>, because
+    supporting that would require yet another string-copy. However, it's not
+    hard to write a simple wrapper function to add this functionality for those
+    few cases that need it.
+    <devname> Device name; specifically, this is the string that contains all
+    of the regular subexpressions.
+    <ex> An array of start and end offsets into <<devname>>, one for each
+    subexpression
+    <numex> Number of subexpressions in the offset-array <<ex>>.
+    [RETURNS] Nothing.
+*/
+{
+	const char last_exp = '0' - 1 + numex;
+	int c = -1;
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	/*  Guarantee NULL termination by writing an explicit '\0' character into
+	the very last byte  */
+	if (outsize)
+		output[--outsize] = '\0';
+	/*  Copy the input string into the output buffer, replacing '\\' with '\'
+	and '\0' .. '\9' with subexpressions 0 .. 9, if they exist. Other \x
+	codes are deleted  */
+	while ( (c != '\0') && (outsize != 0) )
+	{
+		c = *input;
+		++input;
+		if (c == '\\')
+		{
+			c = *input;
+			++input;
+			if (c != '\\')
+			{
+				if ((c >= '0') && (c <= last_exp))
+				{
+					const regmatch_t *subexp = ex + (c - '0');
+					unsigned int sublen = subexp->rm_eo - subexp->rm_so;
+
+					/*  Range checking  */
+					if (sublen > outsize)
+						sublen = outsize;
+					strncpy (output, devname + subexp->rm_so, sublen);
+					output += sublen;
+					outsize -= sublen;
+				}
+				continue;
+			}
+		}
+		*output = c;
+		++output;
+		--outsize;
+	} /* while */
+}   /*  End Function expand_regexp  */
+
+
+/* from compat_name.c */
+
+struct translate_struct
+{
+	char *match;    /*  The string to match to (up to length)                */
+	char *format;   /*  Format of output, "%s" takes data past match string,
+			NULL is effectively "%s" (just more efficient)       */
+};
+
+static struct translate_struct translate_table[] =
+{
+	{"sound/",     NULL},
+	{"printers/",  "lp%s"},
+	{"v4l/",       NULL},
+	{"parports/",  "parport%s"},
+	{"fb/",        "fb%s"},
+	{"netlink/",   NULL},
+	{"loop/",      "loop%s"},
+	{"floppy/",    "fd%s"},
+	{"rd/",        "ram%s"},
+	{"md/",        "md%s"},         /*  Meta-devices                         */
+	{"vc/",        "tty%s"},
+	{"misc/",      NULL},
+	{"isdn/",      NULL},
+	{"pg/",        "pg%s"},         /*  Parallel port generic ATAPI interface*/
+	{"i2c/",       "i2c-%s"},
+	{"staliomem/", "staliomem%s"},  /*  Stallion serial driver control       */
+	{"tts/E",      "ttyE%s"},       /*  Stallion serial driver               */
+	{"cua/E",      "cue%s"},        /*  Stallion serial driver callout       */
+	{"tts/R",      "ttyR%s"},       /*  Rocketport serial driver             */
+	{"cua/R",      "cur%s"},        /*  Rocketport serial driver callout     */
+	{"ip2/",       "ip2%s"},        /*  Computone serial driver control      */
+	{"tts/F",      "ttyF%s"},       /*  Computone serial driver              */
+	{"cua/F",      "cuf%s"},        /*  Computone serial driver callout      */
+	{"tts/C",      "ttyC%s"},       /*  Cyclades serial driver               */
+	{"cua/C",      "cub%s"},        /*  Cyclades serial driver callout       */
+	{"tts/",       "ttyS%s"},       /*  Generic serial: must be after others */
+	{"cua/",       "cua%s"},        /*  Generic serial: must be after others */
+	{"input/js",   "js%s"},         /*  Joystick driver                      */
+	{NULL,         NULL}
+};
+
+const char *get_old_name (const char *devname, unsigned int namelen,
+			  char *buffer, unsigned int major, unsigned int minor)
+/*  [SUMMARY] Translate a kernel-supplied name into an old name.
+    <devname> The device name provided by the kernel.
+    <namelen> The length of the name.
+    <buffer> A buffer that may be used. This should be at least 128 bytes long.
+    <major> The major number for the device.
+    <minor> The minor number for the device.
+    [RETURNS] A pointer to the old name if known, else NULL.
+*/
+{
+	const char *compat_name = NULL;
+	char *ptr;
+	struct translate_struct *trans;
+	unsigned int i;
+	char mode;
+	int indexx;
+	const char *pty1;
+	const char *pty2;
+	size_t len;
+	/* 1 to 5  "scsi/" , 6 to 9 "ide/host", 10 sbp/, 11 vcc/, 12 pty/ */
+	static const char *const fmt[] = {
+		NULL ,
+		"sg%u",			/* scsi/generic */
+		NULL,			/* scsi/disc */
+		"sr%u",			/* scsi/cd */
+		NULL,			/* scsi/part */
+		"nst%u%c",		/* scsi/mt */
+		"hd%c"	,		/* ide/host/disc */
+		"hd%c"	,		/* ide/host/cd */
+		"hd%c%s",		/* ide/host/part */
+		"%sht%d",		/* ide/host/mt */
+		"sbpcd%u",		/* sbp/ */
+		"vcs%s",		/* vcc/ */
+		"%cty%c%c",		/* pty/ */
+		NULL
+	};
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	for (trans = translate_table; trans->match != NULL; ++trans)
+	{
+		 len = strlen (trans->match);
+
+		if (strncmp (devname, trans->match, len) == 0)
+		{
+			if (trans->format == NULL)
+				return (devname + len);
+			sprintf (buffer, trans->format, devname + len);
+			return (buffer);
+		}
+	}
+
+	ptr = (strrchr (devname, '/') + 1);
+	i = scan_dev_name(devname, namelen, ptr);
+
+	if( i > 0 && i < 13)
+		compat_name = buffer;
+	else
+		return NULL;
+
+	debug_msg_logger(LOG_INFO, "%s: scan_dev_name = %d", __FUNCTION__, i);
+
+	/* 1 == scsi/generic, 3 == scsi/cd, 10 == sbp/ */
+	if( i == 1 || i == 3 || i == 10 )
+		sprintf (buffer, fmt[i], minor);
+
+	/* 2 ==scsi/disc, 4 == scsi/part */
+	if( i == 2 || i == 4)
+		compat_name = write_old_sd_name (buffer, major, minor,((i == 2)?"":(ptr + 4)));
+
+	/* 5 == scsi/mt */
+	if( i == 5)
+	{
+		mode = ptr[2];
+		if (mode == 'n')
+			mode = '\0';
+		sprintf (buffer, fmt[i], minor & 0x1f, mode);
+		if (devname[namelen - 1] != 'n')
+			++compat_name;
+	}
+	/* 6 == ide/host/disc, 7 == ide/host/cd, 8 == ide/host/part */
+	if( i == 6 || i == 7 || i == 8 )
+		/* last arg should be ignored for i == 6 or i== 7 */
+		sprintf (buffer, fmt[i] , get_old_ide_name (major, minor), ptr + 4);
+
+	/* 9 ==  ide/host/mt */
+	if( i == 9 )
+		sprintf (buffer, fmt[i], ptr + 2, minor & 0x7f);
+
+	/*  11 == vcc/ */
+	if( i == 11 )
+	{
+		sprintf (buffer, fmt[i], devname + 4);
+		if (buffer[3] == '0')
+			buffer[3] = '\0';
+	}
+	/* 12 ==  pty/ */
+	if( i == 12 )
+	{
+		pty1 = "pqrstuvwxyzabcde";
+		pty2 = "0123456789abcdef";
+		indexx = atoi (devname + 5);
+		sprintf (buffer, fmt[i], (devname[4] == 'm') ? 'p' : 't', pty1[indexx >> 4], pty2[indexx & 0x0f]);
+	}
+
+	if(ENABLE_DEBUG && compat_name!=NULL)
+		msg_logger(LOG_INFO, "%s: compat_name  %s", __FUNCTION__, compat_name);
+
+	return (compat_name);
+}   /*  End Function get_old_name  */
+
+static char get_old_ide_name (unsigned int major, unsigned int minor)
+/*  [SUMMARY] Get the old IDE name for a device.
+    <major> The major number for the device.
+    <minor> The minor number for the device.
+    [RETURNS] The drive letter.
+*/
+{
+	char letter='y';	/* 121 */
+	char c='a';		/*  97 */
+	int i=IDE0_MAJOR;
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	/* I hope it works like the previous code as it saves a few bytes. Tito ;P */
+	do {
+		if(	i==IDE0_MAJOR || i==IDE1_MAJOR || i==IDE2_MAJOR ||
+			i==IDE3_MAJOR || i==IDE4_MAJOR || i==IDE5_MAJOR ||
+			i==IDE6_MAJOR || i==IDE7_MAJOR || i==IDE8_MAJOR ||
+			i==IDE9_MAJOR )
+		{
+			if((unsigned int)i==major)
+			{
+				letter=c;
+				break;
+			}
+			c+=2;
+		}
+		i++;
+	} while(i<=IDE9_MAJOR);
+
+	if (minor > 63)
+		++letter;
+	return (letter);
+}   /*  End Function get_old_ide_name  */
+
+static char *write_old_sd_name (char *buffer,
+				unsigned int major, unsigned int minor,
+				char *part)
+/*  [SUMMARY] Write the old SCSI disc name to a buffer.
+    <buffer> The buffer to write to.
+    <major> The major number for the device.
+    <minor> The minor number for the device.
+    <part> The partition string. Must be "" for a whole-disc entry.
+    [RETURNS] A pointer to the buffer on success, else NULL.
+*/
+{
+	unsigned int disc_index;
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	if (major == 8)
+	{
+		sprintf (buffer, "sd%c%s", 'a' + (minor >> 4), part);
+		return (buffer);
+	}
+	if ( (major > 64) && (major < 72) )
+	{
+		disc_index = ( (major - 64) << 4 ) + (minor >> 4);
+		if (disc_index < 26)
+			sprintf (buffer, "sd%c%s", 'a' + disc_index, part);
+		else
+			sprintf (buffer, "sd%c%c%s", 'a' + (disc_index / 26) - 1, 'a' + disc_index % 26,part);
+		return (buffer);
+	}
+	return (NULL);
+}   /*  End Function write_old_sd_name  */
+
+
+/*  expression.c */
+
+/*EXPERIMENTAL_FUNCTION*/
+
+int st_expr_expand (char *output, unsigned int length, const char *input,
+		     const char *(*get_variable_func) (const char *variable,
+						  void *info),
+		     void *info)
+/*  [SUMMARY] Expand an expression using Borne Shell-like unquoted rules.
+    <output> The output expanded expression is written here.
+    <length> The size of the output buffer.
+    <input> The input expression. This may equal <<output>>.
+    <get_variable> A function which will be used to get variable values. If
+    this returns NULL, the environment is searched instead. If this is NULL,
+    only the environment is searched.
+    <info> An arbitrary pointer passed to <<get_variable>>.
+    [RETURNS] TRUE on success, else FALSE.
+*/
+{
+	char ch;
+	unsigned int len;
+	unsigned int out_pos = 0;
+	const char *env;
+	const char *ptr;
+	struct passwd *pwent;
+	char buffer[BUFFER_SIZE], tmp[STRING_LENGTH];
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	if (length > BUFFER_SIZE)
+		length = BUFFER_SIZE;
+	for (; TRUE; ++input)
+	{
+		switch (ch = *input)
+		{
+			case '$':
+				/*  Variable expansion  */
+				input = expand_variable (buffer, length, &out_pos, ++input, get_variable_func, info);
+				if (input == NULL)
+					return (FALSE);
+				break;
+			case '~':
+				/*  Home directory expansion  */
+				ch = input[1];
+				if ( isspace (ch) || (ch == '/') || (ch == '\0') )
+				{
+					/* User's own home directory: leave separator for next time */
+					if ( ( env = getenv ("HOME") ) == NULL )
+					{
+						msg_logger(LOG_INFO, bb_msg_variable_not_found, "HOME");
+						return (FALSE);
+					}
+					len = strlen (env);
+					if (len + out_pos >= length)
+						goto st_expr_expand_out;
+					memcpy (buffer + out_pos, env, len + 1);
+					out_pos += len;
+					continue;
+				}
+				/*  Someone else's home directory  */
+				for (ptr = ++input; !isspace (ch) && (ch != '/') && (ch != '\0'); ch = *++ptr)
+					/* VOID */ ;
+				len = ptr - input;
+				if (len >= sizeof tmp)
+					goto st_expr_expand_out;
+				safe_memcpy (tmp, input, len);
+				input = ptr - 1;
+				if ( ( pwent = getpwnam (tmp) ) == NULL )
+				{
+					msg_logger(LOG_INFO, "no pwent for: %s", tmp);
+					return (FALSE);
+				}
+				len = strlen (pwent->pw_dir);
+				if (len + out_pos >= length)
+					goto st_expr_expand_out;
+				memcpy (buffer + out_pos, pwent->pw_dir, len + 1);
+				out_pos += len;
+				break;
+			case '\0':
+			/* Falltrough */
+			default:
+				if (out_pos >= length)
+					goto st_expr_expand_out;
+				buffer[out_pos++] = ch;
+				if (ch == '\0')
+				{
+					memcpy (output, buffer, out_pos);
+					return (TRUE);
+				}
+				break;
+			/* esac */
+		}
+	}
+	return (FALSE);
+st_expr_expand_out:
+	msg_logger(LOG_INFO, bb_msg_small_buffer);
+	return (FALSE);
+}   /*  End Function st_expr_expand  */
+
+
+/*  Private functions follow  */
+
+static const char *expand_variable (char *buffer, unsigned int length,
+				    unsigned int *out_pos, const char *input,
+				    const char *(*func) (const char *variable,
+							 void *info),
+				    void *info)
+/*  [SUMMARY] Expand a variable.
+    <buffer> The buffer to write to.
+    <length> The length of the output buffer.
+    <out_pos> The current output position. This is updated.
+    <input> A pointer to the input character pointer.
+    <func> A function which will be used to get variable values. If this
+    returns NULL, the environment is searched instead. If this is NULL, only
+    the environment is searched.
+    <info> An arbitrary pointer passed to <<func>>.
+    <errfp> Diagnostic messages are written here.
+    [RETURNS] A pointer to the end of this subexpression on success, else NULL.
+*/
+{
+	char ch;
+	int len;
+	unsigned int open_braces;
+	const char *env, *ptr;
+	char tmp[STRING_LENGTH];
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	ch = input[0];
+	if (ch == '$')
+	{
+		/*  Special case for "$$": PID  */
+		sprintf ( tmp, "%d", (int) getpid () );
+		len = strlen (tmp);
+		if (len + *out_pos >= length)
+			goto expand_variable_out;
+
+		memcpy (buffer + *out_pos, tmp, len + 1);
+		out_pos += len;
+		return (input);
+	}
+	/*  Ordinary variable expansion, possibly in braces  */
+	if (ch != '{')
+	{
+		/*  Simple variable expansion  */
+		for (ptr = input; isalnum (ch) || (ch == '_') || (ch == ':');ch = *++ptr)
+			/* VOID */ ;
+		len = ptr - input;
+		if ((size_t)len >= sizeof tmp)
+			goto expand_variable_out;
+
+		safe_memcpy (tmp, input, len);
+		input = ptr - 1;
+		if ( ( env = get_variable_v2 (tmp, func, info) ) == NULL )
+		{
+			msg_logger(LOG_INFO, bb_msg_variable_not_found, tmp);
+			return (NULL);
+		}
+		len = strlen (env);
+		if (len + *out_pos >= length)
+			goto expand_variable_out;
+
+		memcpy (buffer + *out_pos, env, len + 1);
+		*out_pos += len;
+		return (input);
+	}
+	/*  Variable in braces: check for ':' tricks  */
+	ch = *++input;
+	for (ptr = input; isalnum (ch) || (ch == '_'); ch = *++ptr)
+		/* VOID */;
+	if (ch == '}')
+	{
+		/*  Must be simple variable expansion with "${var}"  */
+		len = ptr - input;
+		if ((size_t)len >= sizeof tmp)
+			goto expand_variable_out;
+
+		safe_memcpy (tmp, input, len);
+		ptr = expand_variable (buffer, length, out_pos, tmp, func, info );
+		if (ptr == NULL)
+			return (NULL);
+		return (input + len);
+	}
+	if (ch != ':' || ptr[1] != '-' )
+	{
+		msg_logger(LOG_INFO, "illegal char in var name");
+		return (NULL);
+	}
+	/*  It's that handy "${var:-word}" expression. Check if var is defined  */
+	len = ptr - input;
+	if ((size_t)len >= sizeof tmp)
+		goto expand_variable_out;
+
+	safe_memcpy (tmp, input, len);
+	/*  Move input pointer to ':'  */
+	input = ptr;
+	/*  First skip to closing brace, taking note of nested expressions  */
+	ptr += 2;
+	ch = ptr[0];
+	for (open_braces = 1; open_braces > 0; ch = *++ptr)
+	{
+		switch (ch)
+		{
+			case '{':
+				++open_braces;
+				break;
+			case '}':
+				--open_braces;
+				break;
+			case '\0':
+				msg_logger(LOG_INFO,"\"}\" not found in: %s", input);
+				return (NULL);
+			default:
+				break;
+		}
+	}
+	--ptr;
+	/*  At this point ptr should point to closing brace of "${var:-word}"  */
+	if ( ( env = get_variable_v2 (tmp, func, info) ) != NULL )
+	{
+		/*  Found environment variable, so skip the input to the closing brace
+			and return the variable  */
+		input = ptr;
+		len = strlen (env);
+		if (len + *out_pos >= length)
+			goto expand_variable_out;
+
+		memcpy (buffer + *out_pos, env, len + 1);
+		*out_pos += len;
+		return (input);
+	}
+	/*  Environment variable was not found, so process word. Advance input
+	pointer to start of word in "${var:-word}"  */
+	input += 2;
+	len = ptr - input;
+	if ((size_t)len >= sizeof tmp)
+		goto expand_variable_out;
+
+	safe_memcpy (tmp, input, len);
+	input = ptr;
+	if ( !st_expr_expand (tmp, STRING_LENGTH, tmp, func, info ) )
+		return (NULL);
+	len = strlen (tmp);
+	if (len + *out_pos >= length)
+		goto expand_variable_out;
+
+	memcpy (buffer + *out_pos, tmp, len + 1);
+	*out_pos += len;
+	return (input);
+expand_variable_out:
+	msg_logger(LOG_INFO, bb_msg_small_buffer);
+	return (NULL);
+}   /*  End Function expand_variable  */
+
+
+static const char *get_variable_v2 (const char *variable,
+				  const char *(*func) (const char *variable, void *info),
+				 void *info)
+/*  [SUMMARY] Get a variable from the environment or .
+    <variable> The variable name.
+    <func> A function which will be used to get the variable. If this returns
+    NULL, the environment is searched instead. If this is NULL, only the
+    environment is searched.
+    [RETURNS] The value of the variable on success, else NULL.
+*/
+{
+	const char *value;
+
+	debug_msg_logger(LOG_INFO, __FUNCTION__);
+
+	if (func != NULL)
+	{
+		value = (*func) (variable, info);
+		if (value != NULL)
+			return (value);
+	}
+	return getenv (variable);
+}   /*  End Function get_variable  */
+
+/* END OF CODE */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/eject.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/eject.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/eject.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,48 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * eject implementation for busybox
+ *
+ * Copyright (C) 2004  Peter Willis <psyphreak at phreaker.net>
+ * Copyright (C) 2005  Tito Ragusa <farmatito at tiscali.it>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+/*
+ * This is a simple hack of eject based on something Erik posted in #uclibc.
+ * Most of the dirty work blatantly ripped off from cat.c =)
+ */
+
+#include "busybox.h"
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <mntent.h>
+
+/* various defines swiped from linux/cdrom.h */
+#define CDROMCLOSETRAY            0x5319  /* pendant of CDROMEJECT  */
+#define CDROMEJECT                0x5309  /* Ejects the cdrom media */
+#define DEFAULT_CDROM             "/dev/cdrom"
+
+int eject_main(int argc, char **argv)
+{
+	unsigned long flags;
+	char *device;
+	struct mntent *m;
+
+	flags = bb_getopt_ulflags(argc, argv, "t");
+	device = argv[optind] ? : DEFAULT_CDROM;
+
+	if ((m = find_mount_point(device, bb_path_mtab_file))) {
+		if (umount(m->mnt_dir)) {
+			bb_error_msg_and_die("Can't umount");
+		} else if (ENABLE_FEATURE_MTAB_SUPPORT) {
+			erase_mtab(m->mnt_fsname);
+		}
+	}
+	if (ioctl(bb_xopen(device, (O_RDONLY | O_NONBLOCK)),
+				(flags ? CDROMCLOSETRAY : CDROMEJECT))) {
+		bb_perror_msg_and_die("%s", device);
+	}
+	return (EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/hdparm.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/hdparm.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/hdparm.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2198 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * hdparm implementation for busybox
+ *
+ * Copyright (C) [2003] by [Matteo Croce] <3297627799 at wind.it>
+ * Hacked by Tito <farmatito at tiscali.it> for size optimization.
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ * This program is based on the source code of hdparm: see below...
+ * hdparm.c - Command line interface to get/set hard disk parameters
+ *          - by Mark Lord (C) 1994-2002 -- freely distributable
+ */
+
+#include "busybox.h"
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/ioctl.h>
+#include <sys/sysmacros.h>
+#include <sys/times.h>
+#include <sys/mman.h>
+#include <linux/types.h>
+#include <linux/hdreg.h>
+
+#if BB_BIG_ENDIAN && !defined(__USE_XOPEN)
+# define __USE_XOPEN
+#endif
+#include <unistd.h>
+
+/* device types */
+/* ------------ */
+#define NO_DEV                  0xffff
+#define ATA_DEV                 0x0000
+#define ATAPI_DEV               0x0001
+
+/* word definitions */
+/* ---------------- */
+#define GEN_CONFIG		0   /* general configuration */
+#define LCYLS			1   /* number of logical cylinders */
+#define CONFIG			2   /* specific configuration */
+#define LHEADS			3   /* number of logical heads */
+#define TRACK_BYTES		4   /* number of bytes/track (ATA-1) */
+#define SECT_BYTES		5   /* number of bytes/sector (ATA-1) */
+#define LSECTS			6   /* number of logical sectors/track */
+#define START_SERIAL            10  /* ASCII serial number */
+#define LENGTH_SERIAL           10  /* 10 words (20 bytes or characters) */
+#define BUF_TYPE		20  /* buffer type (ATA-1) */
+#define BUFFER__SIZE		21  /* buffer size (ATA-1) */
+#define RW_LONG			22  /* extra bytes in R/W LONG cmd ( < ATA-4)*/
+#define START_FW_REV            23  /* ASCII firmware revision */
+#define LENGTH_FW_REV		 4  /*  4 words (8 bytes or characters) */
+#define START_MODEL		27  /* ASCII model number */
+#define LENGTH_MODEL		20  /* 20 words (40 bytes or characters) */
+#define SECTOR_XFER_MAX	        47  /* r/w multiple: max sectors xfered */
+#define DWORD_IO		48  /* can do double-word IO (ATA-1 only) */
+#define CAPAB_0			49  /* capabilities */
+#define CAPAB_1			50
+#define PIO_MODE		51  /* max PIO mode supported (obsolete)*/
+#define DMA_MODE		52  /* max Singleword DMA mode supported (obs)*/
+#define WHATS_VALID		53  /* what fields are valid */
+#define LCYLS_CUR		54  /* current logical cylinders */
+#define LHEADS_CUR		55  /* current logical heads */
+#define LSECTS_CUR	        56  /* current logical sectors/track */
+#define CAPACITY_LSB		57  /* current capacity in sectors */
+#define CAPACITY_MSB		58
+#define SECTOR_XFER_CUR		59  /* r/w multiple: current sectors xfered */
+#define LBA_SECTS_LSB		60  /* LBA: total number of user */
+#define LBA_SECTS_MSB		61  /*      addressable sectors */
+#define SINGLE_DMA		62  /* singleword DMA modes */
+#define MULTI_DMA		63  /* multiword DMA modes */
+#define ADV_PIO_MODES		64  /* advanced PIO modes supported */
+				    /* multiword DMA xfer cycle time: */
+#define DMA_TIME_MIN		65  /*   - minimum */
+#define DMA_TIME_NORM		66  /*   - manufacturer's recommended	*/
+				    /* minimum PIO xfer cycle time: */
+#define PIO_NO_FLOW		67  /*   - without flow control */
+#define PIO_FLOW		68  /*   - with IORDY flow control */
+#define PKT_REL			71  /* typical #ns from PKT cmd to bus rel */
+#define SVC_NBSY		72  /* typical #ns from SERVICE cmd to !BSY */
+#define CDR_MAJOR		73  /* CD ROM: major version number */
+#define CDR_MINOR		74  /* CD ROM: minor version number */
+#define QUEUE_DEPTH		75  /* queue depth */
+#define MAJOR			80  /* major version number */
+#define MINOR			81  /* minor version number */
+#define CMDS_SUPP_0		82  /* command/feature set(s) supported */
+#define CMDS_SUPP_1		83
+#define CMDS_SUPP_2		84
+#define CMDS_EN_0		85  /* command/feature set(s) enabled */
+#define CMDS_EN_1		86
+#define CMDS_EN_2		87
+#define ULTRA_DMA		88  /* ultra DMA modes */
+				    /* time to complete security erase */
+#define ERASE_TIME		89  /*   - ordinary */
+#define ENH_ERASE_TIME		90  /*   - enhanced */
+#define ADV_PWR			91  /* current advanced power management level
+				       in low byte, 0x40 in high byte. */
+#define PSWD_CODE		92  /* master password revision code	*/
+#define HWRST_RSLT		93  /* hardware reset result */
+#define ACOUSTIC		94  /* acoustic mgmt values ( >= ATA-6) */
+#define LBA_LSB			100 /* LBA: maximum.  Currently only 48 */
+#define LBA_MID			101 /*      bits are used, but addr 103 */
+#define LBA_48_MSB		102 /*      has been reserved for LBA in */
+#define LBA_64_MSB		103 /*      the future. */
+#define RM_STAT			127 /* removable media status notification feature set support */
+#define SECU_STATUS		128 /* security status */
+#define CFA_PWR_MODE		160 /* CFA power mode 1 */
+#define START_MEDIA             176 /* media serial number */
+#define LENGTH_MEDIA            20  /* 20 words (40 bytes or characters)*/
+#define START_MANUF             196 /* media manufacturer I.D. */
+#define LENGTH_MANUF            10  /* 10 words (20 bytes or characters) */
+#define INTEGRITY		255 /* integrity word */
+
+/* bit definitions within the words */
+/* -------------------------------- */
+
+/* many words are considered valid if bit 15 is 0 and bit 14 is 1 */
+#define VALID			0xc000
+#define VALID_VAL		0x4000
+/* many words are considered invalid if they are either all-0 or all-1 */
+#define NOVAL_0			0x0000
+#define NOVAL_1			0xffff
+
+/* word 0: gen_config */
+#define NOT_ATA			0x8000
+#define NOT_ATAPI		0x4000	/* (check only if bit 15 == 1) */
+#define MEDIA_REMOVABLE		0x0080
+#define DRIVE_NOT_REMOVABLE	0x0040  /* bit obsoleted in ATA 6 */
+#define INCOMPLETE		0x0004
+#define CFA_SUPPORT_VAL		0x848a	/* 848a=CFA feature set support */
+#define DRQ_RESPONSE_TIME	0x0060
+#define DRQ_3MS_VAL		0x0000
+#define DRQ_INTR_VAL		0x0020
+#define DRQ_50US_VAL		0x0040
+#define PKT_SIZE_SUPPORTED	0x0003
+#define PKT_SIZE_12_VAL		0x0000
+#define PKT_SIZE_16_VAL		0x0001
+#define EQPT_TYPE		0x1f00
+#define SHIFT_EQPT		8
+
+#define CDROM 0x0005
+
+#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
+static const char * const pkt_str[] = {
+	"Direct-access device",			/* word 0, bits 12-8 = 00 */
+	"Sequential-access device",		/* word 0, bits 12-8 = 01 */
+	"Printer",				/* word 0, bits 12-8 = 02 */
+	"Processor",				/* word 0, bits 12-8 = 03 */
+	"Write-once device",			/* word 0, bits 12-8 = 04 */
+	"CD-ROM",				/* word 0, bits 12-8 = 05 */
+	"Scanner",				/* word 0, bits 12-8 = 06 */
+	"Optical memory",			/* word 0, bits 12-8 = 07 */
+	"Medium changer",			/* word 0, bits 12-8 = 08 */
+	"Communications device",		/* word 0, bits 12-8 = 09 */
+	"ACS-IT8 device",			/* word 0, bits 12-8 = 0a */
+	"ACS-IT8 device",			/* word 0, bits 12-8 = 0b */
+	"Array controller",			/* word 0, bits 12-8 = 0c */
+	"Enclosure services",			/* word 0, bits 12-8 = 0d */
+	"Reduced block command device",		/* word 0, bits 12-8 = 0e */
+	"Optical card reader/writer",		/* word 0, bits 12-8 = 0f */
+	"",					/* word 0, bits 12-8 = 10 */
+	"",					/* word 0, bits 12-8 = 11 */
+	"",					/* word 0, bits 12-8 = 12 */
+	"",					/* word 0, bits 12-8 = 13 */
+	"",					/* word 0, bits 12-8 = 14 */
+	"",					/* word 0, bits 12-8 = 15 */
+	"",					/* word 0, bits 12-8 = 16 */
+	"",					/* word 0, bits 12-8 = 17 */
+	"",					/* word 0, bits 12-8 = 18 */
+	"",					/* word 0, bits 12-8 = 19 */
+	"",					/* word 0, bits 12-8 = 1a */
+	"",					/* word 0, bits 12-8 = 1b */
+	"",					/* word 0, bits 12-8 = 1c */
+	"",					/* word 0, bits 12-8 = 1d */
+	"",					/* word 0, bits 12-8 = 1e */
+	"Unknown",			/* word 0, bits 12-8 = 1f */
+};
+
+static const char * const ata1_cfg_str[] = {			/* word 0 in ATA-1 mode */
+	"Reserved",				/* bit 0 */
+	"hard sectored",			/* bit 1 */
+	"soft sectored",			/* bit 2 */
+	"not MFM encoded ",			/* bit 3 */
+	"head switch time > 15us",		/* bit 4 */
+	"spindle motor control option",		/* bit 5 */
+	"fixed drive",				/* bit 6 */
+	"removable drive",			/* bit 7 */
+	"disk xfer rate <= 5Mbs",		/* bit 8 */
+	"disk xfer rate > 5Mbs, <= 10Mbs",	/* bit 9 */
+	"disk xfer rate > 5Mbs",		/* bit 10 */
+	"rotational speed tol.",		/* bit 11 */
+	"data strobe offset option",		/* bit 12 */
+	"track offset option",			/* bit 13 */
+	"format speed tolerance gap reqd",	/* bit 14 */
+	"ATAPI"					/* bit 14 */
+};
+#endif
+
+/* word 1: number of logical cylinders */
+#define LCYLS_MAX		0x3fff /* maximum allowable value */
+
+/* word 2: specific configuration
+ * (a) require SET FEATURES to spin-up
+ * (b) require spin-up to fully reply to IDENTIFY DEVICE
+ */
+#define STBY_NID_VAL		0x37c8  /*     (a) and     (b) */
+#define STBY_ID_VAL		0x738c	/*     (a) and not (b) */
+#define PWRD_NID_VAL		0x8c73	/* not (a) and     (b) */
+#define PWRD_ID_VAL		0xc837	/* not (a) and not (b) */
+
+/* words 47 & 59: sector_xfer_max & sector_xfer_cur */
+#define SECTOR_XFER		0x00ff  /* sectors xfered on r/w multiple cmds*/
+#define MULTIPLE_SETTING_VALID  0x0100  /* 1=multiple sector setting is valid */
+
+/* word 49: capabilities 0 */
+#define STD_STBY		0x2000  /* 1=standard values supported (ATA);
+					   0=vendor specific values */
+#define IORDY_SUP		0x0800  /* 1=support; 0=may be supported */
+#define IORDY_OFF		0x0400  /* 1=may be disabled */
+#define LBA_SUP			0x0200  /* 1=Logical Block Address support */
+#define DMA_SUP			0x0100  /* 1=Direct Memory Access support */
+#define DMA_IL_SUP		0x8000  /* 1=interleaved DMA support (ATAPI) */
+#define CMD_Q_SUP		0x4000  /* 1=command queuing support (ATAPI) */
+#define OVLP_SUP		0x2000  /* 1=overlap operation support (ATAPI) */
+#define SWRST_REQ		0x1000  /* 1=ATA SW reset required (ATAPI, obsolete */
+
+/* word 50: capabilities 1 */
+#define MIN_STANDBY_TIMER	0x0001  /* 1=device specific standby timer value minimum */
+
+/* words 51 & 52: PIO & DMA cycle times */
+#define MODE			0xff00  /* the mode is in the MSBs */
+
+/* word 53: whats_valid */
+#define OK_W88			0x0004	/* the ultra_dma info is valid */
+#define OK_W64_70		0x0002  /* see above for word descriptions */
+#define OK_W54_58		0x0001  /* current cyl, head, sector, cap. info valid */
+
+/*word 63,88: dma_mode, ultra_dma_mode*/
+#define MODE_MAX		7	/* bit definitions force udma <=7 (when
+					 * udma >=8 comes out it'll have to be
+					 * defined in a new dma_mode word!) */
+
+/* word 64: PIO transfer modes */
+#define PIO_SUP			0x00ff  /* only bits 0 & 1 are used so far,  */
+#define PIO_MODE_MAX		8       /* but all 8 bits are defined        */
+
+/* word 75: queue_depth */
+#define DEPTH_BITS		0x001f  /* bits used for queue depth */
+
+/* words 80-81: version numbers */
+/* NOVAL_0 or  NOVAL_1 means device does not report version */
+
+/* word 81: minor version number */
+#define MINOR_MAX		0x22
+#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
+static const char *minor_str[MINOR_MAX+2] = {			/* word 81 value: */
+	"Unspecified",					/* 0x0000	*/
+	"ATA-1 X3T9.2 781D prior to rev.4",	/* 0x0001	*/
+	"ATA-1 published, ANSI X3.221-1994",		/* 0x0002	*/
+	"ATA-1 X3T9.2 781D rev.4",			/* 0x0003	*/
+	"ATA-2 published, ANSI X3.279-1996",		/* 0x0004	*/
+	"ATA-2 X3T10 948D prior to rev.2k",	/* 0x0005	*/
+	"ATA-3 X3T10 2008D rev.1",			/* 0x0006	*/
+	"ATA-2 X3T10 948D rev.2k",			/* 0x0007	*/
+	"ATA-3 X3T10 2008D rev.0",			/* 0x0008	*/
+	"ATA-2 X3T10 948D rev.3",			/* 0x0009	*/
+	"ATA-3 published, ANSI X3.298-199x",		/* 0x000a	*/
+	"ATA-3 X3T10 2008D rev.6",			/* 0x000b	*/
+	"ATA-3 X3T13 2008D rev.7 and 7a",		/* 0x000c	*/
+	"ATA/ATAPI-4 X3T13 1153D rev.6",		/* 0x000d	*/
+	"ATA/ATAPI-4 T13 1153D rev.13",		/* 0x000e	*/
+	"ATA/ATAPI-4 X3T13 1153D rev.7",		/* 0x000f	*/
+	"ATA/ATAPI-4 T13 1153D rev.18",		/* 0x0010	*/
+	"ATA/ATAPI-4 T13 1153D rev.15",		/* 0x0011	*/
+	"ATA/ATAPI-4 published, ANSI INCITS 317-1998",	/* 0x0012	*/
+	"ATA/ATAPI-5 T13 1321D rev.3",
+	"ATA/ATAPI-4 T13 1153D rev.14",		/* 0x0014	*/
+	"ATA/ATAPI-5 T13 1321D rev.1",		/* 0x0015	*/
+	"ATA/ATAPI-5 published, ANSI INCITS 340-2000",	/* 0x0016	*/
+	"ATA/ATAPI-4 T13 1153D rev.17",		/* 0x0017	*/
+	"ATA/ATAPI-6 T13 1410D rev.0",		/* 0x0018	*/
+	"ATA/ATAPI-6 T13 1410D rev.3a",		/* 0x0019	*/
+	"ATA/ATAPI-7 T13 1532D rev.1",		/* 0x001a	*/
+	"ATA/ATAPI-6 T13 1410D rev.2",		/* 0x001b	*/
+	"ATA/ATAPI-6 T13 1410D rev.1",		/* 0x001c	*/
+	"ATA/ATAPI-7 published, ANSI INCITS 397-2005",	/* 0x001d	*/
+	"ATA/ATAPI-7 T13 1532D rev.0",		/* 0x001e	*/
+	"Reserved"					/* 0x001f	*/
+	"Reserved"					/* 0x0020	*/
+	"ATA/ATAPI-7 T13 1532D rev.4a",		/* 0x0021	*/
+	"ATA/ATAPI-6 published, ANSI INCITS 361-2002",	/* 0x0022	*/
+	"Reserved"					/* 0x0023-0xfffe*/
+};
+#endif
+static const char actual_ver[MINOR_MAX+2] = {
+			/* word 81 value: */
+	0,		/* 0x0000	WARNING:	*/
+	1,		/* 0x0001	WARNING:	*/
+	1,		/* 0x0002	WARNING:	*/
+	1,		/* 0x0003	WARNING:	*/
+	2,		/* 0x0004	WARNING:   This array		*/
+	2,		/* 0x0005	WARNING:   corresponds		*/
+	3,		/* 0x0006	WARNING:   *exactly*		*/
+	2,		/* 0x0007	WARNING:   to the ATA/		*/
+	3,		/* 0x0008	WARNING:   ATAPI version	*/
+	2,		/* 0x0009	WARNING:   listed in		*/
+	3,		/* 0x000a	WARNING:   the			*/
+	3,		/* 0x000b	WARNING:   minor_str		*/
+	3,		/* 0x000c	WARNING:   array		*/
+	4,		/* 0x000d	WARNING:   above.		*/
+	4,		/* 0x000e	WARNING:			*/
+	4,		/* 0x000f	WARNING:   if you change	*/
+	4,		/* 0x0010	WARNING:   that one,		*/
+	4,		/* 0x0011	WARNING:   change this one	*/
+	4,		/* 0x0012	WARNING:   too!!!		*/
+	5,		/* 0x0013	WARNING:	*/
+	4,		/* 0x0014	WARNING:	*/
+	5,		/* 0x0015	WARNING:	*/
+	5,		/* 0x0016	WARNING:	*/
+	4,		/* 0x0017	WARNING:	*/
+	6,		/* 0x0018	WARNING:	*/
+	6,		/* 0x0019	WARNING:	*/
+	7,		/* 0x001a	WARNING:	*/
+	6,		/* 0x001b	WARNING:	*/
+	6,		/* 0x001c	WARNING:	*/
+	7,		/* 0x001d	WARNING:	*/
+	7,		/* 0x001e	WARNING:	*/
+	0,		/* 0x001f	WARNING:	*/
+	0,		/* 0x0020	WARNING:	*/
+	7,		/* 0x0021	WARNING:	*/
+	6,		/* 0x0022	WARNING:	*/
+	0		/* 0x0023-0xfffe    	*/
+};
+
+/* words 82-84: cmds/feats supported */
+#define CMDS_W82		0x77ff  /* word 82: defined command locations*/
+#define CMDS_W83		0x3fff  /* word 83: defined command locations*/
+#define CMDS_W84		0x002f  /* word 83: defined command locations*/
+#define SUPPORT_48_BIT		0x0400
+#define NUM_CMD_FEAT_STR	48
+
+#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
+static const char * const cmd_feat_str[] = {
+	"",					/* word 82 bit 15: obsolete  */
+	"NOP cmd",				/* word 82 bit 14 */
+	"READ BUFFER cmd",			/* word 82 bit 13 */
+	"WRITE BUFFER cmd",			/* word 82 bit 12 */
+	"",					/* word 82 bit 11: obsolete  */
+	"Host Protected Area feature set",	/* word 82 bit 10 */
+	"DEVICE RESET cmd",			/* word 82 bit  9 */
+	"SERVICE interrupt",			/* word 82 bit  8 */
+	"Release interrupt",			/* word 82 bit  7 */
+	"Look-ahead",				/* word 82 bit  6 */
+	"Write cache",				/* word 82 bit  5 */
+	"PACKET command feature set",		/* word 82 bit  4 */
+	"Power Management feature set",		/* word 82 bit  3 */
+	"Removable Media feature set",		/* word 82 bit  2 */
+	"Security Mode feature set",		/* word 82 bit  1 */
+	"SMART feature set",			/* word 82 bit  0 */
+						/* --------------*/
+	"",					/* word 83 bit 15: !valid bit */
+	"",					/* word 83 bit 14:  valid bit */
+	"FLUSH CACHE EXT cmd",		/* word 83 bit 13 */
+	"Mandatory FLUSH CACHE cmd ",	/* word 83 bit 12 */
+	"Device Configuration Overlay feature set ",
+	"48-bit Address feature set ",		/* word 83 bit 10 */
+	"",
+	"SET MAX security extension",		/* word 83 bit  8 */
+	"Address Offset Reserved Area Boot",	/* word 83 bit  7 */
+	"SET FEATURES subcommand required to spinup after power up",
+	"Power-Up In Standby feature set",	/* word 83 bit  5 */
+	"Removable Media Status Notification feature set",
+	"Adv. Power Management feature set",/* word 83 bit  3 */
+	"CFA feature set",			/* word 83 bit  2 */
+	"READ/WRITE DMA QUEUED",		/* word 83 bit  1 */
+	"DOWNLOAD MICROCODE cmd",		/* word 83 bit  0 */
+						/* --------------*/
+	"",					/* word 84 bit 15: !valid bit */
+	"",					/* word 84 bit 14:  valid bit */
+	"",					/* word 84 bit 13:  reserved */
+	"",					/* word 84 bit 12:  reserved */
+	"",					/* word 84 bit 11:  reserved */
+	"",					/* word 84 bit 10:  reserved */
+	"",					/* word 84 bit  9:  reserved */
+	"",					/* word 84 bit  8:  reserved */
+	"",					/* word 84 bit  7:  reserved */
+	"",					/* word 84 bit  6:  reserved */
+	"General Purpose Logging feature set",	/* word 84 bit  5 */
+	"",					/* word 84 bit  4:  reserved */
+	"Media Card Pass Through Command feature set ",
+	"Media serial number ",			/* word 84 bit  2 */
+	"SMART self-test ",			/* word 84 bit  1 */
+	"SMART error logging "			/* word 84 bit  0 */
+};
+
+static void identify(uint16_t *id_supplied) ATTRIBUTE_NORETURN;
+static void identify_from_stdin(void) ATTRIBUTE_NORETURN;
+#else
+void identify_from_stdin(void);
+#endif
+
+
+/* words 85-87: cmds/feats enabled */
+/* use cmd_feat_str[] to display what commands and features have
+ * been enabled with words 85-87
+ */
+
+/* words 89, 90, SECU ERASE TIME */
+#define ERASE_BITS		0x00ff
+
+/* word 92: master password revision */
+/* NOVAL_0 or  NOVAL_1 means no support for master password revision */
+
+/* word 93: hw reset result */
+#define CBLID			0x2000  /* CBLID status */
+#define RST0			0x0001  /* 1=reset to device #0 */
+#define DEV_DET			0x0006  /* how device num determined */
+#define JUMPER_VAL		0x0002  /* device num determined by jumper */
+#define CSEL_VAL		0x0004  /* device num determined by CSEL_VAL */
+
+/* word 127: removable media status notification feature set support */
+#define RM_STAT_BITS		0x0003
+#define RM_STAT_SUP		0x0001
+
+/* word 128: security */
+#define SECU_ENABLED	0x0002
+#define SECU_LEVEL		0x0010
+#define NUM_SECU_STR	6
+#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
+static const char * const secu_str[] = {
+	"supported",			/* word 128, bit 0 */
+	"enabled",			/* word 128, bit 1 */
+	"locked",			/* word 128, bit 2 */
+	"frozen",			/* word 128, bit 3 */
+	"expired: security count",	/* word 128, bit 4 */
+	"supported: enhanced erase"	/* word 128, bit 5 */
+};
+#endif
+
+/* word 160: CFA power mode */
+#define VALID_W160		0x8000  /* 1=word valid */
+#define PWR_MODE_REQ		0x2000  /* 1=CFA power mode req'd by some cmds*/
+#define PWR_MODE_OFF		0x1000  /* 1=CFA power moded disabled */
+#define MAX_AMPS		0x0fff  /* value = max current in ma */
+
+/* word 255: integrity */
+#define SIG			0x00ff  /* signature location */
+#define SIG_VAL			0x00A5  /* signature value */
+
+#define TIMING_MB		64
+#define TIMING_BUF_MB		1
+#define TIMING_BUF_BYTES	(TIMING_BUF_MB * 1024 * 1024)
+#define TIMING_BUF_COUNT	(timing_MB / TIMING_BUF_MB)
+#define BUFCACHE_FACTOR		2
+
+#undef DO_FLUSHCACHE		/* under construction: force cache flush on -W0 */
+
+/* Busybox messages and functions */
+static int bb_ioctl(int fd, int request, void *argp, const char *string)
+{
+	int e = ioctl(fd, request, argp);
+	if (e && string)
+		bb_perror_msg(" %s", string);
+	return e;
+}
+
+static int bb_ioctl_alt(int fd, int cmd, unsigned char *args, int alt, const char *string)
+{
+	if (!ioctl(fd, cmd, args))
+		return 0;
+	args[0] = alt;
+	return bb_ioctl(fd, cmd, args, string);
+}
+
+static void on_off(unsigned int value);
+
+static void print_flag_on_off(unsigned long get_arg, const char *s, unsigned long arg)
+{
+
+	if (get_arg)
+	{
+		printf(" setting %s to %ld", s, arg);
+		on_off(arg);
+	}
+}
+
+static void bb_ioctl_on_off(int fd, int request, void *argp, const char *string,
+							 const char * str)
+{
+	if (ioctl(fd, request, &argp) != 0)
+		bb_perror_msg(" %s", string);
+	else
+	{
+		printf(" %s\t= %2ld", str, (unsigned long) argp);
+		on_off((unsigned long) argp);
+	}
+}
+
+#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
+static void print_ascii(uint16_t *p, uint8_t length);
+
+static void xprint_ascii(uint16_t *val ,int i, char * string, int n)
+{
+	if (val[i])
+	{
+		printf("\t%-20s",string);
+		print_ascii(&val[i], n);
+	}
+}
+#endif
+/* end of  busybox specific stuff */
+
+#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
+static uint8_t mode_loop(uint16_t mode_sup, uint16_t mode_sel, int cc, uint8_t *have_mode)
+{
+	uint16_t ii;
+	uint8_t err_dma = 0;
+
+	for (ii = 0; ii <= MODE_MAX; ii++)
+	{
+		if (mode_sel & 0x0001)
+		{
+			printf("*%cdma%u ",cc,ii);
+			if (*have_mode)
+				err_dma = 1;
+			*have_mode = 1;
+		}
+		else if (mode_sup & 0x0001)
+			printf("%cdma%u ",cc,ii);
+
+		mode_sup >>=1;
+		mode_sel >>=1;
+	}
+	return err_dma;
+}
+
+static void print_ascii(uint16_t *p, uint8_t length) {
+	uint8_t ii;
+	char cl;
+
+	/* find first non-space & print it */
+	for (ii = 0; ii< length; ii++)
+	{
+		if (((char) 0x00ff&((*p)>>8)) != ' ')
+			break;
+		if ((cl = (char) 0x00ff&(*p)) != ' ')
+		{
+			if (cl != '\0') printf("%c",cl);
+			p++;
+			ii++;
+			break;
+		}
+		p++;
+	}
+	/* print the rest */
+	for (; ii< length; ii++)
+	{
+		if (!(*p))
+			break; /* some older devices have NULLs */
+		printf("%c%c",(char)0x00ff&((*p)>>8),(char)(*p)&0x00ff);
+		p++;
+	}
+	printf("\n");
+}
+
+// Parse 512 byte disk identification block and print much crap.
+
+static void identify(uint16_t *id_supplied)
+{
+	uint16_t buf[256];
+	uint16_t *val, ii, jj, kk;
+	uint16_t like_std = 1, std = 0, min_std = 0xffff;
+	uint16_t dev = NO_DEV, eqpt = NO_DEV;
+	uint8_t  have_mode = 0, err_dma = 0;
+	uint8_t  chksum = 0;
+	uint32_t ll, mm, nn, oo;
+	uint64_t bbbig; /* (:) */
+	const char *strng;
+
+	// Adjust for endianness if necessary.
+
+	if (BB_BIG_ENDIAN) {
+		swab(id_supplied, buf, sizeof(buf));
+		val = buf;
+	} else val = id_supplied;
+
+	chksum &= 0xff;
+
+	/* check if we recognise the device type */
+	printf("\n");
+	if(!(val[GEN_CONFIG] & NOT_ATA))
+	{
+		dev = ATA_DEV;
+		printf("ATA device, with ");
+	}
+	else if(val[GEN_CONFIG]==CFA_SUPPORT_VAL)
+	{
+		dev = ATA_DEV;
+		like_std = 4;
+		printf("CompactFlash ATA device, with ");
+	}
+	else if(!(val[GEN_CONFIG] & NOT_ATAPI))
+	{
+		dev = ATAPI_DEV;
+		eqpt = (val[GEN_CONFIG] & EQPT_TYPE) >> SHIFT_EQPT;
+		printf("ATAPI %s, with ", pkt_str[eqpt]);
+		like_std = 3;
+	}
+	else
+		/*"Unknown device type:\n\tbits 15&14 of general configuration word 0 both set to 1.\n"*/
+		bb_error_msg_and_die("Unknown device type");
+
+	printf("%sremovable media\n", !(val[GEN_CONFIG] & MEDIA_REMOVABLE) ? "non-" : "");
+	/* Info from the specific configuration word says whether or not the
+	 * ID command completed correctly.  It is only defined, however in
+	 * ATA/ATAPI-5 & 6; it is reserved (value theoretically 0) in prior
+	 * standards.  Since the values allowed for this word are extremely
+	 * specific, it should be safe to check it now, even though we don't
+	 * know yet what standard this device is using.
+	 */
+	if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL) ||
+	   (val[CONFIG]==PWRD_NID_VAL) || (val[CONFIG]==PWRD_ID_VAL) )
+	{
+		like_std = 5;
+		if((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL))
+			printf("powers-up in standby; SET FEATURES subcmd spins-up.\n");
+		if(((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE))
+			printf("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n\n");
+	}
+
+	/* output the model and serial numbers and the fw revision */
+	xprint_ascii(val, START_MODEL,  "Model Number:",        LENGTH_MODEL);
+	xprint_ascii(val, START_SERIAL, "Serial Number:",       LENGTH_SERIAL);
+	xprint_ascii(val, START_FW_REV, "Firmware Revision:",   LENGTH_FW_REV);
+	xprint_ascii(val, START_MEDIA,  "Media Serial Num:",    LENGTH_MEDIA);
+	xprint_ascii(val, START_MANUF,  "Media Manufacturer:",  LENGTH_MANUF);
+
+	/* major & minor standards version number (Note: these words were not
+	 * defined until ATA-3 & the CDROM std uses different words.) */
+	printf("Standards:");
+	if (eqpt != CDROM)
+	{
+		if (val[MINOR] && (val[MINOR] <= MINOR_MAX))
+		{
+			if(like_std < 3) like_std = 3;
+			std = actual_ver[val[MINOR]];
+			if(std) printf("\n\tUsed: %s ",minor_str[val[MINOR]]);
+
+		}
+		/* looks like when they up-issue the std, they obsolete one;
+		 * thus, only the newest 4 issues need be supported. (That's
+		 * what "kk" and "min_std" are all about.) */
+		if (val[MAJOR] && (val[MAJOR] !=NOVAL_1))
+		{
+			printf("\n\tSupported: ");
+			jj = val[MAJOR] << 1;
+			kk = like_std >4 ? like_std-4: 0;
+			for (ii = 14; (ii >0)&&(ii>kk); ii--)
+			{
+				if (jj & 0x8000)
+				{
+					printf("%u ", ii);
+					if (like_std < ii)
+					{
+						like_std = ii;
+						kk = like_std >4 ? like_std-4: 0;
+					}
+					if(min_std > ii) min_std = ii;
+				}
+				jj <<= 1;
+			}
+			if(like_std < 3) like_std = 3;
+		}
+		/* Figure out what standard the device is using if it hasn't told
+		 * us.  If we know the std, check if the device is using any of
+		 * the words from the next level up.  It happens.
+		 */
+		if(like_std < std) like_std = std;
+
+		if (((std == 5) || (!std && (like_std < 6))) &&
+			((((val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
+			((	val[CMDS_SUPP_1] & CMDS_W83) > 0x00ff)) ||
+			(((	val[CMDS_SUPP_2] & VALID) == VALID_VAL) &&
+			(	val[CMDS_SUPP_2] & CMDS_W84) ) ) )
+		{
+			like_std = 6;
+		}
+		else if (((std == 4) || (!std && (like_std < 5))) &&
+			((((val[INTEGRITY]	& SIG) == SIG_VAL) && !chksum) ||
+			((	val[HWRST_RSLT] & VALID) == VALID_VAL) ||
+			(((	val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
+			((	val[CMDS_SUPP_1] & CMDS_W83) > 0x001f)) ) )
+		{
+			like_std = 5;
+		}
+		else if (((std == 3) || (!std && (like_std < 4))) &&
+				((((val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
+				(((	val[CMDS_SUPP_1] & CMDS_W83) > 0x0000) ||
+				((	val[CMDS_SUPP_0] & CMDS_W82) > 0x000f))) ||
+				((	val[CAPAB_1] & VALID) == VALID_VAL) ||
+				((	val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) ||
+				((	val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP) ) )
+		{
+			like_std = 4;
+		}
+		else if (((std == 2) || (!std && (like_std < 3))) &&
+			   ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) )
+		{
+			like_std = 3;
+		}
+		else if (((std == 1) || (!std && (like_std < 2))) &&
+				((val[CAPAB_0] & (IORDY_SUP | IORDY_OFF)) ||
+				(val[WHATS_VALID] & OK_W64_70)) )
+		{
+			like_std = 2;
+		}
+		if (!std)
+			printf("\n\tLikely used: %u\n",like_std);
+		else if (like_std > std)
+			printf("& some of %u\n",like_std);
+		else
+			printf("\n");
+	}
+	else
+	{
+		/* TBD: do CDROM stuff more thoroughly.  For now... */
+		kk = 0;
+		if (val[CDR_MINOR] == 9)
+		{
+			kk = 1;
+			printf("\n\tUsed: ATAPI for CD-ROMs, SFF-8020i, r2.5");
+		}
+		if (val[CDR_MAJOR] && (val[CDR_MAJOR] !=NOVAL_1))
+		{
+			kk = 1;
+			printf("\n\tSupported: CD-ROM ATAPI");
+			jj = val[CDR_MAJOR] >> 1;
+			for (ii = 1; ii <15; ii++)
+			{
+				if(jj & 0x0001) printf("-%u ", ii);
+				jj >>= 1;
+			}
+		}
+		printf("%s\n", (!kk) ? "\n\tLikely used CD-ROM ATAPI-1" : "" );
+		/* the cdrom stuff is more like ATA-2 than anything else, so: */
+		like_std = 2;
+	}
+
+	if (min_std == 0xffff)
+		min_std = like_std > 4 ? like_std - 3 : 1;
+
+	printf("Configuration:\n");
+	/* more info from the general configuration word */
+	if ((eqpt != CDROM) && (like_std == 1))
+	{
+		jj = val[GEN_CONFIG] >> 1;
+		for (ii = 1; ii < 15; ii++)
+		{
+			if(jj & 0x0001) printf("\t%s\n",ata1_cfg_str[ii]);
+			jj >>=1;
+		}
+	}
+	if (dev == ATAPI_DEV)
+	{
+		if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) ==  DRQ_3MS_VAL)
+			strng = "3ms";
+		else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) ==  DRQ_INTR_VAL)
+			strng = "<=10ms with INTRQ";
+		else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) ==  DRQ_50US_VAL)
+			strng ="50us";
+		else 
+			strng = "Unknown";
+		printf("\tDRQ response: %s\n\tPacket size: ", strng); /* Data Request (DRQ) */
+
+		if ((val[GEN_CONFIG] & PKT_SIZE_SUPPORTED) == PKT_SIZE_12_VAL)
+			strng = "12 bytes";
+		else if ((val[GEN_CONFIG] & PKT_SIZE_SUPPORTED) == PKT_SIZE_16_VAL)
+			strng = "16 bytes";
+		else
+			strng = "Unknown";
+		puts(strng);
+	}
+	else
+	{
+		/* addressing...CHS? See section 6.2 of ATA specs 4 or 5 */
+		ll = (uint32_t)val[LBA_SECTS_MSB] << 16 | val[LBA_SECTS_LSB];
+		mm = 0; bbbig = 0;
+		if ( (ll > 0x00FBFC10) && (!val[LCYLS]))
+			printf("\tCHS addressing not supported\n");
+		else
+		{
+			jj = val[WHATS_VALID] & OK_W54_58;
+			printf("\tLogical\t\tmax\tcurrent\n\tcylinders\t%u\t%u\n\theads\t\t%u\t%u\n\tsectors/track\t%u\t%u\n\t--\n",
+					val[LCYLS],jj?val[LCYLS_CUR]:0, val[LHEADS],jj?val[LHEADS_CUR]:0, val[LSECTS],jj?val[LSECTS_CUR]:0);
+
+			if ((min_std == 1) && (val[TRACK_BYTES] || val[SECT_BYTES]))
+				printf("\tbytes/track: %u\tbytes/sector: %u\n",val[TRACK_BYTES], val[SECT_BYTES]);
+
+			if (jj)
+			{
+				mm = (uint32_t)val[CAPACITY_MSB] << 16 | val[CAPACITY_LSB];
+				if (like_std < 3)
+				{
+					 /* check Endian of capacity bytes */
+					nn = val[LCYLS_CUR] * val[LHEADS_CUR] * val[LSECTS_CUR];
+					oo = (uint32_t)val[CAPACITY_LSB] << 16 | val[CAPACITY_MSB];
+					if (abs(mm - nn) > abs(oo - nn))
+						mm = oo;
+				}
+				printf("\tCHS current addressable sectors:%11u\n",mm);
+			}
+		}
+		/* LBA addressing */
+		printf("\tLBA    user addressable sectors:%11u\n",ll);
+		if ( ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
+		     (val[CMDS_SUPP_1] & SUPPORT_48_BIT) )
+		{
+			bbbig = (uint64_t)val[LBA_64_MSB]	<< 48 |
+			        (uint64_t)val[LBA_48_MSB]	<< 32 |
+			        (uint64_t)val[LBA_MID]	<< 16 |
+					val[LBA_LSB] ;
+			printf("\tLBA48  user addressable sectors:%11"PRIu64"\n",bbbig);
+		}
+
+		if (!bbbig)
+			bbbig = (uint64_t)(ll>mm ? ll : mm); /* # 512 byte blocks */
+		printf("\tdevice size with M = 1024*1024: %11"PRIu64" MBytes\n",bbbig>>11);
+		bbbig = (bbbig<<9)/1000000;
+		printf("\tdevice size with M = 1000*1000: %11"PRIu64" MBytes ",bbbig);
+
+		if (bbbig > 1000)
+			printf("(%"PRIu64" GB)\n", bbbig/1000);
+		else 
+			printf("\n");
+	}
+
+	/* hw support of commands (capabilities) */
+	printf("Capabilities:\n\t");
+
+	if (dev == ATAPI_DEV)
+	{
+		if (eqpt != CDROM && (val[CAPAB_0] & CMD_Q_SUP)) printf("Cmd queuing, ");
+		if (val[CAPAB_0] & OVLP_SUP) printf("Cmd overlap, ");
+	}
+	if (val[CAPAB_0] & LBA_SUP) printf("LBA, ");
+
+	if (like_std != 1)
+	{
+		printf("IORDY%s(can%s be disabled)\n", 
+				!(val[CAPAB_0] & IORDY_SUP) ? "(may be)" : "", 
+				(val[CAPAB_0] & IORDY_OFF) ? "" :"not");
+	}
+	else
+		printf("no IORDY\n");
+
+	if ((like_std == 1) && val[BUF_TYPE])
+	{
+		printf("\tBuffer type: %04x: %s%s\n", val[BUF_TYPE],
+				(val[BUF_TYPE] < 2) ? "single port, single-sector" : "dual port, multi-sector", 
+				(val[BUF_TYPE] > 2) ? " with read caching ability" : "");
+	}
+
+	if ((min_std == 1) && (val[BUFFER__SIZE] && (val[BUFFER__SIZE] != NOVAL_1)))
+	{
+		printf("\tBuffer size: %.1fkB\n",(float)val[BUFFER__SIZE]/2);
+	}
+	if ((min_std < 4) && (val[RW_LONG]))
+	{
+		printf("\tbytes avail on r/w long: %u\n",val[RW_LONG]);
+	}
+	if ((eqpt != CDROM) && (like_std > 3))
+	{
+		printf("\tQueue depth: %u\n",(val[QUEUE_DEPTH] & DEPTH_BITS)+1);
+	}
+
+	if (dev == ATA_DEV)
+	{
+		if (like_std == 1)
+			printf("\tCan%s perform double-word IO\n",(!val[DWORD_IO]) ?"not":"");
+		else
+		{
+			printf("\tStandby timer values: spec'd by %s", (val[CAPAB_0] & STD_STBY) ? "Standard" : "Vendor");
+			if ((like_std > 3) && ((val[CAPAB_1] & VALID) == VALID_VAL))
+				printf(", %s device specific minimum\n",(val[CAPAB_1] & MIN_STANDBY_TIMER)?"with":"no");
+			else
+			  printf("\n");
+		}
+		printf("\tR/W multiple sector transfer: ");
+		if ((like_std < 3) && !(val[SECTOR_XFER_MAX] & SECTOR_XFER))
+			printf("not supported\n");
+		else
+		{
+			printf("Max = %u\tCurrent = ",val[SECTOR_XFER_MAX] & SECTOR_XFER);
+			if (val[SECTOR_XFER_CUR] & MULTIPLE_SETTING_VALID)
+				printf("%u\n", val[SECTOR_XFER_CUR] & SECTOR_XFER);
+			else
+				printf("?\n");
+		}
+		if ((like_std > 3) && (val[CMDS_SUPP_1] & 0x0008))
+		{
+			/* We print out elsewhere whether the APM feature is enabled or
+			   not.  If it's not enabled, let's not repeat the info; just print
+			   nothing here. */
+			printf("\tAdvancedPM level: ");
+			if ( (val[ADV_PWR] & 0xFF00) == 0x4000 )
+			{
+				uint8_t apm_level = val[ADV_PWR] & 0x00FF;
+				printf("%u (0x%x)\n", apm_level, apm_level);
+			}
+			else
+				printf("unknown setting (0x%04x)\n", val[ADV_PWR]);
+		}
+		if (like_std > 5 && val[ACOUSTIC]) {
+			printf("\tRecommended acoustic management value: %u, current value: %u\n",
+									(val[ACOUSTIC] >> 8) & 0x00ff, val[ACOUSTIC] & 0x00ff);
+		}
+	}
+	else
+	{
+		 /* ATAPI */
+		if (eqpt != CDROM && (val[CAPAB_0] & SWRST_REQ))
+			printf("\tATA sw reset required\n");
+
+		if (val[PKT_REL] || val[SVC_NBSY])
+		{
+			printf("\tOverlap support:");
+			if (val[PKT_REL]) printf(" %uus to release bus.",val[PKT_REL]);
+			if (val[SVC_NBSY]) printf(" %uus to clear BSY after SERVICE cmd.",val[SVC_NBSY]);
+			printf("\n");
+		}
+	}
+
+	/* DMA stuff. Check that only one DMA mode is selected. */
+	printf("\tDMA: ");
+	if (!(val[CAPAB_0] & DMA_SUP))
+		printf("not supported\n");
+	else
+	{
+		if (val[DMA_MODE] && !val[SINGLE_DMA] && !val[MULTI_DMA])
+			printf(" sdma%u\n",(val[DMA_MODE] & MODE) >> 8);
+		if (val[SINGLE_DMA])
+		{
+			jj = val[SINGLE_DMA];
+			kk = val[SINGLE_DMA] >> 8;
+			err_dma += mode_loop(jj,kk,'s',&have_mode);
+		}
+		if (val[MULTI_DMA])
+		{
+			jj = val[MULTI_DMA];
+			kk = val[MULTI_DMA] >> 8;
+			err_dma += mode_loop(jj,kk,'m',&have_mode);
+		}
+		if ((val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA])
+		{
+			jj = val[ULTRA_DMA];
+			kk = val[ULTRA_DMA] >> 8;
+			err_dma += mode_loop(jj,kk,'u',&have_mode);
+		}
+		if (err_dma || !have_mode) printf("(?)");
+		printf("\n");
+
+		if ((dev == ATAPI_DEV) && (eqpt != CDROM) && (val[CAPAB_0] & DMA_IL_SUP))
+			printf("\t\tInterleaved DMA support\n");
+
+		if ((val[WHATS_VALID] & OK_W64_70) &&
+		   (val[DMA_TIME_MIN] || val[DMA_TIME_NORM]))
+		{
+			printf("\t\tCycle time:");
+			if (val[DMA_TIME_MIN]) printf(" min=%uns",val[DMA_TIME_MIN]);
+			if (val[DMA_TIME_NORM]) printf(" recommended=%uns",val[DMA_TIME_NORM]);
+			printf("\n");
+		}
+	}
+
+	/* Programmed IO stuff */
+	printf("\tPIO: ");
+	/* If a drive supports mode n (e.g. 3), it also supports all modes less
+	 * than n (e.g. 3, 2, 1 and 0).  Print all the modes. */
+	if ((val[WHATS_VALID] & OK_W64_70) && (val[ADV_PIO_MODES] & PIO_SUP))
+	{
+		jj = ((val[ADV_PIO_MODES] & PIO_SUP) << 3) | 0x0007;
+		for (ii = 0; ii <= PIO_MODE_MAX ; ii++)
+		{
+			if (jj & 0x0001) printf("pio%d ",ii);
+			jj >>=1;
+		}
+		printf("\n");
+	}
+	else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE) )
+	{
+		for (ii = 0; ii <= val[PIO_MODE]>>8; ii++)
+			printf("pio%d ",ii);
+		printf("\n");
+	}
+	else
+		printf("unknown\n");
+
+	if (val[WHATS_VALID] & OK_W64_70)
+	{
+		if (val[PIO_NO_FLOW] || val[PIO_FLOW])
+		{
+			printf("\t\tCycle time:");
+			if (val[PIO_NO_FLOW]) printf(" no flow control=%uns", val[PIO_NO_FLOW]);
+			if (val[PIO_FLOW]) printf("  IORDY flow control=%uns", val[PIO_FLOW]);
+			printf("\n");
+		}
+	}
+
+	if ((val[CMDS_SUPP_1] & VALID) == VALID_VAL)
+	{
+		printf("Commands/features:\n\tEnabled\tSupported:\n");
+		jj = val[CMDS_SUPP_0];
+		kk = val[CMDS_EN_0];
+		for (ii = 0; ii < NUM_CMD_FEAT_STR; ii++)
+		{
+			if ((jj & 0x8000) && (*cmd_feat_str[ii] != '\0'))
+			{
+				printf("\t%s\t%s\n", (kk & 0x8000) ? "   *" : "", cmd_feat_str[ii]);
+			}
+			jj <<=1; kk<<=1;
+			if (ii%16 == 15)
+			{
+				jj = val[CMDS_SUPP_0+1+(ii/16)];
+				kk = val[CMDS_EN_0+1+(ii/16)];
+			}
+			if (ii == 31)
+			{
+				if ((val[CMDS_SUPP_2] & VALID) != VALID_VAL)
+					ii +=16;
+			}
+		}
+	}
+	/* Removable Media Status Notification feature set */
+	if((val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP)
+		printf("\t%s supported\n", cmd_feat_str[27]);
+
+
+	/* security */
+	if ((eqpt != CDROM) && (like_std > 3) &&
+	   (val[SECU_STATUS] || val[ERASE_TIME] || val[ENH_ERASE_TIME]))
+	{
+		printf("Security:\n");
+		if (val[PSWD_CODE] && (val[PSWD_CODE] != NOVAL_1))
+			printf("\tMaster password revision code = %u\n",val[PSWD_CODE]);
+		jj = val[SECU_STATUS];
+		if (jj)
+		{
+			for (ii = 0; ii < NUM_SECU_STR; ii++)
+			{
+				printf("\t%s\t%s\n", (!(jj & 0x0001)) ? "not" : "",  secu_str[ii]);
+				jj >>=1;
+			}
+			if (val[SECU_STATUS] & SECU_ENABLED)
+			{
+				printf("\tSecurity level %s\n", (val[SECU_STATUS] & SECU_LEVEL) ? "maximum" : "high");
+			}
+		}
+		jj =  val[ERASE_TIME]     & ERASE_BITS;
+		kk =  val[ENH_ERASE_TIME] & ERASE_BITS;
+		if (jj || kk)
+		{
+			printf("\t");
+			if (jj) printf("%umin for %sSECURITY ERASE UNIT. ", jj==ERASE_BITS ? 508 : jj<<1, "");
+			if (kk) printf("%umin for %sSECURITY ERASE UNIT. ", kk==ERASE_BITS ? 508 : kk<<1, "ENHANCED ");
+			printf("\n");
+		}
+	}
+
+	/* reset result */
+	jj = val[HWRST_RSLT];
+	if ((jj & VALID) == VALID_VAL)
+	{
+		if (!(oo = (jj & RST0)))
+			jj >>= 8;
+		if ((jj & DEV_DET) == JUMPER_VAL)
+			strng = " determined by the jumper";
+		else if ((jj & DEV_DET) == CSEL_VAL)
+			strng = " determined by CSEL";
+		else 
+			strng = "";
+		printf("HW reset results:\n\tCBLID- %s Vih\n\tDevice num = %i%s\n", 
+				(val[HWRST_RSLT] & CBLID) ? "above" : "below", !(oo), strng);
+	}
+
+	/* more stuff from std 5 */
+	if ((like_std > 4) && (eqpt != CDROM))
+	{
+		if (val[CFA_PWR_MODE] & VALID_W160)
+		{
+			printf("CFA power mode 1:\n\t%s%s\n", (val[CFA_PWR_MODE] & PWR_MODE_OFF) ? "disabled" : "enabled",
+										(val[CFA_PWR_MODE] & PWR_MODE_REQ) ? " and required by some commands" : "");
+
+			if (val[CFA_PWR_MODE] & MAX_AMPS) printf("\tMaximum current = %uma\n",val[CFA_PWR_MODE] & MAX_AMPS);
+		}
+		if ((val[INTEGRITY] & SIG) == SIG_VAL)
+		{
+			printf("Checksum: %scorrect\n", chksum ? "in" : "");
+		}
+	}
+
+	exit(EXIT_SUCCESS);
+}
+#endif
+
+static int get_identity, get_geom;
+static int do_flush;
+static int do_ctimings, do_timings;
+static unsigned long set_readahead, get_readahead, Xreadahead;
+static unsigned long set_readonly, get_readonly, readonly;
+static unsigned long set_unmask, get_unmask, unmask;
+static unsigned long set_mult, get_mult, mult;
+#ifdef CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA
+static unsigned long set_dma, get_dma, dma;
+#endif
+static unsigned long set_dma_q, get_dma_q, dma_q;
+static unsigned long set_nowerr, get_nowerr, nowerr;
+static unsigned long set_keep, get_keep, keep;
+static unsigned long set_io32bit, get_io32bit, io32bit;
+static unsigned long set_piomode, noisy_piomode;
+static int piomode;
+#ifdef HDIO_DRIVE_CMD
+static unsigned long set_dkeep, get_dkeep, dkeep;
+static unsigned long set_standby, get_standby, standby_requested;
+static unsigned long set_xfermode, get_xfermode;
+static int xfermode_requested;
+static unsigned long set_lookahead, get_lookahead, lookahead;
+static unsigned long set_prefetch, get_prefetch, prefetch;
+static unsigned long set_defects, get_defects, defects;
+static unsigned long set_wcache, get_wcache, wcache;
+static unsigned long set_doorlock, get_doorlock, doorlock;
+static unsigned long set_seagate, get_seagate;
+static unsigned long set_standbynow, get_standbynow;
+static unsigned long set_sleepnow, get_sleepnow;
+static unsigned long get_powermode;
+static unsigned long set_apmmode, get_apmmode, apmmode;
+#endif
+#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
+static int get_IDentity;
+#endif
+#ifdef CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
+static unsigned long	unregister_hwif;
+static unsigned long	hwif;
+#endif
+#ifdef CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF
+static unsigned long scan_hwif;
+static unsigned long hwif_data;
+static unsigned long hwif_ctrl;
+static unsigned long hwif_irq;
+#endif
+#ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
+static unsigned long	set_busstate, get_busstate, busstate;
+#endif
+static int	reread_partn;
+
+#ifdef CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET
+static int	perform_reset;
+#endif /* CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET */
+#ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
+static unsigned long	perform_tristate,	tristate;
+#endif /* CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF */
+
+// Historically, if there was no HDIO_OBSOLETE_IDENTITY, then
+// then the HDIO_GET_IDENTITY only returned 142 bytes.
+// Otherwise, HDIO_OBSOLETE_IDENTITY returns 142 bytes,
+// and HDIO_GET_IDENTITY returns 512 bytes.  But the latest
+// 2.5.xx kernels no longer define HDIO_OBSOLETE_IDENTITY
+// (which they should, but they should just return -EINVAL).
+//
+// So.. we must now assume that HDIO_GET_IDENTITY returns 512 bytes.
+// On a really old system, it will not, and we will be confused.
+// Too bad, really.
+
+#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
+static const char * const cfg_str[] =
+{	"",	     "HardSect",   "SoftSect",   "NotMFM",
+	"HdSw>15uSec", "SpinMotCtl", "Fixed",     "Removeable",
+	"DTR<=5Mbs",   "DTR>5Mbs",   "DTR>10Mbs", "RotSpdTol>.5%",
+	"dStbOff",     "TrkOff",     "FmtGapReq", "nonMagnetic"
+};
+
+static const char * const BuffType[] = {"Unknown", "1Sect", "DualPort", "DualPortCache"};
+
+static void dump_identity(const struct hd_driveid *id)
+{
+	int i;
+	const unsigned short int *id_regs= (const void*) id;
+
+	printf("\n Model=%.40s, FwRev=%.8s, SerialNo=%.20s\n Config={",
+				id->model, id->fw_rev, id->serial_no);
+	for (i=0; i<=15; i++) {
+		if (id->config & (1<<i))
+			printf(" %s", cfg_str[i]);
+	}
+	printf(	" }\n RawCHS=%u/%u/%u, TrkSize=%u, SectSize=%u, ECCbytes=%u\n"
+			" BuffType=(%u) %s, BuffSize=%ukB, MaxMultSect=%u",
+				id->cyls, id->heads, id->sectors, id->track_bytes,
+				id->sector_bytes, id->ecc_bytes,
+				id->buf_type, BuffType[(id->buf_type > 3) ? 0 :  id->buf_type],
+				id->buf_size/2, id->max_multsect);
+	if (id->max_multsect)
+	{
+		printf(", MultSect=");
+		if (!(id->multsect_valid&1))
+			printf("?%u?", id->multsect);
+		else if (id->multsect)
+			printf("%u", id->multsect);
+		else
+			printf("off");
+	}
+	printf("\n");
+
+	if(!(id->field_valid&1))
+		printf(" (maybe):");
+
+	printf(" CurCHS=%u/%u/%u, CurSects=%lu, LBA=%s",id->cur_cyls, id->cur_heads,
+													id->cur_sectors, 
+ 													(BB_BIG_ENDIAN) ? 
+													(long unsigned int)(id->cur_capacity0 << 16) | id->cur_capacity1 :
+													(long unsigned int)(id->cur_capacity1 << 16) | id->cur_capacity0,
+													((id->capability&2) == 0) ? "no" : "yes");
+
+	if (id->capability&2)
+		printf(", LBAsects=%u", id->lba_capacity);
+
+	printf("\n IORDY=%s", (id->capability&8) ? (id->capability&4) ?  "on/off" : "yes" : "no");
+
+	if (((id->capability&8) || (id->field_valid&2)) && id->field_valid&2)
+		printf(", tPIO={min:%u,w/IORDY:%u}", id->eide_pio, id->eide_pio_iordy);
+	
+	if ((id->capability&1) && (id->field_valid&2))
+		printf(", tDMA={min:%u,rec:%u}", id->eide_dma_min, id->eide_dma_time);
+
+	printf("\n PIO modes:  ");
+	if (id->tPIO <= 5)
+	{
+		printf("pio0 ");
+		if (id->tPIO >= 1) printf("pio1 ");
+		if (id->tPIO >= 2) printf("pio2 ");
+	}
+	if (id->field_valid&2)
+	{
+		if (id->eide_pio_modes & 1) printf("pio3 ");
+		if (id->eide_pio_modes & 2) printf("pio4 ");
+		if (id->eide_pio_modes &~3) printf("pio? ");
+	}
+	if (id->capability&1)
+	{
+		if (id->dma_1word | id->dma_mword)
+		{
+			printf("\n DMA modes:  ");
+			if (id->dma_1word & 0x100) printf("*");
+			if (id->dma_1word & 1) printf("sdma0 ");
+			if (id->dma_1word & 0x200) printf("*");
+			if (id->dma_1word & 2) printf("sdma1 ");
+			if (id->dma_1word & 0x400) printf("*");
+			if (id->dma_1word & 4) printf("sdma2 ");
+			if (id->dma_1word & 0xf800) printf("*");
+			if (id->dma_1word & 0xf8) printf("sdma? ");
+			if (id->dma_mword & 0x100) printf("*");
+			if (id->dma_mword & 1) printf("mdma0 ");
+			if (id->dma_mword & 0x200) printf("*");
+			if (id->dma_mword & 2) printf("mdma1 ");
+			if (id->dma_mword & 0x400) printf("*");
+			if (id->dma_mword & 4) printf("mdma2 ");
+			if (id->dma_mword & 0xf800) printf("*");
+			if (id->dma_mword & 0xf8) printf("mdma? ");
+		}
+	}
+	if (((id->capability&8) || (id->field_valid&2))	&& id->field_valid&4)
+	{	
+		printf("\n UDMA modes: ");
+		if (id->dma_ultra & 0x100) printf("*");
+		if (id->dma_ultra & 0x001) printf("udma0 ");
+		if (id->dma_ultra & 0x200) printf("*");
+		if (id->dma_ultra & 0x002) printf("udma1 ");
+		if (id->dma_ultra & 0x400) printf("*");
+		if (id->dma_ultra & 0x004) printf("udma2 ");
+#ifdef __NEW_HD_DRIVE_ID
+		if (id->hw_config & 0x2000)
+		{
+#else /* !__NEW_HD_DRIVE_ID */
+		if (id->word93 & 0x2000)
+		{
+#endif /* __NEW_HD_DRIVE_ID */
+			if (id->dma_ultra & 0x0800) printf("*");
+			if (id->dma_ultra & 0x0008) printf("udma3 ");
+			if (id->dma_ultra & 0x1000) printf("*");
+			if (id->dma_ultra & 0x0010) printf("udma4 ");
+			if (id->dma_ultra & 0x2000) printf("*");
+			if (id->dma_ultra & 0x0020) printf("udma5 ");
+			if (id->dma_ultra & 0x4000) printf("*");
+			if (id->dma_ultra & 0x0040) printf("udma6 ");
+			if (id->dma_ultra & 0x8000) printf("*");
+			if (id->dma_ultra & 0x0080) printf("udma7 ");
+		}
+	}
+	printf("\n AdvancedPM=%s",((id_regs[83]&8)==0)?"no":"yes");
+	if (id_regs[83] & 8)
+	{
+		if (!(id_regs[86]&8))
+			printf(": disabled (255)");
+		else if ((id_regs[91]&0xFF00)!=0x4000)
+			printf(": unknown setting");
+		else
+			printf(": mode=0x%02X (%u)",id_regs[91]&0xFF,id_regs[91]&0xFF);
+	}
+	if (id_regs[82]&0x20)
+		printf(" WriteCache=%s",(id_regs[85]&0x20) ? "enabled" : "disabled");
+#ifdef __NEW_HD_DRIVE_ID
+	if ((id->minor_rev_num && id->minor_rev_num <= 31) || (id->major_rev_num && id->minor_rev_num <= 31))
+	{
+		printf("\n Drive conforms to: %s: ", (id->minor_rev_num <= 31) ? minor_str[id->minor_rev_num] : "Unknown");
+		if (id->major_rev_num != 0x0000 &&  /* NOVAL_0 */
+		    id->major_rev_num != 0xFFFF) {  /* NOVAL_1 */
+			for (i=0; i <= 15; i++) {
+				if (id->major_rev_num & (1<<i))
+						printf(" ATA/ATAPI-%u", i);
+			}
+		}
+	}
+#endif /* __NEW_HD_DRIVE_ID */
+	printf("\n\n * current active mode\n\n");
+}
+#endif
+
+static void flush_buffer_cache(int fd)
+{
+	fsync(fd);				/* flush buffers */
+	bb_ioctl(fd, BLKFLSBUF, NULL,"BLKFLSBUF" ) ;/* do it again, big time */
+#ifdef HDIO_DRIVE_CMD
+	sleep(1);
+	if (ioctl(fd, HDIO_DRIVE_CMD, NULL) && errno != EINVAL)	/* await completion */
+		bb_perror_msg("HDIO_DRIVE_CMD");
+#endif
+}
+
+static int seek_to_zero(int fd)
+{
+	if (lseek(fd, (off_t) 0, SEEK_SET))
+		return 1;
+	return 0;
+}
+
+static int read_big_block(int fd, char *buf)
+{
+	int i;
+
+	if ((i = read(fd, buf, TIMING_BUF_BYTES)) != TIMING_BUF_BYTES) {
+		bb_error_msg("read(%d bytes) failed (rc=%d)", TIMING_BUF_BYTES, i);
+		return 1;
+	}
+	/* access all sectors of buf to ensure the read fully completed */
+	for (i = 0; i < TIMING_BUF_BYTES; i += 512)
+		buf[i] &= 1;
+	return 0;
+}
+
+static void print_timing(int t, double e)
+{
+	if (t >= e)  /* more than 1MB/s */
+		printf("%2d MB in %5.2f seconds =%6.2f %cB/sec\n", t, e, t / e, 'M');
+	else
+		printf("%2d MB in %5.2f seconds =%6.2f %cB/sec\n", t, e, t / e * 1024, 'k');
+}
+
+static int do_blkgetsize (int fd, unsigned long long *blksize64)
+{
+	int		rc;
+	unsigned int	blksize32 = 0;
+
+	if (0 == ioctl(fd, BLKGETSIZE64, blksize64)) {	// returns bytes
+		*blksize64 /= 512;
+		return 0;
+	}
+	rc = ioctl(fd, BLKGETSIZE, &blksize32);	// returns sectors
+	if (rc)
+		bb_perror_msg("BLKGETSIZE");
+	*blksize64 = blksize32;
+	return rc;
+}
+
+static void do_time(int flag, int fd)
+/*
+	flag = 0 time_cache
+	flag = 1 time_device
+*/
+{
+	struct itimerval e1, e2;
+	double elapsed, elapsed2;
+	unsigned int max_iterations = 1024, total_MB, iterations;
+	unsigned long long blksize;
+	RESERVE_CONFIG_BUFFER(buf, TIMING_BUF_BYTES);
+
+	if (mlock(buf, TIMING_BUF_BYTES)) {
+		bb_perror_msg("mlock");
+		goto quit2;
+	}
+
+	if (0 == do_blkgetsize(fd, &blksize)) {
+		max_iterations = blksize / (2 * 1024) / TIMING_BUF_MB;
+	}
+
+	/* Clear out the device request queues & give them time to complete */
+	sync();
+	sleep(3);
+
+	setitimer(ITIMER_REAL, &(struct itimerval){{1000,0},{1000,0}}, NULL);
+
+	if (flag  == 0) /* Time cache */
+	{
+		if (seek_to_zero (fd)) return;
+		if (read_big_block (fd, buf)) return;
+		printf(" Timing cached reads:   ");
+		fflush(stdout);
+	
+		/* Now do the timing */
+		iterations = 0;
+		getitimer(ITIMER_REAL, &e1);
+		do {
+			++iterations;
+			if (seek_to_zero (fd) || read_big_block (fd, buf))
+				goto quit;
+			getitimer(ITIMER_REAL, &e2);
+			elapsed = (e1.it_value.tv_sec - e2.it_value.tv_sec)
+			+ ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0);
+		} while (elapsed < 2.0);
+		total_MB = iterations * TIMING_BUF_MB;
+
+		/* Now remove the lseek() and getitimer() overheads from the elapsed time */
+		getitimer(ITIMER_REAL, &e1);
+		do {
+			if (seek_to_zero (fd))
+				goto quit;
+			getitimer(ITIMER_REAL, &e2);
+			elapsed2 = (e1.it_value.tv_sec - e2.it_value.tv_sec)
+			+ ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0);
+		} while (--iterations);
+	
+		elapsed -= elapsed2;
+		print_timing(BUFCACHE_FACTOR * total_MB, elapsed);	
+		flush_buffer_cache(fd);
+		sleep(1);
+	}
+	else /* Time device */
+	{
+		printf(" Timing buffered disk reads:  ");
+		fflush(stdout);
+		/*
+		* getitimer() is used rather than gettimeofday() because
+		* it is much more consistent (on my machine, at least).
+		*/
+		/* Now do the timings for real */
+		iterations = 0;
+		getitimer(ITIMER_REAL, &e1);
+		do {
+			++iterations;
+			if (read_big_block (fd, buf))
+				goto quit;
+			getitimer(ITIMER_REAL, &e2);
+			elapsed = (e1.it_value.tv_sec - e2.it_value.tv_sec)
+			+ ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0);
+		} while (elapsed < 3.0 && iterations < max_iterations);
+	
+		total_MB = iterations * TIMING_BUF_MB;
+		print_timing(total_MB, elapsed);
+	}
+quit:
+	munlock(buf, TIMING_BUF_BYTES);
+quit2:
+	RELEASE_CONFIG_BUFFER(buf);
+}
+
+static void on_off (unsigned int value)
+{
+	printf(value ? " (on)\n" : " (off)\n");
+}
+
+#ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
+static void bus_state_value(unsigned int value)
+{
+	if (value == BUSSTATE_ON)
+		on_off(1);
+	else if (value == BUSSTATE_OFF)
+		on_off(0);
+	else if (value == BUSSTATE_TRISTATE)
+		printf(" (tristate)\n");
+	else
+		printf(" (unknown: %d)\n", value);
+}
+#endif
+
+#ifdef HDIO_DRIVE_CMD
+static void interpret_standby(unsigned int standby)
+{
+	unsigned int t;
+
+
+	if (standby == 0)
+		printf("off");
+	else if (standby == 252)
+		printf("21 minutes");
+	else if (standby == 253)
+		printf("vendor-specific");
+	else if (standby == 254)
+		printf("Reserved");
+	else if (standby == 255)
+		printf("21 minutes + 15 seconds");
+	else {
+		if (standby <= 240) {
+			t = standby * 5;
+			printf("%u minutes + %u seconds", t / 60, t % 60);
+		} else if (standby <= 251) {
+			t = (standby - 240) * 30;
+			printf("%u hours + %u minutes", t / 60, t % 60);
+		} else
+			printf("illegal value");
+	}
+	printf(")\n");
+}
+
+struct xfermode_entry {
+    int val;
+    const char *name;
+};
+
+static const struct xfermode_entry xfermode_table[] = {
+    { 8,    "pio0" },
+    { 9,    "pio1" },
+    { 10,   "pio2" },
+    { 11,   "pio3" },
+    { 12,   "pio4" },
+    { 13,   "pio5" },
+    { 14,   "pio6" },
+    { 15,   "pio7" },
+    { 16,   "sdma0" },
+    { 17,   "sdma1" },
+    { 18,   "sdma2" },
+    { 19,   "sdma3" },
+    { 20,   "sdma4" },
+    { 21,   "sdma5" },
+    { 22,   "sdma6" },
+    { 23,   "sdma7" },
+    { 32,   "mdma0" },
+    { 33,   "mdma1" },
+    { 34,   "mdma2" },
+    { 35,   "mdma3" },
+    { 36,   "mdma4" },
+    { 37,   "mdma5" },
+    { 38,   "mdma6" },
+    { 39,   "mdma7" },
+    { 64,   "udma0" },
+    { 65,   "udma1" },
+    { 66,   "udma2" },
+    { 67,   "udma3" },
+    { 68,   "udma4" },
+    { 69,   "udma5" },
+    { 70,   "udma6" },
+    { 71,   "udma7" },
+    { 0, NULL }
+};
+
+static int translate_xfermode(char * name)
+{
+	const struct xfermode_entry *tmp;
+	char *endptr;
+	int val = -1;
+
+
+	for (tmp = xfermode_table; tmp->name != NULL; ++tmp)
+	{
+		if (!strcmp(name, tmp->name))
+			return tmp->val;
+	}
+
+	val = strtol(name, &endptr, 10);
+	if (*endptr == '\0')
+		return val;
+
+	return -1;
+}
+
+static void interpret_xfermode(unsigned int xfermode)
+{
+	printf(" (");
+	if (xfermode == 0)
+		printf("default PIO mode");
+	else if (xfermode == 1)
+		printf("default PIO mode, disable IORDY");
+	else if (xfermode >= 8 && xfermode <= 15)
+		printf("PIO flow control mode%u", xfermode-8);
+	else if (xfermode >= 16 && xfermode <= 23)
+		printf("singleword DMA mode%u", xfermode-16);
+	else if (xfermode >= 32 && xfermode <= 39)
+		printf("multiword DMA mode%u", xfermode-32);
+	else if (xfermode >= 64 && xfermode <= 71)
+		printf("UltraDMA mode%u", xfermode-64);
+	else
+		printf("Unknown");
+	printf(")\n");
+}
+#endif /* HDIO_DRIVE_CMD */
+
+static void print_flag(unsigned long flag, char *s, unsigned long value)
+{
+	if(flag)
+		printf(" setting %s to %ld\n", s, value);
+}
+
+static void process_dev(char *devname)
+{
+	int fd;
+	static long parm, multcount;
+#ifndef HDIO_DRIVE_CMD
+	int force_operation = 0;
+#endif
+	/* Please restore args[n] to these values after each ioctl
+	   except for args[2] */
+	unsigned char args[4] = {WIN_SETFEATURES,0,0,0};
+	const char *fmt = " %s\t= %2ld";
+
+	fd = bb_xopen(devname, O_RDONLY|O_NONBLOCK);
+	printf("\n%s:\n", devname);
+
+	if (set_readahead)
+	{
+		print_flag(get_readahead,"fs readahead", Xreadahead);
+		bb_ioctl(fd, BLKRASET,(int *)Xreadahead,"BLKRASET");
+	}
+#ifdef CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
+	if (unregister_hwif)
+	{
+		printf(" attempting to unregister hwif#%lu\n", hwif);
+		bb_ioctl(fd, HDIO_UNREGISTER_HWIF,(int *)(unsigned long)hwif,"HDIO_UNREGISTER_HWIF");
+	}
+#endif
+#ifdef CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF
+	if (scan_hwif)
+	{
+		printf(" attempting to scan hwif (0x%lx, 0x%lx, %lu)\n", hwif_data, hwif_ctrl, hwif_irq);
+		args[0] = hwif_data;
+		args[1] = hwif_ctrl;
+		args[2] = hwif_irq;
+		bb_ioctl(fd, HDIO_SCAN_HWIF, args, "HDIO_SCAN_HWIF");
+		args[0] = WIN_SETFEATURES;
+		args[1] = 0;
+	}
+#endif
+	if (set_piomode)
+	{
+		if (noisy_piomode)
+		{
+			printf(" attempting to ");
+			if (piomode == 255)
+				printf("auto-tune PIO mode\n");
+			else if (piomode < 100)
+				printf("set PIO mode to %d\n", piomode);
+			else if (piomode < 200)
+				printf("set MDMA mode to %d\n", (piomode-100));
+			else
+				printf("set UDMA mode to %d\n", (piomode-200));
+		}
+		bb_ioctl(fd, HDIO_SET_PIO_MODE, (int *)(unsigned long)piomode, "HDIO_SET_PIO_MODE");
+	}
+	if (set_io32bit)
+	{
+		print_flag(get_io32bit,"32-bit IO_support flag", io32bit);
+		bb_ioctl(fd, HDIO_SET_32BIT, (int *)io32bit, "HDIO_SET_32BIT");
+	}
+	if (set_mult)
+	{
+		print_flag(get_mult, "multcount", mult);
+#ifdef HDIO_DRIVE_CMD
+		bb_ioctl(fd, HDIO_SET_MULTCOUNT, &mult, "HDIO_SET_MULTCOUNT");
+#else
+		force_operation |= (!bb_ioctl(fd, HDIO_SET_MULTCOUNT, &mult, "HDIO_SET_MULTCOUNT"));
+#endif
+	}
+	if (set_readonly)
+	{
+		print_flag_on_off(get_readonly,"readonly", readonly);
+		bb_ioctl(fd, BLKROSET, &readonly, "BLKROSET");
+	}
+	if (set_unmask)
+	{
+		print_flag_on_off(get_unmask,"unmaskirq", unmask);
+		bb_ioctl(fd, HDIO_SET_UNMASKINTR, (int *)unmask, "HDIO_SET_UNMASKINTR");
+	}
+#ifdef CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA
+	if (set_dma)
+	{
+		print_flag_on_off(get_dma, "using_dma", dma);
+		bb_ioctl(fd, HDIO_SET_DMA, (int *)dma, "HDIO_SET_DMA");
+	}
+#endif /* CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA */
+	if (set_dma_q)
+	{
+		print_flag_on_off(get_dma_q,"DMA queue_depth", dma_q);
+		bb_ioctl(fd, HDIO_SET_QDMA, (int *)dma_q, "HDIO_SET_QDMA");
+	}
+	if (set_nowerr)
+	{
+		print_flag_on_off(get_nowerr,"nowerr", nowerr);
+		bb_ioctl(fd, HDIO_SET_NOWERR, (int *)nowerr,"HDIO_SET_NOWERR");
+	}
+	if (set_keep)
+	{
+		print_flag_on_off(get_keep,"keep_settings", keep);
+		bb_ioctl(fd, HDIO_SET_KEEPSETTINGS, (int *)keep,"HDIO_SET_KEEPSETTINGS");
+	}
+#ifdef HDIO_DRIVE_CMD
+	if (set_doorlock)
+	{
+		args[0] = doorlock ? WIN_DOORLOCK : WIN_DOORUNLOCK;
+		args[2] = 0;
+		print_flag_on_off(get_doorlock,"drive doorlock", doorlock);
+		bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD(doorlock)");
+		args[0] = WIN_SETFEATURES;
+	}
+	if (set_dkeep)
+	{
+		/* lock/unlock the drive's "feature" settings */
+		print_flag_on_off(get_dkeep,"drive keep features", dkeep);
+		args[2] = dkeep ? 0x66 : 0xcc;
+		bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD(keepsettings)");
+	}
+	if (set_defects)
+	{
+		args[2] = defects ? 0x04 : 0x84;
+		print_flag(get_defects,"drive defect-mgmt", defects);
+		bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD(defectmgmt)");
+	}
+	if (set_prefetch)
+	{
+		args[1] = prefetch;
+		args[2] = 0xab;
+		print_flag(get_prefetch,"drive prefetch", prefetch);
+		bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(setprefetch)");
+		args[1] = 0;
+	}
+	if (set_xfermode)
+	{
+		args[1] = xfermode_requested;
+		args[2] = 3;
+		if (get_xfermode)
+		{
+			print_flag(1,"xfermode", xfermode_requested);
+			interpret_xfermode(xfermode_requested);
+		}
+		bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD(setxfermode)");
+		args[1] = 0;
+	}
+	if (set_lookahead)
+	{
+		args[2] = lookahead ? 0xaa : 0x55;
+		print_flag_on_off(get_lookahead,"drive read-lookahead", lookahead);
+		bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(setreadahead)");
+	}
+	if (set_apmmode)
+	{
+		args[2] = (apmmode == 255) ? 0x85 /* disable */ : 0x05 /* set */; /* feature register */
+		args[1] = apmmode; /* sector count register 1-255 */
+		if (get_apmmode)
+			printf(" setting APM level to %s 0x%02lX (%ld)\n", (apmmode == 255) ? "disabled" : "", apmmode, apmmode);
+		bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD");
+		args[1] = 0;
+	}
+	if (set_wcache)
+	{
+#ifdef DO_FLUSHCACHE
+#ifndef WIN_FLUSHCACHE
+#define WIN_FLUSHCACHE 0xe7
+#endif
+		static unsigned char flushcache[4] = {WIN_FLUSHCACHE,0,0,0};
+#endif /* DO_FLUSHCACHE */
+		args[2] = wcache ? 0x02 : 0x82;
+		print_flag_on_off(get_wcache,"drive write-caching", wcache);
+#ifdef DO_FLUSHCACHE
+		if (!wcache)
+			bb_ioctl(fd, HDIO_DRIVE_CMD, &flushcache, "HDIO_DRIVE_CMD(flushcache)");
+#endif /* DO_FLUSHCACHE */
+		bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(setcache)");
+#ifdef DO_FLUSHCACHE
+		if (!wcache)
+			bb_ioctl(fd, HDIO_DRIVE_CMD, &flushcache, "HDIO_DRIVE_CMD(flushcache)");
+#endif /* DO_FLUSHCACHE */
+	}
+
+	/* In code below, we do not preserve args[0], but the rest
+	   is preserved, including args[2] */
+	args[2] = 0;
+
+	if (set_standbynow)
+	{
+#ifndef WIN_STANDBYNOW1
+#define WIN_STANDBYNOW1 0xE0
+#endif
+#ifndef WIN_STANDBYNOW2
+#define WIN_STANDBYNOW2 0x94
+#endif
+		if (get_standbynow) printf(" issuing standby command\n");
+		args[0] = WIN_STANDBYNOW1;
+		bb_ioctl_alt(fd, HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2, "HDIO_DRIVE_CMD(standby)");
+	}
+	if (set_sleepnow)
+	{
+#ifndef WIN_SLEEPNOW1
+#define WIN_SLEEPNOW1 0xE6
+#endif
+#ifndef WIN_SLEEPNOW2
+#define WIN_SLEEPNOW2 0x99
+#endif
+		if (get_sleepnow) printf(" issuing sleep command\n");
+		args[0] = WIN_SLEEPNOW1;
+		bb_ioctl_alt(fd, HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2, "HDIO_DRIVE_CMD(sleep)");
+	}
+	if (set_seagate)
+	{
+		args[0] = 0xfb;
+		if (get_seagate) printf(" disabling Seagate auto powersaving mode\n");
+		bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(seagatepwrsave)");
+	}
+	if (set_standby)
+	{
+		args[0] = WIN_SETIDLE1;
+		args[1] = standby_requested;
+		if (get_standby)
+		{
+			print_flag(1,"standby", standby_requested);
+			interpret_standby(standby_requested);
+		}
+		bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(setidle1)");
+		args[1] = 0;
+	}
+#else	/* HDIO_DRIVE_CMD */
+	if (force_operation)
+	{
+		char buf[512];
+		flush_buffer_cache(fd);
+		if (-1 == read(fd, buf, sizeof(buf)))
+			bb_perror_msg("read(%d bytes) failed (rc=%d)", sizeof(buf), -1);
+	}
+#endif	/* HDIO_DRIVE_CMD */
+
+	if (get_mult || get_identity)
+	{
+		multcount = -1;
+		if (ioctl(fd, HDIO_GET_MULTCOUNT, &multcount))
+		{
+			if (get_mult)
+				bb_perror_msg("HDIO_GET_MULTCOUNT");
+		}
+		else if (get_mult)
+		{
+			printf(fmt, "multcount", multcount);
+			on_off(multcount);
+		}
+	}
+	if (get_io32bit)
+	{
+		if (!bb_ioctl(fd, HDIO_GET_32BIT, &parm, "HDIO_GET_32BIT"))
+		{
+			printf(" IO_support\t=%3ld (", parm);
+			if (parm == 0)
+				printf("default 16-bit)\n");
+			else if (parm == 2)
+				printf("16-bit)\n");
+			else if (parm == 1)
+				printf("32-bit)\n");
+			else if (parm == 3)
+				printf("32-bit w/sync)\n");
+			else if (parm == 8)
+				printf("Request-Queue-Bypass)\n");
+			else
+				printf("\?\?\?)\n");
+		}
+	}
+	if (get_unmask)
+	{
+		bb_ioctl_on_off(fd, HDIO_GET_UNMASKINTR,(unsigned long *)parm,
+						"HDIO_GET_UNMASKINTR","unmaskirq");
+	}
+
+
+#ifdef CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA
+	if (get_dma) {
+		if (!bb_ioctl(fd, HDIO_GET_DMA, &parm, "HDIO_GET_DMA"))
+		{
+			printf(fmt, "using_dma", parm);
+			if (parm == 8)
+				printf(" (DMA-Assisted-PIO)\n");
+			else
+				on_off(parm);
+		}
+	}
+#endif
+	if (get_dma_q)
+	{
+		bb_ioctl_on_off (fd, HDIO_GET_QDMA,(unsigned long *)parm,
+						  "HDIO_GET_QDMA","queue_depth");
+	}
+	if (get_keep)
+	{
+		bb_ioctl_on_off (fd, HDIO_GET_KEEPSETTINGS,(unsigned long *)parm,
+							"HDIO_GET_KEEPSETTINGS","keepsettings");
+	}
+
+	if (get_nowerr)
+	{
+		bb_ioctl_on_off  (fd, HDIO_GET_NOWERR,(unsigned long *)&parm,
+							"HDIO_GET_NOWERR","nowerr");
+	}
+	if (get_readonly)
+	{
+		bb_ioctl_on_off(fd, BLKROGET,(unsigned long *)parm,
+						  "BLKROGET","readonly");
+	}
+	if (get_readahead)
+	{
+		bb_ioctl_on_off (fd, BLKRAGET, (unsigned long *) parm,
+							"BLKRAGET","readahead");
+	}
+	if (get_geom)
+	{
+		if (!bb_ioctl(fd, BLKGETSIZE, &parm, "BLKGETSIZE"))
+		{
+			struct hd_geometry g;
+
+			if (!bb_ioctl(fd, HDIO_GETGEO, &g, "HDIO_GETGEO"))
+				printf(" geometry\t= %u/%u/%u, sectors = %ld, start = %ld\n",
+						g.cylinders, g.heads, g.sectors, parm, g.start);
+		}
+	}
+#ifdef HDIO_DRIVE_CMD
+	if (get_powermode)
+	{
+#ifndef WIN_CHECKPOWERMODE1
+#define WIN_CHECKPOWERMODE1 0xE5
+#endif
+#ifndef WIN_CHECKPOWERMODE2
+#define WIN_CHECKPOWERMODE2 0x98
+#endif
+		const char *state;
+
+		args[0] = WIN_CHECKPOWERMODE1;
+		if (bb_ioctl_alt(fd, HDIO_DRIVE_CMD, args, WIN_CHECKPOWERMODE2, 0))
+		{
+			if (errno != EIO || args[0] != 0 || args[1] != 0)
+				state = "Unknown";
+			else
+				state = "sleeping";
+		}
+		else
+			state = (args[2] == 255) ? "active/idle" : "standby";
+		args[1] = args[2] = 0;
+
+		printf(" drive state is:  %s\n", state);
+	}
+#endif
+#ifdef CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET
+	if (perform_reset)
+	{
+		bb_ioctl(fd, HDIO_DRIVE_RESET, NULL, "HDIO_DRIVE_RESET");
+	}
+#endif /* CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET */
+#ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
+	if (perform_tristate)
+	{
+		args[0] = 0;
+		args[1] = tristate;
+		bb_ioctl(fd, HDIO_TRISTATE_HWIF, &args, "HDIO_TRISTATE_HWIF");
+	}
+#endif /* CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF */
+#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
+	if (get_identity)
+	{
+		static struct hd_driveid id;
+
+		if (!ioctl(fd, HDIO_GET_IDENTITY, &id))
+		{
+			if (multcount != -1)
+			{
+				id.multsect = multcount;
+				id.multsect_valid |= 1;
+			}
+			else
+				id.multsect_valid &= ~1;
+			dump_identity(&id);
+		}
+		else if (errno == -ENOMSG)
+			printf(" no identification info available\n");
+		else
+			bb_perror_msg("HDIO_GET_IDENTITY");
+	}
+
+	if (get_IDentity)
+	{
+		unsigned char args1[4+512]; /* = { ... } will eat 0.5k of rodata! */
+
+		memset(args1, 0, sizeof(args1));
+		args1[0] = WIN_IDENTIFY;
+		args1[3] = 1;
+		if (!bb_ioctl_alt(fd, HDIO_DRIVE_CMD, args1, WIN_PIDENTIFY, "HDIO_DRIVE_CMD(identify)"))
+			identify((void *)(args1 + 4));
+	}
+#endif
+#ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
+	if (set_busstate)
+	{
+		if (get_busstate)
+		{
+			print_flag(1, "bus state", busstate);
+			bus_state_value(busstate);
+		}
+		bb_ioctl(fd, HDIO_SET_BUSSTATE, (int *)(unsigned long)busstate, "HDIO_SET_BUSSTATE");
+	}
+	if (get_busstate)
+	{
+		if (!bb_ioctl(fd, HDIO_GET_BUSSTATE, &parm, "HDIO_GET_BUSSTATE"))
+		{
+			printf(fmt, "bus state", parm);
+			bus_state_value(parm);
+		}
+	}
+#endif
+	if (reread_partn)
+		bb_ioctl(fd, BLKRRPART, NULL, "BLKRRPART");
+
+
+	if (do_ctimings)
+		do_time(0,fd);		/*time cache  */
+	if (do_timings)
+		do_time(1,fd);		/*time device */
+	if (do_flush)
+		flush_buffer_cache(fd);
+	close(fd);
+}
+
+#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY
+static int fromhex(unsigned char c)
+{
+	if (c >= 'a' && c <= 'f')
+		return 10 + (c - 'a');
+	if (c >= '0' && c <= '9')
+		return (c - '0');
+	bb_error_msg_and_die("bad char: '%c' 0x%02x", c, c);
+}
+
+static void identify_from_stdin(void)
+{
+	uint16_t sbuf[256];
+	unsigned char  buf[1280], *b = (unsigned char *)buf;
+	int i, count = read(0, buf, 1280);
+
+	if (count != 1280)
+		bb_error_msg_and_die("read(%d bytes) failed (rc=%d)", 1280, count);
+
+	// Convert the newline-separated hex data into an identify block.
+
+	for (i = 0; i<256; i++)
+	{
+		int j;
+		for(j=0;j<4;j++) sbuf[i] = (sbuf[i] <<4) + fromhex(*(b++));
+	}
+
+	// Parse the data.
+
+	identify(sbuf);
+}
+#endif
+
+/* busybox specific stuff */
+static void parse_opts(unsigned long *get, unsigned long *set, unsigned long *value, int min, int max)
+{
+		if (get) {
+			*get = 1;
+		}
+		if (optarg) {
+			*set = 1;
+			*value = bb_xgetlarg(optarg, 10, min, max);
+		}
+}
+
+static void parse_xfermode(int flag, unsigned long *get, unsigned long *set, int *value)
+{
+	if (flag) {
+		*get = 1;
+		if (optarg) {
+			*set = ((*value = translate_xfermode(optarg)) > -1);
+		}
+	}
+}
+
+/*------- getopt short options --------*/
+static const char hdparm_options[]=	"gfu::n::p:r::m::c::k::a::B:tTh"\
+	USE_FEATURE_HDPARM_GET_IDENTITY("iI")
+	USE_FEATURE_HDPARM_HDIO_GETSET_DMA("d::")
+#ifdef HDIO_DRIVE_CMD
+									"S::D::P::X::K::A::L::W::CyYzZ"
+#endif
+	USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF("U:")
+#ifdef HDIO_GET_QDMA
+#ifdef HDIO_SET_QDMA
+									"Q:"
+#else
+									"Q"
+#endif
+#endif
+	USE_FEATURE_HDPARM_HDIO_DRIVE_RESET("w")
+	USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF("x::b:")
+	USE_FEATURE_HDPARM_HDIO_SCAN_HWIF("R:");
+/*-------------------------------------*/
+
+/* our main() routine: */
+int hdparm_main(int argc, char **argv) ATTRIBUTE_NORETURN;
+int hdparm_main(int argc, char **argv)
+{
+	int c;
+	int flagcount = 0;
+
+	while ((c = getopt(argc, argv, hdparm_options)) >= 0) {
+		flagcount++;
+		if (c == 'h') bb_show_usage(); /* EXIT */
+		USE_FEATURE_HDPARM_GET_IDENTITY(get_IDentity |= (c == 'I'));
+		USE_FEATURE_HDPARM_GET_IDENTITY(get_identity |= (c == 'i'));
+		get_geom |= (c == 'g');
+		do_flush |= (c == 'f');
+		if (c == 'u') parse_opts(&get_unmask, &set_unmask, &unmask, 0, 1);
+		USE_FEATURE_HDPARM_HDIO_GETSET_DMA(if (c == 'd') parse_opts(&get_dma, &set_dma, &dma, 0, 9));
+		if (c == 'n') parse_opts(&get_nowerr, &set_nowerr, &nowerr, 0, 1);
+		parse_xfermode((c == 'p'),&noisy_piomode, &set_piomode, &piomode);
+		if (c == 'r') parse_opts(&get_readonly, &set_readonly, &readonly, 0, 1);
+		if (c == 'm') parse_opts(&get_mult, &set_mult, &mult, 0, INT_MAX /*32*/);
+		if (c == 'c') parse_opts(&get_io32bit, &set_io32bit, &io32bit, 0, INT_MAX /*8*/);
+		if (c == 'k') parse_opts(&get_keep, &set_keep, &keep, 0, 1);
+		if (c == 'a') parse_opts(&get_readahead, &set_readahead, &Xreadahead, 0, INT_MAX);
+		if (c == 'B') parse_opts(&get_apmmode, &set_apmmode, &apmmode, 1, 255);
+		do_flush |= do_timings |= (c == 't');
+		do_flush |= do_ctimings |= (c == 'T');
+#ifdef HDIO_DRIVE_CMD
+		if (c == 'S') parse_opts(&get_standby, &set_standby, &standby_requested, 0, INT_MAX);	
+		if (c == 'D') parse_opts(&get_defects, &set_defects, &defects, 0, INT_MAX);
+		if (c == 'P') parse_opts(&get_prefetch, &set_prefetch, &prefetch, 0, INT_MAX);
+		parse_xfermode((c == 'X'), &get_xfermode, &set_xfermode, &xfermode_requested);
+		if (c == 'K') parse_opts(&get_dkeep, &set_dkeep, &prefetch, 0, 1);
+		if (c == 'A') parse_opts(&get_lookahead, &set_lookahead, &lookahead, 0, 1);
+		if (c == 'L') parse_opts(&get_doorlock, &set_doorlock, &doorlock, 0, 1);
+		if (c == 'W') parse_opts(&get_wcache, &set_wcache, &wcache, 0, 1);
+		get_powermode |= (c == 'C');
+		get_standbynow = set_standbynow |= (c == 'y');
+		get_sleepnow = set_sleepnow |= (c == 'Y');
+		reread_partn |= (c == 'z');
+		get_seagate = set_seagate |= (c == 'Z');
+#endif
+		USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(if (c == 'U') parse_opts(NULL, &unregister_hwif, &hwif, 0, INT_MAX));	
+#ifdef HDIO_GET_QDMA
+		if (c == 'Q') {
+#ifdef HDIO_SET_QDMA
+			parse_opts(&get_dma_q, &set_dma_q, &dma_q, 0, INT_MAX);
+#else
+			parse_opts(&get_dma_q, NULL, NULL, 0, 0);	
+#endif
+		}
+#endif		
+		USE_FEATURE_HDPARM_HDIO_DRIVE_RESET(perform_reset = (c == 'r'));
+		USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'x') parse_opts(NULL, &perform_tristate, &tristate, 0, 1));	
+		USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'b') parse_opts(&get_busstate, &set_busstate, &busstate, 0, 2));	
+#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
+		if (c == 'R') {
+			parse_opts(NULL, &scan_hwif, &hwif_data, 0, INT_MAX);	
+			hwif_ctrl =  bb_xgetlarg((argv[optind]) ? argv[optind] : "", 10, 0, INT_MAX);
+			hwif_irq  =  bb_xgetlarg((argv[optind+1]) ? argv[optind+1] : "", 10, 0, INT_MAX);
+			/* Move past the 2 additional arguments */
+			argv += 2;
+			argc -= 2;
+		}
+#endif
+	}
+	/* When no flags are given (flagcount = 0), -acdgkmnru is assumed. */
+	if (!flagcount){
+		get_mult = get_io32bit = get_unmask = get_keep = get_readonly = get_readahead = get_geom = 1;
+		USE_FEATURE_HDPARM_HDIO_GETSET_DMA(get_dma = 1);
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc < 1) {
+		if (ENABLE_FEATURE_HDPARM_GET_IDENTITY && !isatty(STDIN_FILENO))
+			identify_from_stdin(); /* EXIT */
+		else bb_show_usage();
+	}
+
+	while (argc--) {
+		process_dev(*argv);
+		argv++;
+	}
+	exit(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/last.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/last.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/last.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,99 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * last implementation for busybox
+ *
+ * Copyright (C) 2003-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <utmp.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef SHUTDOWN_TIME
+#  define SHUTDOWN_TIME 254
+#endif
+
+/* Grr... utmp char[] members  do not have to be nul-terminated.
+ * Do what we can while still keeping this reasonably small.
+ * Note: We are assuming the ut_id[] size is fixed at 4. */
+
+#if defined UT_LINESIZE \
+	&& ((UT_LINESIZE != 32) || (UT_NAMESIZE != 32) || (UT_HOSTSIZE != 256))
+#error struct utmp member char[] size(s) have changed!
+#elif defined __UT_LINESIZE \
+	&& ((__UT_LINESIZE != 32) || (__UT_NAMESIZE != 64) || (__UT_HOSTSIZE != 256))
+#error struct utmp member char[] size(s) have changed!
+#endif
+
+int last_main(int argc, char **argv)
+{
+	struct utmp ut;
+	int n, file = STDIN_FILENO;
+	time_t t_tmp;
+
+	if (argc > 1) {
+		bb_show_usage();
+	}
+	file = bb_xopen(bb_path_wtmp_file, O_RDONLY);
+
+	printf("%-10s %-14s %-18s %-12.12s %s\n", "USER", "TTY", "HOST", "LOGIN", "TIME");
+	while ((n = safe_read(file, (void*)&ut, sizeof(struct utmp))) != 0) {
+
+		if (n != sizeof(struct utmp)) {
+			bb_perror_msg_and_die("short read");
+		}
+
+		if (strncmp(ut.ut_line, "~", 1) == 0) {
+			if (strncmp(ut.ut_user, "shutdown", 8) == 0)
+				ut.ut_type = SHUTDOWN_TIME;
+			else if (strncmp(ut.ut_user, "reboot", 6) == 0)
+				ut.ut_type = BOOT_TIME;
+			else if (strncmp(ut.ut_user, "runlevel", 7) == 0)
+				ut.ut_type = RUN_LVL;
+		} else {
+			if (!ut.ut_name[0] || strcmp(ut.ut_name, "LOGIN") == 0 ||
+					ut.ut_name[0] == 0)
+			{
+				/* Don't bother.  This means we can't find how long
+				 * someone was logged in for.  Oh well. */
+				continue;
+			}
+			if (ut.ut_type != DEAD_PROCESS &&
+					ut.ut_name[0] && ut.ut_line[0])
+			{
+				ut.ut_type = USER_PROCESS;
+			}
+			if (strcmp(ut.ut_name, "date") == 0) {
+				if (ut.ut_line[0] == '|') ut.ut_type = OLD_TIME;
+				if (ut.ut_line[0] == '{') ut.ut_type = NEW_TIME;
+			}
+		}
+
+		if (ut.ut_type!=USER_PROCESS) {
+			switch (ut.ut_type) {
+				case OLD_TIME:
+				case NEW_TIME:
+				case RUN_LVL:
+				case SHUTDOWN_TIME:
+					continue;
+				case BOOT_TIME:
+					strcpy(ut.ut_line, "system boot");
+					break;
+			}
+		}
+		t_tmp = (time_t)ut.ut_tv.tv_sec;
+		printf("%-10s %-14s %-18s %-12.12s\n", ut.ut_user, ut.ut_line, ut.ut_host,
+				ctime(&t_tmp) + 4);
+	}
+
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/less.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/less.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/less.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1151 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini less implementation for busybox
+ *
+ * Copyright (C) 2005 by Rob Sullivan <cogito.ergo.cogito at gmail.com>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+/*
+ *      This program needs a lot of development, so consider it in a beta stage
+ *      at best.
+ *
+ *      TODO:
+ *      - Add more regular expression support - search modifiers, certain matches, etc.
+ *      - Add more complex bracket searching - currently, nested brackets are
+ *      not considered.
+ *      - Add support for "F" as an input. This causes less to act in
+ *      a similar way to tail -f.
+ *      - Check for binary files, and prompt the user if a binary file
+ *      is detected.
+ *      - Allow horizontal scrolling. Currently, lines simply continue onto
+ *      the next line, per the terminal's discretion
+ *
+ *      Notes:
+ *      - filename is an array and not a pointer because that avoids all sorts
+ *      of complications involving the fact that something that is pointed to
+ *      will be changed if the pointer is changed.
+ *      - the inp file pointer is used so that keyboard input works after
+ *      redirected input has been read from stdin
+*/
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#ifdef CONFIG_FEATURE_LESS_REGEXP
+#include "xregex.h"
+#endif
+
+
+/* These are the escape sequences corresponding to special keys */
+#define REAL_KEY_UP 'A'
+#define REAL_KEY_DOWN 'B'
+#define REAL_KEY_RIGHT 'C'
+#define REAL_KEY_LEFT 'D'
+#define REAL_PAGE_UP '5'
+#define REAL_PAGE_DOWN '6'
+
+/* These are the special codes assigned by this program to the special keys */
+#define PAGE_UP 20
+#define PAGE_DOWN 21
+#define KEY_UP 22
+#define KEY_DOWN 23
+#define KEY_RIGHT 24
+#define KEY_LEFT 25
+
+/* The escape codes for highlighted and normal text */
+#define HIGHLIGHT "\033[7m"
+#define NORMAL "\033[0m"
+
+/* The escape code to clear the screen */
+#define CLEAR "\033[H\033[J"
+
+/* Maximum number of lines in a file */
+#define MAXLINES 10000
+
+static int height;
+static int width;
+static char **files;
+static char filename[256];
+static char **buffer;
+static char **flines;
+static int current_file = 1;
+static int line_pos;
+static int num_flines;
+static int num_files = 1;
+static int past_eof;
+
+/* Command line options */
+static unsigned long flags;
+#define FLAG_E 1
+#define FLAG_M (1<<1)
+#define FLAG_m (1<<2)
+#define FLAG_N (1<<3)
+#define FLAG_TILDE (1<<4)
+
+/* This is needed so that program behaviour changes when input comes from
+   stdin */
+static int inp_stdin;
+
+#ifdef CONFIG_FEATURE_LESS_MARKS
+static int mark_lines[15][2];
+static int num_marks;
+#endif
+
+#ifdef CONFIG_FEATURE_LESS_REGEXP
+static int match_found;
+static int *match_lines;
+static int match_pos;
+static int num_matches;
+static int match_backwards;
+static regex_t old_pattern;
+#endif
+
+/* Needed termios structures */
+static struct termios term_orig, term_vi;
+
+/* File pointer to get input from */
+static FILE *inp;
+
+/* Reset terminal input to normal */
+static void set_tty_cooked(void)
+{
+	fflush(stdout);
+	tcsetattr(fileno(inp), TCSANOW, &term_orig);
+}
+
+/* Set terminal input to raw mode  (taken from vi.c) */
+static void set_tty_raw(void)
+{
+	tcsetattr(fileno(inp), TCSANOW, &term_vi);
+}
+
+/* Exit the program gracefully */
+static void tless_exit(int code)
+{
+	/* TODO: We really should save the terminal state when we start,
+		 and restore it when we exit. Less does this with the
+		 "ti" and "te" termcap commands; can this be done with
+		 only termios.h? */
+
+	putchar('\n');
+	exit(code);
+}
+
+/* Grab a character from input without requiring the return key. If the
+   character is ASCII \033, get more characters and assign certain sequences
+   special return codes. Note that this function works best with raw input. */
+static int tless_getch(void)
+{
+	int input;
+
+	set_tty_raw();
+
+	input = getc(inp);
+	/* Detect escape sequences (i.e. arrow keys) and handle
+	   them accordingly */
+
+	if (input == '\033' && getc(inp) == '[') {
+		input = getc(inp);
+		set_tty_cooked();
+		if (input == REAL_KEY_UP)
+			return KEY_UP;
+		else if (input == REAL_KEY_DOWN)
+			return KEY_DOWN;
+		else if (input == REAL_KEY_RIGHT)
+			return KEY_RIGHT;
+		else if (input == REAL_KEY_LEFT)
+			return KEY_LEFT;
+		else if (input == REAL_PAGE_UP)
+			return PAGE_UP;
+		else if (input == REAL_PAGE_DOWN)
+			return PAGE_DOWN;
+	}
+	/* The input is a normal ASCII value */
+	else {
+		set_tty_cooked();
+		return input;
+	}
+	return 0;
+}
+
+/* Move the cursor to a position (x,y), where (0,0) is the
+   top-left corner of the console */
+static void move_cursor(int x, int y)
+{
+	printf("\033[%i;%iH", x, y);
+}
+
+static void clear_line(void)
+{
+	move_cursor(height, 0);
+	printf("\033[K");
+}
+
+/* This adds line numbers to every line, as the -N flag necessitates */
+static void add_linenumbers(void)
+{
+	char current_line[256];
+	int i;
+
+	for (i = 0; i <= num_flines; i++) {
+		safe_strncpy(current_line, flines[i], 256);
+		flines[i] = bb_xasprintf("%5d %s", i + 1, current_line);
+	}
+}
+
+static void data_readlines(void)
+{
+	int i;
+	char current_line[256];
+	FILE *fp;
+
+	fp = (inp_stdin) ? stdin : bb_xfopen(filename, "r");
+	flines = NULL;
+	for (i = 0; (feof(fp)==0) && (i <= MAXLINES); i++) {
+		strcpy(current_line, "");
+		fgets(current_line, 256, fp);
+		if (fp != stdin)
+			bb_xferror(fp, filename);
+		flines = xrealloc(flines, (i+1) * sizeof(char *));
+		flines[i] = bb_xstrdup(current_line);
+	}
+	num_flines = i - 2;
+
+	/* Reset variables for a new file */
+
+	line_pos = 0;
+	past_eof = 0;
+
+	fclose(fp);
+
+	if (inp == NULL)
+		inp = (inp_stdin) ? bb_xfopen(CURRENT_TTY, "r") : stdin;
+
+	if (flags & FLAG_N)
+		add_linenumbers();
+}
+
+#ifdef CONFIG_FEATURE_LESS_FLAGS
+
+/* Interestingly, writing calc_percent as a function and not a prototype saves around 32 bytes
+ * on my build. */
+static int calc_percent(void)
+{
+	return ((100 * (line_pos + height - 2) / num_flines) + 1);
+}
+
+/* Print a status line if -M was specified */
+static void m_status_print(void)
+{
+	int percentage;
+
+	if (!past_eof) {
+		if (!line_pos) {
+			if (num_files > 1)
+				printf("%s%s %s%i%s%i%s%i-%i/%i ", HIGHLIGHT, filename, "(file ", current_file, " of ", num_files, ") lines ", line_pos + 1, line_pos + height - 1, num_flines + 1);
+			else {
+				printf("%s%s lines %i-%i/%i ", HIGHLIGHT, filename, line_pos + 1, line_pos + height - 1, num_flines + 1);
+			}
+		}
+		else {
+			printf("%s %s lines %i-%i/%i ", HIGHLIGHT, filename, line_pos + 1, line_pos + height - 1, num_flines + 1);
+		}
+
+		if (line_pos == num_flines - height + 2) {
+			printf("(END) %s", NORMAL);
+			if ((num_files > 1) && (current_file != num_files))
+				printf("%s- Next: %s%s", HIGHLIGHT, files[current_file], NORMAL);
+		}
+		else {
+			percentage = calc_percent();
+			printf("%i%% %s", percentage, NORMAL);
+		}
+	}
+	else {
+		printf("%s%s lines %i-%i/%i (END) ", HIGHLIGHT, filename, line_pos + 1, num_flines + 1, num_flines + 1);
+		if ((num_files > 1) && (current_file != num_files))
+			printf("- Next: %s", files[current_file]);
+		printf("%s", NORMAL);
+	}
+}
+
+/* Print a status line if -m was specified */
+static void medium_status_print(void)
+{
+	int percentage;
+	percentage = calc_percent();
+
+	if (!line_pos)
+		printf("%s%s %i%%%s", HIGHLIGHT, filename, percentage, NORMAL);
+	else if (line_pos == num_flines - height + 2)
+		printf("%s(END)%s", HIGHLIGHT, NORMAL);
+	else
+		printf("%s%i%%%s", HIGHLIGHT, percentage, NORMAL);
+}
+#endif
+
+/* Print the status line */
+static void status_print(void)
+{
+	/* Change the status if flags have been set */
+#ifdef CONFIG_FEATURE_LESS_FLAGS
+	if (flags & FLAG_M)
+		m_status_print();
+	else if (flags & FLAG_m)
+		medium_status_print();
+	/* No flags set */
+	else {
+#endif
+		if (!line_pos) {
+			printf("%s%s %s", HIGHLIGHT, filename, NORMAL);
+			if (num_files > 1)
+				printf("%s%s%i%s%i%s%s", HIGHLIGHT, "(file ", current_file, " of ", num_files, ")", NORMAL);
+		}
+		else if (line_pos == num_flines - height + 2) {
+			printf("%s%s %s", HIGHLIGHT, "(END)", NORMAL);
+			if ((num_files > 1) && (current_file != num_files))
+				printf("%s%s%s%s", HIGHLIGHT, "- Next: ", files[current_file], NORMAL);
+		}
+		else {
+			putchar(':');
+		}
+#ifdef CONFIG_FEATURE_LESS_FLAGS
+	}
+#endif
+}
+
+/* Print the buffer */
+static void buffer_print(void)
+{
+	int i;
+
+	printf("%s", CLEAR);
+	if (num_flines >= height - 2) {
+		for (i = 0; i < height - 1; i++)
+			printf("%s", buffer[i]);
+	}
+	else {
+		for (i = 1; i < (height - 1 - num_flines); i++)
+			putchar('\n');
+		for (i = 0; i < height - 1; i++)
+			printf("%s", buffer[i]);
+	}
+
+	status_print();
+}
+
+/* Initialise the buffer */
+static void buffer_init(void)
+{
+	int i;
+
+	if (buffer == NULL) {
+		/* malloc the number of lines needed for the buffer */
+		buffer = xrealloc(buffer, height * sizeof(char *));
+	} else {
+		for (i = 0; i < (height - 1); i++)
+			free(buffer[i]);
+	}
+
+	/* Fill the buffer until the end of the file or the
+	   end of the buffer is reached */
+	for (i = 0; (i < (height - 1)) && (i <= num_flines); i++) {
+		buffer[i] = bb_xstrdup(flines[i]);
+	}
+
+	/* If the buffer still isn't full, fill it with blank lines */
+	for (; i < (height - 1); i++) {
+		buffer[i] = bb_xstrdup("");
+	}
+}
+
+/* Move the buffer up and down in the file in order to scroll */
+static void buffer_down(int nlines)
+{
+	int i;
+
+	if (!past_eof) {
+		if (line_pos + (height - 3) + nlines < num_flines) {
+			line_pos += nlines;
+			for (i = 0; i < (height - 1); i++) {
+				free(buffer[i]);
+				buffer[i] = bb_xstrdup(flines[line_pos + i]);
+			}
+		}
+		else {
+			/* As the number of lines requested was too large, we just move
+			to the end of the file */
+			while (line_pos + (height - 3) + 1 < num_flines) {
+				line_pos += 1;
+				for (i = 0; i < (height - 1); i++) {
+					free(buffer[i]);
+					buffer[i] = bb_xstrdup(flines[line_pos + i]);
+				}
+			}
+		}
+
+		/* We exit if the -E flag has been set */
+		if ((flags & FLAG_E) && (line_pos + (height - 2) == num_flines))
+			tless_exit(0);
+	}
+}
+
+static void buffer_up(int nlines)
+{
+	int i;
+	int tilde_line;
+
+	if (!past_eof) {
+		if (line_pos - nlines >= 0) {
+			line_pos -= nlines;
+			for (i = 0; i < (height - 1); i++) {
+				free(buffer[i]);
+				buffer[i] = bb_xstrdup(flines[line_pos + i]);
+			}
+		}
+		else {
+		/* As the requested number of lines to move was too large, we
+		   move one line up at a time until we can't. */
+			while (line_pos != 0) {
+				line_pos -= 1;
+				for (i = 0; i < (height - 1); i++) {
+					free(buffer[i]);
+					buffer[i] = bb_xstrdup(flines[line_pos + i]);
+				}
+			}
+		}
+	}
+	else {
+		/* Work out where the tildes start */
+		tilde_line = num_flines - line_pos + 3;
+
+		line_pos -= nlines;
+		/* Going backwards nlines lines has taken us to a point where
+		   nothing is past the EOF, so we revert to normal. */
+		if (line_pos < num_flines - height + 3) {
+			past_eof = 0;
+			buffer_up(nlines);
+		}
+		else {
+			/* We only move part of the buffer, as the rest
+			is past the EOF */
+			for (i = 0; i < (height - 1); i++) {
+				free(buffer[i]);
+				if (i < tilde_line - nlines + 1)
+					buffer[i] = bb_xstrdup(flines[line_pos + i]);
+				else {
+					if (line_pos >= num_flines - height + 2)
+						buffer[i] = bb_xstrdup("~\n");
+				}
+			}
+		}
+	}
+}
+
+static void buffer_line(int linenum)
+{
+	int i;
+	past_eof = 0;
+
+	if (linenum < 0 || linenum > num_flines) {
+		clear_line();
+		printf("%s%s%i%s", HIGHLIGHT, "Cannot seek to line number ", linenum + 1, NORMAL);
+	}
+	else if (linenum < (num_flines - height - 2)) {
+		for (i = 0; i < (height - 1); i++) {
+			free(buffer[i]);
+			buffer[i] = bb_xstrdup(flines[linenum + i]);
+		}
+		line_pos = linenum;
+		buffer_print();
+	}
+	else {
+		for (i = 0; i < (height - 1); i++) {
+			free(buffer[i]);
+			if (linenum + i < num_flines + 2)
+				buffer[i] = bb_xstrdup(flines[linenum + i]);
+			else
+				buffer[i] = bb_xstrdup((flags & FLAG_TILDE) ? "\n" : "~\n");
+		}
+		line_pos = linenum;
+		/* Set past_eof so buffer_down and buffer_up act differently */
+		past_eof = 1;
+		buffer_print();
+	}
+}
+
+/* Reinitialise everything for a new file - free the memory and start over */
+static void reinitialise(void)
+{
+	int i;
+
+	for (i = 0; i <= num_flines; i++)
+		free(flines[i]);
+	free(flines);
+
+	data_readlines();
+	buffer_init();
+	buffer_print();
+}
+
+static void examine_file(void)
+{
+	int newline_offset;
+
+	clear_line();
+	printf("Examine: ");
+	fgets(filename, 256, inp);
+
+	/* As fgets adds a newline to the end of an input string, we
+	   need to remove it */
+	newline_offset = strlen(filename) - 1;
+	filename[newline_offset] = '\0';
+
+	files[num_files] = bb_xstrdup(filename);
+	current_file = num_files + 1;
+	num_files++;
+
+	inp_stdin = 0;
+	reinitialise();
+}
+
+/* This function changes the file currently being paged. direction can be one of the following:
+ * -1: go back one file
+ *  0: go to the first file
+ *  1: go forward one file
+*/
+static void change_file(int direction)
+{
+	if (current_file != ((direction > 0) ? num_files : 1)) {
+		current_file = direction ? current_file + direction : 1;
+		strcpy(filename, files[current_file - 1]);
+		reinitialise();
+	}
+	else {
+		clear_line();
+		printf("%s%s%s", HIGHLIGHT, (direction > 0) ? "No next file" : "No previous file", NORMAL);
+	}
+}
+
+static void remove_current_file(void)
+{
+	int i;
+
+	if (current_file != 1) {
+		change_file(-1);
+		for (i = 3; i <= num_files; i++)
+			files[i - 2] = files[i - 1];
+		num_files--;
+		buffer_print();
+	}
+	else {
+		change_file(1);
+		for (i = 2; i <= num_files; i++)
+			files[i - 2] = files[i - 1];
+		num_files--;
+		current_file--;
+		buffer_print();
+	}
+}
+
+static void colon_process(void)
+{
+	int keypress;
+
+	/* Clear the current line and print a prompt */
+	clear_line();
+	printf(" :");
+
+	keypress = tless_getch();
+	switch (keypress) {
+		case 'd':
+			remove_current_file();
+			break;
+		case 'e':
+			examine_file();
+			break;
+#ifdef CONFIG_FEATURE_LESS_FLAGS
+		case 'f':
+			clear_line();
+			m_status_print();
+			break;
+#endif
+		case 'n':
+			change_file(1);
+			break;
+		case 'p':
+			change_file(-1);
+			break;
+		case 'q':
+			tless_exit(0);
+			break;
+		case 'x':
+			change_file(0);
+			break;
+		default:
+			break;
+	}
+}
+
+#ifdef CONFIG_FEATURE_LESS_REGEXP
+/* The below two regular expression handler functions NEED development. */
+
+/* Get a regular expression from the user, and then go through the current
+   file line by line, running a processing regex function on each one. */
+
+static char *process_regex_on_line(char *line, regex_t *pattern, int action)
+{
+	/* This function takes the regex and applies it to the line.
+	   Each part of the line that matches has the HIGHLIGHT
+	   and NORMAL escape sequences placed around it by
+	   insert_highlights if action = 1, or has the escape sequences
+	   removed if action = 0, and then the line is returned. */
+	int match_status;
+	char *line2 = (char *) xmalloc((sizeof(char) * (strlen(line) + 1)) + 64);
+	char *growline = "";
+	regmatch_t match_structs;
+
+	line2 = bb_xstrdup(line);
+
+	match_found = 0;
+	match_status = regexec(pattern, line2, 1, &match_structs, 0);
+	
+	while (match_status == 0) {
+		if (match_found == 0)
+			match_found = 1;
+		
+		if (action) {
+			growline = bb_xasprintf("%s%.*s%s%.*s%s", growline, match_structs.rm_so, line2, HIGHLIGHT, match_structs.rm_eo - match_structs.rm_so, line2 + match_structs.rm_so, NORMAL); 
+		}
+		else {
+			growline = bb_xasprintf("%s%.*s%.*s", growline, match_structs.rm_so - 4, line2, match_structs.rm_eo - match_structs.rm_so, line2 + match_structs.rm_so);
+		}
+		
+		line2 += match_structs.rm_eo;
+		match_status = regexec(pattern, line2, 1, &match_structs, REG_NOTBOL);
+	}
+	
+	growline = bb_xasprintf("%s%s", growline, line2);
+	
+	return (match_found ? growline : line);
+	
+	free(growline);
+	free(line2);
+}
+
+static void goto_match(int match)
+{
+	/* This goes to a specific match - all line positions of matches are
+	   stored within the match_lines[] array. */
+	if ((match < num_matches) && (match >= 0)) {
+		buffer_line(match_lines[match]);
+		match_pos = match;
+	}
+}
+
+static void regex_process(void)
+{
+	char uncomp_regex[100];
+	char *current_line;
+	int i;
+	int j = 0;
+	regex_t pattern;
+	/* Get the uncompiled regular expression from the user */
+	clear_line();
+	putchar((match_backwards) ? '?' : '/');
+	uncomp_regex[0] = 0;
+	fgets(uncomp_regex, sizeof(uncomp_regex), inp);
+	
+	if (strlen(uncomp_regex) == 1) {
+		if (num_matches)
+			goto_match(match_backwards ? match_pos - 1 : match_pos + 1);
+		else
+			buffer_print();
+		return;
+	}
+	uncomp_regex[strlen(uncomp_regex) - 1] = '\0';
+	
+	/* Compile the regex and check for errors */
+	xregcomp(&pattern, uncomp_regex, 0);
+
+	if (num_matches) {
+		/* Get rid of all the highlights we added previously */
+		for (i = 0; i <= num_flines; i++) {
+			current_line = process_regex_on_line(flines[i], &old_pattern, 0);
+			flines[i] = bb_xstrdup(current_line);
+		}
+	}
+	old_pattern = pattern;
+	
+	/* Reset variables */
+	match_lines = xrealloc(match_lines, sizeof(int));
+	match_lines[0] = -1;
+	match_pos = 0;
+	num_matches = 0;
+	match_found = 0;
+	/* Run the regex on each line of the current file here */
+	for (i = 0; i <= num_flines; i++) {
+		current_line = process_regex_on_line(flines[i], &pattern, 1);
+		flines[i] = bb_xstrdup(current_line);
+		if (match_found) {
+			match_lines = xrealloc(match_lines, (j + 1) * sizeof(int));
+			match_lines[j] = i;
+			j++;
+		}
+	}
+	
+	num_matches = j;
+	if ((match_lines[0] != -1) && (num_flines > height - 2)) {
+		if (match_backwards) {
+			for (i = 0; i < num_matches; i++) {
+				if (match_lines[i] > line_pos) {
+					match_pos = i - 1;
+					buffer_line(match_lines[match_pos]);
+					break;
+				}
+			}
+		}
+		else
+			buffer_line(match_lines[0]);
+	}
+	else
+		buffer_init();
+}
+#endif
+
+static void number_process(int first_digit)
+{
+	int i = 1;
+	int num;
+	char num_input[80];
+	char keypress;
+	char *endptr;
+
+	num_input[0] = first_digit;
+
+	/* Clear the current line, print a prompt, and then print the digit */
+	clear_line();
+	printf(":%c", first_digit);
+
+	/* Receive input until a letter is given (max 80 chars)*/
+	while((i < 80) && (num_input[i] = tless_getch()) && isdigit(num_input[i])) {
+		putchar(num_input[i]);
+		i++;
+	}
+
+	/* Take the final letter out of the digits string */
+	keypress = num_input[i];
+	num_input[i] = '\0';
+	num = strtol(num_input, &endptr, 10);
+	if (endptr==num_input || *endptr!='\0' || num < 1 || num > MAXLINES) {
+		buffer_print();
+		return;
+	}
+
+	/* We now know the number and the letter entered, so we process them */
+	switch (keypress) {
+		case KEY_DOWN: case 'z': case 'd': case 'e': case ' ': case '\015':
+			buffer_down(num);
+			break;
+		case KEY_UP: case 'b': case 'w': case 'y': case 'u':
+			buffer_up(num);
+			break;
+		case 'g': case '<': case 'G': case '>':
+			if (num_flines >= height - 2)
+				buffer_line(num - 1);
+			break;
+		case 'p': case '%':
+			buffer_line(((num / 100) * num_flines) - 1);
+			break;
+#ifdef CONFIG_FEATURE_LESS_REGEXP
+		case 'n':
+			goto_match(match_pos + num);
+			break;
+		case '/':
+			match_backwards = 0;
+			regex_process();
+			break;
+		case '?':
+			match_backwards = 1;
+			regex_process();
+			break;
+#endif
+		default:
+			break;
+	}
+}
+
+#ifdef CONFIG_FEATURE_LESS_FLAGCS
+static void flag_change(void)
+{
+	int keypress;
+
+	clear_line();
+	putchar('-');
+	keypress = tless_getch();
+
+	switch (keypress) {
+		case 'M':
+			flags ^= FLAG_M;
+			break;
+		case 'm':
+			flags ^= FLAG_m;
+			break;
+		case 'E':
+			flags ^= FLAG_E;
+			break;
+		case '~':
+			flags ^= FLAG_TILDE;
+			break;
+		default:
+			break;
+	}
+}
+
+static void show_flag_status(void)
+{
+	int keypress;
+	int flag_val;
+
+	clear_line();
+	putchar('_');
+	keypress = tless_getch();
+
+	switch (keypress) {
+		case 'M':
+			flag_val = flags & FLAG_M;
+			break;
+		case 'm':
+			flag_val = flags & FLAG_m;
+			break;
+		case '~':
+			flag_val = flags & FLAG_TILDE;
+			break;
+		case 'N':
+			flag_val = flags & FLAG_N;
+			break;
+		case 'E':
+			flag_val = flags & FLAG_E;
+			break;
+		default:
+			flag_val = 0;
+			break;
+	}
+
+	clear_line();
+	printf("%s%s%i%s", HIGHLIGHT, "The status of the flag is: ", flag_val != 0, NORMAL);
+}
+#endif
+
+static void full_repaint(void)
+{
+	int temp_line_pos = line_pos;
+	data_readlines();
+	buffer_init();
+	buffer_line(temp_line_pos);
+}
+
+
+static void save_input_to_file(void)
+{
+	char current_line[256];
+	int i;
+	FILE *fp;
+
+	clear_line();
+	printf("Log file: ");
+	fgets(current_line, 256, inp);
+	current_line[strlen(current_line) - 1] = '\0';
+	if (strlen(current_line) > 1) {
+		fp = bb_xfopen(current_line, "w");
+		for (i = 0; i < num_flines; i++)
+			fprintf(fp, "%s", flines[i]);
+		fclose(fp);
+		buffer_print();
+	}
+	else
+		printf("%sNo log file%s", HIGHLIGHT, NORMAL);
+}
+
+#ifdef CONFIG_FEATURE_LESS_MARKS
+static void add_mark(void)
+{
+	int letter;
+	int mark_line;
+
+	clear_line();
+	printf("Mark: ");
+	letter = tless_getch();
+
+	if (isalpha(letter)) {
+		mark_line = line_pos;
+
+		/* If we exceed 15 marks, start overwriting previous ones */
+		if (num_marks == 14)
+			num_marks = 0;
+
+		mark_lines[num_marks][0] = letter;
+		mark_lines[num_marks][1] = line_pos;
+		num_marks++;
+	}
+	else {
+		clear_line();
+		printf("%s%s%s", HIGHLIGHT, "Invalid mark letter", NORMAL);
+	}
+}
+
+static void goto_mark(void)
+{
+	int letter;
+	int i;
+
+	clear_line();
+	printf("Go to mark: ");
+	letter = tless_getch();
+	clear_line();
+
+	if (isalpha(letter)) {
+		for (i = 0; i <= num_marks; i++)
+			if (letter == mark_lines[i][0]) {
+				buffer_line(mark_lines[i][1]);
+				break;
+			}
+		if ((num_marks == 14) && (letter != mark_lines[14][0]))
+			printf("%s%s%s", HIGHLIGHT, "Mark not set", NORMAL);
+	}
+	else
+		printf("%s%s%s", HIGHLIGHT, "Invalid mark letter", NORMAL);
+}
+#endif
+
+
+#ifdef CONFIG_FEATURE_LESS_BRACKETS
+
+static char opp_bracket(char bracket)
+{
+	switch (bracket) {
+		case '{': case '[':
+			return bracket + 2;
+			break;
+		case '(':
+			return ')';
+			break;
+		case '}': case ']':
+			return bracket - 2;
+			break;
+		case ')':
+			return '(';
+			break;
+		default:
+			return 0;
+			break;
+	}
+}
+
+static void match_right_bracket(char bracket)
+{
+	int bracket_line = -1;
+	int i;
+
+	clear_line();
+
+	if (strchr(flines[line_pos], bracket) == NULL)
+		printf("%s%s%s", HIGHLIGHT, "No bracket in top line", NORMAL);
+	else {
+		for (i = line_pos + 1; i < num_flines; i++) {
+			if (strchr(flines[i], opp_bracket(bracket)) != NULL) {
+				bracket_line = i;
+				break;
+			}
+		}
+
+		if (bracket_line == -1)
+			printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL);
+
+		buffer_line(bracket_line - height + 2);
+	}
+}
+
+static void match_left_bracket(char bracket)
+{
+	int bracket_line = -1;
+	int i;
+
+	clear_line();
+
+	if (strchr(flines[line_pos + height - 2], bracket) == NULL) {
+		printf("%s%s%s", HIGHLIGHT, "No bracket in bottom line", NORMAL);
+		printf("%s", flines[line_pos + height]);
+		sleep(4);
+	}
+	else {
+		for (i = line_pos + height - 2; i >= 0; i--) {
+			if (strchr(flines[i], opp_bracket(bracket)) != NULL) {
+				bracket_line = i;
+				break;
+			}
+		}
+
+		if (bracket_line == -1)
+			printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL);
+
+		buffer_line(bracket_line);
+	}
+}
+
+#endif  /* CONFIG_FEATURE_LESS_BRACKETS */
+
+static void keypress_process(int keypress)
+{
+	switch (keypress) {
+		case KEY_DOWN: case 'e': case 'j': case '\015':
+			buffer_down(1);
+			buffer_print();
+			break;
+		case KEY_UP: case 'y': case 'k':
+			buffer_up(1);
+			buffer_print();
+			break;
+		case PAGE_DOWN: case ' ': case 'z':
+			buffer_down(height - 1);
+			buffer_print();
+			break;
+		case PAGE_UP: case 'w': case 'b':
+			buffer_up(height - 1);
+			buffer_print();
+			break;
+		case 'd':
+			buffer_down((height - 1) / 2);
+			buffer_print();
+			break;
+		case 'u':
+			buffer_up((height - 1) / 2);
+			buffer_print();
+			break;
+		case 'g': case 'p': case '<': case '%':
+			buffer_line(0);
+			break;
+		case 'G': case '>':
+			buffer_line(num_flines - height + 2);
+			break;
+		case 'q': case 'Q':
+			tless_exit(0);
+			break;
+#ifdef CONFIG_FEATURE_LESS_MARKS
+		case 'm':
+			add_mark();
+			buffer_print();
+			break;
+		case '\'':
+			goto_mark();
+			buffer_print();
+			break;
+#endif
+		case 'r':
+			buffer_print();
+			break;
+		case 'R':
+			full_repaint();
+			break;
+		case 's':
+			if (inp_stdin)
+				save_input_to_file();
+			break;
+		case 'E':
+			examine_file();
+			break;
+#ifdef CONFIG_FEATURE_LESS_FLAGS
+		case '=':
+			clear_line();
+			m_status_print();
+			break;
+#endif
+#ifdef CONFIG_FEATURE_LESS_REGEXP
+		case '/':
+			match_backwards = 0;
+			regex_process();
+			break;
+		case 'n':
+			goto_match(match_pos + 1);
+			break;
+		case 'N':
+			goto_match(match_pos - 1);
+			break;
+		case '?':
+			match_backwards = 1;
+			regex_process();
+			break;
+#endif
+#ifdef CONFIG_FEATURE_LESS_FLAGCS
+		case '-':
+			flag_change();
+			buffer_print();
+			break;
+		case '_':
+			show_flag_status();
+			break;
+#endif
+#ifdef CONFIG_FEATURE_LESS_BRACKETS
+		case '{': case '(': case '[':
+			match_right_bracket(keypress);
+			break;
+		case '}': case ')': case ']':
+			match_left_bracket(keypress);
+			break;
+#endif
+		case ':':
+			colon_process();
+			break;
+		default:
+			break;
+	}
+
+	if (isdigit(keypress))
+		number_process(keypress);
+}
+
+int less_main(int argc, char **argv) {
+
+	int keypress;
+
+	flags = bb_getopt_ulflags(argc, argv, "EMmN~");
+
+	argc -= optind;
+	argv += optind;
+	files = argv;
+	num_files = argc;
+
+	if (!num_files) {
+		if (ttyname(STDIN_FILENO) == NULL)
+			inp_stdin = 1;
+		else {
+			bb_error_msg("Missing filename");
+			bb_show_usage();
+		}
+	}
+
+	strcpy(filename, (inp_stdin) ? bb_msg_standard_input : files[0]);
+	get_terminal_width_height(0, &width, &height);
+	data_readlines();
+	tcgetattr(fileno(inp), &term_orig);
+	term_vi = term_orig;
+	term_vi.c_lflag &= (~ICANON & ~ECHO);
+	term_vi.c_iflag &= (~IXON & ~ICRNL);
+	term_vi.c_oflag &= (~ONLCR);
+	term_vi.c_cc[VMIN] = 1;
+	term_vi.c_cc[VTIME] = 0;
+	buffer_init();
+	buffer_print();
+
+	while (1) {
+		keypress = tless_getch();
+		keypress_process(keypress);
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/makedevs.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/makedevs.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/makedevs.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,240 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * public domain -- Dave 'Kill a Cop' Cinege <dcinege at psychosis.com>
+ *
+ * makedevs
+ * Make ranges of device files quickly.
+ * known bugs: can't deal with alpha ranges
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <time.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/sysmacros.h>     /* major() and minor() */
+
+#ifdef CONFIG_FEATURE_MAKEDEVS_LEAF
+int makedevs_main(int argc, char **argv)
+{
+	mode_t mode;
+	char *basedev, *type, *nodname, buf[255];
+	int Smajor, Sminor, S, E;
+
+	if (argc < 7 || *argv[1]=='-')
+		bb_show_usage();
+
+	basedev = argv[1];
+	type = argv[2];
+	Smajor = atoi(argv[3]);
+	Sminor = atoi(argv[4]);
+	S = atoi(argv[5]);
+	E = atoi(argv[6]);
+	nodname = argc == 8 ? basedev : buf;
+
+	mode = 0660;
+
+	switch (type[0]) {
+	case 'c':
+		mode |= S_IFCHR;
+		break;
+	case 'b':
+		mode |= S_IFBLK;
+		break;
+	case 'f':
+		mode |= S_IFIFO;
+		break;
+	default:
+		bb_show_usage();
+	}
+
+	while (S <= E) {
+		int sz;
+
+		sz = snprintf(buf, sizeof(buf), "%s%d", basedev, S);
+		if(sz<0 || sz>=sizeof(buf))  /* libc different */
+			bb_error_msg_and_die("%s too large", basedev);
+
+	/* if mode != S_IFCHR and != S_IFBLK third param in mknod() ignored */
+
+		if (mknod(nodname, mode, makedev(Smajor, Sminor)))
+			bb_error_msg("Failed to create: %s", nodname);
+
+		if (nodname == basedev) /* ex. /dev/hda - to /dev/hda1 ... */
+			nodname = buf;
+		S++;
+		Sminor++;
+	}
+
+	return 0;
+}
+
+#elif defined CONFIG_FEATURE_MAKEDEVS_TABLE
+
+/* Licensed under the GPL v2 or later, see the file LICENSE in this tarball. */
+
+int makedevs_main(int argc, char **argv)
+{
+	FILE *table = stdin;
+	char *rootdir = NULL;
+	char *line = NULL;
+	int linenum = 0;
+	int ret = EXIT_SUCCESS;
+
+	unsigned long flags;
+	flags = bb_getopt_ulflags(argc, argv, "d:", &line);
+	if (line)
+		table = bb_xfopen(line, "r");
+
+	if (optind >= argc || (rootdir=argv[optind])==NULL) {
+		bb_error_msg_and_die("root directory not specified");
+	}
+
+	bb_xchdir(rootdir);
+
+	umask(0);
+
+	printf("rootdir=%s\n", rootdir);
+	if (line) {
+		printf("table='%s'\n", line);
+	} else {
+		printf("table=<stdin>\n");
+	}
+
+	while ((line = bb_get_chomped_line_from_file(table))) {
+		char type;
+		unsigned int mode = 0755;
+		unsigned int major = 0;
+		unsigned int minor = 0;
+		unsigned int count = 0;
+		unsigned int increment = 0;
+		unsigned int start = 0;
+		char name[41];
+		char user[41];
+		char group[41];
+		char *full_name;
+		uid_t uid;
+		gid_t gid;
+
+		linenum++;
+
+		if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u", name,
+						&type, &mode, user, group, &major,
+						&minor, &start, &increment, &count)) ||
+				((major | minor | start | count | increment) > 255))
+		{
+			if (*line=='\0' || *line=='#' || isspace(*line))
+				continue;
+			bb_error_msg("line %d invalid: '%s'\n", linenum, line);
+			ret = EXIT_FAILURE;
+			continue;
+		}
+		if (name[0] == '#') {
+			continue;
+		}
+
+		gid = (*group) ? get_ug_id(group, bb_xgetgrnam) : getgid();
+		uid = (*user) ? get_ug_id(user, bb_xgetpwnam) : getuid();
+		full_name = concat_path_file(rootdir, name);
+
+		if (type == 'd') {
+			bb_make_directory(full_name, mode | S_IFDIR, FILEUTILS_RECUR);
+			if (chown(full_name, uid, gid) == -1) {
+				bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
+				ret = EXIT_FAILURE;
+				goto loop;
+			}
+			if ((mode != -1) && (chmod(full_name, mode) < 0)){
+				bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
+				ret = EXIT_FAILURE;
+				goto loop;
+			}
+		} else if (type == 'f') {
+			struct stat st;
+			if ((stat(full_name, &st) < 0 || !S_ISREG(st.st_mode))) {
+				bb_perror_msg("line %d: regular file '%s' does not exist", linenum, full_name);
+				ret = EXIT_FAILURE;
+				goto loop;
+			}
+			if (chown(full_name, uid, gid) == -1) {
+				bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
+				ret = EXIT_FAILURE;
+				goto loop;
+			}
+			if ((mode != -1) && (chmod(full_name, mode) < 0)){
+				bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
+				ret = EXIT_FAILURE;
+				goto loop;
+			}
+		} else
+		{
+			dev_t rdev;
+
+			if (type == 'p') {
+				mode |= S_IFIFO;
+			}
+			else if (type == 'c') {
+				mode |= S_IFCHR;
+			}
+			else if (type == 'b') {
+				mode |= S_IFBLK;
+			} else {
+				bb_error_msg("line %d: unsupported file type %c", linenum, type);
+				ret = EXIT_FAILURE;
+				goto loop;
+			}
+
+			if (count > 0) {
+				int i;
+				char *full_name_inc;
+
+				full_name_inc = xmalloc(strlen(full_name) + 4);
+				for (i = start; i < count; i++) {
+					sprintf(full_name_inc, "%s%d", full_name, i);
+					rdev = (major << 8) + minor + (i * increment - start);
+					if (mknod(full_name_inc, mode, rdev) == -1) {
+						bb_perror_msg("line %d: could not create node %s", linenum, full_name_inc);
+						ret = EXIT_FAILURE;
+					}
+					else if (chown(full_name_inc, uid, gid) == -1) {
+						bb_perror_msg("line %d: chown failed for %s", linenum, full_name_inc);
+						ret = EXIT_FAILURE;
+					}
+					if ((mode != -1) && (chmod(full_name_inc, mode) < 0)){
+						bb_perror_msg("line %d: chmod failed for %s", linenum, full_name_inc);
+						ret = EXIT_FAILURE;
+					}
+				}
+				free(full_name_inc);
+			} else {
+				rdev = (major << 8) + minor;
+				if (mknod(full_name, mode, rdev) == -1) {
+					bb_perror_msg("line %d: could not create node %s", linenum, full_name);
+					ret = EXIT_FAILURE;
+				}
+				else if (chown(full_name, uid, gid) == -1) {
+					bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
+					ret = EXIT_FAILURE;
+				}
+				if ((mode != -1) && (chmod(full_name, mode) < 0)){
+					bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
+					ret = EXIT_FAILURE;
+				}
+			}
+		}
+loop:
+		free(line);
+		free(full_name);
+	}
+	fclose(table);
+
+	return ret;
+}
+
+#else
+# error makedevs configuration error, either leaf or table must be selected
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/mountpoint.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/mountpoint.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/mountpoint.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,70 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * mountpoint implementation for busybox
+ *
+ * Copyright (C) 2005 Bernhard Fischer
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ * Based on sysvinit's mountpoint
+ */
+
+#include "busybox.h"
+#include <sys/stat.h>
+#include <errno.h> /* errno */
+#include <string.h> /* strerror */
+#include <getopt.h> /* optind */
+
+int mountpoint_main(int argc, char **argv)
+{
+	int opt = bb_getopt_ulflags(argc, argv, "qdx");
+#define OPT_q (1)
+#define OPT_d (2)
+#define OPT_x (4)
+
+	if (optind != argc - 1)
+		bb_show_usage();
+	{
+		char *arg = argv[optind];
+		struct stat st;
+
+		if ( (opt & OPT_x && stat(arg, &st) == 0) || (lstat(arg, &st) == 0) ) {
+			if (opt & OPT_x) {
+				if (S_ISBLK(st.st_mode))
+				{
+					bb_printf("%u:%u\n", major(st.st_rdev),
+								minor(st.st_rdev));
+					return EXIT_SUCCESS;
+				} else {
+					if (opt & OPT_q)
+						putchar('\n');
+					else
+						bb_error_msg("%s: not a block device", arg);
+				}
+				return EXIT_FAILURE;
+			} else
+			if (S_ISDIR(st.st_mode)) {
+				dev_t st_dev = st.st_dev;
+				ino_t st_ino = st.st_ino;
+				char *p = bb_xasprintf("%s/..", arg);
+
+				if (stat(p, &st) == 0) {
+					short ret = (st_dev != st.st_dev) ||
+						(st_dev == st.st_dev && st_ino == st.st_ino);
+					if (opt & OPT_d)
+						bb_printf("%u:%u\n", major(st_dev), minor(st_dev));
+					else if (!(opt & OPT_q))
+						bb_printf("%s is %sa mountpoint\n", arg, ret?"":"not ");
+					return !ret;
+				}
+			} else {
+				if (!(opt & OPT_q))
+					bb_error_msg("%s: not a directory", arg);
+				return EXIT_FAILURE;
+			}
+		}
+		if (!(opt & OPT_q))
+			bb_perror_msg("%s", arg);
+		return EXIT_FAILURE;
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/mt.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/mt.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/mt.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,120 @@
+/* vi: set sw=4 ts=4: */
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mtio.h>
+#include <fcntl.h>
+
+struct mt_opcodes {
+	char *name;
+	short value;
+};
+
+/* missing: eod/seod, stoptions, stwrthreshold, densities */
+static const struct mt_opcodes opcodes[] = {
+	{"bsf", MTBSF},
+	{"bsfm", MTBSFM},
+	{"bsr", MTBSR},
+	{"bss", MTBSS},
+	{"datacompression", MTCOMPRESSION},
+	{"eom", MTEOM},
+	{"erase", MTERASE},
+	{"fsf", MTFSF},
+	{"fsfm", MTFSFM},
+	{"fsr", MTFSR},
+	{"fss", MTFSS},
+	{"load", MTLOAD},
+	{"lock", MTLOCK},
+	{"mkpart", MTMKPART},
+	{"nop", MTNOP},
+	{"offline", MTOFFL},
+	{"rewoffline", MTOFFL},
+	{"ras1", MTRAS1},
+	{"ras2", MTRAS2},
+	{"ras3", MTRAS3},
+	{"reset", MTRESET},
+	{"retension", MTRETEN},
+	{"rewind", MTREW},
+	{"seek", MTSEEK},
+	{"setblk", MTSETBLK},
+	{"setdensity", MTSETDENSITY},
+	{"drvbuffer", MTSETDRVBUFFER},
+	{"setpart", MTSETPART},
+	{"tell", MTTELL},
+	{"wset", MTWSM},
+	{"unload", MTUNLOAD},
+	{"unlock", MTUNLOCK},
+	{"eof", MTWEOF},
+	{"weof", MTWEOF},
+	{0, 0}
+};
+
+int mt_main(int argc, char **argv)
+{
+	const char *file = "/dev/tape";
+	const struct mt_opcodes *code = opcodes;
+	struct mtop op;
+	struct mtpos position;
+	int fd, mode;
+
+	if (argc < 2) {
+		bb_show_usage();
+	}
+
+	if (strcmp(argv[1], "-f") == 0) {
+		if (argc < 4) {
+			bb_show_usage();
+		}
+		file = argv[2];
+		argv += 2;
+		argc -= 2;
+	}
+
+	while (code->name != 0) {
+		if (strcmp(code->name, argv[1]) == 0)
+			break;
+		code++;
+	}
+
+	if (code->name == 0) {
+		bb_error_msg("unrecognized opcode %s.", argv[1]);
+		return EXIT_FAILURE;
+	}
+
+	op.mt_op = code->value;
+	if (argc >= 3)
+		op.mt_count = atoi(argv[2]);
+	else
+		op.mt_count = 1;		/* One, not zero, right? */
+
+	switch (code->value) {
+		case MTWEOF:
+		case MTERASE:
+		case MTWSM:
+		case MTSETDRVBUFFER:
+			mode = O_WRONLY;
+			break;
+
+		default:
+			mode = O_RDONLY;
+			break;
+	}
+
+	fd = bb_xopen3(file, mode, 0);
+
+	switch (code->value) {
+		case MTTELL:
+			if (ioctl(fd, MTIOCPOS, &position) < 0)
+				bb_perror_msg_and_die("%s", file);
+			printf ("At block %d.\n", (int) position.mt_blkno);
+			break;
+
+		default:
+			if (ioctl(fd, MTIOCTOP, &op) != 0)
+				bb_perror_msg_and_die("%s", file);
+			break;
+	}
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/runlevel.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/runlevel.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/runlevel.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,43 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * runlevel	Prints out the previous and the current runlevel.
+ *
+ * Version:	@(#)runlevel  1.20  16-Apr-1997  MvS
+ *
+ *		This file is part of the sysvinit suite,
+ *		Copyright 1991-1997 Miquel van Smoorenburg.
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ * initially busyboxified by Bernhard Fischer
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <utmp.h>
+#include <time.h>
+#include <stdlib.h>
+
+int runlevel_main(int argc, char *argv[])
+{
+  struct utmp *ut;
+  char prev;
+
+  if (argc > 1) utmpname(argv[1]);
+
+  setutent();
+  while ((ut = getutent()) != NULL) {
+	if (ut->ut_type == RUN_LVL) {
+		prev = ut->ut_pid / 256;
+		if (prev == 0) prev = 'N';
+		printf("%c %c\n", prev, ut->ut_pid % 256);
+		endutent();
+		return (0);
+	}
+  }
+
+  printf("unknown\n");
+  endutent();
+  return (1);
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/rx.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/rx.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/rx.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,303 @@
+/* vi: set sw=4 ts=4: */
+/*-------------------------------------------------------------------------
+ * Filename:      xmodem.c
+ * Version:       $Id: rx.c,v 1.2 2004/03/15 08:28:46 andersen Exp $
+ * Copyright:     Copyright (C) 2001, Hewlett-Packard Company
+ * Author:        Christopher Hoover <ch at hpl.hp.com>
+ * Description:   xmodem functionality for uploading of kernels
+ *                and the like
+ * Created at:    Thu Dec 20 01:58:08 PST 2001
+ *-----------------------------------------------------------------------*/
+/*
+ * xmodem.c: xmodem functionality for uploading of kernels and
+ *            the like
+ *
+ * Copyright (C) 2001 Hewlett-Packard Laboratories
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * This was originally written for blob and then adapted for busybox.
+ *
+ */
+
+#include "busybox.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <termios.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+
+#define SOH 0x01
+#define STX 0x02
+#define EOT 0x04
+#define ACK 0x06
+#define NAK 0x15
+#define BS  0x08
+
+/*
+
+Cf:
+
+  http://www.textfiles.com/apple/xmodem
+  http://www.phys.washington.edu/~belonis/xmodem/docxmodem.txt
+  http://www.phys.washington.edu/~belonis/xmodem/docymodem.txt
+  http://www.phys.washington.edu/~belonis/xmodem/modmprot.col
+
+*/
+
+#define TIMEOUT 1
+#define TIMEOUT_LONG 10
+#define MAXERRORS 10
+
+static int read_byte(int fd, unsigned int timeout) {
+	char buf[1];
+	int n;
+
+	alarm(timeout);
+
+	n = read(fd, &buf, 1);
+
+	alarm(0);
+
+	if (n == 1)
+		return buf[0] & 0xff;
+	else
+		return -1;
+}
+
+static int receive(char *error_buf, size_t error_buf_size,
+				   int ttyfd, int filefd)
+{
+	char blockBuf[1024];
+	unsigned int errors = 0;
+	unsigned int wantBlockNo = 1;
+	unsigned int length = 0;
+	int docrc = 1;
+	char nak = 'C';
+	unsigned int timeout = TIMEOUT_LONG;
+
+#define note_error(fmt,args...) \
+	snprintf(error_buf, error_buf_size, fmt,##args)
+
+	/* Flush pending input */
+	tcflush(ttyfd, TCIFLUSH);
+
+	/* Ask for CRC; if we get errors, we will go with checksum */
+	write(ttyfd, &nak, 1);
+
+	for (;;) {
+		int blockBegin;
+		int blockNo, blockNoOnesCompl;
+		int blockLength;
+		int cksum = 0;
+		int crcHi = 0;
+		int crcLo = 0;
+
+		blockBegin = read_byte(ttyfd, timeout);
+		if (blockBegin < 0)
+			goto timeout;
+
+		timeout = TIMEOUT;
+		nak = NAK;
+
+		switch (blockBegin) {
+		case SOH:
+		case STX:
+			break;
+
+		case EOT:
+			nak = ACK;
+			write(ttyfd, &nak, 1);
+			goto done;
+
+		default:
+			goto error;
+		}
+
+		/* block no */
+		blockNo = read_byte(ttyfd, TIMEOUT);
+		if (blockNo < 0)
+			goto timeout;
+
+		/* block no one's compliment */
+		blockNoOnesCompl = read_byte(ttyfd, TIMEOUT);
+		if (blockNoOnesCompl < 0)
+			goto timeout;
+
+		if (blockNo != (255 - blockNoOnesCompl)) {
+			note_error("bad block ones compl");
+			goto error;
+		}
+
+		blockLength = (blockBegin == SOH) ? 128 : 1024;
+
+		{
+			int i;
+
+			for (i = 0; i < blockLength; i++) {
+				int cc = read_byte(ttyfd, TIMEOUT);
+				if (cc < 0)
+					goto timeout;
+				blockBuf[i] = cc;
+			}
+		}
+
+		if (docrc) {
+			crcHi = read_byte(ttyfd, TIMEOUT);
+			if (crcHi < 0)
+				goto timeout;
+
+			crcLo = read_byte(ttyfd, TIMEOUT);
+			if (crcLo < 0)
+				goto timeout;
+		} else {
+			cksum = read_byte(ttyfd, TIMEOUT);
+			if (cksum < 0)
+				goto timeout;
+		}
+
+		if (blockNo == ((wantBlockNo - 1) & 0xff)) {
+			/* a repeat of the last block is ok, just ignore it. */
+			/* this also ignores the initial block 0 which is */
+			/* meta data. */
+			goto next;
+		} else if (blockNo != (wantBlockNo & 0xff)) {
+			note_error("unexpected block no, 0x%08x, expecting 0x%08x", blockNo, wantBlockNo);
+			goto error;
+		}
+
+		if (docrc) {
+			int crc = 0;
+			int i, j;
+			int expectedCrcHi;
+			int expectedCrcLo;
+
+			for (i = 0; i < blockLength; i++) {
+				crc = crc ^ (int) blockBuf[i] << 8;
+				for (j = 0; j < 8; j++)
+					if (crc & 0x8000)
+						crc = crc << 1 ^ 0x1021;
+					else
+						crc = crc << 1;
+			}
+
+			expectedCrcHi = (crc >> 8) & 0xff;
+			expectedCrcLo = crc & 0xff;
+
+			if ((crcHi != expectedCrcHi) ||
+			    (crcLo != expectedCrcLo)) {
+				note_error("crc error, expected 0x%02x 0x%02x, got 0x%02x 0x%02x", expectedCrcHi, expectedCrcLo, crcHi, crcLo);
+				goto error;
+			}
+		} else {
+			unsigned char expectedCksum = 0;
+			int i;
+
+			for (i = 0; i < blockLength; i++)
+				expectedCksum += blockBuf[i];
+
+			if (cksum != expectedCksum) {
+				note_error("checksum error, expected 0x%02x, got 0x%02x", expectedCksum, cksum);
+				goto error;
+			}
+		}
+
+		wantBlockNo++;
+		length += blockLength;
+
+		if (bb_full_write(filefd, blockBuf, blockLength) < 0) {
+			note_error("write to file failed: %m");
+			goto fatal;
+		}
+
+	next:
+		errors = 0;
+		nak = ACK;
+		write(ttyfd, &nak, 1);
+		continue;
+
+	error:
+	timeout:
+		errors++;
+		if (errors == MAXERRORS) {
+			/* Abort */
+
+			// if using crc, try again w/o crc
+			if (nak == 'C') {
+				nak = NAK;
+				errors = 0;
+				docrc = 0;
+				goto timeout;
+			}
+
+			note_error("too many errors; giving up");
+
+		fatal:
+			/* 5 CAN followed by 5 BS */
+			write(ttyfd, "\030\030\030\030\030\010\010\010\010\010", 10);
+			return -1;
+		}
+
+		/* Flush pending input */
+		tcflush(ttyfd, TCIFLUSH);
+
+		write(ttyfd, &nak, 1);
+	}
+
+ done:
+	return length;
+
+#undef note_error
+}
+
+static void sigalrm_handler(int ATTRIBUTE_UNUSED signum)
+{
+}
+
+int rx_main(int argc, char **argv)
+{
+	char *fn;
+	int ttyfd, filefd;
+	struct termios tty, orig_tty;
+	struct sigaction act;
+	int n;
+	char error_buf[256];
+
+	if (argc != 2)
+			bb_show_usage();
+
+	fn = argv[1];
+	ttyfd = bb_xopen3(CURRENT_TTY, O_RDWR, 0);
+	filefd = bb_xopen3(fn, O_RDWR|O_CREAT|O_TRUNC, 0666);
+
+	if (tcgetattr(ttyfd, &tty) < 0)
+			bb_error_msg_and_die("%s: tcgetattr failed: %m\n", argv[0]);
+
+	orig_tty = tty;
+
+	cfmakeraw(&tty);
+	tcsetattr(ttyfd, TCSAFLUSH, &tty);
+
+	memset(&act, 0, sizeof(act));
+	act.sa_handler = sigalrm_handler;
+	sigaction(SIGALRM, &act, 0);
+
+	n = receive(error_buf, sizeof(error_buf), ttyfd, filefd);
+
+	close(filefd);
+
+	tcsetattr(ttyfd, TCSAFLUSH, &orig_tty);
+
+	if (n < 0)
+			bb_error_msg_and_die("\n%s: receive failed:\n  %s\n",
+							   argv[0], error_buf);
+
+	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/setsid.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/setsid.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/setsid.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,44 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * setsid.c -- execute a command in a new session
+ * Rick Sladkey <jrs at world.std.com>
+ * In the public domain.
+ *
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek at pld.ORG.PL>
+ * - added Native Language Support
+ *
+ * 2001-01-18 John Fremlin <vii at penguinpowered.com>
+ * - fork in case we are process group leader
+ *
+ * 2004-11-12 Paul Fox
+ * - busyboxed
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+int setsid_main(int argc, char *argv[])
+{
+	if (argc < 2)
+		bb_show_usage();
+
+	if (getpgrp() == getpid()) {
+		switch(fork()){
+		case -1:
+			bb_perror_msg_and_die("fork");
+		case 0:
+			break;
+		default:	/* parent */
+			exit(0);
+		}
+		/* child falls through */
+	}
+
+	setsid();  /* no error possible */
+
+	execvp(argv[1], argv + 1);
+
+	bb_perror_msg_and_die("%s", argv[1]);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/strings.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/strings.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/strings.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,126 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * strings implementation for busybox
+ *
+ * Copyright (c) 1980, 1987
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ * Original copyright notice is retained at the end of this file.
+ *
+ * Modified for BusyBox by Erik Andersen <andersen at codepoet.org>
+ * Badly hacked by Tito Ragusa <farmatito at tiscali.it>
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ctype.h>
+
+#define WHOLE_FILE		1
+#define PRINT_NAME		2
+#define PRINT_OFFSET	4
+#define SIZE			8
+
+int strings_main(int argc, char **argv)
+{
+	int n, c, i = 0, status = EXIT_SUCCESS;
+	unsigned long opt;
+	unsigned long count;
+	FILE *file = stdin;
+	char *string;
+	const char *fmt = "%s: ";
+	char *n_arg = "4";
+
+	opt = bb_getopt_ulflags(argc, argv, "afon:", &n_arg);
+	/* -a is our default behaviour */
+
+	argc -= optind;
+	argv += optind;
+
+	n = bb_xgetlarg(n_arg, 10, 1, INT_MAX);
+	string = xzalloc(n + 1);
+	n--;
+
+	if (argc == 0) {
+		fmt = "{%s}: ";
+		*argv = (char *)bb_msg_standard_input;
+		goto PIPE;
+	}
+
+	do {
+		if ((file = bb_wfopen(*argv, "r"))) {
+PIPE:
+			count = 0;
+			do {
+				c = fgetc(file);
+				if (isprint(c) || c == '\t') {
+					if (i <= n) {
+						string[i] = c;
+					} else {
+						putchar(c);
+					}
+					if (i == n) {
+						if (opt & PRINT_NAME) {
+							printf(fmt, *argv);
+						}
+						if (opt & PRINT_OFFSET) {
+							printf("%7lo ", count - n);
+						}
+						printf("%s", string);
+					}
+					i++;
+				} else {
+					if (i > n) {
+						putchar('\n');
+					}
+					i = 0;
+				}
+				count++;
+			} while (c != EOF);
+			bb_fclose_nonstdin(file);
+		} else {
+			status = EXIT_FAILURE;
+		}
+	} while (--argc > 0);
+
+	if (ENABLE_FEATURE_CLEAN_UP)
+		free(string);
+
+	bb_fflush_stdout_and_exit(status);
+}
+
+/*
+ * Copyright (c) 1980, 1987
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
+ *		ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
+ *
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/time.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/time.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/time.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,479 @@
+/* vi: set sw=4 ts=4: */
+/* `time' utility to display resource usage of processes.
+   Copyright (C) 1990, 91, 92, 93, 96 Free Software Foundation, Inc.
+
+   Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+*/
+/* Originally written by David Keppel <pardo at cs.washington.edu>.
+   Heavily modified by David MacKenzie <djm at gnu.ai.mit.edu>.
+   Heavily modified for busybox by Erik Andersen <andersen at codepoet.org>
+*/
+
+#include "busybox.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+#include <getopt.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+#include <sys/types.h>	/* For pid_t. */
+#include <sys/wait.h>
+#include <sys/param.h>	/* For getpagesize, maybe.  */
+
+#define TV_MSEC tv_usec / 1000
+#include <sys/resource.h>
+
+/* Information on the resources used by a child process.  */
+typedef struct {
+	int waitstatus;
+	struct rusage ru;
+	struct timeval start, elapsed;	/* Wallclock time of process.  */
+} resource_t;
+
+/* msec = milliseconds = 1/1,000 (1*10e-3) second.
+   usec = microseconds = 1/1,000,000 (1*10e-6) second.  */
+
+#ifndef TICKS_PER_SEC
+#define TICKS_PER_SEC 100
+#endif
+
+/* The number of milliseconds in one `tick' used by the `rusage' structure.  */
+#define MSEC_PER_TICK (1000 / TICKS_PER_SEC)
+
+/* Return the number of clock ticks that occur in M milliseconds.  */
+#define MSEC_TO_TICKS(m) ((m) / MSEC_PER_TICK)
+
+#define UL unsigned long
+
+static const char *const default_format = "real\t%E\nuser\t%u\nsys\t%T";
+
+/* The output format for the -p option .*/
+static const char *const posix_format = "real %e\nuser %U\nsys %S";
+
+
+/* Format string for printing all statistics verbosely.
+   Keep this output to 24 lines so users on terminals can see it all.*/
+static const char *const long_format =
+	"\tCommand being timed: \"%C\"\n"
+	"\tUser time (seconds): %U\n"
+	"\tSystem time (seconds): %S\n"
+	"\tPercent of CPU this job got: %P\n"
+	"\tElapsed (wall clock) time (h:mm:ss or m:ss): %E\n"
+	"\tAverage shared text size (kbytes): %X\n"
+	"\tAverage unshared data size (kbytes): %D\n"
+	"\tAverage stack size (kbytes): %p\n"
+	"\tAverage total size (kbytes): %K\n"
+	"\tMaximum resident set size (kbytes): %M\n"
+	"\tAverage resident set size (kbytes): %t\n"
+	"\tMajor (requiring I/O) page faults: %F\n"
+	"\tMinor (reclaiming a frame) page faults: %R\n"
+	"\tVoluntary context switches: %w\n"
+	"\tInvoluntary context switches: %c\n"
+	"\tSwaps: %W\n"
+	"\tFile system inputs: %I\n"
+	"\tFile system outputs: %O\n"
+	"\tSocket messages sent: %s\n"
+	"\tSocket messages received: %r\n"
+	"\tSignals delivered: %k\n"
+	"\tPage size (bytes): %Z\n" "\tExit status: %x";
+
+
+  /* Wait for and fill in data on child process PID.
+     Return 0 on error, 1 if ok.  */
+
+/* pid_t is short on BSDI, so don't try to promote it.  */
+static int resuse_end(pid_t pid, resource_t * resp)
+{
+	int status;
+
+	pid_t caught;
+
+	/* Ignore signals, but don't ignore the children.  When wait3
+	   returns the child process, set the time the command finished. */
+	while ((caught = wait3(&status, 0, &resp->ru)) != pid) {
+		if (caught == -1)
+			return 0;
+	}
+
+	gettimeofday(&resp->elapsed, (struct timezone *) 0);
+	resp->elapsed.tv_sec -= resp->start.tv_sec;
+	if (resp->elapsed.tv_usec < resp->start.tv_usec) {
+		/* Manually carry a one from the seconds field.  */
+		resp->elapsed.tv_usec += 1000000;
+		--resp->elapsed.tv_sec;
+	}
+	resp->elapsed.tv_usec -= resp->start.tv_usec;
+
+	resp->waitstatus = status;
+
+	return 1;
+}
+
+/* Print ARGV to FP, with each entry in ARGV separated by FILLER.  */
+static void fprintargv(FILE * fp, char *const *argv, const char *filler)
+{
+	char *const *av;
+
+	av = argv;
+	fputs(*av, fp);
+	while (*++av) {
+		fputs(filler, fp);
+		fputs(*av, fp);
+	}
+	if (ferror(fp))
+		bb_error_msg_and_die(bb_msg_write_error);
+}
+
+/* Return the number of kilobytes corresponding to a number of pages PAGES.
+   (Actually, we use it to convert pages*ticks into kilobytes*ticks.)
+
+   Try to do arithmetic so that the risk of overflow errors is minimized.
+   This is funky since the pagesize could be less than 1K.
+   Note: Some machines express getrusage statistics in terms of K,
+   others in terms of pages.  */
+
+static unsigned long ptok(unsigned long pages)
+{
+	static unsigned long ps = 0;
+	unsigned long tmp;
+	static long size = LONG_MAX;
+
+	/* Initialization.  */
+	if (ps == 0)
+		ps = (long) getpagesize();
+
+	/* Conversion.  */
+	if (pages > (LONG_MAX / ps)) {	/* Could overflow.  */
+		tmp = pages / 1024;	/* Smaller first, */
+		size = tmp * ps;	/* then larger.  */
+	} else {			/* Could underflow.  */
+		tmp = pages * ps;	/* Larger first, */
+		size = tmp / 1024;	/* then smaller.  */
+	}
+	return size;
+}
+
+/* summarize: Report on the system use of a command.
+
+   Copy the FMT argument to FP except that `%' sequences
+   have special meaning, and `\n' and `\t' are translated into
+   newline and tab, respectively, and `\\' is translated into `\'.
+
+   The character following a `%' can be:
+   (* means the tcsh time builtin also recognizes it)
+   % == a literal `%'
+   C == command name and arguments
+*  D == average unshared data size in K (ru_idrss+ru_isrss)
+*  E == elapsed real (wall clock) time in [hour:]min:sec
+*  F == major page faults (required physical I/O) (ru_majflt)
+*  I == file system inputs (ru_inblock)
+*  K == average total mem usage (ru_idrss+ru_isrss+ru_ixrss)
+*  M == maximum resident set size in K (ru_maxrss)
+*  O == file system outputs (ru_oublock)
+*  P == percent of CPU this job got (total cpu time / elapsed time)
+*  R == minor page faults (reclaims; no physical I/O involved) (ru_minflt)
+*  S == system (kernel) time (seconds) (ru_stime)
+*  T == system time in [hour:]min:sec
+*  U == user time (seconds) (ru_utime)
+*  u == user time in [hour:]min:sec
+*  W == times swapped out (ru_nswap)
+*  X == average amount of shared text in K (ru_ixrss)
+   Z == page size
+*  c == involuntary context switches (ru_nivcsw)
+   e == elapsed real time in seconds
+*  k == signals delivered (ru_nsignals)
+   p == average unshared stack size in K (ru_isrss)
+*  r == socket messages received (ru_msgrcv)
+*  s == socket messages sent (ru_msgsnd)
+   t == average resident set size in K (ru_idrss)
+*  w == voluntary context switches (ru_nvcsw)
+   x == exit status of command
+
+   Various memory usages are found by converting from page-seconds
+   to kbytes by multiplying by the page size, dividing by 1024,
+   and dividing by elapsed real time.
+
+   FP is the stream to print to.
+   FMT is the format string, interpreted as described above.
+   COMMAND is the command and args that are being summarized.
+   RESP is resource information on the command.  */
+
+static void summarize(FILE * fp, const char *fmt, char **command,
+					  resource_t * resp)
+{
+	unsigned long r;	/* Elapsed real milliseconds.  */
+	unsigned long v;	/* Elapsed virtual (CPU) milliseconds.  */
+
+	if (WIFSTOPPED(resp->waitstatus))
+		fprintf(fp, "Command stopped by signal %d\n",
+				WSTOPSIG(resp->waitstatus));
+	else if (WIFSIGNALED(resp->waitstatus))
+		fprintf(fp, "Command terminated by signal %d\n",
+				WTERMSIG(resp->waitstatus));
+	else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus))
+		fprintf(fp, "Command exited with non-zero status %d\n",
+				WEXITSTATUS(resp->waitstatus));
+
+	/* Convert all times to milliseconds.  Occasionally, one of these values
+	   comes out as zero.  Dividing by zero causes problems, so we first
+	   check the time value.  If it is zero, then we take `evasive action'
+	   instead of calculating a value.  */
+
+	r = resp->elapsed.tv_sec * 1000 + resp->elapsed.tv_usec / 1000;
+
+	v = resp->ru.ru_utime.tv_sec * 1000 + resp->ru.ru_utime.TV_MSEC +
+		resp->ru.ru_stime.tv_sec * 1000 + resp->ru.ru_stime.TV_MSEC;
+
+	while (*fmt) {
+		switch (*fmt) {
+		case '%':
+			switch (*++fmt) {
+			case '%':	/* Literal '%'.  */
+				putc('%', fp);
+				break;
+			case 'C':	/* The command that got timed.  */
+				fprintargv(fp, command, " ");
+				break;
+			case 'D':	/* Average unshared data size.  */
+				fprintf(fp, "%lu",
+						MSEC_TO_TICKS(v) == 0 ? 0 :
+						ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) +
+						ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v));
+				break;
+			case 'E':	/* Elapsed real (wall clock) time.  */
+				if (resp->elapsed.tv_sec >= 3600)	/* One hour -> h:m:s.  */
+					fprintf(fp, "%ldh %ldm %02lds",
+							resp->elapsed.tv_sec / 3600,
+							(resp->elapsed.tv_sec % 3600) / 60,
+							resp->elapsed.tv_sec % 60);
+				else
+					fprintf(fp, "%ldm %ld.%02lds",	/* -> m:s.  */
+							resp->elapsed.tv_sec / 60,
+							resp->elapsed.tv_sec % 60,
+							resp->elapsed.tv_usec / 10000);
+				break;
+			case 'F':	/* Major page faults.  */
+				fprintf(fp, "%ld", resp->ru.ru_majflt);
+				break;
+			case 'I':	/* Inputs.  */
+				fprintf(fp, "%ld", resp->ru.ru_inblock);
+				break;
+			case 'K':	/* Average mem usage == data+stack+text.  */
+				fprintf(fp, "%lu",
+						MSEC_TO_TICKS(v) == 0 ? 0 :
+						ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) +
+						ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v) +
+						ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v));
+				break;
+			case 'M':	/* Maximum resident set size.  */
+				fprintf(fp, "%lu", ptok((UL) resp->ru.ru_maxrss));
+				break;
+			case 'O':	/* Outputs.  */
+				fprintf(fp, "%ld", resp->ru.ru_oublock);
+				break;
+			case 'P':	/* Percent of CPU this job got.  */
+				/* % cpu is (total cpu time)/(elapsed time).  */
+				if (r > 0)
+					fprintf(fp, "%lu%%", (v * 100 / r));
+				else
+					fprintf(fp, "?%%");
+				break;
+			case 'R':	/* Minor page faults (reclaims).  */
+				fprintf(fp, "%ld", resp->ru.ru_minflt);
+				break;
+			case 'S':	/* System time.  */
+				fprintf(fp, "%ld.%02ld",
+						resp->ru.ru_stime.tv_sec,
+						resp->ru.ru_stime.TV_MSEC / 10);
+				break;
+			case 'T':	/* System time.  */
+				if (resp->ru.ru_stime.tv_sec >= 3600) /* One hour -> h:m:s.  */
+					fprintf(fp, "%ldh %ldm %02lds",
+							resp->ru.ru_stime.tv_sec / 3600,
+							(resp->ru.ru_stime.tv_sec % 3600) / 60,
+							resp->ru.ru_stime.tv_sec % 60);
+				else
+					fprintf(fp, "%ldm %ld.%02lds",	/* -> m:s.  */
+							resp->ru.ru_stime.tv_sec / 60,
+							resp->ru.ru_stime.tv_sec % 60,
+							resp->ru.ru_stime.tv_usec / 10000);
+				break;
+			case 'U':	/* User time.  */
+				fprintf(fp, "%ld.%02ld",
+						resp->ru.ru_utime.tv_sec,
+						resp->ru.ru_utime.TV_MSEC / 10);
+				break;
+			case 'u':	/* User time.  */
+				if (resp->ru.ru_utime.tv_sec >= 3600) /* One hour -> h:m:s.  */
+					fprintf(fp, "%ldh %ldm %02lds",
+							resp->ru.ru_utime.tv_sec / 3600,
+							(resp->ru.ru_utime.tv_sec % 3600) / 60,
+							resp->ru.ru_utime.tv_sec % 60);
+				else
+					fprintf(fp, "%ldm %ld.%02lds",	/* -> m:s.  */
+							resp->ru.ru_utime.tv_sec / 60,
+							resp->ru.ru_utime.tv_sec % 60,
+							resp->ru.ru_utime.tv_usec / 10000);
+				break;
+			case 'W':	/* Times swapped out.  */
+				fprintf(fp, "%ld", resp->ru.ru_nswap);
+				break;
+			case 'X':	/* Average shared text size.  */
+				fprintf(fp, "%lu",
+						MSEC_TO_TICKS(v) == 0 ? 0 :
+						ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v));
+				break;
+			case 'Z':	/* Page size.  */
+				fprintf(fp, "%d", getpagesize());
+				break;
+			case 'c':	/* Involuntary context switches.  */
+				fprintf(fp, "%ld", resp->ru.ru_nivcsw);
+				break;
+			case 'e':	/* Elapsed real time in seconds.  */
+				fprintf(fp, "%ld.%02ld",
+						resp->elapsed.tv_sec, resp->elapsed.tv_usec / 10000);
+				break;
+			case 'k':	/* Signals delivered.  */
+				fprintf(fp, "%ld", resp->ru.ru_nsignals);
+				break;
+			case 'p':	/* Average stack segment.  */
+				fprintf(fp, "%lu",
+						MSEC_TO_TICKS(v) == 0 ? 0 :
+						ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v));
+				break;
+			case 'r':	/* Incoming socket messages received.  */
+				fprintf(fp, "%ld", resp->ru.ru_msgrcv);
+				break;
+			case 's':	/* Outgoing socket messages sent.  */
+				fprintf(fp, "%ld", resp->ru.ru_msgsnd);
+				break;
+			case 't':	/* Average resident set size.  */
+				fprintf(fp, "%lu",
+						MSEC_TO_TICKS(v) == 0 ? 0 :
+						ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v));
+				break;
+			case 'w':	/* Voluntary context switches.  */
+				fprintf(fp, "%ld", resp->ru.ru_nvcsw);
+				break;
+			case 'x':	/* Exit status.  */
+				fprintf(fp, "%d", WEXITSTATUS(resp->waitstatus));
+				break;
+			case '\0':
+				putc('?', fp);
+				return;
+			default:
+				putc('?', fp);
+				putc(*fmt, fp);
+			}
+			++fmt;
+			break;
+
+		case '\\':		/* Format escape.  */
+			switch (*++fmt) {
+			case 't':
+				putc('\t', fp);
+				break;
+			case 'n':
+				putc('\n', fp);
+				break;
+			case '\\':
+				putc('\\', fp);
+				break;
+			default:
+				putc('?', fp);
+				putc('\\', fp);
+				putc(*fmt, fp);
+			}
+			++fmt;
+			break;
+
+		default:
+			putc(*fmt++, fp);
+		}
+
+		if (ferror(fp))
+			bb_error_msg_and_die(bb_msg_write_error);
+	}
+	putc('\n', fp);
+
+	if (ferror(fp))
+		bb_error_msg_and_die(bb_msg_write_error);
+}
+
+/* Run command CMD and return statistics on it.
+   Put the statistics in *RESP.  */
+static void run_command(char *const *cmd, resource_t * resp)
+{
+	pid_t pid;			/* Pid of child.  */
+	__sighandler_t interrupt_signal, quit_signal;
+
+	gettimeofday(&resp->start, (struct timezone *) 0);
+	pid = vfork();		/* Run CMD as child process.  */
+	if (pid < 0)
+		bb_error_msg_and_die("cannot fork");
+	else if (pid == 0) {	/* If child.  */
+		/* Don't cast execvp arguments; that causes errors on some systems,
+		   versus merely warnings if the cast is left off.  */
+		execvp(cmd[0], cmd);
+		bb_error_msg("cannot run %s", cmd[0]);
+		_exit(errno == ENOENT ? 127 : 126);
+	}
+
+	/* Have signals kill the child but not self (if possible).  */
+	interrupt_signal = signal(SIGINT, SIG_IGN);
+	quit_signal = signal(SIGQUIT, SIG_IGN);
+
+	if (resuse_end(pid, resp) == 0)
+		bb_error_msg("error waiting for child process");
+
+	/* Re-enable signals.  */
+	signal(SIGINT, interrupt_signal);
+	signal(SIGQUIT, quit_signal);
+}
+
+int time_main(int argc, char **argv)
+{
+	int gotone;
+	resource_t res;
+	const char *output_format = default_format;
+
+	argc--;
+	argv++;
+	/* Parse any options  -- don't use getopt() here so we don't
+	 * consume the args of our client application... */
+	while (argc > 0 && **argv == '-') {
+		gotone = 0;
+		while (gotone == 0 && *++(*argv)) {
+			switch (**argv) {
+			case 'v':
+				output_format = long_format;
+				break;
+			case 'p':
+				output_format = posix_format;
+				break;
+			default:
+				bb_show_usage();
+			}
+			argc--;
+			argv++;
+			gotone = 1;
+		}
+	}
+
+	if (argv == NULL || *argv == NULL)
+		bb_show_usage();
+
+	run_command(argv, &res);
+	summarize(stderr, output_format, argv, &res);
+	fflush(stderr);
+
+	if (WIFSTOPPED(res.waitstatus))
+		exit(WSTOPSIG(res.waitstatus));
+	else if (WIFSIGNALED(res.waitstatus))
+		exit(WTERMSIG(res.waitstatus));
+	else if (WIFEXITED(res.waitstatus))
+		exit(WEXITSTATUS(res.waitstatus));
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/watchdog.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/watchdog.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/miscutils/watchdog.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,70 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini watchdog implementation for busybox
+ *
+ * Copyright (C) 2003  Paul Mundt <lethal at linux-sh.org>
+ * Copyright (C) 2006  Bernhard Fischer <busybox at busybox.net>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+
+#define OPT_FOREGROUND 0x01
+#define OPT_TIMER      0x02
+
+/* Watchdog file descriptor */
+static int fd;
+
+static void watchdog_shutdown(int ATTRIBUTE_UNUSED unused)
+{
+	write(fd, "V", 1);	/* Magic, see watchdog-api.txt in kernel */
+	close(fd);
+	exit(0);
+}
+
+int watchdog_main(int argc, char **argv)
+{
+	unsigned long opts;
+	unsigned long timer_duration = 30; /* Userspace timer duration, in seconds */
+	char *t_arg;
+
+	opts = bb_getopt_ulflags(argc, argv, "Ft:", &t_arg);
+
+	if (opts & OPT_TIMER)
+		timer_duration = bb_xgetlarg(t_arg, 10, 0, INT_MAX);
+
+	/* We're only interested in the watchdog device .. */
+	if (optind < argc - 1 || argc == 1)
+		bb_show_usage();
+
+#ifdef BB_NOMMU
+	if (!(opts & OPT_FOREGROUND))
+		vfork_daemon_rexec(0, 1, argc, argv, "-F");
+#else
+	bb_xdaemon(0, 1);
+#endif
+
+	signal(SIGHUP, watchdog_shutdown);
+	signal(SIGINT, watchdog_shutdown);
+
+	fd = bb_xopen(argv[argc - 1], O_WRONLY);
+
+	while (1) {
+		/*
+		 * Make sure we clear the counter before sleeping, as the counter value
+		 * is undefined at this point -- PFM
+		 */
+		write(fd, "\0", 1);
+		sleep(timer_duration);
+	}
+
+	watchdog_shutdown(0);
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,147 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Linux Module Utilities"
+
+config CONFIG_INSMOD
+	bool "insmod"
+	default n
+	help
+	  insmod is used to load specified modules in the running kernel.
+
+config CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+	bool "Module version checking"
+	default n
+	depends on CONFIG_INSMOD && CONFIG_FEATURE_2_4_MODULES
+	help
+	  Support checking of versions for modules.  This is used to
+	  ensure that the kernel and module are made for each other.
+
+config CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
+	bool "Add module symbols to kernel symbol table"
+	default n
+	depends on CONFIG_INSMOD && CONFIG_FEATURE_2_4_MODULES
+	help
+	  By adding module symbols to the kernel symbol table, Oops messages
+	  occuring within kernel modules can be properly debugged.  By enabling
+	  this feature, module symbols will always be added to the kernel symbol
+	  table for properly debugging support.  If you are not interested in
+	  Oops messages from kernel modules, say N.
+
+config CONFIG_FEATURE_INSMOD_LOADINKMEM
+	bool "In kernel memory optimization (uClinux only)"
+	default n
+	depends on CONFIG_INSMOD && CONFIG_FEATURE_2_4_MODULES
+	help
+	  This is a special uClinux only memory optimization that lets insmod
+	  load the specified kernel module directly into kernel space, reducing
+	  memory usage by preventing the need for two copies of the module
+	  being loaded into memory.
+
+config CONFIG_FEATURE_INSMOD_LOAD_MAP
+	bool "Enable load map (-m) option"
+	default n
+	depends on CONFIG_INSMOD && CONFIG_FEATURE_2_4_MODULES
+	help
+	  Enabling this, one would be able to get a load map
+	  output on stdout. This makes kernel module debugging
+	  easier.
+	  If you don't plan to debug kernel modules, you
+	  don't need this option.
+
+config CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
+	bool "Symbols in load map"
+	default y
+	depends on CONFIG_FEATURE_INSMOD_LOAD_MAP
+	help
+	  Without this option, -m will only output section
+	  load map.  With this option, -m will also output
+	  symbols load map.
+
+config CONFIG_RMMOD
+	bool "rmmod"
+	default n
+	help
+	  rmmod is used to unload specified modules from the kernel.
+
+config CONFIG_LSMOD
+	bool "lsmod"
+	default n
+	help
+	  lsmod is used to display a list of loaded modules.
+
+config CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT
+	bool "lsmod pretty output for 2.6.x Linux kernels "
+	default n
+	depends on CONFIG_LSMOD
+	help
+	  This option makes output format of lsmod adjusted to
+	  the format of module-init-tools for Linux kernel 2.6.
+
+config CONFIG_MODPROBE
+	bool "modprobe"
+	default n
+	help
+	  Handle the loading of modules, and their dependencies on a high
+	  level.
+
+	  Note that in the state, modprobe does not understand multiple
+	  module options from the configuration file. See option below.
+
+config CONFIG_FEATURE_MODPROBE_MULTIPLE_OPTIONS
+	bool "Multiple options parsing"
+	default y
+	depends on CONFIG_MODPROBE
+	help
+	  Allow modprobe to understand more than one option to pass to
+	  modules.
+
+	  This is a WIP, while waiting for a common argument parsing
+	  common amongst all BB applets (shell, modprobe, etc...) and
+	  adds around 600 bytes on x86, 700 bytes on ARM. The code is
+	  biggish and uggly, but just works.
+
+	  Saying Y here is not a bad idea if you're not that short
+	  on storage capacity.
+
+comment "Options common to multiple modutils"
+	depends on CONFIG_INSMOD || CONFIG_RMMOD || CONFIG_MODPROBE || CONFIG_LSMOD
+
+config CONFIG_FEATURE_CHECK_TAINTED_MODULE
+	# Simulate indentation
+	bool "Support tainted module checking with new kernels"
+	default y
+	depends on CONFIG_INSMOD || CONFIG_LSMOD
+	help
+	  Support checking for tainted modules.  These are usually binary
+	  only modules that will make the linux-kernel list ignore your
+	  support request.
+	  This option is required to support GPLONLY modules.
+
+config CONFIG_FEATURE_2_4_MODULES
+	# Simulate indentation
+	bool "Support version 2.2.x to 2.4.x Linux kernels"
+	default y
+	depends on CONFIG_INSMOD || CONFIG_RMMOD
+	help
+	  Support module loading for 2.2.x and 2.4.x Linux kernels.
+
+config CONFIG_FEATURE_2_6_MODULES
+	# Simulate indentation
+	bool "Support version 2.6.x Linux kernels"
+	default y
+	depends on CONFIG_INSMOD || CONFIG_RMMOD || CONFIG_MODPROBE
+	help
+	  Support module loading for newer 2.6.x Linux kernels.
+
+
+config CONFIG_FEATURE_QUERY_MODULE_INTERFACE
+	bool
+	default y
+	depends on CONFIG_FEATURE_2_4_MODULES && !CONFIG_FEATURE_2_6_MODULES
+
+
+endmenu
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/modutils
+MODUTILS_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,32 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+MODUTILS_AR:=modutils.a
+ifndef $(MODUTILS_DIR)
+MODUTILS_DIR:=$(top_builddir)/modutils/
+endif
+srcdir=$(top_srcdir)/modutils
+
+MODUTILS-y:=
+MODUTILS-$(CONFIG_INSMOD)		+= insmod.o
+MODUTILS-$(CONFIG_LSMOD)		+= lsmod.o
+MODUTILS-$(CONFIG_MODPROBE)		+= modprobe.o
+MODUTILS-$(CONFIG_RMMOD)		+= rmmod.o
+
+ifneq ($(strip $(MODUTILS-y)),)
+libraries-y+=$(MODUTILS_DIR)$(MODUTILS_AR)
+endif
+
+MODUTILS_SRC-y:=$(patsubst %.o,$(srcdir)/%.c,$(MODUTILS-y))
+MODUTILS_SRC-a:=$(wildcard $(srcdir)/*.c)
+APPLET_SRC-y+=$(MODUTILS_SRC-y)
+APPLET_SRC-a+=$(MODUTILS_SRC-a)
+
+$(MODUTILS_DIR)$(MODUTILS_AR): $(patsubst %,$(MODUTILS_DIR)%, $(MODUTILS-y))
+	$(do_ar)
+
+$(MODUTILS_DIR)%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/insmod.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/insmod.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/insmod.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4381 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini insmod implementation for busybox
+ *
+ * This version of insmod supports ARM, CRIS, H8/300, x86, ia64, x86_64,
+ * m68k, MIPS, PowerPC, S390, SH3/4/5, Sparc, v850e, and x86_64.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ * and Ron Alder <alder at lineo.com>
+ *
+ * Rodney Radford <rradford at mindspring.com> 17-Aug-2004.
+ *   Added x86_64 support.
+ *
+ * Miles Bader <miles at gnu.org> added NEC V850E support.
+ *
+ * Modified by Bryan Rittmeyer <bryan at ixiacom.com> to support SH4
+ * and (theoretically) SH3. I have only tested SH4 in little endian mode.
+ *
+ * Modified by Alcove, Julien Gaulmin <julien.gaulmin at alcove.fr> and
+ * Nicolas Ferre <nicolas.ferre at alcove.fr> to support ARM7TDMI.  Only
+ * very minor changes required to also work with StrongArm and presumably
+ * all ARM based systems.
+ *
+ * Yoshinori Sato <ysato at users.sourceforge.jp> 19-May-2004.
+ *   added Renesas H8/300 support.
+ *
+ * Paul Mundt <lethal at linux-sh.org> 08-Aug-2003.
+ *   Integrated support for sh64 (SH-5), from preliminary modutils
+ *   patches from Benedict Gaster <benedict.gaster at superh.com>.
+ *   Currently limited to support for 32bit ABI.
+ *
+ * Magnus Damm <damm at opensource.se> 22-May-2002.
+ *   The plt and got code are now using the same structs.
+ *   Added generic linked list code to fully support PowerPC.
+ *   Replaced the mess in arch_apply_relocation() with architecture blocks.
+ *   The arch_create_got() function got cleaned up with architecture blocks.
+ *   These blocks should be easy maintain and sync with obj_xxx.c in modutils.
+ *
+ * Magnus Damm <damm at opensource.se> added PowerPC support 20-Feb-2001.
+ *   PowerPC specific code stolen from modutils-2.3.16,
+ *   written by Paul Mackerras, Copyright 1996, 1997 Linux International.
+ *   I've only tested the code on mpc8xx platforms in big-endian mode.
+ *   Did some cleanup and added CONFIG_USE_xxx_ENTRIES...
+ *
+ * Quinn Jensen <jensenq at lineo.com> added MIPS support 23-Feb-2001.
+ *   based on modutils-2.4.2
+ *   MIPS specific support for Elf loading and relocation.
+ *   Copyright 1996, 1997 Linux International.
+ *   Contributed by Ralf Baechle <ralf at gnu.ai.mit.edu>
+ *
+ * Based almost entirely on the Linux modutils-2.3.11 implementation.
+ *   Copyright 1996, 1997 Linux International.
+ *   New implementation contributed by Richard Henderson <rth at tamu.edu>
+ *   Based on original work by Bjorn Ekwall <bj0rn at blox.se>
+ *   Restructured (and partly rewritten) by:
+ *   Björn Ekwall <bj0rn at blox.se> February 1999
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <assert.h>
+#include <string.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <sys/utsname.h>
+
+#if !defined(CONFIG_FEATURE_2_4_MODULES) && \
+	!defined(CONFIG_FEATURE_2_6_MODULES)
+#define CONFIG_FEATURE_2_4_MODULES
+#endif
+
+#if !defined(CONFIG_FEATURE_2_4_MODULES)
+#define insmod_ng_main insmod_main
+#endif
+
+#if defined(CONFIG_FEATURE_2_6_MODULES)
+extern int insmod_ng_main( int argc, char **argv);
+#endif
+
+
+#if defined(CONFIG_FEATURE_2_4_MODULES)
+
+
+#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
+#define LOADBITS 0
+#else
+#define LOADBITS 1
+#endif
+
+
+/* Alpha */
+#if defined(__alpha__)
+#define MATCH_MACHINE(x) (x == EM_ALPHA)
+#define SHT_RELM       SHT_RELA
+#define Elf64_RelM     Elf64_Rela
+#define ELFCLASSM      ELFCLASS64
+#endif
+
+/* ARM support */
+#if defined(__arm__)
+#define MATCH_MACHINE(x) (x == EM_ARM)
+#define SHT_RELM	SHT_REL
+#define Elf32_RelM	Elf32_Rel
+#define ELFCLASSM	ELFCLASS32
+#define CONFIG_USE_PLT_ENTRIES
+#define CONFIG_PLT_ENTRY_SIZE 8
+#define CONFIG_USE_GOT_ENTRIES
+#define CONFIG_GOT_ENTRY_SIZE 8
+#define CONFIG_USE_SINGLE
+#endif
+
+/* blackfin */
+#if defined(BFIN)
+#define MATCH_MACHINE(x) (x == EM_BLACKFIN)
+#define SHT_RELM	SHT_RELA
+#define Elf32_RelM	Elf32_Rela
+#define ELFCLASSM	ELFCLASS32
+#endif
+
+/* CRIS */
+#if defined(__cris__)
+#define MATCH_MACHINE(x) (x == EM_CRIS)
+#define SHT_RELM	SHT_RELA
+#define Elf32_RelM	Elf32_Rela
+#define ELFCLASSM	ELFCLASS32
+#ifndef EM_CRIS
+#define EM_CRIS 76
+#define R_CRIS_NONE 0
+#define R_CRIS_32   3
+#endif
+#endif
+
+/* H8/300 */
+#if defined(__H8300H__) || defined(__H8300S__)
+#define MATCH_MACHINE(x) (x == EM_H8_300)
+#define SHT_RELM	SHT_RELA
+#define Elf32_RelM	Elf32_Rela
+#define ELFCLASSM	ELFCLASS32
+#define CONFIG_USE_SINGLE
+#define SYMBOL_PREFIX	"_"
+#endif
+
+/* PA-RISC / HP-PA */
+#if defined(__hppa__)
+#define MATCH_MACHINE(x) (x == EM_PARISC)
+#define SHT_RELM       SHT_RELA
+#if defined(__LP64__)
+#define Elf64_RelM     Elf64_Rela
+#define ELFCLASSM      ELFCLASS64
+#else
+#define Elf32_RelM     Elf32_Rela
+#define ELFCLASSM      ELFCLASS32
+#endif
+#endif
+
+/* x86 */
+#if defined(__i386__)
+#ifndef EM_486
+#define MATCH_MACHINE(x) (x == EM_386)
+#else
+#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
+#endif
+#define SHT_RELM	SHT_REL
+#define Elf32_RelM	Elf32_Rel
+#define ELFCLASSM	ELFCLASS32
+#define CONFIG_USE_GOT_ENTRIES
+#define CONFIG_GOT_ENTRY_SIZE 4
+#define CONFIG_USE_SINGLE
+#endif
+
+/* IA64, aka Itanium */
+#if defined(__ia64__)
+#define MATCH_MACHINE(x) (x == EM_IA_64)
+#define SHT_RELM       SHT_RELA
+#define Elf64_RelM     Elf64_Rela
+#define ELFCLASSM      ELFCLASS64
+#endif
+
+/* m68k */
+#if defined(__mc68000__)
+#define MATCH_MACHINE(x) (x == EM_68K)
+#define SHT_RELM	SHT_RELA
+#define Elf32_RelM	Elf32_Rela
+#define ELFCLASSM	ELFCLASS32
+#define CONFIG_USE_GOT_ENTRIES
+#define CONFIG_GOT_ENTRY_SIZE 4
+#define CONFIG_USE_SINGLE
+#endif
+
+/* Microblaze */
+#if defined(__microblaze__)
+#define CONFIG_USE_SINGLE
+#define MATCH_MACHINE(x) (x == EM_XILINX_MICROBLAZE)
+#define SHT_RELM	SHT_RELA
+#define Elf32_RelM	Elf32_Rela
+#define ELFCLASSM	ELFCLASS32
+#endif
+
+/* MIPS */
+#if defined(__mips__)
+#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
+#define SHT_RELM	SHT_REL
+#define Elf32_RelM	Elf32_Rel
+#define ELFCLASSM	ELFCLASS32
+/* Account for ELF spec changes.  */
+#ifndef EM_MIPS_RS3_LE
+#ifdef EM_MIPS_RS4_BE
+#define EM_MIPS_RS3_LE	EM_MIPS_RS4_BE
+#else
+#define EM_MIPS_RS3_LE	10
+#endif
+#endif /* !EM_MIPS_RS3_LE */
+#define ARCHDATAM       "__dbe_table"
+#endif
+
+/* Nios II */
+#if defined(__nios2__)
+#define MATCH_MACHINE(x) (x == EM_ALTERA_NIOS2)
+#define SHT_RELM	SHT_RELA
+#define Elf32_RelM	Elf32_Rela
+#define ELFCLASSM	ELFCLASS32
+#endif
+
+/* PowerPC */
+#if defined(__powerpc64__)
+#define MATCH_MACHINE(x) (x == EM_PPC64)
+#define SHT_RELM	SHT_RELA
+#define Elf64_RelM	Elf64_Rela
+#define ELFCLASSM	ELFCLASS64
+#elif defined(__powerpc__)
+#define MATCH_MACHINE(x) (x == EM_PPC)
+#define SHT_RELM	SHT_RELA
+#define Elf32_RelM	Elf32_Rela
+#define ELFCLASSM	ELFCLASS32
+#define CONFIG_USE_PLT_ENTRIES
+#define CONFIG_PLT_ENTRY_SIZE 16
+#define CONFIG_USE_PLT_LIST
+#define CONFIG_LIST_ARCHTYPE ElfW(Addr)
+#define CONFIG_USE_LIST
+#define ARCHDATAM       "__ftr_fixup"
+#endif
+
+/* S390 */
+#if defined(__s390__)
+#define MATCH_MACHINE(x) (x == EM_S390)
+#define SHT_RELM	SHT_RELA
+#define Elf32_RelM	Elf32_Rela
+#define ELFCLASSM	ELFCLASS32
+#define CONFIG_USE_PLT_ENTRIES
+#define CONFIG_PLT_ENTRY_SIZE 8
+#define CONFIG_USE_GOT_ENTRIES
+#define CONFIG_GOT_ENTRY_SIZE 8
+#define CONFIG_USE_SINGLE
+#endif
+
+/* SuperH */
+#if defined(__sh__)
+#define MATCH_MACHINE(x) (x == EM_SH)
+#define SHT_RELM	SHT_RELA
+#define Elf32_RelM	Elf32_Rela
+#define ELFCLASSM	ELFCLASS32
+#define CONFIG_USE_GOT_ENTRIES
+#define CONFIG_GOT_ENTRY_SIZE 4
+#define CONFIG_USE_SINGLE
+/* the SH changes have only been tested in =little endian= mode */
+/* I'm not sure about big endian, so let's warn: */
+#if defined(__sh__) && BB_BIG_ENDIAN
+# error insmod.c may require changes for use on big endian SH
+#endif
+/* it may or may not work on the SH1/SH2... Error on those also */
+#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__))
+#error insmod.c may require changes for SH1 or SH2 use
+#endif
+#endif
+
+/* Sparc */
+#if defined(__sparc__)
+#define MATCH_MACHINE(x) (x == EM_SPARC)
+#define SHT_RELM       SHT_RELA
+#define Elf32_RelM     Elf32_Rela
+#define ELFCLASSM      ELFCLASS32
+#endif
+
+/* v850e */
+#if defined (__v850e__)
+#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
+#define SHT_RELM	SHT_RELA
+#define Elf32_RelM	Elf32_Rela
+#define ELFCLASSM	ELFCLASS32
+#define CONFIG_USE_PLT_ENTRIES
+#define CONFIG_PLT_ENTRY_SIZE 8
+#define CONFIG_USE_SINGLE
+#ifndef EM_CYGNUS_V850	/* grumble */
+#define EM_CYGNUS_V850	0x9080
+#endif
+#define SYMBOL_PREFIX	"_"
+#endif
+
+/* X86_64  */
+#if defined(__x86_64__)
+#define MATCH_MACHINE(x) (x == EM_X86_64)
+#define SHT_RELM	SHT_RELA
+#define CONFIG_USE_GOT_ENTRIES
+#define CONFIG_GOT_ENTRY_SIZE 8
+#define CONFIG_USE_SINGLE
+#define Elf64_RelM	Elf64_Rela
+#define ELFCLASSM	ELFCLASS64
+#endif
+
+#ifndef SHT_RELM
+#error Sorry, but insmod.c does not yet support this architecture...
+#endif
+
+
+//----------------------------------------------------------------------------
+//--------modutils module.h, lines 45-242
+//----------------------------------------------------------------------------
+
+/* Definitions for the Linux module syscall interface.
+   Copyright 1996, 1997 Linux International.
+
+   Contributed by Richard Henderson <rth at tamu.edu>
+
+   This file is part of the Linux modutils.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+
+#ifndef MODUTILS_MODULE_H
+/* Why? static const int MODUTILS_MODULE_H = 1;*/
+
+#ident "$Id: insmod.c,v 1.126 2004/12/26 09:13:32 vapier Exp $"
+
+/*======================================================================*/
+/* For sizeof() which are related to the module platform and not to the
+   environment isnmod is running in, use sizeof_xx instead of sizeof(xx).  */
+
+#define tgt_sizeof_char		sizeof(char)
+#define tgt_sizeof_short	sizeof(short)
+#define tgt_sizeof_int		sizeof(int)
+#define tgt_sizeof_long		sizeof(long)
+#define tgt_sizeof_char_p	sizeof(char *)
+#define tgt_sizeof_void_p	sizeof(void *)
+#define tgt_long		long
+
+#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
+#undef tgt_sizeof_long
+#undef tgt_sizeof_char_p
+#undef tgt_sizeof_void_p
+#undef tgt_long
+enum {
+	tgt_sizeof_long = 8,
+	tgt_sizeof_char_p = 8,
+	tgt_sizeof_void_p = 8
+};
+#define tgt_long		long long
+#endif
+
+/*======================================================================*/
+/* The structures used in Linux 2.1.  */
+
+/* Note: new_module_symbol does not use tgt_long intentionally */
+struct new_module_symbol
+{
+	unsigned long value;
+	unsigned long name;
+};
+
+struct new_module_persist;
+
+struct new_module_ref
+{
+	unsigned tgt_long dep;		/* kernel addresses */
+	unsigned tgt_long ref;
+	unsigned tgt_long next_ref;
+};
+
+struct new_module
+{
+	unsigned tgt_long size_of_struct;	/* == sizeof(module) */
+	unsigned tgt_long next;
+	unsigned tgt_long name;
+	unsigned tgt_long size;
+
+	tgt_long usecount;
+	unsigned tgt_long flags;		/* AUTOCLEAN et al */
+
+	unsigned nsyms;
+	unsigned ndeps;
+
+	unsigned tgt_long syms;
+	unsigned tgt_long deps;
+	unsigned tgt_long refs;
+	unsigned tgt_long init;
+	unsigned tgt_long cleanup;
+	unsigned tgt_long ex_table_start;
+	unsigned tgt_long ex_table_end;
+#ifdef __alpha__
+	unsigned tgt_long gp;
+#endif
+	/* Everything after here is extension.  */
+	unsigned tgt_long persist_start;
+	unsigned tgt_long persist_end;
+	unsigned tgt_long can_unload;
+	unsigned tgt_long runsize;
+	const char *kallsyms_start;     /* All symbols for kernel debugging */
+	const char *kallsyms_end;
+	const char *archdata_start;     /* arch specific data for module */
+	const char *archdata_end;
+	const char *kernel_data;        /* Reserved for kernel internal use */
+};
+
+#ifdef ARCHDATAM
+#define ARCHDATA_SEC_NAME ARCHDATAM
+#else
+#define ARCHDATA_SEC_NAME "__archdata"
+#endif
+#define KALLSYMS_SEC_NAME "__kallsyms"
+
+
+struct new_module_info
+{
+	unsigned long addr;
+	unsigned long size;
+	unsigned long flags;
+	long usecount;
+};
+
+/* Bits of module.flags.  */
+enum {
+	NEW_MOD_RUNNING = 1,
+	NEW_MOD_DELETED = 2,
+	NEW_MOD_AUTOCLEAN = 4,
+	NEW_MOD_VISITED = 8,
+	NEW_MOD_USED_ONCE = 16
+};
+
+int init_module(const char *name, const struct new_module *);
+int query_module(const char *name, int which, void *buf,
+		size_t bufsize, size_t *ret);
+
+/* Values for query_module's which.  */
+enum {
+	QM_MODULES = 1,
+	QM_DEPS = 2,
+	QM_REFS = 3,
+	QM_SYMBOLS = 4,
+	QM_INFO = 5
+};
+
+/*======================================================================*/
+/* The system calls unchanged between 2.0 and 2.1.  */
+
+unsigned long create_module(const char *, size_t);
+int delete_module(const char *);
+
+
+#endif /* module.h */
+
+//----------------------------------------------------------------------------
+//--------end of modutils module.h
+//----------------------------------------------------------------------------
+
+
+
+//----------------------------------------------------------------------------
+//--------modutils obj.h, lines 253-462
+//----------------------------------------------------------------------------
+
+/* Elf object file loading and relocation routines.
+   Copyright 1996, 1997 Linux International.
+
+   Contributed by Richard Henderson <rth at tamu.edu>
+
+   This file is part of the Linux modutils.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2 of the License, or (at your
+   option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+
+#ifndef MODUTILS_OBJ_H
+/* Why? static const int MODUTILS_OBJ_H = 1; */
+
+#ident "$Id: insmod.c,v 1.126 2004/12/26 09:13:32 vapier Exp $"
+
+/* The relocatable object is manipulated using elfin types.  */
+
+#include <stdio.h>
+#include <elf.h>
+#include <endian.h>
+
+#ifndef ElfW
+# if ELFCLASSM == ELFCLASS32
+#  define ElfW(x)  Elf32_ ## x
+#  define ELFW(x)  ELF32_ ## x
+# else
+#  define ElfW(x)  Elf64_ ## x
+#  define ELFW(x)  ELF64_ ## x
+# endif
+#endif
+
+/* For some reason this is missing from some ancient C libraries....  */
+#ifndef ELF32_ST_INFO
+# define ELF32_ST_INFO(bind, type)       (((bind) << 4) + ((type) & 0xf))
+#endif
+
+#ifndef ELF64_ST_INFO
+# define ELF64_ST_INFO(bind, type)       (((bind) << 4) + ((type) & 0xf))
+#endif
+
+#define ELF_ST_BIND(info) ELFW(ST_BIND)(info)
+#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info)
+#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type)
+#define ELF_R_TYPE(val) ELFW(R_TYPE)(val)
+#define ELF_R_SYM(val) ELFW(R_SYM)(val)
+
+struct obj_string_patch;
+struct obj_symbol_patch;
+
+struct obj_section
+{
+	ElfW(Shdr) header;
+	const char *name;
+	char *contents;
+	struct obj_section *load_next;
+	int idx;
+};
+
+struct obj_symbol
+{
+	struct obj_symbol *next;	/* hash table link */
+	const char *name;
+	unsigned long value;
+	unsigned long size;
+	int secidx;			/* the defining section index/module */
+	int info;
+	int ksymidx;			/* for export to the kernel symtab */
+	int referenced;		/* actually used in the link */
+};
+
+/* Hardcode the hash table size.  We shouldn't be needing so many
+   symbols that we begin to degrade performance, and we get a big win
+   by giving the compiler a constant divisor.  */
+
+#define HASH_BUCKETS  521
+
+struct obj_file
+{
+	ElfW(Ehdr) header;
+	ElfW(Addr) baseaddr;
+	struct obj_section **sections;
+	struct obj_section *load_order;
+	struct obj_section **load_order_search_start;
+	struct obj_string_patch *string_patches;
+	struct obj_symbol_patch *symbol_patches;
+	int (*symbol_cmp)(const char *, const char *);
+	unsigned long (*symbol_hash)(const char *);
+	unsigned long local_symtab_size;
+	struct obj_symbol **local_symtab;
+	struct obj_symbol *symtab[HASH_BUCKETS];
+};
+
+enum obj_reloc
+{
+	obj_reloc_ok,
+	obj_reloc_overflow,
+	obj_reloc_dangerous,
+	obj_reloc_unhandled
+};
+
+struct obj_string_patch
+{
+	struct obj_string_patch *next;
+	int reloc_secidx;
+	ElfW(Addr) reloc_offset;
+	ElfW(Addr) string_offset;
+};
+
+struct obj_symbol_patch
+{
+	struct obj_symbol_patch *next;
+	int reloc_secidx;
+	ElfW(Addr) reloc_offset;
+	struct obj_symbol *sym;
+};
+
+
+/* Generic object manipulation routines.  */
+
+static unsigned long obj_elf_hash(const char *);
+
+static unsigned long obj_elf_hash_n(const char *, unsigned long len);
+
+static struct obj_symbol *obj_find_symbol (struct obj_file *f,
+					 const char *name);
+
+static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
+				  struct obj_symbol *sym);
+
+#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+static void obj_set_symbol_compare(struct obj_file *f,
+			    int (*cmp)(const char *, const char *),
+			    unsigned long (*hash)(const char *));
+#endif
+
+static struct obj_section *obj_find_section (struct obj_file *f,
+					   const char *name);
+
+static void obj_insert_section_load_order (struct obj_file *f,
+				    struct obj_section *sec);
+
+static struct obj_section *obj_create_alloced_section (struct obj_file *f,
+						const char *name,
+						unsigned long align,
+						unsigned long size);
+
+static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
+						      const char *name,
+						      unsigned long align,
+						      unsigned long size);
+
+static void *obj_extend_section (struct obj_section *sec, unsigned long more);
+
+static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
+		     const char *string);
+
+static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
+		     struct obj_symbol *sym);
+
+static int obj_check_undefineds(struct obj_file *f);
+
+static void obj_allocate_commons(struct obj_file *f);
+
+static unsigned long obj_load_size (struct obj_file *f);
+
+static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
+
+static struct obj_file *obj_load(FILE *f, int loadprogbits);
+
+static int obj_create_image (struct obj_file *f, char *image);
+
+/* Architecture specific manipulation routines.  */
+
+static struct obj_file *arch_new_file (void);
+
+static struct obj_section *arch_new_section (void);
+
+static struct obj_symbol *arch_new_symbol (void);
+
+static enum obj_reloc arch_apply_relocation (struct obj_file *f,
+				      struct obj_section *targsec,
+				      struct obj_section *symsec,
+				      struct obj_symbol *sym,
+				      ElfW(RelM) *rel, ElfW(Addr) value);
+
+static void arch_create_got (struct obj_file *f);
+#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
+static int obj_gpl_license(struct obj_file *f, const char **license);
+#endif /* ENABLE_FEATURE_CHECK_TAINTED_MODULE */
+#endif /* obj.h */
+//----------------------------------------------------------------------------
+//--------end of modutils obj.h
+//----------------------------------------------------------------------------
+
+
+/* SPFX is always a string, so it can be concatenated to string constants.  */
+#ifdef SYMBOL_PREFIX
+#define SPFX	SYMBOL_PREFIX
+#else
+#define SPFX	""
+#endif
+
+
+#define _PATH_MODULES	"/lib/modules"
+enum { STRVERSIONLEN = 32 };
+
+/*======================================================================*/
+
+static int flag_force_load = 0;
+static int flag_autoclean = 0;
+static int flag_verbose = 0;
+static int flag_quiet = 0;
+static int flag_export = 1;
+
+
+/*======================================================================*/
+
+#if defined(CONFIG_USE_LIST)
+
+struct arch_list_entry
+{
+	struct arch_list_entry *next;
+	CONFIG_LIST_ARCHTYPE addend;
+	int offset;
+	int inited : 1;
+};
+
+#endif
+
+#if defined(CONFIG_USE_SINGLE)
+
+struct arch_single_entry
+{
+	int offset;
+	int inited : 1;
+	int allocated : 1;
+};
+
+#endif
+
+#if defined(__mips__)
+struct mips_hi16
+{
+	struct mips_hi16 *next;
+	ElfW(Addr) *addr;
+	ElfW(Addr) value;
+};
+#endif
+
+struct arch_file {
+	struct obj_file root;
+#if defined(CONFIG_USE_PLT_ENTRIES)
+	struct obj_section *plt;
+#endif
+#if defined(CONFIG_USE_GOT_ENTRIES)
+	struct obj_section *got;
+#endif
+#if defined(__mips__)
+	struct mips_hi16 *mips_hi16_list;
+#endif
+};
+
+struct arch_symbol {
+	struct obj_symbol root;
+#if defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(CONFIG_USE_PLT_LIST)
+	struct arch_list_entry *pltent;
+#else
+	struct arch_single_entry pltent;
+#endif
+#endif
+#if defined(CONFIG_USE_GOT_ENTRIES)
+	struct arch_single_entry gotent;
+#endif
+};
+
+
+struct external_module {
+	const char *name;
+	ElfW(Addr) addr;
+	int used;
+	size_t nsyms;
+	struct new_module_symbol *syms;
+};
+
+static struct new_module_symbol *ksyms;
+static size_t nksyms;
+
+static struct external_module *ext_modules;
+static int n_ext_modules;
+static int n_ext_modules_used;
+extern int delete_module(const char *);
+
+static char *m_filename;
+static char *m_fullName;
+
+
+
+/*======================================================================*/
+
+
+static int check_module_name_match(const char *filename, struct stat *statbuf,
+						   void *userdata)
+{
+	char *fullname = (char *) userdata;
+
+	if (fullname[0] == '\0')
+		return (FALSE);
+	else {
+		char *tmp, *tmp1 = bb_xstrdup(filename);
+		tmp = bb_get_last_path_component(tmp1);
+		if (strcmp(tmp, fullname) == 0) {
+			free(tmp1);
+			/* Stop searching if we find a match */
+			m_filename = bb_xstrdup(filename);
+			return (FALSE);
+		}
+		free(tmp1);
+	}
+	return (TRUE);
+}
+
+
+/*======================================================================*/
+
+static struct obj_file *arch_new_file(void)
+{
+	struct arch_file *f;
+	f = xmalloc(sizeof(*f));
+
+	memset(f, 0, sizeof(*f));
+
+	return &f->root;
+}
+
+static struct obj_section *arch_new_section(void)
+{
+	return xmalloc(sizeof(struct obj_section));
+}
+
+static struct obj_symbol *arch_new_symbol(void)
+{
+	struct arch_symbol *sym;
+	sym = xmalloc(sizeof(*sym));
+
+	memset(sym, 0, sizeof(*sym));
+
+	return &sym->root;
+}
+
+static enum obj_reloc
+arch_apply_relocation(struct obj_file *f,
+					  struct obj_section *targsec,
+					  struct obj_section *symsec,
+					  struct obj_symbol *sym,
+					  ElfW(RelM) *rel, ElfW(Addr) v)
+{
+	struct arch_file *ifile = (struct arch_file *) f;
+	enum obj_reloc ret = obj_reloc_ok;
+	ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
+	ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
+#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
+	struct arch_symbol *isym = (struct arch_symbol *) sym;
+#endif
+#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__)
+#if defined(CONFIG_USE_GOT_ENTRIES)
+	ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
+#endif
+#endif
+#if defined(CONFIG_USE_PLT_ENTRIES)
+	ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
+	unsigned long *ip;
+# if defined(CONFIG_USE_PLT_LIST)
+	struct arch_list_entry *pe;
+# else
+	struct arch_single_entry *pe;
+# endif
+#endif
+
+	switch (ELF_R_TYPE(rel->r_info)) {
+
+#if defined(__arm__)
+
+		case R_ARM_NONE:
+			break;
+
+		case R_ARM_ABS32:
+			*loc += v;
+			break;
+
+		case R_ARM_GOT32:
+			goto bb_use_got;
+
+		case R_ARM_GOTPC:
+			/* relative reloc, always to _GLOBAL_OFFSET_TABLE_
+			 * (which is .got) similar to branch,
+			 * but is full 32 bits relative */
+
+			assert(got != 0);
+			*loc += got - dot;
+			break;
+
+		case R_ARM_PC24:
+		case R_ARM_PLT32:
+			goto bb_use_plt;
+
+		case R_ARM_GOTOFF: /* address relative to the got */
+			assert(got != 0);
+			*loc += v - got;
+			break;
+
+#elif defined(__cris__)
+
+		case R_CRIS_NONE:
+			break;
+
+		case R_CRIS_32:
+			/* CRIS keeps the relocation value in the r_addend field and
+			 * should not use whats in *loc at all
+			 */
+			*loc = v;
+			break;
+
+#elif defined(__H8300H__) || defined(__H8300S__)
+
+		case R_H8_DIR24R8:
+			loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
+			*loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
+			break;
+		case R_H8_DIR24A8:
+			*loc += v;
+			break;
+		case R_H8_DIR32:
+		case R_H8_DIR32A16:
+			*loc += v;
+			break;
+		case R_H8_PCREL16:
+			v -= dot + 2;
+			if ((ElfW(Sword))v > 0x7fff ||
+			    (ElfW(Sword))v < -(ElfW(Sword))0x8000)
+				ret = obj_reloc_overflow;
+			else
+				*(unsigned short *)loc = v;
+			break;
+		case R_H8_PCREL8:
+			v -= dot + 1;
+			if ((ElfW(Sword))v > 0x7f ||
+			    (ElfW(Sword))v < -(ElfW(Sword))0x80)
+				ret = obj_reloc_overflow;
+			else
+				*(unsigned char *)loc = v;
+			break;
+
+#elif defined(__i386__)
+
+		case R_386_NONE:
+			break;
+
+		case R_386_32:
+			*loc += v;
+			break;
+
+		case R_386_PLT32:
+		case R_386_PC32:
+			*loc += v - dot;
+			break;
+
+		case R_386_GLOB_DAT:
+		case R_386_JMP_SLOT:
+			*loc = v;
+			break;
+
+		case R_386_RELATIVE:
+			*loc += f->baseaddr;
+			break;
+
+		case R_386_GOTPC:
+			assert(got != 0);
+			*loc += got - dot;
+			break;
+
+		case R_386_GOT32:
+			goto bb_use_got;
+
+		case R_386_GOTOFF:
+			assert(got != 0);
+			*loc += v - got;
+			break;
+
+#elif defined (__microblaze__)
+		case R_MICROBLAZE_NONE:
+		case R_MICROBLAZE_64_NONE:
+		case R_MICROBLAZE_32_SYM_OP_SYM:
+		case R_MICROBLAZE_32_PCREL:
+			break;
+
+		case R_MICROBLAZE_64_PCREL: {
+			/* dot is the address of the current instruction.
+			 * v is the target symbol address.
+			 * So we need to extract the offset in the code,
+			 * adding v, then subtrating the current address 
+			 * of this instruction.
+			 * Ex: "IMM 0xFFFE  bralid 0x0000" = "bralid 0xFFFE0000"
+			 */
+
+			/* Get split offset stored in code */
+			unsigned int temp = (loc[0] & 0xFFFF) << 16 |
+						(loc[1] & 0xFFFF);
+
+			/* Adjust relative offset. -4 adjustment required 
+			 * because dot points to the IMM insn, but branch
+			 * is computed relative to the branch instruction itself.
+			 */
+			temp += v - dot - 4;
+
+			/* Store back into code */
+			loc[0] = (loc[0] & 0xFFFF0000) | temp >> 16;
+			loc[1] = (loc[1] & 0xFFFF0000) | (temp & 0xFFFF);
+
+			break;
+		}
+
+		case R_MICROBLAZE_32:
+			*loc += v;
+			break;
+
+		case R_MICROBLAZE_64: {
+			/* Get split pointer stored in code */
+			unsigned int temp1 = (loc[0] & 0xFFFF) << 16 |
+						(loc[1] & 0xFFFF);
+
+			/* Add reloc offset */
+			temp1+=v;
+
+			/* Store back into code */
+			loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16;
+			loc[1] = (loc[1] & 0xFFFF0000) | (temp1 & 0xFFFF);
+
+			break;
+		}
+
+		case R_MICROBLAZE_32_PCREL_LO:
+		case R_MICROBLAZE_32_LO:
+		case R_MICROBLAZE_SRO32:
+		case R_MICROBLAZE_SRW32:
+			ret = obj_reloc_unhandled;
+			break;
+
+#elif defined(__mc68000__)
+
+		case R_68K_NONE:
+			break;
+
+		case R_68K_32:
+			*loc += v;
+			break;
+
+		case R_68K_8:
+			if (v > 0xff) {
+				ret = obj_reloc_overflow;
+			}
+			*(char *)loc = v;
+			break;
+
+		case R_68K_16:
+			if (v > 0xffff) {
+				ret = obj_reloc_overflow;
+			}
+			*(short *)loc = v;
+			break;
+
+		case R_68K_PC8:
+			v -= dot;
+			if ((ElfW(Sword))v > 0x7f ||
+					(ElfW(Sword))v < -(ElfW(Sword))0x80) {
+				ret = obj_reloc_overflow;
+			}
+			*(char *)loc = v;
+			break;
+
+		case R_68K_PC16:
+			v -= dot;
+			if ((ElfW(Sword))v > 0x7fff ||
+					(ElfW(Sword))v < -(ElfW(Sword))0x8000) {
+				ret = obj_reloc_overflow;
+			}
+			*(short *)loc = v;
+			break;
+
+		case R_68K_PC32:
+			*(int *)loc = v - dot;
+			break;
+
+		case R_68K_GLOB_DAT:
+		case R_68K_JMP_SLOT:
+			*loc = v;
+			break;
+
+		case R_68K_RELATIVE:
+			*(int *)loc += f->baseaddr;
+			break;
+
+		case R_68K_GOT32:
+			goto bb_use_got;
+
+# ifdef R_68K_GOTOFF
+		case R_68K_GOTOFF:
+			assert(got != 0);
+			*loc += v - got;
+			break;
+# endif
+
+#elif defined(__mips__)
+
+		case R_MIPS_NONE:
+			break;
+
+		case R_MIPS_32:
+			*loc += v;
+			break;
+
+		case R_MIPS_26:
+			if (v % 4)
+				ret = obj_reloc_dangerous;
+			if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
+				ret = obj_reloc_overflow;
+			*loc =
+				(*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
+										0x03ffffff);
+			break;
+
+		case R_MIPS_HI16:
+			{
+				struct mips_hi16 *n;
+
+				/* We cannot relocate this one now because we don't know the value
+				   of the carry we need to add.  Save the information, and let LO16
+				   do the actual relocation.  */
+				n = (struct mips_hi16 *) xmalloc(sizeof *n);
+				n->addr = loc;
+				n->value = v;
+				n->next = ifile->mips_hi16_list;
+				ifile->mips_hi16_list = n;
+				break;
+			}
+
+		case R_MIPS_LO16:
+			{
+				unsigned long insnlo = *loc;
+				ElfW(Addr) val, vallo;
+
+				/* Sign extend the addend we extract from the lo insn.  */
+				vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
+
+				if (ifile->mips_hi16_list != NULL) {
+					struct mips_hi16 *l;
+
+					l = ifile->mips_hi16_list;
+					while (l != NULL) {
+						struct mips_hi16 *next;
+						unsigned long insn;
+
+						/* The value for the HI16 had best be the same. */
+						assert(v == l->value);
+
+						/* Do the HI16 relocation.  Note that we actually don't
+						   need to know anything about the LO16 itself, except where
+						   to find the low 16 bits of the addend needed by the LO16.  */
+						insn = *l->addr;
+						val =
+							((insn & 0xffff) << 16) +
+							vallo;
+						val += v;
+
+						/* Account for the sign extension that will happen in the
+						   low bits.  */
+						val =
+							((val >> 16) +
+							 ((val & 0x8000) !=
+							  0)) & 0xffff;
+
+						insn = (insn & ~0xffff) | val;
+						*l->addr = insn;
+
+						next = l->next;
+						free(l);
+						l = next;
+					}
+
+					ifile->mips_hi16_list = NULL;
+				}
+
+				/* Ok, we're done with the HI16 relocs.  Now deal with the LO16.  */
+				val = v + vallo;
+				insnlo = (insnlo & ~0xffff) | (val & 0xffff);
+				*loc = insnlo;
+				break;
+			}
+
+#elif defined(__nios2__)
+
+		case R_NIOS2_NONE:
+			break;
+
+		case R_NIOS2_BFD_RELOC_32:
+			*loc += v;
+			break;
+
+		case R_NIOS2_BFD_RELOC_16:
+			if (v > 0xffff) {
+				ret = obj_reloc_overflow;
+			}
+			*(short *)loc = v;
+			break;
+
+		case R_NIOS2_BFD_RELOC_8:
+			if (v > 0xff) {
+				ret = obj_reloc_overflow;
+			}
+			*(char *)loc = v;
+			break;
+
+		case R_NIOS2_S16:
+			{
+				Elf32_Addr word;
+
+				if ((Elf32_Sword)v > 0x7fff ||
+				    (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
+					ret = obj_reloc_overflow;
+				}
+
+				word = *loc;
+				*loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
+				       (word & 0x3f);
+			}
+			break;
+
+		case R_NIOS2_U16:
+			{
+				Elf32_Addr word;
+
+				if (v > 0xffff) {
+					ret = obj_reloc_overflow;
+				}
+
+				word = *loc;
+				*loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
+				       (word & 0x3f);
+			}
+			break;
+
+		case R_NIOS2_PCREL16:
+			{
+				Elf32_Addr word;
+
+				v -= dot + 4;
+				if ((Elf32_Sword)v > 0x7fff ||
+				    (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
+					ret = obj_reloc_overflow;
+				}
+
+				word = *loc;
+				*loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
+			}
+			break;
+
+		case R_NIOS2_GPREL:
+			{
+				Elf32_Addr word, gp;
+				/* get _gp */
+				gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
+				v-=gp;
+				if ((Elf32_Sword)v > 0x7fff ||
+						(Elf32_Sword)v < -(Elf32_Sword)0x8000) {
+					ret = obj_reloc_overflow;
+				}
+
+				word = *loc;
+				*loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
+			}
+			break;
+
+		case R_NIOS2_CALL26:
+			if (v & 3)
+				ret = obj_reloc_dangerous;
+			if ((v >> 28) != (dot >> 28))
+				ret = obj_reloc_overflow;
+			*loc = (*loc & 0x3f) | ((v >> 2) << 6);
+			break;
+
+		case R_NIOS2_IMM5:
+			{
+				Elf32_Addr word;
+
+				if (v > 0x1f) {
+					ret = obj_reloc_overflow;
+				}
+
+				word = *loc & ~0x7c0;
+				*loc = word | ((v & 0x1f) << 6);
+			}
+			break;
+
+		case R_NIOS2_IMM6:
+			{
+				Elf32_Addr word;
+
+				if (v > 0x3f) {
+					ret = obj_reloc_overflow;
+				}
+
+				word = *loc & ~0xfc0;
+				*loc = word | ((v & 0x3f) << 6);
+			}
+			break;
+
+		case R_NIOS2_IMM8:
+			{
+				Elf32_Addr word;
+
+				if (v > 0xff) {
+					ret = obj_reloc_overflow;
+				}
+
+				word = *loc & ~0x3fc0;
+				*loc = word | ((v & 0xff) << 6);
+			}
+			break;
+
+		case R_NIOS2_HI16:
+			{
+				Elf32_Addr word;
+
+				word = *loc;
+				*loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
+				       (word & 0x3f);
+			}
+			break;
+
+		case R_NIOS2_LO16:
+			{
+				Elf32_Addr word;
+
+				word = *loc;
+				*loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
+				       (word & 0x3f);
+			}
+			break;
+
+		case R_NIOS2_HIADJ16:
+			{
+				Elf32_Addr word1, word2;
+
+				word1 = *loc;
+				word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
+				*loc = ((((word1 >> 22) << 16) | word2) << 6) |
+				       (word1 & 0x3f);
+			}
+			break;
+
+#elif defined(__powerpc64__)
+		/* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
+
+#elif defined(__powerpc__)
+
+		case R_PPC_ADDR16_HA:
+			*(unsigned short *)loc = (v + 0x8000) >> 16;
+			break;
+
+		case R_PPC_ADDR16_HI:
+			*(unsigned short *)loc = v >> 16;
+			break;
+
+		case R_PPC_ADDR16_LO:
+			*(unsigned short *)loc = v;
+			break;
+
+		case R_PPC_REL24:
+			goto bb_use_plt;
+
+		case R_PPC_REL32:
+			*loc = v - dot;
+			break;
+
+		case R_PPC_ADDR32:
+			*loc = v;
+			break;
+
+#elif defined(__s390__)
+
+		case R_390_32:
+			*(unsigned int *) loc += v;
+			break;
+		case R_390_16:
+			*(unsigned short *) loc += v;
+			break;
+		case R_390_8:
+			*(unsigned char *) loc += v;
+			break;
+
+		case R_390_PC32:
+			*(unsigned int *) loc += v - dot;
+			break;
+		case R_390_PC16DBL:
+			*(unsigned short *) loc += (v - dot) >> 1;
+			break;
+		case R_390_PC16:
+			*(unsigned short *) loc += v - dot;
+			break;
+
+		case R_390_PLT32:
+		case R_390_PLT16DBL:
+			/* find the plt entry and initialize it.  */
+			assert(isym != NULL);
+			pe = (struct arch_single_entry *) &isym->pltent;
+			assert(pe->allocated);
+			if (pe->inited == 0) {
+				ip = (unsigned long *)(ifile->plt->contents + pe->offset);
+				ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
+				ip[1] = 0x100607f1;
+				if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
+					ip[2] = v - 2;
+				else
+					ip[2] = v;
+				pe->inited = 1;
+			}
+
+			/* Insert relative distance to target.  */
+			v = plt + pe->offset - dot;
+			if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
+				*(unsigned int *) loc = (unsigned int) v;
+			else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
+				*(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
+			break;
+
+		case R_390_GLOB_DAT:
+		case R_390_JMP_SLOT:
+			*loc = v;
+			break;
+
+		case R_390_RELATIVE:
+			*loc += f->baseaddr;
+			break;
+
+		case R_390_GOTPC:
+			assert(got != 0);
+			*(unsigned long *) loc += got - dot;
+			break;
+
+		case R_390_GOT12:
+		case R_390_GOT16:
+		case R_390_GOT32:
+			assert(isym != NULL);
+			assert(got != 0);
+			if (!isym->gotent.inited)
+			{
+				isym->gotent.inited = 1;
+				*(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
+			}
+			if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
+				*(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
+			else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
+				*(unsigned short *) loc += isym->gotent.offset;
+			else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
+				*(unsigned int *) loc += isym->gotent.offset;
+			break;
+
+# ifndef R_390_GOTOFF32
+#  define R_390_GOTOFF32 R_390_GOTOFF
+# endif
+		case R_390_GOTOFF32:
+			assert(got != 0);
+			*loc += v - got;
+			break;
+
+#elif defined(__sh__)
+
+		case R_SH_NONE:
+			break;
+
+		case R_SH_DIR32:
+			*loc += v;
+			break;
+
+		case R_SH_REL32:
+			*loc += v - dot;
+			break;
+
+		case R_SH_PLT32:
+			*loc = v - dot;
+			break;
+
+		case R_SH_GLOB_DAT:
+		case R_SH_JMP_SLOT:
+			*loc = v;
+			break;
+
+		case R_SH_RELATIVE:
+			*loc = f->baseaddr + rel->r_addend;
+			break;
+
+		case R_SH_GOTPC:
+			assert(got != 0);
+			*loc = got - dot + rel->r_addend;
+			break;
+
+		case R_SH_GOT32:
+			goto bb_use_got;
+
+		case R_SH_GOTOFF:
+			assert(got != 0);
+			*loc = v - got;
+			break;
+
+# if defined(__SH5__)
+		case R_SH_IMM_MEDLOW16:
+		case R_SH_IMM_LOW16:
+			{
+				ElfW(Addr) word;
+
+				if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
+					v >>= 16;
+
+				/*
+				 *  movi and shori have the format:
+				 *
+				 *  |  op  | imm  | reg | reserved |
+				 *   31..26 25..10 9.. 4 3   ..   0
+				 *
+				 * so we simply mask and or in imm.
+				 */
+				word = *loc & ~0x3fffc00;
+				word |= (v & 0xffff) << 10;
+
+				*loc = word;
+
+				break;
+			}
+
+		case R_SH_IMM_MEDLOW16_PCREL:
+		case R_SH_IMM_LOW16_PCREL:
+			{
+				ElfW(Addr) word;
+
+				word = *loc & ~0x3fffc00;
+
+				v -= dot;
+
+				if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
+					v >>= 16;
+
+				word |= (v & 0xffff) << 10;
+
+				*loc = word;
+
+				break;
+			}
+# endif /* __SH5__ */
+
+#elif defined (__v850e__)
+
+		case R_V850_NONE:
+			break;
+
+		case R_V850_32:
+			/* We write two shorts instead of a long because even
+			   32-bit insns only need half-word alignment, but
+			   32-bit data needs to be long-word aligned.  */
+			v += ((unsigned short *)loc)[0];
+			v += ((unsigned short *)loc)[1] << 16;
+			((unsigned short *)loc)[0] = v & 0xffff;
+			((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
+			break;
+
+		case R_V850_22_PCREL:
+			goto bb_use_plt;
+
+#elif defined(__x86_64__)
+
+		case R_X86_64_NONE:
+			break;
+
+		case R_X86_64_64:
+			*loc += v;
+			break;
+
+		case R_X86_64_32:
+			*(unsigned int *) loc += v;
+			if (v > 0xffffffff)
+			{
+				ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
+				/* error("Possibly is module compiled without -mcmodel=kernel!"); */
+			}
+			break;
+
+		case R_X86_64_32S:
+			*(signed int *) loc += v;
+			break;
+
+		case R_X86_64_16:
+			*(unsigned short *) loc += v;
+			break;
+
+		case R_X86_64_8:
+			*(unsigned char *) loc += v;
+			break;
+
+		case R_X86_64_PC32:
+			*(unsigned int *) loc += v - dot;
+			break;
+
+		case R_X86_64_PC16:
+			*(unsigned short *) loc += v - dot;
+			break;
+
+		case R_X86_64_PC8:
+			*(unsigned char *) loc += v - dot;
+			break;
+
+		case R_X86_64_GLOB_DAT:
+		case R_X86_64_JUMP_SLOT:
+			*loc = v;
+			break;
+
+		case R_X86_64_RELATIVE:
+			*loc += f->baseaddr;
+			break;
+
+		case R_X86_64_GOT32:
+		case R_X86_64_GOTPCREL:
+			goto bb_use_got;
+# if 0
+			assert(isym != NULL);
+			if (!isym->gotent.reloc_done)
+			{
+				isym->gotent.reloc_done = 1;
+				*(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
+			}
+			/* XXX are these really correct?  */
+			if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
+				*(unsigned int *) loc += v + isym->gotent.offset;
+			else
+				*loc += isym->gotent.offset;
+			break;
+# endif
+
+#else
+# warning "no idea how to handle relocations on your arch"
+#endif
+
+		default:
+			printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
+			ret = obj_reloc_unhandled;
+			break;
+
+#if defined(CONFIG_USE_PLT_ENTRIES)
+
+bb_use_plt:
+
+			/* find the plt entry and initialize it if necessary */
+			assert(isym != NULL);
+
+#if defined(CONFIG_USE_PLT_LIST)
+			for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
+				pe = pe->next;
+			assert(pe != NULL);
+#else
+			pe = &isym->pltent;
+#endif
+
+			if (! pe->inited) {
+				ip = (unsigned long *) (ifile->plt->contents + pe->offset);
+
+				/* generate some machine code */
+
+#if defined(__arm__)
+				ip[0] = 0xe51ff004;			/* ldr pc,[pc,#-4] */
+				ip[1] = v;				/* sym@ */
+#endif
+#if defined(__powerpc__)
+				ip[0] = 0x3d600000 + ((v + 0x8000) >> 16);  /* lis r11,sym at ha */
+				ip[1] = 0x396b0000 + (v & 0xffff);          /* addi r11,r11,sym at l */
+				ip[2] = 0x7d6903a6;			      /* mtctr r11 */
+				ip[3] = 0x4e800420;			      /* bctr */
+#endif
+#if defined (__v850e__)
+				/* We have to trash a register, so we assume that any control
+				   transfer more than 21-bits away must be a function call
+				   (so we can use a call-clobbered register).  */
+				ip[0] = 0x0621 + ((v & 0xffff) << 16);   /* mov sym, r1 ... */
+				ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
+#endif
+				pe->inited = 1;
+			}
+
+			/* relative distance to target */
+			v -= dot;
+			/* if the target is too far away.... */
+#if defined (__arm__) || defined (__powerpc__)
+			if ((int)v < -0x02000000 || (int)v >= 0x02000000)
+#elif defined (__v850e__)
+				if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
+#endif
+					/* go via the plt */
+					v = plt + pe->offset - dot;
+
+#if defined (__v850e__)
+			if (v & 1)
+#else
+				if (v & 3)
+#endif
+					ret = obj_reloc_dangerous;
+
+			/* merge the offset into the instruction. */
+#if defined(__arm__)
+			/* Convert to words. */
+			v >>= 2;
+
+			*loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
+#endif
+#if defined(__powerpc__)
+			*loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
+#endif
+#if defined (__v850e__)
+			/* We write two shorts instead of a long because even 32-bit insns
+			   only need half-word alignment, but the 32-bit data write needs
+			   to be long-word aligned.  */
+			((unsigned short *)loc)[0] =
+				(*(unsigned short *)loc & 0xffc0) /* opcode + reg */
+				| ((v >> 16) & 0x3f);             /* offs high part */
+			((unsigned short *)loc)[1] =
+				(v & 0xffff);                    /* offs low part */
+#endif
+			break;
+#endif /* CONFIG_USE_PLT_ENTRIES */
+
+#if defined(CONFIG_USE_GOT_ENTRIES)
+bb_use_got:
+
+			assert(isym != NULL);
+			/* needs an entry in the .got: set it, once */
+			if (!isym->gotent.inited) {
+				isym->gotent.inited = 1;
+				*(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
+			}
+			/* make the reloc with_respect_to_.got */
+#if defined(__sh__)
+			*loc += isym->gotent.offset + rel->r_addend;
+#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
+			*loc += isym->gotent.offset;
+#endif
+			break;
+
+#endif /* CONFIG_USE_GOT_ENTRIES */
+	}
+
+	return ret;
+}
+
+
+#if defined(CONFIG_USE_LIST)
+
+static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
+			  int offset, int size)
+{
+	struct arch_list_entry *pe;
+
+	for (pe = *list; pe != NULL; pe = pe->next) {
+		if (pe->addend == rel->r_addend) {
+			break;
+		}
+	}
+
+	if (pe == NULL) {
+		pe = xmalloc(sizeof(struct arch_list_entry));
+		pe->next = *list;
+		pe->addend = rel->r_addend;
+		pe->offset = offset;
+		pe->inited = 0;
+		*list = pe;
+		return size;
+	}
+	return 0;
+}
+
+#endif
+
+#if defined(CONFIG_USE_SINGLE)
+
+static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
+			     int offset, int size)
+{
+	if (single->allocated == 0) {
+		single->allocated = 1;
+		single->offset = offset;
+		single->inited = 0;
+		return size;
+	}
+	return 0;
+}
+
+#endif
+
+#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
+
+static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
+					   int offset, int size)
+{
+	struct obj_section *myrelsec = obj_find_section(f, name);
+
+	if (offset == 0) {
+		offset += size;
+	}
+
+	if (myrelsec) {
+		obj_extend_section(myrelsec, offset);
+	} else {
+		myrelsec = obj_create_alloced_section(f, name,
+				size, offset);
+		assert(myrelsec);
+	}
+
+	return myrelsec;
+}
+
+#endif
+
+static void arch_create_got(struct obj_file *f)
+{
+#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
+	struct arch_file *ifile = (struct arch_file *) f;
+	int i;
+#if defined(CONFIG_USE_GOT_ENTRIES)
+	int got_offset = 0, got_needed = 0, got_allocate;
+#endif
+#if defined(CONFIG_USE_PLT_ENTRIES)
+	int plt_offset = 0, plt_needed = 0, plt_allocate;
+#endif
+	struct obj_section *relsec, *symsec, *strsec;
+	ElfW(RelM) *rel, *relend;
+	ElfW(Sym) *symtab, *extsym;
+	const char *strtab, *name;
+	struct arch_symbol *intsym;
+
+	for (i = 0; i < f->header.e_shnum; ++i) {
+		relsec = f->sections[i];
+		if (relsec->header.sh_type != SHT_RELM)
+			continue;
+
+		symsec = f->sections[relsec->header.sh_link];
+		strsec = f->sections[symsec->header.sh_link];
+
+		rel = (ElfW(RelM) *) relsec->contents;
+		relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
+		symtab = (ElfW(Sym) *) symsec->contents;
+		strtab = (const char *) strsec->contents;
+
+		for (; rel < relend; ++rel) {
+			extsym = &symtab[ELF_R_SYM(rel->r_info)];
+
+#if defined(CONFIG_USE_GOT_ENTRIES)
+			got_allocate = 0;
+#endif
+#if defined(CONFIG_USE_PLT_ENTRIES)
+			plt_allocate = 0;
+#endif
+
+			switch (ELF_R_TYPE(rel->r_info)) {
+#if defined(__arm__)
+				case R_ARM_PC24:
+				case R_ARM_PLT32:
+					plt_allocate = 1;
+					break;
+
+				case R_ARM_GOTOFF:
+				case R_ARM_GOTPC:
+					got_needed = 1;
+					continue;
+
+				case R_ARM_GOT32:
+					got_allocate = 1;
+					break;
+
+#elif defined(__i386__)
+				case R_386_GOTPC:
+				case R_386_GOTOFF:
+					got_needed = 1;
+					continue;
+
+				case R_386_GOT32:
+					got_allocate = 1;
+					break;
+
+#elif defined(__powerpc__)
+				case R_PPC_REL24:
+					plt_allocate = 1;
+					break;
+
+#elif defined(__mc68000__)
+				case R_68K_GOT32:
+					got_allocate = 1;
+					break;
+
+#ifdef R_68K_GOTOFF
+				case R_68K_GOTOFF:
+					got_needed = 1;
+					continue;
+#endif
+
+#elif defined(__sh__)
+				case R_SH_GOT32:
+					got_allocate = 1;
+					break;
+
+				case R_SH_GOTPC:
+				case R_SH_GOTOFF:
+					got_needed = 1;
+					continue;
+
+#elif defined (__v850e__)
+				case R_V850_22_PCREL:
+					plt_needed = 1;
+					break;
+
+#endif
+				default:
+					continue;
+			}
+
+			if (extsym->st_name != 0) {
+				name = strtab + extsym->st_name;
+			} else {
+				name = f->sections[extsym->st_shndx]->name;
+			}
+			intsym = (struct arch_symbol *) obj_find_symbol(f, name);
+#if defined(CONFIG_USE_GOT_ENTRIES)
+			if (got_allocate) {
+				got_offset += arch_single_init(
+						rel, &intsym->gotent,
+						got_offset, CONFIG_GOT_ENTRY_SIZE);
+
+				got_needed = 1;
+			}
+#endif
+#if defined(CONFIG_USE_PLT_ENTRIES)
+			if (plt_allocate) {
+#if defined(CONFIG_USE_PLT_LIST)
+				plt_offset += arch_list_add(
+						rel, &intsym->pltent,
+						plt_offset, CONFIG_PLT_ENTRY_SIZE);
+#else
+				plt_offset += arch_single_init(
+						rel, &intsym->pltent,
+						plt_offset, CONFIG_PLT_ENTRY_SIZE);
+#endif
+				plt_needed = 1;
+			}
+#endif
+		}
+	}
+
+#if defined(CONFIG_USE_GOT_ENTRIES)
+	if (got_needed) {
+		ifile->got = arch_xsect_init(f, ".got", got_offset,
+				CONFIG_GOT_ENTRY_SIZE);
+	}
+#endif
+
+#if defined(CONFIG_USE_PLT_ENTRIES)
+	if (plt_needed) {
+		ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
+				CONFIG_PLT_ENTRY_SIZE);
+	}
+#endif
+
+#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
+}
+
+/*======================================================================*/
+
+/* Standard ELF hash function.  */
+static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
+{
+	unsigned long h = 0;
+	unsigned long g;
+	unsigned char ch;
+
+	while (n > 0) {
+		ch = *name++;
+		h = (h << 4) + ch;
+		if ((g = (h & 0xf0000000)) != 0) {
+			h ^= g >> 24;
+			h &= ~g;
+		}
+		n--;
+	}
+	return h;
+}
+
+static unsigned long obj_elf_hash(const char *name)
+{
+	return obj_elf_hash_n(name, strlen(name));
+}
+
+#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+/* String comparison for non-co-versioned kernel and module.  */
+
+static int ncv_strcmp(const char *a, const char *b)
+{
+	size_t alen = strlen(a), blen = strlen(b);
+
+	if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
+		return strncmp(a, b, alen);
+	else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
+		return strncmp(a, b, blen);
+	else
+		return strcmp(a, b);
+}
+
+/* String hashing for non-co-versioned kernel and module.  Here
+   we are simply forced to drop the crc from the hash.  */
+
+static unsigned long ncv_symbol_hash(const char *str)
+{
+	size_t len = strlen(str);
+	if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
+		len -= 10;
+	return obj_elf_hash_n(str, len);
+}
+
+static void
+obj_set_symbol_compare(struct obj_file *f,
+					   int (*cmp) (const char *, const char *),
+					   unsigned long (*hash) (const char *))
+{
+	if (cmp)
+		f->symbol_cmp = cmp;
+	if (hash) {
+		struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
+		int i;
+
+		f->symbol_hash = hash;
+
+		memcpy(tmptab, f->symtab, sizeof(tmptab));
+		memset(f->symtab, 0, sizeof(f->symtab));
+
+		for (i = 0; i < HASH_BUCKETS; ++i)
+			for (sym = tmptab[i]; sym; sym = next) {
+				unsigned long h = hash(sym->name) % HASH_BUCKETS;
+				next = sym->next;
+				sym->next = f->symtab[h];
+				f->symtab[h] = sym;
+			}
+	}
+}
+
+#endif							/* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+
+static struct obj_symbol *
+obj_add_symbol(struct obj_file *f, const char *name,
+								  unsigned long symidx, int info,
+								  int secidx, ElfW(Addr) value,
+								  unsigned long size)
+{
+	struct obj_symbol *sym;
+	unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
+	int n_type = ELF_ST_TYPE(info);
+	int n_binding = ELF_ST_BIND(info);
+
+	for (sym = f->symtab[hash]; sym; sym = sym->next)
+		if (f->symbol_cmp(sym->name, name) == 0) {
+			int o_secidx = sym->secidx;
+			int o_info = sym->info;
+			int o_type = ELF_ST_TYPE(o_info);
+			int o_binding = ELF_ST_BIND(o_info);
+
+			/* A redefinition!  Is it legal?  */
+
+			if (secidx == SHN_UNDEF)
+				return sym;
+			else if (o_secidx == SHN_UNDEF)
+				goto found;
+			else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
+				/* Cope with local and global symbols of the same name
+				   in the same object file, as might have been created
+				   by ld -r.  The only reason locals are now seen at this
+				   level at all is so that we can do semi-sensible things
+				   with parameters.  */
+
+				struct obj_symbol *nsym, **p;
+
+				nsym = arch_new_symbol();
+				nsym->next = sym->next;
+				nsym->ksymidx = -1;
+
+				/* Excise the old (local) symbol from the hash chain.  */
+				for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
+					continue;
+				*p = sym = nsym;
+				goto found;
+			} else if (n_binding == STB_LOCAL) {
+				/* Another symbol of the same name has already been defined.
+				   Just add this to the local table.  */
+				sym = arch_new_symbol();
+				sym->next = NULL;
+				sym->ksymidx = -1;
+				f->local_symtab[symidx] = sym;
+				goto found;
+			} else if (n_binding == STB_WEAK)
+				return sym;
+			else if (o_binding == STB_WEAK)
+				goto found;
+			/* Don't unify COMMON symbols with object types the programmer
+			   doesn't expect.  */
+			else if (secidx == SHN_COMMON
+					&& (o_type == STT_NOTYPE || o_type == STT_OBJECT))
+				return sym;
+			else if (o_secidx == SHN_COMMON
+					&& (n_type == STT_NOTYPE || n_type == STT_OBJECT))
+				goto found;
+			else {
+				/* Don't report an error if the symbol is coming from
+				   the kernel or some external module.  */
+				if (secidx <= SHN_HIRESERVE)
+					bb_error_msg("%s multiply defined", name);
+				return sym;
+			}
+		}
+
+	/* Completely new symbol.  */
+	sym = arch_new_symbol();
+	sym->next = f->symtab[hash];
+	f->symtab[hash] = sym;
+	sym->ksymidx = -1;
+
+	if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
+		if (symidx >= f->local_symtab_size)
+			bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
+					name, (long) symidx, (long) f->local_symtab_size);
+		else
+			f->local_symtab[symidx] = sym;
+	}
+
+found:
+	sym->name = name;
+	sym->value = value;
+	sym->size = size;
+	sym->secidx = secidx;
+	sym->info = info;
+
+	return sym;
+}
+
+static struct obj_symbol *
+obj_find_symbol(struct obj_file *f, const char *name)
+{
+	struct obj_symbol *sym;
+	unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
+
+	for (sym = f->symtab[hash]; sym; sym = sym->next)
+		if (f->symbol_cmp(sym->name, name) == 0)
+			return sym;
+
+	return NULL;
+}
+
+static ElfW(Addr)
+	obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
+{
+	if (sym) {
+		if (sym->secidx >= SHN_LORESERVE)
+			return sym->value;
+
+		return sym->value + f->sections[sym->secidx]->header.sh_addr;
+	} else {
+		/* As a special case, a NULL sym has value zero.  */
+		return 0;
+	}
+}
+
+static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
+{
+	int i, n = f->header.e_shnum;
+
+	for (i = 0; i < n; ++i)
+		if (strcmp(f->sections[i]->name, name) == 0)
+			return f->sections[i];
+
+	return NULL;
+}
+
+static int obj_load_order_prio(struct obj_section *a)
+{
+	unsigned long af, ac;
+
+	af = a->header.sh_flags;
+
+	ac = 0;
+	if (a->name[0] != '.' || strlen(a->name) != 10 ||
+			strcmp(a->name + 5, ".init"))
+		ac |= 32;
+	if (af & SHF_ALLOC)
+		ac |= 16;
+	if (!(af & SHF_WRITE))
+		ac |= 8;
+	if (af & SHF_EXECINSTR)
+		ac |= 4;
+	if (a->header.sh_type != SHT_NOBITS)
+		ac |= 2;
+
+	return ac;
+}
+
+static void
+obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
+{
+	struct obj_section **p;
+	int prio = obj_load_order_prio(sec);
+	for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
+		if (obj_load_order_prio(*p) < prio)
+			break;
+	sec->load_next = *p;
+	*p = sec;
+}
+
+static struct obj_section *obj_create_alloced_section(struct obj_file *f,
+											   const char *name,
+											   unsigned long align,
+											   unsigned long size)
+{
+	int newidx = f->header.e_shnum++;
+	struct obj_section *sec;
+
+	f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
+	f->sections[newidx] = sec = arch_new_section();
+
+	memset(sec, 0, sizeof(*sec));
+	sec->header.sh_type = SHT_PROGBITS;
+	sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
+	sec->header.sh_size = size;
+	sec->header.sh_addralign = align;
+	sec->name = name;
+	sec->idx = newidx;
+	if (size)
+		sec->contents = xmalloc(size);
+
+	obj_insert_section_load_order(f, sec);
+
+	return sec;
+}
+
+static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
+													 const char *name,
+													 unsigned long align,
+													 unsigned long size)
+{
+	int newidx = f->header.e_shnum++;
+	struct obj_section *sec;
+
+	f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
+	f->sections[newidx] = sec = arch_new_section();
+
+	memset(sec, 0, sizeof(*sec));
+	sec->header.sh_type = SHT_PROGBITS;
+	sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
+	sec->header.sh_size = size;
+	sec->header.sh_addralign = align;
+	sec->name = name;
+	sec->idx = newidx;
+	if (size)
+		sec->contents = xmalloc(size);
+
+	sec->load_next = f->load_order;
+	f->load_order = sec;
+	if (f->load_order_search_start == &f->load_order)
+		f->load_order_search_start = &sec->load_next;
+
+	return sec;
+}
+
+static void *obj_extend_section(struct obj_section *sec, unsigned long more)
+{
+	unsigned long oldsize = sec->header.sh_size;
+	if (more) {
+		sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
+	}
+	return sec->contents + oldsize;
+}
+
+
+/* Conditionally add the symbols from the given symbol set to the
+   new module.  */
+
+static int
+add_symbols_from( struct obj_file *f,
+				 int idx, struct new_module_symbol *syms, size_t nsyms)
+{
+	struct new_module_symbol *s;
+	size_t i;
+	int used = 0;
+#ifdef SYMBOL_PREFIX
+	char *name_buf = 0;
+	size_t name_alloced_size = 0;
+#endif
+#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
+	int gpl;
+
+	gpl = obj_gpl_license(f, NULL) == 0;
+#endif
+	for (i = 0, s = syms; i < nsyms; ++i, ++s) {
+		/* Only add symbols that are already marked external.
+		   If we override locals we may cause problems for
+		   argument initialization.  We will also create a false
+		   dependency on the module.  */
+		struct obj_symbol *sym;
+		char *name;
+
+		/* GPL licensed modules can use symbols exported with
+		 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
+		 * exported names.  Non-GPL modules never see any GPLONLY_
+		 * symbols so they cannot fudge it by adding the prefix on
+		 * their references.
+		 */
+		if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
+#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
+			if (gpl)
+				s->name += 8;
+			else
+#endif
+				continue;
+		}
+		name = (char *)s->name;
+
+#ifdef SYMBOL_PREFIX
+		/* Prepend SYMBOL_PREFIX to the symbol's name (the
+		   kernel exports `C names', but module object files
+		   reference `linker names').  */
+		size_t extra = sizeof SYMBOL_PREFIX;
+		size_t name_size = strlen (name) + extra;
+		if (name_size > name_alloced_size) {
+			name_alloced_size = name_size * 2;
+			name_buf = alloca (name_alloced_size);
+		}
+		strcpy (name_buf, SYMBOL_PREFIX);
+		strcpy (name_buf + extra - 1, name);
+		name = name_buf;
+#endif /* SYMBOL_PREFIX */
+
+		sym = obj_find_symbol(f, name);
+		if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
+#ifdef SYMBOL_PREFIX
+			/* Put NAME_BUF into more permanent storage.  */
+			name = xmalloc (name_size);
+			strcpy (name, name_buf);
+#endif
+			sym = obj_add_symbol(f, name, -1,
+					ELF_ST_INFO(STB_GLOBAL,
+						STT_NOTYPE),
+					idx, s->value, 0);
+			/* Did our symbol just get installed?  If so, mark the
+			   module as "used".  */
+			if (sym->secidx == idx)
+				used = 1;
+		}
+	}
+
+	return used;
+}
+
+static void add_kernel_symbols(struct obj_file *f)
+{
+	struct external_module *m;
+	int i, nused = 0;
+
+	/* Add module symbols first.  */
+
+	for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
+		if (m->nsyms
+				&& add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
+					m->nsyms)) m->used = 1, ++nused;
+
+	n_ext_modules_used = nused;
+
+	/* And finally the symbols from the kernel proper.  */
+
+	if (nksyms)
+		add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
+}
+
+static char *get_modinfo_value(struct obj_file *f, const char *key)
+{
+	struct obj_section *sec;
+	char *p, *v, *n, *ep;
+	size_t klen = strlen(key);
+
+	sec = obj_find_section(f, ".modinfo");
+	if (sec == NULL)
+		return NULL;
+	p = sec->contents;
+	ep = p + sec->header.sh_size;
+	while (p < ep) {
+		v = strchr(p, '=');
+		n = strchr(p, '\0');
+		if (v) {
+			if (p + klen == v && strncmp(p, key, klen) == 0)
+				return v + 1;
+		} else {
+			if (p + klen == n && strcmp(p, key) == 0)
+				return n;
+		}
+		p = n + 1;
+	}
+
+	return NULL;
+}
+
+
+/*======================================================================*/
+/* Functions relating to module loading after 2.1.18.  */
+
+static int
+new_process_module_arguments(struct obj_file *f, int argc, char **argv)
+{
+	while (argc > 0) {
+		char *p, *q, *key, *sym_name;
+		struct obj_symbol *sym;
+		char *contents, *loc;
+		int min, max, n;
+
+		p = *argv;
+		if ((q = strchr(p, '=')) == NULL) {
+			argc--;
+			continue;
+		}
+
+		key = alloca(q - p + 6);
+		memcpy(key, "parm_", 5);
+		memcpy(key + 5, p, q - p);
+		key[q - p + 5] = 0;
+
+		p = get_modinfo_value(f, key);
+		key += 5;
+		if (p == NULL) {
+			bb_error_msg("invalid parameter %s", key);
+			return 0;
+		}
+
+#ifdef SYMBOL_PREFIX
+		sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
+		strcpy (sym_name, SYMBOL_PREFIX);
+		strcat (sym_name, key);
+#else
+		sym_name = key;
+#endif
+		sym = obj_find_symbol(f, sym_name);
+
+		/* Also check that the parameter was not resolved from the kernel.  */
+		if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
+			bb_error_msg("symbol for parameter %s not found", key);
+			return 0;
+		}
+
+		if (isdigit(*p)) {
+			min = strtoul(p, &p, 10);
+			if (*p == '-')
+				max = strtoul(p + 1, &p, 10);
+			else
+				max = min;
+		} else
+			min = max = 1;
+
+		contents = f->sections[sym->secidx]->contents;
+		loc = contents + sym->value;
+		n = (*++q != '\0');
+
+		while (1) {
+			if ((*p == 's') || (*p == 'c')) {
+				char *str;
+
+				/* Do C quoting if we begin with a ", else slurp the lot.  */
+				if (*q == '"') {
+					char *r;
+
+					str = alloca(strlen(q));
+					for (r = str, q++; *q != '"'; ++q, ++r) {
+						if (*q == '\0') {
+							bb_error_msg("improperly terminated string argument for %s",
+									key);
+							return 0;
+						} else if (*q == '\\')
+							switch (*++q) {
+								case 'a':
+									*r = '\a';
+									break;
+								case 'b':
+									*r = '\b';
+									break;
+								case 'e':
+									*r = '\033';
+									break;
+								case 'f':
+									*r = '\f';
+									break;
+								case 'n':
+									*r = '\n';
+									break;
+								case 'r':
+									*r = '\r';
+									break;
+								case 't':
+									*r = '\t';
+									break;
+
+								case '0':
+								case '1':
+								case '2':
+								case '3':
+								case '4':
+								case '5':
+								case '6':
+								case '7':
+									{
+										int c = *q - '0';
+										if (q[1] >= '0' && q[1] <= '7') {
+											c = (c * 8) + *++q - '0';
+											if (q[1] >= '0' && q[1] <= '7')
+												c = (c * 8) + *++q - '0';
+										}
+										*r = c;
+									}
+									break;
+
+								default:
+									*r = *q;
+									break;
+							} else
+								*r = *q;
+					}
+					*r = '\0';
+					++q;
+				} else {
+					char *r;
+
+					/* In this case, the string is not quoted. We will break
+					   it using the coma (like for ints). If the user wants to
+					   include comas in a string, he just has to quote it */
+
+					/* Search the next coma */
+					r = strchr(q, ',');
+
+					/* Found ? */
+					if (r != (char *) NULL) {
+						/* Recopy the current field */
+						str = alloca(r - q + 1);
+						memcpy(str, q, r - q);
+
+						/* I don't know if it is useful, as the previous case
+						   doesn't nul terminate the string ??? */
+						str[r - q] = '\0';
+
+						/* Keep next fields */
+						q = r;
+					} else {
+						/* last string */
+						str = q;
+						q = "";
+					}
+				}
+
+				if (*p == 's') {
+					/* Normal string */
+					obj_string_patch(f, sym->secidx, loc - contents, str);
+					loc += tgt_sizeof_char_p;
+				} else {
+					/* Array of chars (in fact, matrix !) */
+					unsigned long charssize;	/* size of each member */
+
+					/* Get the size of each member */
+					/* Probably we should do that outside the loop ? */
+					if (!isdigit(*(p + 1))) {
+						bb_error_msg("parameter type 'c' for %s must be followed by"
+								" the maximum size", key);
+						return 0;
+					}
+					charssize = strtoul(p + 1, (char **) NULL, 10);
+
+					/* Check length */
+					if (strlen(str) >= charssize) {
+						bb_error_msg("string too long for %s (max %ld)", key,
+								charssize - 1);
+						return 0;
+					}
+
+					/* Copy to location */
+					strcpy((char *) loc, str);
+					loc += charssize;
+				}
+			} else {
+				long v = strtoul(q, &q, 0);
+				switch (*p) {
+					case 'b':
+						*loc++ = v;
+						break;
+					case 'h':
+						*(short *) loc = v;
+						loc += tgt_sizeof_short;
+						break;
+					case 'i':
+						*(int *) loc = v;
+						loc += tgt_sizeof_int;
+						break;
+					case 'l':
+						*(long *) loc = v;
+						loc += tgt_sizeof_long;
+						break;
+
+					default:
+						bb_error_msg("unknown parameter type '%c' for %s", *p, key);
+						return 0;
+				}
+			}
+
+retry_end_of_value:
+			switch (*q) {
+				case '\0':
+					goto end_of_arg;
+
+				case ' ':
+				case '\t':
+				case '\n':
+				case '\r':
+					++q;
+					goto retry_end_of_value;
+
+				case ',':
+					if (++n > max) {
+						bb_error_msg("too many values for %s (max %d)", key, max);
+						return 0;
+					}
+					++q;
+					break;
+
+				default:
+					bb_error_msg("invalid argument syntax for %s", key);
+					return 0;
+			}
+		}
+
+end_of_arg:
+		if (n < min) {
+			bb_error_msg("too few values for %s (min %d)", key, min);
+			return 0;
+		}
+
+		argc--, argv++;
+	}
+
+	return 1;
+}
+
+#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+static int new_is_module_checksummed(struct obj_file *f)
+{
+	const char *p = get_modinfo_value(f, "using_checksums");
+	if (p)
+		return atoi(p);
+	else
+		return 0;
+}
+
+/* Get the module's kernel version in the canonical integer form.  */
+
+static int
+new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
+{
+	char *p, *q;
+	int a, b, c;
+
+	p = get_modinfo_value(f, "kernel_version");
+	if (p == NULL)
+		return -1;
+	safe_strncpy(str, p, STRVERSIONLEN);
+
+	a = strtoul(p, &p, 10);
+	if (*p != '.')
+		return -1;
+	b = strtoul(p + 1, &p, 10);
+	if (*p != '.')
+		return -1;
+	c = strtoul(p + 1, &q, 10);
+	if (p + 1 == q)
+		return -1;
+
+	return a << 16 | b << 8 | c;
+}
+
+#endif   /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+
+
+/* Fetch the loaded modules, and all currently exported symbols.  */
+
+static int new_get_kernel_symbols(void)
+{
+	char *module_names, *mn;
+	struct external_module *modules, *m;
+	struct new_module_symbol *syms, *s;
+	size_t ret, bufsize, nmod, nsyms, i, j;
+
+	/* Collect the loaded modules.  */
+
+	module_names = xmalloc(bufsize = 256);
+retry_modules_load:
+	if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
+		if (errno == ENOSPC && bufsize < ret) {
+			module_names = xrealloc(module_names, bufsize = ret);
+			goto retry_modules_load;
+		}
+		bb_perror_msg("QM_MODULES");
+		return 0;
+	}
+
+	n_ext_modules = nmod = ret;
+
+	/* Collect the modules' symbols.  */
+
+	if (nmod){
+		ext_modules = modules = xmalloc(nmod * sizeof(*modules));
+		memset(modules, 0, nmod * sizeof(*modules));
+		for (i = 0, mn = module_names, m = modules;
+				i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
+			struct new_module_info info;
+
+			if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
+				if (errno == ENOENT) {
+					/* The module was removed out from underneath us.  */
+					continue;
+				}
+				bb_perror_msg("query_module: QM_INFO: %s", mn);
+				return 0;
+			}
+
+			syms = xmalloc(bufsize = 1024);
+retry_mod_sym_load:
+			if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
+				switch (errno) {
+					case ENOSPC:
+						syms = xrealloc(syms, bufsize = ret);
+						goto retry_mod_sym_load;
+					case ENOENT:
+						/* The module was removed out from underneath us.  */
+						continue;
+					default:
+						bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
+						return 0;
+				}
+			}
+			nsyms = ret;
+
+			m->name = mn;
+			m->addr = info.addr;
+			m->nsyms = nsyms;
+			m->syms = syms;
+
+			for (j = 0, s = syms; j < nsyms; ++j, ++s) {
+				s->name += (unsigned long) syms;
+			}
+		}
+	}
+
+	/* Collect the kernel's symbols.  */
+
+	syms = xmalloc(bufsize = 16 * 1024);
+retry_kern_sym_load:
+	if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
+		if (errno == ENOSPC && bufsize < ret) {
+			syms = xrealloc(syms, bufsize = ret);
+			goto retry_kern_sym_load;
+		}
+		bb_perror_msg("kernel: QM_SYMBOLS");
+		return 0;
+	}
+	nksyms = nsyms = ret;
+	ksyms = syms;
+
+	for (j = 0, s = syms; j < nsyms; ++j, ++s) {
+		s->name += (unsigned long) syms;
+	}
+	return 1;
+}
+
+
+/* Return the kernel symbol checksum version, or zero if not used.  */
+
+static int new_is_kernel_checksummed(void)
+{
+	struct new_module_symbol *s;
+	size_t i;
+
+	/* Using_Versions is not the first symbol, but it should be in there.  */
+
+	for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
+		if (strcmp((char *) s->name, "Using_Versions") == 0)
+			return s->value;
+
+	return 0;
+}
+
+
+static int new_create_this_module(struct obj_file *f, const char *m_name)
+{
+	struct obj_section *sec;
+
+	sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
+			sizeof(struct new_module));
+	memset(sec->contents, 0, sizeof(struct new_module));
+
+	obj_add_symbol(f, SPFX "__this_module", -1,
+			ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
+			sizeof(struct new_module));
+
+	obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
+			m_name);
+
+	return 1;
+}
+
+#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
+/* add an entry to the __ksymtab section, creating it if necessary */
+static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
+{
+	struct obj_section *sec;
+	ElfW(Addr) ofs;
+
+	/* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
+	 * If __ksymtab is defined but not marked alloc, x out the first character
+	 * (no obj_delete routine) and create a new __ksymtab with the correct
+	 * characteristics.
+	 */
+	sec = obj_find_section(f, "__ksymtab");
+	if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
+		*((char *)(sec->name)) = 'x';	/* override const */
+		sec = NULL;
+	}
+	if (!sec)
+		sec = obj_create_alloced_section(f, "__ksymtab",
+				tgt_sizeof_void_p, 0);
+	if (!sec)
+		return;
+	sec->header.sh_flags |= SHF_ALLOC;
+	sec->header.sh_addralign = tgt_sizeof_void_p;	/* Empty section might
+													   be byte-aligned */
+	ofs = sec->header.sh_size;
+	obj_symbol_patch(f, sec->idx, ofs, sym);
+	obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
+	obj_extend_section(sec, 2 * tgt_sizeof_char_p);
+}
+#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
+
+static int new_create_module_ksymtab(struct obj_file *f)
+{
+	struct obj_section *sec;
+	int i;
+
+	/* We must always add the module references.  */
+
+	if (n_ext_modules_used) {
+		struct new_module_ref *dep;
+		struct obj_symbol *tm;
+
+		sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
+				(sizeof(struct new_module_ref)
+				 * n_ext_modules_used));
+		if (!sec)
+			return 0;
+
+		tm = obj_find_symbol(f, SPFX "__this_module");
+		dep = (struct new_module_ref *) sec->contents;
+		for (i = 0; i < n_ext_modules; ++i)
+			if (ext_modules[i].used) {
+				dep->dep = ext_modules[i].addr;
+				obj_symbol_patch(f, sec->idx,
+						(char *) &dep->ref - sec->contents, tm);
+				dep->next_ref = 0;
+				++dep;
+			}
+	}
+
+	if (flag_export && !obj_find_section(f, "__ksymtab")) {
+		size_t nsyms;
+		int *loaded;
+
+		sec =
+			obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
+					0);
+
+		/* We don't want to export symbols residing in sections that
+		   aren't loaded.  There are a number of these created so that
+		   we make sure certain module options don't appear twice.  */
+
+		loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
+		while (--i >= 0)
+			loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
+
+		for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
+			struct obj_symbol *sym;
+			for (sym = f->symtab[i]; sym; sym = sym->next)
+				if (ELF_ST_BIND(sym->info) != STB_LOCAL
+						&& sym->secidx <= SHN_HIRESERVE
+						&& (sym->secidx >= SHN_LORESERVE
+							|| loaded[sym->secidx])) {
+					ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
+
+					obj_symbol_patch(f, sec->idx, ofs, sym);
+					obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
+							sym->name);
+
+					nsyms++;
+				}
+		}
+
+		obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
+	}
+
+	return 1;
+}
+
+
+static int
+new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
+{
+	struct new_module *module;
+	struct obj_section *sec;
+	void *image;
+	int ret;
+	tgt_long m_addr;
+
+	sec = obj_find_section(f, ".this");
+	if (!sec || !sec->contents) {
+		bb_perror_msg_and_die("corrupt module %s?",m_name);
+	}
+	module = (struct new_module *) sec->contents;
+	m_addr = sec->header.sh_addr;
+
+	module->size_of_struct = sizeof(*module);
+	module->size = m_size;
+	module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
+
+	sec = obj_find_section(f, "__ksymtab");
+	if (sec && sec->header.sh_size) {
+		module->syms = sec->header.sh_addr;
+		module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
+	}
+
+	if (n_ext_modules_used) {
+		sec = obj_find_section(f, ".kmodtab");
+		module->deps = sec->header.sh_addr;
+		module->ndeps = n_ext_modules_used;
+	}
+
+	module->init =
+		obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
+	module->cleanup =
+		obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
+
+	sec = obj_find_section(f, "__ex_table");
+	if (sec) {
+		module->ex_table_start = sec->header.sh_addr;
+		module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
+	}
+
+	sec = obj_find_section(f, ".text.init");
+	if (sec) {
+		module->runsize = sec->header.sh_addr - m_addr;
+	}
+	sec = obj_find_section(f, ".data.init");
+	if (sec) {
+		if (!module->runsize ||
+				module->runsize > sec->header.sh_addr - m_addr)
+			module->runsize = sec->header.sh_addr - m_addr;
+	}
+	sec = obj_find_section(f, ARCHDATA_SEC_NAME);
+	if (sec && sec->header.sh_size) {
+		module->archdata_start = (void*)sec->header.sh_addr;
+		module->archdata_end = module->archdata_start + sec->header.sh_size;
+	}
+	sec = obj_find_section(f, KALLSYMS_SEC_NAME);
+	if (sec && sec->header.sh_size) {
+		module->kallsyms_start = (void*)sec->header.sh_addr;
+		module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
+	}
+
+	/* Whew!  All of the initialization is complete.  Collect the final
+	   module image and give it to the kernel.  */
+
+	image = xmalloc(m_size);
+	obj_create_image(f, image);
+
+	ret = init_module(m_name, (struct new_module *) image);
+	if (ret)
+		bb_perror_msg("init_module: %s", m_name);
+
+	free(image);
+
+	return ret == 0;
+}
+
+
+/*======================================================================*/
+
+static int
+obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
+				 const char *string)
+{
+	struct obj_string_patch *p;
+	struct obj_section *strsec;
+	size_t len = strlen(string) + 1;
+	char *loc;
+
+	p = xmalloc(sizeof(*p));
+	p->next = f->string_patches;
+	p->reloc_secidx = secidx;
+	p->reloc_offset = offset;
+	f->string_patches = p;
+
+	strsec = obj_find_section(f, ".kstrtab");
+	if (strsec == NULL) {
+		strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
+		p->string_offset = 0;
+		loc = strsec->contents;
+	} else {
+		p->string_offset = strsec->header.sh_size;
+		loc = obj_extend_section(strsec, len);
+	}
+	memcpy(loc, string, len);
+
+	return 1;
+}
+
+static int
+obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
+				 struct obj_symbol *sym)
+{
+	struct obj_symbol_patch *p;
+
+	p = xmalloc(sizeof(*p));
+	p->next = f->symbol_patches;
+	p->reloc_secidx = secidx;
+	p->reloc_offset = offset;
+	p->sym = sym;
+	f->symbol_patches = p;
+
+	return 1;
+}
+
+static int obj_check_undefineds(struct obj_file *f)
+{
+	unsigned long i;
+	int ret = 1;
+
+	for (i = 0; i < HASH_BUCKETS; ++i) {
+		struct obj_symbol *sym;
+		for (sym = f->symtab[i]; sym; sym = sym->next)
+			if (sym->secidx == SHN_UNDEF) {
+				if (ELF_ST_BIND(sym->info) == STB_WEAK) {
+					sym->secidx = SHN_ABS;
+					sym->value = 0;
+				} else {
+					if (!flag_quiet) {
+						bb_error_msg("unresolved symbol %s", sym->name);
+					}
+					ret = 0;
+				}
+			}
+	}
+
+	return ret;
+}
+
+static void obj_allocate_commons(struct obj_file *f)
+{
+	struct common_entry {
+		struct common_entry *next;
+		struct obj_symbol *sym;
+	} *common_head = NULL;
+
+	unsigned long i;
+
+	for (i = 0; i < HASH_BUCKETS; ++i) {
+		struct obj_symbol *sym;
+		for (sym = f->symtab[i]; sym; sym = sym->next)
+			if (sym->secidx == SHN_COMMON) {
+				/* Collect all COMMON symbols and sort them by size so as to
+				   minimize space wasted by alignment requirements.  */
+				{
+					struct common_entry **p, *n;
+					for (p = &common_head; *p; p = &(*p)->next)
+						if (sym->size <= (*p)->sym->size)
+							break;
+
+					n = alloca(sizeof(*n));
+					n->next = *p;
+					n->sym = sym;
+					*p = n;
+				}
+			}
+	}
+
+	for (i = 1; i < f->local_symtab_size; ++i) {
+		struct obj_symbol *sym = f->local_symtab[i];
+		if (sym && sym->secidx == SHN_COMMON) {
+			struct common_entry **p, *n;
+			for (p = &common_head; *p; p = &(*p)->next)
+				if (sym == (*p)->sym)
+					break;
+				else if (sym->size < (*p)->sym->size) {
+					n = alloca(sizeof(*n));
+					n->next = *p;
+					n->sym = sym;
+					*p = n;
+					break;
+				}
+		}
+	}
+
+	if (common_head) {
+		/* Find the bss section.  */
+		for (i = 0; i < f->header.e_shnum; ++i)
+			if (f->sections[i]->header.sh_type == SHT_NOBITS)
+				break;
+
+		/* If for some reason there hadn't been one, create one.  */
+		if (i == f->header.e_shnum) {
+			struct obj_section *sec;
+
+			f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
+			f->sections[i] = sec = arch_new_section();
+			f->header.e_shnum = i + 1;
+
+			memset(sec, 0, sizeof(*sec));
+			sec->header.sh_type = SHT_PROGBITS;
+			sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
+			sec->name = ".bss";
+			sec->idx = i;
+		}
+
+		/* Allocate the COMMONS.  */
+		{
+			ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
+			ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
+			struct common_entry *c;
+
+			for (c = common_head; c; c = c->next) {
+				ElfW(Addr) align = c->sym->value;
+
+				if (align > max_align)
+					max_align = align;
+				if (bss_size & (align - 1))
+					bss_size = (bss_size | (align - 1)) + 1;
+
+				c->sym->secidx = i;
+				c->sym->value = bss_size;
+
+				bss_size += c->sym->size;
+			}
+
+			f->sections[i]->header.sh_size = bss_size;
+			f->sections[i]->header.sh_addralign = max_align;
+		}
+	}
+
+	/* For the sake of patch relocation and parameter initialization,
+	   allocate zeroed data for NOBITS sections now.  Note that after
+	   this we cannot assume NOBITS are really empty.  */
+	for (i = 0; i < f->header.e_shnum; ++i) {
+		struct obj_section *s = f->sections[i];
+		if (s->header.sh_type == SHT_NOBITS) {
+			if (s->header.sh_size != 0)
+				s->contents = memset(xmalloc(s->header.sh_size),
+						0, s->header.sh_size);
+			else
+				s->contents = NULL;
+
+			s->header.sh_type = SHT_PROGBITS;
+		}
+	}
+}
+
+static unsigned long obj_load_size(struct obj_file *f)
+{
+	unsigned long dot = 0;
+	struct obj_section *sec;
+
+	/* Finalize the positions of the sections relative to one another.  */
+
+	for (sec = f->load_order; sec; sec = sec->load_next) {
+		ElfW(Addr) align;
+
+		align = sec->header.sh_addralign;
+		if (align && (dot & (align - 1)))
+			dot = (dot | (align - 1)) + 1;
+
+		sec->header.sh_addr = dot;
+		dot += sec->header.sh_size;
+	}
+
+	return dot;
+}
+
+static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
+{
+	int i, n = f->header.e_shnum;
+	int ret = 1;
+
+	/* Finalize the addresses of the sections.  */
+
+	f->baseaddr = base;
+	for (i = 0; i < n; ++i)
+		f->sections[i]->header.sh_addr += base;
+
+	/* And iterate over all of the relocations.  */
+
+	for (i = 0; i < n; ++i) {
+		struct obj_section *relsec, *symsec, *targsec, *strsec;
+		ElfW(RelM) * rel, *relend;
+		ElfW(Sym) * symtab;
+		const char *strtab;
+
+		relsec = f->sections[i];
+		if (relsec->header.sh_type != SHT_RELM)
+			continue;
+
+		symsec = f->sections[relsec->header.sh_link];
+		targsec = f->sections[relsec->header.sh_info];
+		strsec = f->sections[symsec->header.sh_link];
+
+		rel = (ElfW(RelM) *) relsec->contents;
+		relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
+		symtab = (ElfW(Sym) *) symsec->contents;
+		strtab = (const char *) strsec->contents;
+
+		for (; rel < relend; ++rel) {
+			ElfW(Addr) value = 0;
+			struct obj_symbol *intsym = NULL;
+			unsigned long symndx;
+			ElfW(Sym) * extsym = 0;
+			const char *errmsg;
+
+			/* Attempt to find a value to use for this relocation.  */
+
+			symndx = ELF_R_SYM(rel->r_info);
+			if (symndx) {
+				/* Note we've already checked for undefined symbols.  */
+
+				extsym = &symtab[symndx];
+				if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
+					/* Local symbols we look up in the local table to be sure
+					   we get the one that is really intended.  */
+					intsym = f->local_symtab[symndx];
+				} else {
+					/* Others we look up in the hash table.  */
+					const char *name;
+					if (extsym->st_name)
+						name = strtab + extsym->st_name;
+					else
+						name = f->sections[extsym->st_shndx]->name;
+					intsym = obj_find_symbol(f, name);
+				}
+
+				value = obj_symbol_final_value(f, intsym);
+				intsym->referenced = 1;
+			}
+#if SHT_RELM == SHT_RELA
+#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
+			/* Work around a nasty GAS bug, that is fixed as of 2.7.0.9.  */
+			if (!extsym || !extsym->st_name ||
+					ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
+#endif
+				value += rel->r_addend;
+#endif
+
+			/* Do it! */
+			switch (arch_apply_relocation
+					(f, targsec, symsec, intsym, rel, value)) {
+				case obj_reloc_ok:
+					break;
+
+				case obj_reloc_overflow:
+					errmsg = "Relocation overflow";
+					goto bad_reloc;
+				case obj_reloc_dangerous:
+					errmsg = "Dangerous relocation";
+					goto bad_reloc;
+				case obj_reloc_unhandled:
+					errmsg = "Unhandled relocation";
+bad_reloc:
+					if (extsym) {
+						bb_error_msg("%s of type %ld for %s", errmsg,
+								(long) ELF_R_TYPE(rel->r_info),
+								strtab + extsym->st_name);
+					} else {
+						bb_error_msg("%s of type %ld", errmsg,
+								(long) ELF_R_TYPE(rel->r_info));
+					}
+					ret = 0;
+					break;
+			}
+		}
+	}
+
+	/* Finally, take care of the patches.  */
+
+	if (f->string_patches) {
+		struct obj_string_patch *p;
+		struct obj_section *strsec;
+		ElfW(Addr) strsec_base;
+		strsec = obj_find_section(f, ".kstrtab");
+		strsec_base = strsec->header.sh_addr;
+
+		for (p = f->string_patches; p; p = p->next) {
+			struct obj_section *targsec = f->sections[p->reloc_secidx];
+			*(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
+				= strsec_base + p->string_offset;
+		}
+	}
+
+	if (f->symbol_patches) {
+		struct obj_symbol_patch *p;
+
+		for (p = f->symbol_patches; p; p = p->next) {
+			struct obj_section *targsec = f->sections[p->reloc_secidx];
+			*(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
+				= obj_symbol_final_value(f, p->sym);
+		}
+	}
+
+	return ret;
+}
+
+static int obj_create_image(struct obj_file *f, char *image)
+{
+	struct obj_section *sec;
+	ElfW(Addr) base = f->baseaddr;
+
+	for (sec = f->load_order; sec; sec = sec->load_next) {
+		char *secimg;
+
+		if (sec->contents == 0 || sec->header.sh_size == 0)
+			continue;
+
+		secimg = image + (sec->header.sh_addr - base);
+
+		/* Note that we allocated data for NOBITS sections earlier.  */
+		memcpy(secimg, sec->contents, sec->header.sh_size);
+	}
+
+	return 1;
+}
+
+/*======================================================================*/
+
+static struct obj_file *obj_load(FILE * fp, int loadprogbits)
+{
+	struct obj_file *f;
+	ElfW(Shdr) * section_headers;
+	int shnum, i;
+	char *shstrtab;
+
+	/* Read the file header.  */
+
+	f = arch_new_file();
+	memset(f, 0, sizeof(*f));
+	f->symbol_cmp = strcmp;
+	f->symbol_hash = obj_elf_hash;
+	f->load_order_search_start = &f->load_order;
+
+	fseek(fp, 0, SEEK_SET);
+	if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
+		bb_perror_msg("error reading ELF header");
+		return NULL;
+	}
+
+	if (f->header.e_ident[EI_MAG0] != ELFMAG0
+			|| f->header.e_ident[EI_MAG1] != ELFMAG1
+			|| f->header.e_ident[EI_MAG2] != ELFMAG2
+			|| f->header.e_ident[EI_MAG3] != ELFMAG3) {
+		bb_error_msg("not an ELF file");
+		return NULL;
+	}
+	if (f->header.e_ident[EI_CLASS] != ELFCLASSM
+			|| f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
+				? ELFDATA2MSB : ELFDATA2LSB)
+			|| f->header.e_ident[EI_VERSION] != EV_CURRENT
+			|| !MATCH_MACHINE(f->header.e_machine)) {
+		bb_error_msg("ELF file not for this architecture");
+		return NULL;
+	}
+	if (f->header.e_type != ET_REL) {
+		bb_error_msg("ELF file not a relocatable object");
+		return NULL;
+	}
+
+	/* Read the section headers.  */
+
+	if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
+		bb_error_msg("section header size mismatch: %lu != %lu",
+				(unsigned long) f->header.e_shentsize,
+				(unsigned long) sizeof(ElfW(Shdr)));
+		return NULL;
+	}
+
+	shnum = f->header.e_shnum;
+	f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
+	memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
+
+	section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
+	fseek(fp, f->header.e_shoff, SEEK_SET);
+	if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
+		bb_perror_msg("error reading ELF section headers");
+		return NULL;
+	}
+
+	/* Read the section data.  */
+
+	for (i = 0; i < shnum; ++i) {
+		struct obj_section *sec;
+
+		f->sections[i] = sec = arch_new_section();
+		memset(sec, 0, sizeof(*sec));
+
+		sec->header = section_headers[i];
+		sec->idx = i;
+
+		if(sec->header.sh_size) switch (sec->header.sh_type) {
+			case SHT_NULL:
+			case SHT_NOTE:
+			case SHT_NOBITS:
+				/* ignore */
+				break;
+
+			case SHT_PROGBITS:
+#if LOADBITS
+				if (!loadprogbits) {
+					sec->contents = NULL;
+					break;
+				}
+#endif
+			case SHT_SYMTAB:
+			case SHT_STRTAB:
+			case SHT_RELM:
+				if (sec->header.sh_size > 0) {
+					sec->contents = xmalloc(sec->header.sh_size);
+					fseek(fp, sec->header.sh_offset, SEEK_SET);
+					if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
+						bb_perror_msg("error reading ELF section data");
+						return NULL;
+					}
+				} else {
+					sec->contents = NULL;
+				}
+				break;
+
+#if SHT_RELM == SHT_REL
+			case SHT_RELA:
+				bb_error_msg("RELA relocations not supported on this architecture");
+				return NULL;
+#else
+			case SHT_REL:
+				bb_error_msg("REL relocations not supported on this architecture");
+				return NULL;
+#endif
+
+			default:
+				if (sec->header.sh_type >= SHT_LOPROC) {
+					/* Assume processor specific section types are debug
+					   info and can safely be ignored.  If this is ever not
+					   the case (Hello MIPS?), don't put ifdefs here but
+					   create an arch_load_proc_section().  */
+					break;
+				}
+
+				bb_error_msg("can't handle sections of type %ld",
+						(long) sec->header.sh_type);
+				return NULL;
+		}
+	}
+
+	/* Do what sort of interpretation as needed by each section.  */
+
+	shstrtab = f->sections[f->header.e_shstrndx]->contents;
+
+	for (i = 0; i < shnum; ++i) {
+		struct obj_section *sec = f->sections[i];
+		sec->name = shstrtab + sec->header.sh_name;
+	}
+
+	for (i = 0; i < shnum; ++i) {
+		struct obj_section *sec = f->sections[i];
+
+		/* .modinfo should be contents only but gcc has no attribute for that.
+		 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
+		 */
+		if (strcmp(sec->name, ".modinfo") == 0)
+			sec->header.sh_flags &= ~SHF_ALLOC;
+
+		if (sec->header.sh_flags & SHF_ALLOC)
+			obj_insert_section_load_order(f, sec);
+
+		switch (sec->header.sh_type) {
+			case SHT_SYMTAB:
+				{
+					unsigned long nsym, j;
+					char *strtab;
+					ElfW(Sym) * sym;
+
+					if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
+						bb_error_msg("symbol size mismatch: %lu != %lu",
+								(unsigned long) sec->header.sh_entsize,
+								(unsigned long) sizeof(ElfW(Sym)));
+						return NULL;
+					}
+
+					nsym = sec->header.sh_size / sizeof(ElfW(Sym));
+					strtab = f->sections[sec->header.sh_link]->contents;
+					sym = (ElfW(Sym) *) sec->contents;
+
+					/* Allocate space for a table of local symbols.  */
+					j = f->local_symtab_size = sec->header.sh_info;
+					f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
+
+					/* Insert all symbols into the hash table.  */
+					for (j = 1, ++sym; j < nsym; ++j, ++sym) {
+						ElfW(Addr) val = sym->st_value;
+						const char *name;
+						if (sym->st_name)
+							name = strtab + sym->st_name;
+						else if (sym->st_shndx < shnum)
+							name = f->sections[sym->st_shndx]->name;
+						else
+							continue;
+
+#if defined(__SH5__)
+						/*
+						 * For sh64 it is possible that the target of a branch
+						 * requires a mode switch (32 to 16 and back again).
+						 *
+						 * This is implied by the lsb being set in the target
+						 * address for SHmedia mode and clear for SHcompact.
+						 */
+						val |= sym->st_other & 4;
+#endif
+
+						obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
+								val, sym->st_size);
+					}
+				}
+				break;
+
+			case SHT_RELM:
+				if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
+					bb_error_msg("relocation entry size mismatch: %lu != %lu",
+							(unsigned long) sec->header.sh_entsize,
+							(unsigned long) sizeof(ElfW(RelM)));
+					return NULL;
+				}
+				break;
+				/* XXX  Relocation code from modutils-2.3.19 is not here.
+				 * Why?  That's about 20 lines of code from obj/obj_load.c,
+				 * which gets done in a second pass through the sections.
+				 * This BusyBox insmod does similar work in obj_relocate(). */
+		}
+	}
+
+	return f;
+}
+
+#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
+/*
+ * load the unloaded sections directly into the memory allocated by
+ * kernel for the module
+ */
+
+static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
+{
+	ElfW(Addr) base = f->baseaddr;
+	struct obj_section* sec;
+
+	for (sec = f->load_order; sec; sec = sec->load_next) {
+
+		/* section already loaded? */
+		if (sec->contents != NULL)
+			continue;
+
+		if (sec->header.sh_size == 0)
+			continue;
+
+		sec->contents = imagebase + (sec->header.sh_addr - base);
+		fseek(fp, sec->header.sh_offset, SEEK_SET);
+		if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
+			bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
+			return 0;
+		}
+
+	}
+	return 1;
+}
+#endif
+
+static void hide_special_symbols(struct obj_file *f)
+{
+	static const char *const specials[] = {
+		SPFX "cleanup_module",
+		SPFX "init_module",
+		SPFX "kernel_version",
+		NULL
+	};
+
+	struct obj_symbol *sym;
+	const char *const *p;
+
+	for (p = specials; *p; ++p)
+		if ((sym = obj_find_symbol(f, *p)) != NULL)
+			sym->info =
+				ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
+}
+
+
+#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
+static int obj_gpl_license(struct obj_file *f, const char **license)
+{
+	struct obj_section *sec;
+	/* This list must match *exactly* the list of allowable licenses in
+	 * linux/include/linux/module.h.  Checking for leading "GPL" will not
+	 * work, somebody will use "GPL sucks, this is proprietary".
+	 */
+	static const char * const gpl_licenses[] = {
+		"GPL",
+		"GPL v2",
+		"GPL and additional rights",
+		"Dual BSD/GPL",
+		"Dual MPL/GPL",
+	};
+
+	if ((sec = obj_find_section(f, ".modinfo"))) {
+		const char *value, *ptr, *endptr;
+		ptr = sec->contents;
+		endptr = ptr + sec->header.sh_size;
+		while (ptr < endptr) {
+			if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
+				int i;
+				if (license)
+					*license = value+1;
+				for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
+					if (strcmp(value+1, gpl_licenses[i]) == 0)
+						return(0);
+				}
+				return(2);
+			}
+			if (strchr(ptr, '\0'))
+				ptr = strchr(ptr, '\0') + 1;
+			else
+				ptr = endptr;
+		}
+	}
+	return(1);
+}
+
+#define TAINT_FILENAME                  "/proc/sys/kernel/tainted"
+#define TAINT_PROPRIETORY_MODULE        (1<<0)
+#define TAINT_FORCED_MODULE             (1<<1)
+#define TAINT_UNSAFE_SMP                (1<<2)
+#define TAINT_URL                       "http://www.tux.org/lkml/#export-tainted"
+
+static void set_tainted(struct obj_file *f, int fd, char *m_name,
+		int kernel_has_tainted, int taint, const char *text1, const char *text2)
+{
+	char buf[80];
+	int oldval;
+	static int first = 1;
+	if (fd < 0 && !kernel_has_tainted)
+		return;		/* New modutils on old kernel */
+	printf("Warning: loading %s will taint the kernel: %s%s\n",
+			m_name, text1, text2);
+	if (first) {
+		printf("  See %s for information about tainted modules\n", TAINT_URL);
+		first = 0;
+	}
+	if (fd >= 0) {
+		read(fd, buf, sizeof(buf)-1);
+		buf[sizeof(buf)-1] = '\0';
+		oldval = strtoul(buf, NULL, 10);
+		sprintf(buf, "%d\n", oldval | taint);
+		write(fd, buf, strlen(buf));
+	}
+}
+
+/* Check if loading this module will taint the kernel. */
+static void check_tainted_module(struct obj_file *f, char *m_name)
+{
+	static const char tainted_file[] = TAINT_FILENAME;
+	int fd, kernel_has_tainted;
+	const char *ptr;
+
+	kernel_has_tainted = 1;
+	if ((fd = open(tainted_file, O_RDWR)) < 0) {
+		if (errno == ENOENT)
+			kernel_has_tainted = 0;
+		else if (errno == EACCES)
+			kernel_has_tainted = 1;
+		else {
+			perror(tainted_file);
+			kernel_has_tainted = 0;
+		}
+	}
+
+	switch (obj_gpl_license(f, &ptr)) {
+		case 0:
+			break;
+		case 1:
+			set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
+			break;
+		case 2:
+			/* The module has a non-GPL license so we pretend that the
+			 * kernel always has a taint flag to get a warning even on
+			 * kernels without the proc flag.
+			 */
+			set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
+			break;
+		default:
+			set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
+			break;
+	}
+
+	if (flag_force_load)
+		set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
+
+	if (fd >= 0)
+		close(fd);
+}
+#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
+#define check_tainted_module(x, y) do { } while(0);
+#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
+
+#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
+/* add module source, timestamp, kernel version and a symbol for the
+ * start of some sections.  this info is used by ksymoops to do better
+ * debugging.
+ */
+static int
+get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
+{
+#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+	return new_get_module_version(f, str);
+#else  /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+	strncpy(str, "???", sizeof(str));
+	return -1;
+#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+}
+
+/* add module source, timestamp, kernel version and a symbol for the
+ * start of some sections.  this info is used by ksymoops to do better
+ * debugging.
+ */
+static void
+add_ksymoops_symbols(struct obj_file *f, const char *filename,
+				 const char *m_name)
+{
+	static const char symprefix[] = "__insmod_";
+	struct obj_section *sec;
+	struct obj_symbol *sym;
+	char *name, *absolute_filename;
+	char str[STRVERSIONLEN], real[PATH_MAX];
+	int i, l, lm_name, lfilename, use_ksymtab, version;
+	struct stat statbuf;
+
+	static const char *section_names[] = {
+		".text",
+		".rodata",
+		".data",
+		".bss",
+		".sbss"
+	};
+
+	if (realpath(filename, real)) {
+		absolute_filename = bb_xstrdup(real);
+	}
+	else {
+		int save_errno = errno;
+		bb_error_msg("cannot get realpath for %s", filename);
+		errno = save_errno;
+		perror("");
+		absolute_filename = bb_xstrdup(filename);
+	}
+
+	lm_name = strlen(m_name);
+	lfilename = strlen(absolute_filename);
+
+	/* add to ksymtab if it already exists or there is no ksymtab and other symbols
+	 * are not to be exported.  otherwise leave ksymtab alone for now, the
+	 * "export all symbols" compatibility code will export these symbols later.
+	 */
+	use_ksymtab =  obj_find_section(f, "__ksymtab") || !flag_export;
+
+	if ((sec = obj_find_section(f, ".this"))) {
+		/* tag the module header with the object name, last modified
+		 * timestamp and module version.  worst case for module version
+		 * is 0xffffff, decimal 16777215.  putting all three fields in
+		 * one symbol is less readable but saves kernel space.
+		 */
+		l = sizeof(symprefix)+			/* "__insmod_" */
+			lm_name+				/* module name */
+			2+					/* "_O" */
+			lfilename+				/* object filename */
+			2+					/* "_M" */
+			2*sizeof(statbuf.st_mtime)+		/* mtime in hex */
+			2+					/* "_V" */
+			8+					/* version in dec */
+			1;					/* nul */
+		name = xmalloc(l);
+		if (stat(absolute_filename, &statbuf) != 0)
+			statbuf.st_mtime = 0;
+		version = get_module_version(f, str);	/* -1 if not found */
+		snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
+				symprefix, m_name, absolute_filename,
+				(int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
+				version);
+		sym = obj_add_symbol(f, name, -1,
+				ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
+				sec->idx, sec->header.sh_addr, 0);
+		if (use_ksymtab)
+			new_add_ksymtab(f, sym);
+	}
+	free(absolute_filename);
+#ifdef _NOT_SUPPORTED_
+	/* record where the persistent data is going, same address as previous symbol */
+
+	if (f->persist) {
+		l = sizeof(symprefix)+		/* "__insmod_" */
+			lm_name+		/* module name */
+			2+			/* "_P" */
+			strlen(f->persist)+	/* data store */
+			1;			/* nul */
+		name = xmalloc(l);
+		snprintf(name, l, "%s%s_P%s",
+				symprefix, m_name, f->persist);
+		sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
+				sec->idx, sec->header.sh_addr, 0);
+		if (use_ksymtab)
+			new_add_ksymtab(f, sym);
+	}
+#endif /* _NOT_SUPPORTED_ */
+	/* tag the desired sections if size is non-zero */
+
+	for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
+		if ((sec = obj_find_section(f, section_names[i])) &&
+				sec->header.sh_size) {
+			l = sizeof(symprefix)+		/* "__insmod_" */
+				lm_name+		/* module name */
+				2+			/* "_S" */
+				strlen(sec->name)+	/* section name */
+				2+			/* "_L" */
+				8+			/* length in dec */
+				1;			/* nul */
+			name = xmalloc(l);
+			snprintf(name, l, "%s%s_S%s_L%ld",
+					symprefix, m_name, sec->name,
+					(long)sec->header.sh_size);
+			sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
+					sec->idx, sec->header.sh_addr, 0);
+			if (use_ksymtab)
+				new_add_ksymtab(f, sym);
+		}
+	}
+}
+#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
+
+#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
+static void print_load_map(struct obj_file *f)
+{
+	struct obj_symbol *sym;
+	struct obj_symbol **all, **p;
+	struct obj_section *sec;
+	int i, nsyms, *loaded;
+
+	/* Report on the section layout.  */
+
+	printf("Sections:       Size      %-*s  Align\n",
+			(int) (2 * sizeof(void *)), "Address");
+
+	for (sec = f->load_order; sec; sec = sec->load_next) {
+		int a;
+		unsigned long tmp;
+
+		for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
+			tmp >>= 1;
+		if (a == -1)
+			a = 0;
+
+		printf("%-15s %08lx  %0*lx  2**%d\n",
+				sec->name,
+				(long)sec->header.sh_size,
+				(int) (2 * sizeof(void *)),
+				(long)sec->header.sh_addr,
+				a);
+	}
+#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
+	/* Quick reference which section indicies are loaded.  */
+
+	loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
+	while (--i >= 0)
+		loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
+
+	/* Collect the symbols we'll be listing.  */
+
+	for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
+		for (sym = f->symtab[i]; sym; sym = sym->next)
+			if (sym->secidx <= SHN_HIRESERVE
+					&& (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
+				++nsyms;
+
+	all = alloca(nsyms * sizeof(struct obj_symbol *));
+
+	for (i = 0, p = all; i < HASH_BUCKETS; ++i)
+		for (sym = f->symtab[i]; sym; sym = sym->next)
+			if (sym->secidx <= SHN_HIRESERVE
+					&& (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
+				*p++ = sym;
+
+	/* And list them.  */
+	printf("\nSymbols:\n");
+	for (p = all; p < all + nsyms; ++p) {
+		char type = '?';
+		unsigned long value;
+
+		sym = *p;
+		if (sym->secidx == SHN_ABS) {
+			type = 'A';
+			value = sym->value;
+		} else if (sym->secidx == SHN_UNDEF) {
+			type = 'U';
+			value = 0;
+		} else {
+			sec = f->sections[sym->secidx];
+
+			if (sec->header.sh_type == SHT_NOBITS)
+				type = 'B';
+			else if (sec->header.sh_flags & SHF_ALLOC) {
+				if (sec->header.sh_flags & SHF_EXECINSTR)
+					type = 'T';
+				else if (sec->header.sh_flags & SHF_WRITE)
+					type = 'D';
+				else
+					type = 'R';
+			}
+			value = sym->value + sec->header.sh_addr;
+		}
+
+		if (ELF_ST_BIND(sym->info) == STB_LOCAL)
+			type = tolower(type);
+
+		printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
+				type, sym->name);
+	}
+#endif
+}
+
+#endif
+
+int insmod_main( int argc, char **argv)
+{
+	int opt;
+	int len;
+	int k_crcs;
+	char *tmp, *tmp1;
+	unsigned long m_size;
+	ElfW(Addr) m_addr;
+	struct obj_file *f;
+	struct stat st;
+	char *m_name = 0;
+	int exit_status = EXIT_FAILURE;
+	int m_has_modinfo;
+#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+	struct utsname uts_info;
+	char m_strversion[STRVERSIONLEN];
+	int m_version, m_crcs;
+#endif
+#ifdef CONFIG_FEATURE_CLEAN_UP
+	FILE *fp = 0;
+#else
+	FILE *fp;
+#endif
+#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
+	int flag_print_load_map = 0;
+#endif
+	int k_version = 0;
+	struct utsname myuname;
+
+	/* Parse any options */
+#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
+	while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
+#else
+	while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
+#endif
+		{
+			switch (opt) {
+				case 'f':			/* force loading */
+					flag_force_load = 1;
+					break;
+				case 'k':			/* module loaded by kerneld, auto-cleanable */
+					flag_autoclean = 1;
+					break;
+				case 's':			/* log to syslog */
+					/* log to syslog -- not supported              */
+					/* but kernel needs this for request_module(), */
+					/* as this calls: modprobe -k -s -- <module>   */
+					/* so silently ignore this flag                */
+					break;
+				case 'v':			/* verbose output */
+					flag_verbose = 1;
+					break;
+				case 'q':			/* silent */
+					flag_quiet = 1;
+					break;
+				case 'x':			/* do not export externs */
+					flag_export = 0;
+					break;
+				case 'o':			/* name the output module */
+					free(m_name);
+					m_name = bb_xstrdup(optarg);
+					break;
+				case 'L':			/* Stub warning */
+					/* This is needed for compatibility with modprobe.
+					 * In theory, this does locking, but we don't do
+					 * that.  So be careful and plan your life around not
+					 * loading the same module 50 times concurrently. */
+					break;
+#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
+				case 'm':			/* print module load map */
+					flag_print_load_map = 1;
+					break;
+#endif
+				default:
+					bb_show_usage();
+			}
+		}
+
+	if (argv[optind] == NULL) {
+		bb_show_usage();
+	}
+
+	/* Grab the module name */
+	tmp1 = bb_xstrdup(argv[optind]);
+	tmp = basename(tmp1);
+	len = strlen(tmp);
+
+	if (uname(&myuname) == 0) {
+		if (myuname.release[0] == '2') {
+			k_version = myuname.release[2] - '0';
+		}
+	}
+
+#if defined(CONFIG_FEATURE_2_6_MODULES)
+	if (k_version > 4 && len > 3 && tmp[len - 3] == '.' &&
+			tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
+		len-=3;
+		tmp[len] = '\0';
+	}
+	else
+#endif
+		if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
+			len-=2;
+			tmp[len] = '\0';
+		}
+
+
+#if defined(CONFIG_FEATURE_2_6_MODULES)
+	if (k_version > 4)
+		m_fullName = bb_xasprintf("%s.ko", tmp);
+	else
+#endif
+		m_fullName = bb_xasprintf("%s.o", tmp);
+
+	if (!m_name) {
+		m_name = tmp;
+	} else {
+		free(tmp1);
+		tmp1 = 0;       /* flag for free(m_name) before exit() */
+	}
+
+	/* Get a filedesc for the module.  Check we we have a complete path */
+	if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
+			(fp = fopen(argv[optind], "r")) == NULL) {
+		/* Hmm.  Could not open it.  First search under /lib/modules/`uname -r`,
+		 * but do not error out yet if we fail to find it... */
+		if (k_version) {	/* uname succeedd */
+			char *module_dir;
+			char *tmdn;
+			char real_module_dir[FILENAME_MAX];
+
+			tmdn = concat_path_file(_PATH_MODULES, myuname.release);
+			/* Jump through hoops in case /lib/modules/`uname -r`
+			 * is a symlink.  We do not want recursive_action to
+			 * follow symlinks, but we do want to follow the
+			 * /lib/modules/`uname -r` dir, So resolve it ourselves
+			 * if it is a link... */
+			if (realpath (tmdn, real_module_dir) == NULL)
+				module_dir = tmdn;
+			else
+				module_dir = real_module_dir;
+			recursive_action(module_dir, TRUE, FALSE, FALSE,
+					check_module_name_match, 0, m_fullName);
+			free(tmdn);
+		}
+
+		/* Check if we have found anything yet */
+		if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
+		{
+			char module_dir[FILENAME_MAX];
+
+			free(m_filename);
+			m_filename = 0;
+			if (realpath (_PATH_MODULES, module_dir) == NULL)
+				strcpy(module_dir, _PATH_MODULES);
+			/* No module found under /lib/modules/`uname -r`, this
+			 * time cast the net a bit wider.  Search /lib/modules/ */
+			if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
+						check_module_name_match, 0, m_fullName))
+			{
+				if (m_filename == 0
+						|| ((fp = fopen(m_filename, "r")) == NULL))
+				{
+					bb_error_msg("%s: no module by that name found", m_fullName);
+					goto out;
+				}
+			} else
+				bb_error_msg_and_die("%s: no module by that name found", m_fullName);
+		}
+	} else
+		m_filename = bb_xstrdup(argv[optind]);
+
+	if (flag_verbose)
+		printf("Using %s\n", m_filename);
+
+#ifdef CONFIG_FEATURE_2_6_MODULES
+	if (k_version > 4)
+	{
+		optind--;
+		argv[optind + 1] = m_filename;
+		return insmod_ng_main(argc - optind, argv + optind);
+	}
+#endif
+
+	if ((f = obj_load(fp, LOADBITS)) == NULL)
+		bb_perror_msg_and_die("Could not load the module");
+
+	if (get_modinfo_value(f, "kernel_version") == NULL)
+		m_has_modinfo = 0;
+	else
+		m_has_modinfo = 1;
+
+#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+	/* Version correspondence?  */
+	if (!flag_quiet) {
+		if (uname(&uts_info) < 0)
+			uts_info.release[0] = '\0';
+		if (m_has_modinfo) {
+			m_version = new_get_module_version(f, m_strversion);
+			if (m_version == -1) {
+				bb_error_msg("couldn't find the kernel version the module was "
+						"compiled for");
+				goto out;
+			}
+		}
+
+		if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
+			if (flag_force_load) {
+				bb_error_msg("Warning: kernel-module version mismatch\n"
+						"\t%s was compiled for kernel version %s\n"
+						"\twhile this kernel is version %s",
+						m_filename, m_strversion, uts_info.release);
+			} else {
+				bb_error_msg("kernel-module version mismatch\n"
+						"\t%s was compiled for kernel version %s\n"
+						"\twhile this kernel is version %s.",
+						m_filename, m_strversion, uts_info.release);
+				goto out;
+			}
+		}
+	}
+	k_crcs = 0;
+#endif							/* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+
+	if (!query_module(NULL, 0, NULL, 0, NULL)) {
+		if (!new_get_kernel_symbols())
+			goto out;
+		k_crcs = new_is_kernel_checksummed();
+	} else {
+		bb_error_msg("Not configured to support old kernels");
+		goto out;
+	}
+
+#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+	m_crcs = 0;
+	if (m_has_modinfo)
+		m_crcs = new_is_module_checksummed(f);
+
+	if (m_crcs != k_crcs)
+		obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
+#endif							/* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+
+	/* Let the module know about the kernel symbols.  */
+	add_kernel_symbols(f);
+
+	/* Allocate common symbols, symbol tables, and string tables.  */
+
+	if (!new_create_this_module(f, m_name))
+	{
+		goto out;
+	}
+
+	if (!obj_check_undefineds(f)) {
+		goto out;
+	}
+	obj_allocate_commons(f);
+	check_tainted_module(f, m_name);
+
+	/* done with the module name, on to the optional var=value arguments */
+	++optind;
+
+	if (optind < argc) {
+		if (!new_process_module_arguments(f, argc - optind, argv + optind))
+		{
+			goto out;
+		}
+	}
+
+	arch_create_got(f);
+	hide_special_symbols(f);
+
+#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
+	add_ksymoops_symbols(f, m_filename, m_name);
+#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
+
+	new_create_module_ksymtab(f);
+
+	/* Find current size of the module */
+	m_size = obj_load_size(f);
+
+
+	m_addr = create_module(m_name, m_size);
+	if (m_addr == -1) switch (errno) {
+		case EEXIST:
+			bb_error_msg("A module named %s already exists", m_name);
+			goto out;
+		case ENOMEM:
+			bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
+					m_size);
+			goto out;
+		default:
+			bb_perror_msg("create_module: %s", m_name);
+			goto out;
+	}
+
+#if  !LOADBITS
+	/*
+	 * the PROGBITS section was not loaded by the obj_load
+	 * now we can load them directly into the kernel memory
+	 */
+	if (!obj_load_progbits(fp, f, (char*)m_addr)) {
+		delete_module(m_name);
+		goto out;
+	}
+#endif
+
+	if (!obj_relocate(f, m_addr)) {
+		delete_module(m_name);
+		goto out;
+	}
+
+	if (!new_init_module(m_name, f, m_size))
+	{
+		delete_module(m_name);
+		goto out;
+	}
+
+#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
+	if(flag_print_load_map)
+		print_load_map(f);
+#endif
+
+	exit_status = EXIT_SUCCESS;
+
+out:
+#ifdef CONFIG_FEATURE_CLEAN_UP
+	if(fp)
+		fclose(fp);
+	free(tmp1);
+	if(!tmp1) {
+		free(m_name);
+	}
+	free(m_filename);
+#endif
+	return(exit_status);
+}
+
+
+#endif
+
+
+#ifdef CONFIG_FEATURE_2_6_MODULES
+
+#include <sys/mman.h>
+#include <asm/unistd.h>
+#include <sys/syscall.h>
+
+/* We use error numbers in a loose translation... */
+static const char *moderror(int err)
+{
+	switch (err) {
+		case ENOEXEC:
+			return "Invalid module format";
+		case ENOENT:
+			return "Unknown symbol in module";
+		case ESRCH:
+			return "Module has wrong symbol version";
+		case EINVAL:
+			return "Invalid parameters";
+		default:
+			return strerror(err);
+	}
+}
+
+int insmod_ng_main( int argc, char **argv)
+{
+	int i;
+	int fd;
+	long int ret;
+	struct stat st;
+	unsigned long len;
+	void *map;
+	char *filename, *options = bb_xstrdup("");
+
+	filename = argv[1];
+	if (!filename) {
+		bb_show_usage();
+		return -1;
+	}
+
+	/* Rest is options */
+	for (i = 2; i < argc; i++) {
+		options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
+		/* Spaces handled by "" pairs, but no way of escaping quotes */
+		if (strchr(argv[i], ' ')) {
+			strcat(options, "\"");
+			strcat(options, argv[i]);
+			strcat(options, "\"");
+		} else {
+			strcat(options, argv[i]);
+		}
+		strcat(options, " ");
+	}
+
+	fd = bb_xopen3(filename, O_RDONLY, 0);
+
+	fstat(fd, &st);
+	len = st.st_size;
+	map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
+	if (map == MAP_FAILED) {
+		bb_perror_msg_and_die("cannot mmap `%s'", filename);
+	}
+
+	ret = syscall(__NR_init_module, map, len, options);
+	if (ret != 0) {
+		bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
+				filename, moderror(errno), ret);
+	}
+
+	return 0;
+}
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/lsmod.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/lsmod.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/lsmod.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,202 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini lsmod implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Modified by Alcove, Julien Gaulmin <julien.gaulmin at alcove.fr> and
+ * Nicolas Ferre <nicolas.ferre at alcove.fr> to support pre 2.1 kernels
+ * (which lack the query_module() interface).
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <assert.h>
+#include <getopt.h>
+#include <sys/utsname.h>
+#include <sys/file.h>
+
+
+#ifndef CONFIG_FEATURE_CHECK_TAINTED_MODULE
+static inline void check_tainted(void) { printf("\n"); }
+#else
+#define TAINT_FILENAME                  "/proc/sys/kernel/tainted"
+#define TAINT_PROPRIETORY_MODULE        (1<<0)
+#define TAINT_FORCED_MODULE             (1<<1)
+#define TAINT_UNSAFE_SMP                (1<<2)
+
+static void check_tainted(void)
+{
+	int tainted;
+	FILE *f;
+
+	tainted = 0;
+	if ((f = fopen(TAINT_FILENAME, "r"))) {
+		fscanf(f, "%d", &tainted);
+		fclose(f);
+	}
+	if (f && tainted) {
+		printf("    Tainted: %c%c%c\n",
+				tainted & TAINT_PROPRIETORY_MODULE      ? 'P' : 'G',
+				tainted & TAINT_FORCED_MODULE           ? 'F' : ' ',
+				tainted & TAINT_UNSAFE_SMP              ? 'S' : ' ');
+	}
+	else {
+		printf("    Not tainted\n");
+	}
+}
+#endif
+
+#ifdef CONFIG_FEATURE_QUERY_MODULE_INTERFACE
+
+struct module_info
+{
+	unsigned long addr;
+	unsigned long size;
+	unsigned long flags;
+	long usecount;
+};
+
+
+int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret);
+
+enum {
+/* Values for query_module's which.  */
+	QM_MODULES = 1,
+	QM_DEPS = 2,
+	QM_REFS = 3,
+	QM_SYMBOLS = 4,
+	QM_INFO = 5,
+
+/* Bits of module.flags.  */
+	NEW_MOD_RUNNING = 1,
+	NEW_MOD_DELETED = 2,
+	NEW_MOD_AUTOCLEAN = 4,
+	NEW_MOD_VISITED = 8,
+	NEW_MOD_USED_ONCE = 16,
+	NEW_MOD_INITIALIZING = 64
+};
+
+int lsmod_main(int argc, char **argv)
+{
+	struct module_info info;
+	char *module_names, *mn, *deps, *dn;
+	size_t bufsize, depsize, nmod, count, i, j;
+
+	module_names = xmalloc(bufsize = 256);
+	if (my_query_module(NULL, QM_MODULES, (void **)&module_names, &bufsize,
+				&nmod)) {
+		bb_perror_msg_and_die("QM_MODULES");
+	}
+
+	deps = xmalloc(depsize = 256);
+	printf("Module                  Size  Used by");
+	check_tainted();
+
+	for (i = 0, mn = module_names; i < nmod; mn += strlen(mn) + 1, i++) {
+		if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) {
+			if (errno == ENOENT) {
+				/* The module was removed out from underneath us. */
+				continue;
+			}
+			/* else choke */
+			bb_perror_msg_and_die("module %s: QM_INFO", mn);
+		}
+		if (my_query_module(mn, QM_REFS, (void **)&deps, &depsize, &count)) {
+			if (errno == ENOENT) {
+				/* The module was removed out from underneath us. */
+				continue;
+			}
+			bb_perror_msg_and_die("module %s: QM_REFS", mn);
+		}
+		printf("%-20s%8lu%4ld", mn, info.size, info.usecount);
+		if (info.flags & NEW_MOD_DELETED)
+			printf(" (deleted)");
+		else if (info.flags & NEW_MOD_INITIALIZING)
+			printf(" (initializing)");
+		else if (!(info.flags & NEW_MOD_RUNNING))
+			printf(" (uninitialized)");
+		else {
+			if (info.flags & NEW_MOD_AUTOCLEAN)
+				printf(" (autoclean) ");
+			if (!(info.flags & NEW_MOD_USED_ONCE))
+				printf(" (unused)");
+		}
+		if (count) printf(" [");
+		for (j = 0, dn = deps; j < count; dn += strlen(dn) + 1, j++) {
+			printf("%s%s", dn, (j==count-1)? "":" ");
+		}
+		if (count) printf("]");
+
+		printf("\n");
+	}
+
+#ifdef CONFIG_FEATURE_CLEAN_UP
+	free(module_names);
+#endif
+
+	return( 0);
+}
+
+#else /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */
+
+int lsmod_main(int argc, char **argv)
+{
+	printf("Module                  Size  Used by");
+	check_tainted();
+#if defined(CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT)
+	{
+	  FILE *file;
+	  char line[4096];
+
+	  file = bb_xfopen("/proc/modules", "r");
+
+	  while (fgets(line, sizeof(line), file)) {
+	    char *tok;
+
+	    tok = strtok(line, " \t");
+	    printf("%-19s", tok);
+	    tok = strtok(NULL, " \t\n");
+	    printf(" %8s", tok);
+	    tok = strtok(NULL, " \t\n");
+	    /* Null if no module unloading support. */
+	    if (tok) {
+	      printf("  %s", tok);
+	      tok = strtok(NULL, "\n");
+	      if (!tok)
+		tok = "";
+	      /* New-style has commas, or -.  If so,
+		 truncate (other fields might follow). */
+	      else if (strchr(tok, ',')) {
+		tok = strtok(tok, "\t ");
+		/* Strip trailing comma. */
+		if (tok[strlen(tok)-1] == ',')
+		  tok[strlen(tok)-1] = '\0';
+	      } else if (tok[0] == '-'
+			 && (tok[1] == '\0' || isspace(tok[1])))
+		tok = "";
+	      printf(" %s", tok);
+	    }
+	    printf("\n");
+	  }
+	  fclose(file);
+	}
+	return EXIT_SUCCESS;
+#else
+	if (bb_xprint_file_by_name("/proc/modules") == 0)
+		return EXIT_SUCCESS;
+#endif  /*  CONFIG_FEATURE_2_6_MODULES  */
+
+	return EXIT_FAILURE;
+}
+
+#endif /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/modprobe.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/modprobe.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/modprobe.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,907 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Modprobe written from scratch for BusyBox
+ *
+ * Copyright (c) 2002 by Robert Griebl, griebl at gmx.de
+ * Copyright (c) 2003 by Andrew Dennison, andrew.dennison at motec.com.au
+ * Copyright (c) 2005 by Jim Bauer, jfbauer at nfr.com
+ *
+ * Portions Copyright (c) 2005 by Yann E. MORIN, yann.morin.1998 at anciens.enib.fr
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+*/
+
+#include "busybox.h"
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+
+struct mod_opt_t {	/* one-way list of options to pass to a module */
+	char *  m_opt_val;
+	struct mod_opt_t * m_next;
+};
+
+struct dep_t {	/* one-way list of dependency rules */
+	/* a dependency rule */
+	char *  m_name;				/* the module name*/
+	char *  m_path;				/* the module file path */
+	struct mod_opt_t *  m_options;	/* the module options */
+
+	int     m_isalias  : 1;			/* the module is an alias */
+	int     m_reserved : 15;		/* stuffin' */
+
+	int     m_depcnt   : 16;		/* the number of dependable module(s) */
+	char ** m_deparr;			/* the list of dependable module(s) */
+
+	struct dep_t * m_next;			/* the next dependency rule */
+};
+
+struct mod_list_t {	/* two-way list of modules to process */
+	/* a module description */
+	char *  m_name;
+	char *  m_path;
+	struct mod_opt_t *  m_options;
+
+	struct mod_list_t * m_prev;
+	struct mod_list_t * m_next;
+};
+
+
+static struct dep_t *depend;
+
+#define main_options "acdklnqrst:vVC:"
+#define INSERT_ALL     1        /* a */
+#define DUMP_CONF_EXIT 2        /* c */
+#define D_OPT_IGNORED  4        /* d */
+#define AUTOCLEAN_FLG  8        /* k */
+#define LIST_ALL       16       /* l */
+#define SHOW_ONLY      32       /* n */
+#define QUIET          64       /* q */
+#define REMOVE_OPT     128      /* r */
+#define DO_SYSLOG      256      /* s */
+#define RESTRICT_DIR   512      /* t */
+#define VERBOSE        1024     /* v */
+#define VERSION_ONLY   2048     /* V */
+#define CONFIG_FILE    4096     /* C */
+
+#define autoclean       (main_opts & AUTOCLEAN_FLG)
+#define show_only       (main_opts & SHOW_ONLY)
+#define quiet           (main_opts & QUIET)
+#define remove_opt      (main_opts & REMOVE_OPT)
+#define do_syslog       (main_opts & DO_SYSLOG)
+#define verbose         (main_opts & VERBOSE)
+
+static int main_opts;
+
+static int parse_tag_value ( char *buffer, char **ptag, char **pvalue )
+{
+	char *tag, *value;
+
+	while ( isspace ( *buffer ))
+		buffer++;
+	tag = value = buffer;
+	while ( !isspace ( *value ))
+		if (!*value) return 0;
+		else value++;
+	*value++ = 0;
+	while ( isspace ( *value ))
+		value++;
+	if (!*value) return 0;
+
+	*ptag = tag;
+	*pvalue = value;
+
+	return 1;
+}
+
+/* Jump through hoops to simulate how fgets() grabs just one line at a
+ * time... Don't use any stdio since modprobe gets called from a kernel
+ * thread and stdio junk can overflow the limited stack...
+ */
+static char *reads ( int fd, char *buffer, size_t len )
+{
+	int n = read ( fd, buffer, len );
+
+	if ( n > 0 ) {
+		char *p;
+
+		buffer [len-1] = 0;
+		p = strchr ( buffer, '\n' );
+
+		if ( p ) {
+			off_t offset;
+
+			offset = lseek ( fd, 0L, SEEK_CUR );               // Get the current file descriptor offset
+			lseek ( fd, offset-n + (p-buffer) + 1, SEEK_SET ); // Set the file descriptor offset to right after the \n
+
+			p[1] = 0;
+		}
+		return buffer;
+	}
+
+	else
+		return 0;
+}
+
+/*
+ * This function appends an option to a list
+ */
+static struct mod_opt_t *append_option( struct mod_opt_t *opt_list, char *opt )
+{
+	struct mod_opt_t *ol = opt_list;
+
+	if( ol ) {
+		while( ol-> m_next ) {
+			ol = ol-> m_next;
+		}
+		ol-> m_next = xmalloc( sizeof( struct mod_opt_t ) );
+		ol = ol-> m_next;
+	} else {
+		ol = opt_list = xmalloc( sizeof( struct mod_opt_t ) );
+	}
+
+	ol-> m_opt_val = bb_xstrdup( opt );
+	ol-> m_next = NULL;
+
+	return opt_list;
+}
+
+#if ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS
+/* static char* parse_command_string( char* src, char **dst );
+ *   src: pointer to string containing argument
+ *   dst: pointer to where to store the parsed argument
+ *   return value: the pointer to the first char after the parsed argument,
+ *                 NULL if there was no argument parsed (only trailing spaces).
+ *   Note that memory is allocated with bb_xstrdup when a new argument was
+ *   parsed. Don't forget to free it!
+ */
+#define ARG_EMPTY      0x00
+#define ARG_IN_DQUOTES 0x01
+#define ARG_IN_SQUOTES 0x02
+static char *parse_command_string( char *src, char **dst )
+{
+	int opt_status = ARG_EMPTY;
+	char* tmp_str;
+
+	/* Dumb you, I have nothing to do... */
+	if( src == NULL ) return src;
+
+	/* Skip leading spaces */
+	while( *src == ' ' ) {
+		src++;
+	}
+	/* Is the end of string reached? */
+	if( *src == '\0' ) {
+		return NULL;
+	}
+	/* Reached the start of an argument
+	 * By the way, we duplicate a little too much
+	 * here but what is too much is freed later. */
+	*dst = tmp_str = bb_xstrdup( src );
+	/* Get to the end of that argument */
+	while(    ( *tmp_str != '\0' )
+	       && (    ( *tmp_str != ' ' )
+		    || ( opt_status & ( ARG_IN_DQUOTES | ARG_IN_SQUOTES ) ) ) ) {
+		switch( *tmp_str ) {
+			case '\'':
+				if( opt_status & ARG_IN_DQUOTES ) {
+					/* Already in double quotes, keep current char as is */
+				} else {
+					/* shift left 1 char, until end of string: get rid of the opening/closing quotes */
+					memmove( tmp_str, tmp_str + 1, strlen( tmp_str ) );
+					/* mark me: we enter or leave single quotes */
+					opt_status ^= ARG_IN_SQUOTES;
+					/* Back one char, as we need to re-scan the new char there. */
+					tmp_str--;
+				}
+			break;
+			case '"':
+				if( opt_status & ARG_IN_SQUOTES ) {
+					/* Already in single quotes, keep current char as is */
+				} else {
+					/* shift left 1 char, until end of string: get rid of the opening/closing quotes */
+					memmove( tmp_str, tmp_str + 1, strlen( tmp_str ) );
+					/* mark me: we enter or leave double quotes */
+					opt_status ^= ARG_IN_DQUOTES;
+					/* Back one char, as we need to re-scan the new char there. */
+					tmp_str--;
+				}
+			break;
+			case '\\':
+				if( opt_status & ARG_IN_SQUOTES ) {
+					/* Between single quotes: keep as is. */
+				} else {
+					switch( *(tmp_str+1) ) {
+						case 'a':
+						case 'b':
+						case 't':
+						case 'n':
+						case 'v':
+						case 'f':
+						case 'r':
+						case '0':
+							/* We escaped a special character. For now, keep
+							 * both the back-slash and the following char. */
+							tmp_str++; src++;
+							break;
+						default:
+							/* We escaped a space or a single or double quote,
+							 * or a back-slash, or a non-escapable char. Remove
+							 * the '\' and keep the new current char as is. */
+							memmove( tmp_str, tmp_str + 1, strlen( tmp_str ) );
+							break;
+					}
+				}
+			break;
+			/* Any other char that is special shall appear here.
+			 * Example: $ starts a variable
+			case '$':
+				do_variable_expansion();
+				break;
+			 * */
+			default:
+				/* any other char is kept as is. */
+				break;
+		}
+		tmp_str++; /* Go to next char */
+		src++; /* Go to next char to find the end of the argument. */
+	}
+	/* End of string, but still no ending quote */
+	if( opt_status & ( ARG_IN_DQUOTES | ARG_IN_SQUOTES ) ) {
+		bb_error_msg_and_die( "unterminated (single or double) quote in options list: %s", src );
+	}
+	*tmp_str++ = '\0';
+	*dst = xrealloc( *dst, (tmp_str - *dst ) );
+	return src;
+}
+#else
+#define parse_command_string(src, dst)	(0)
+#endif /* ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS */
+
+/*
+ * This function reads aliases and default module options from a configuration file
+ * (/etc/modprobe.conf syntax). It supports includes (only files, no directories).
+ */
+static void include_conf ( struct dep_t **first, struct dep_t **current, char *buffer, int buflen, int fd )
+{
+	int continuation_line = 0;
+
+	// alias parsing is not 100% correct (no correct handling of continuation lines within an alias) !
+
+	while ( reads ( fd, buffer, buflen)) {
+		int l;
+		char *p;
+
+		p = strchr ( buffer, '#' );
+		if ( p )
+			*p = 0;
+
+		l = strlen ( buffer );
+
+		while ( l && isspace ( buffer [l-1] )) {
+			buffer [l-1] = 0;
+			l--;
+		}
+
+		if ( l == 0 ) {
+			continuation_line = 0;
+			continue;
+		}
+
+		if ( !continuation_line ) {
+			if (( strncmp ( buffer, "alias", 5 ) == 0 ) && isspace ( buffer [5] )) {
+				char *alias, *mod;
+
+				if ( parse_tag_value ( buffer + 6, &alias, &mod )) {
+					/* handle alias as a module dependent on the aliased module */
+					if ( !*current ) {
+						(*first) = (*current) = (struct dep_t *) xcalloc ( 1, sizeof ( struct dep_t ));
+					}
+					else {
+						(*current)-> m_next = (struct dep_t *) xcalloc ( 1, sizeof ( struct dep_t ));
+						(*current) = (*current)-> m_next;
+					}
+					(*current)-> m_name  = bb_xstrdup ( alias );
+					(*current)-> m_isalias = 1;
+
+					if (( strcmp ( mod, "off" ) == 0 ) || ( strcmp ( mod, "null" ) == 0 )) {
+						(*current)-> m_depcnt = 0;
+						(*current)-> m_deparr = 0;
+					}
+					else {
+						(*current)-> m_depcnt  = 1;
+						(*current)-> m_deparr  = xmalloc ( 1 * sizeof( char * ));
+						(*current)-> m_deparr[0] = bb_xstrdup ( mod );
+					}
+					(*current)-> m_next    = 0;
+				}
+			}
+			else if (( strncmp ( buffer, "options", 7 ) == 0 ) && isspace ( buffer [7] )) {
+				char *mod, *opt;
+
+				/* split the line in the module/alias name, and options */
+				if ( parse_tag_value ( buffer + 8, &mod, &opt )) {
+					struct dep_t *dt;
+
+					/* find the corresponding module */
+					for ( dt = *first; dt; dt = dt-> m_next ) {
+						if ( strcmp ( dt-> m_name, mod ) == 0 )
+							break;
+					}
+					if ( dt ) {
+						if ( ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS ) {
+							char* new_opt = NULL;
+							while( ( opt = parse_command_string( opt, &new_opt ) ) ) {
+								dt-> m_options = append_option( dt-> m_options, new_opt );
+							}
+						} else {
+							dt-> m_options = append_option( dt-> m_options, opt );
+						}
+					}
+				}
+			}
+			else if (( strncmp ( buffer, "include", 7 ) == 0 ) && isspace ( buffer [7] )) {
+
+				int fdi; char *filename = buffer + 8;
+
+				while ( isspace ( *filename ))
+					filename++;
+
+				if (( fdi = open ( filename, O_RDONLY )) >= 0 ) {
+					include_conf(first, current, buffer, buflen, fdi);
+					close(fdi);
+				}
+			}
+		}
+	}
+}
+
+/*
+ * This function builds a list of dependency rules from /lib/modules/`uname -r`\modules.dep.
+ * It then fills every modules and aliases with their default options, found by parsing
+ * modprobe.conf (or modules.conf, or conf.modules).
+ */
+static struct dep_t *build_dep ( void )
+{
+	int fd;
+	struct utsname un;
+	struct dep_t *first = 0;
+	struct dep_t *current = 0;
+	char buffer[2048];
+	char *filename;
+	int continuation_line = 0;
+	int k_version;
+
+	k_version = 0;
+	if ( uname ( &un ))
+		bb_error_msg_and_die("can't determine kernel version");
+
+	if (un.release[0] == '2') {
+		k_version = un.release[2] - '0';
+	}
+
+	filename = bb_xasprintf("/lib/modules/%s/modules.dep", un.release );
+	fd = open ( filename, O_RDONLY );
+	if (ENABLE_FEATURE_CLEAN_UP)
+		free(filename);
+	if (fd < 0) {
+		/* Ok, that didn't work.  Fall back to looking in /lib/modules */
+		if (( fd = open ( "/lib/modules/modules.dep", O_RDONLY )) < 0 ) {
+			return 0;
+		}
+	}
+
+	while ( reads ( fd, buffer, sizeof( buffer ))) {
+		int l = strlen ( buffer );
+		char *p = 0;
+
+		while ( l > 0 && isspace ( buffer [l-1] )) {
+			buffer [l-1] = 0;
+			l--;
+		}
+
+		if ( l == 0 ) {
+			continuation_line = 0;
+			continue;
+		}
+
+		/* Is this a new module dep description? */
+		if ( !continuation_line ) {
+			/* find the dep beginning */
+			char *col = strchr ( buffer, ':' );
+			char *dot = col;
+
+			if ( col ) {
+				/* This line is a dep description */
+				char *mods;
+				char *modpath;
+				char *mod;
+
+				/* Find the beginning of the module file name */
+				*col = 0;
+				mods = strrchr ( buffer, '/' );
+
+				if ( !mods )
+					mods = buffer; /* no path for this module */
+				else
+					mods++; /* there was a path for this module... */
+
+				/* find the path of the module */
+				modpath = strchr ( buffer, '/' ); /* ... and this is the path */
+				if ( !modpath )
+					modpath = buffer; /* module with no path */
+				/* find the end of the module name in the file name */
+				if ( ENABLE_FEATURE_2_6_MODULES &&
+				     (k_version > 4) && ( *(col-3) == '.' ) &&
+				     ( *(col-2) == 'k' ) && ( *(col-1) == 'o' ) )
+					dot = col - 3;
+				else
+					if (( *(col-2) == '.' ) && ( *(col-1) == 'o' ))
+						dot = col - 2;
+
+				mod = bb_xstrndup ( mods, dot - mods );
+
+				/* enqueue new module */
+				if ( !current ) {
+					first = current = (struct dep_t *) xmalloc ( sizeof ( struct dep_t ));
+				}
+				else {
+					current-> m_next = (struct dep_t *) xmalloc ( sizeof ( struct dep_t ));
+					current = current-> m_next;
+				}
+				current-> m_name  = mod;
+				current-> m_path  = bb_xstrdup(modpath);
+				current-> m_options = NULL;
+				current-> m_isalias = 0;
+				current-> m_depcnt  = 0;
+				current-> m_deparr  = 0;
+				current-> m_next    = 0;
+
+				p = col + 1;
+			}
+			else
+				/* this line is not a dep description */
+				p = 0;
+		}
+		else
+			/* It's a dep description continuation */
+			p = buffer;
+
+		while ( p && *p && isblank(*p))
+			p++;
+
+		/* p points to the first dependable module; if NULL, no dependable module */
+		if ( p && *p ) {
+			char *end = &buffer [l-1];
+			char *deps;
+			char *dep;
+			char *next;
+			int ext = 0;
+
+			while ( isblank ( *end ) || ( *end == '\\' ))
+				end--;
+
+			do
+			{
+				/* search the end of the dependency */
+				next = strchr (p, ' ' );
+				if (next)
+				{
+					*next = 0;
+					next--;
+				}
+				else
+					next = end;
+
+				/* find the beginning of the module file name */
+				deps = strrchr ( p, '/' );
+
+				if ( !deps || ( deps < p )) {
+					deps = p;
+
+					while ( isblank ( *deps ))
+						deps++;
+				}
+				else
+					deps++;
+
+				/* find the end of the module name in the file name */
+				if ( ENABLE_FEATURE_2_6_MODULES &&
+				     (k_version > 4) && ( *(next-2) == '.' ) &&
+				     ( *(next-1) == 'k' )  && ( *next == 'o' ) )
+					ext = 3;
+				else
+					if (( *(next-1) == '.' ) && ( *next == 'o' ))
+						ext = 2;
+
+				/* Cope with blank lines */
+				if ((next-deps-ext+1) <= 0)
+					continue;
+				dep = bb_xstrndup ( deps, next - deps - ext + 1 );
+
+				/* Add the new dependable module name */
+				current-> m_depcnt++;
+				current-> m_deparr = (char **) xrealloc ( current-> m_deparr,
+						sizeof ( char *) * current-> m_depcnt );
+				current-> m_deparr [current-> m_depcnt - 1] = dep;
+
+				p = next + 2;
+			} while (next < end);
+		}
+
+		/* is there other dependable module(s) ? */
+		if ( buffer [l-1] == '\\' )
+			continuation_line = 1;
+		else
+			continuation_line = 0;
+	}
+	close ( fd );
+
+	/*
+	 * First parse system-specific options and aliases
+	 * as they take precedence over the kernel ones.
+	 */
+	if (!ENABLE_FEATURE_2_6_MODULES
+			|| ( fd = open ( "/etc/modprobe.conf", O_RDONLY )) < 0 )
+		if (( fd = open ( "/etc/modules.conf", O_RDONLY )) < 0 )
+			fd = open ( "/etc/conf.modules", O_RDONLY );
+
+	if (fd >= 0) {
+		include_conf (&first, &current, buffer, sizeof(buffer), fd);
+		close(fd);
+	}
+
+	/* Only 2.6 has a modules.alias file */
+	if (ENABLE_FEATURE_2_6_MODULES) {
+		/* Parse kernel-declared aliases */
+		filename = bb_xasprintf("/lib/modules/%s/modules.alias", un.release);
+		if ((fd = open ( filename, O_RDONLY )) < 0) {
+			/* Ok, that didn't work.  Fall back to looking in /lib/modules */
+			fd = open ( "/lib/modules/modules.alias", O_RDONLY );
+		}
+		if (ENABLE_FEATURE_CLEAN_UP)
+			free(filename);
+
+		if (fd >= 0) {
+			include_conf (&first, &current, buffer, sizeof(buffer), fd);
+			close(fd);
+		}
+	}
+
+	return first;
+}
+
+/* return 1 = loaded, 0 = not loaded, -1 = can't tell */
+static int already_loaded (const char *name)
+{
+	int fd, ret = 0;
+	char buffer[4096];
+
+	fd = open ("/proc/modules", O_RDONLY);
+	if (fd < 0)
+		return -1;
+
+	while ( reads ( fd, buffer, sizeof( buffer ))) {
+		char *p;
+
+		p = strchr (buffer, ' ');
+		if (p) {
+			const char *n;
+
+			// Truncate buffer at first space and check for matches, with
+			// the idiosyncrasy that _ and - are interchangeable because the
+			// 2.6 kernel does weird things.
+
+			*p = 0;
+			for (p = buffer, n = name; ; p++, n++) {
+				if (*p != *n) {
+					if ((*p == '_' || *p == '-') && (*n == '_' || *n == '-'))
+						continue;
+					break;
+				}
+				// If we made it to the end, that's a match.
+				if (!*p) {
+					ret = 1;
+					goto done;
+				}
+			}
+		}
+	}
+done:
+	close (fd);
+	return ret;
+}
+
+static int mod_process ( struct mod_list_t *list, int do_insert )
+{
+	int rc = 0;
+	char **argv = NULL;
+	struct mod_opt_t *opts;
+	int argc_malloc; /* never used when CONFIG_FEATURE_CLEAN_UP not defined */
+	int argc;
+
+	while ( list ) {
+		argc = 0;
+		if( ENABLE_FEATURE_CLEAN_UP )
+			argc_malloc = 0;
+		/* If CONFIG_FEATURE_CLEAN_UP is not defined, then we leak memory
+		 * each time we allocate memory for argv.
+		 * But it is (quite) small amounts of memory that leak each
+		 * time a module is loaded,  and it is reclaimed when modprobe
+		 * exits anyway (even when standalone shell?).
+		 * This could become a problem when loading a module with LOTS of
+		 * dependencies, with LOTS of options for each dependencies, with
+		 * very little memory on the target... But in that case, the module
+		 * would not load because there is no more memory, so there's no
+		 * problem. */
+		/* enough for minimal insmod (5 args + NULL) or rmmod (3 args + NULL) */
+		argv = (char**) malloc( 6 * sizeof( char* ) );
+		if ( do_insert ) {
+			if (already_loaded (list->m_name) != 1) {
+				argv[argc++] = "insmod";
+				if (ENABLE_FEATURE_2_4_MODULES) {
+					if (do_syslog)
+						argv[argc++] = "-s";
+					if (autoclean)
+						argv[argc++] = "-k";
+					if (quiet)
+						argv[argc++] = "-q";
+					else if(verbose) /* verbose and quiet are mutually exclusive */
+						argv[argc++] = "-v";
+				}
+				argv[argc++] = list-> m_path;
+				if( ENABLE_FEATURE_CLEAN_UP )
+					argc_malloc = argc;
+				opts = list-> m_options;
+				while( opts ) {
+					/* Add one more option */
+					argc++;
+					argv = (char**) xrealloc( argv, ( argc + 1 ) * sizeof( char* ) );
+					argv[argc-1] = opts-> m_opt_val;
+					opts = opts-> m_next;
+				}
+			}
+		} else {
+			/* modutils uses short name for removal */
+			if (already_loaded (list->m_name) != 0) {
+				argv[argc++] = "rmmod";
+				if (do_syslog)
+					argv[argc++] = "-s";
+				argv[argc++] = list->m_name;
+				if( ENABLE_FEATURE_CLEAN_UP )
+					argc_malloc = argc;
+			}
+		}
+		argv[argc] = NULL;
+
+		if (argc) {
+			if (verbose) {
+				printf("%s module %s\n", do_insert?"Loading":"Unloading", list-> m_name );
+			}
+			if (!show_only) {
+				int rc2 = wait4pid(bb_spawn(argv));
+				
+				if (do_insert) {
+					rc = rc2; /* only last module matters */
+				}
+				else if (!rc2) {
+					rc = 0; /* success if remove any mod */
+				}
+			}
+			if( ENABLE_FEATURE_CLEAN_UP )
+				/* the last value in the array has index == argc, but
+				 * it is the terminating NULL, so we must not free it. */
+				while( argc_malloc < argc ) {
+					free( argv[argc_malloc++] );
+			}
+		}
+		if( ENABLE_FEATURE_CLEAN_UP ) {
+			free( argv );
+			argv = NULL;
+		}
+		list = do_insert ? list-> m_prev : list-> m_next;
+	}
+	return (show_only) ? 0 : rc;
+}
+
+/*
+ * Builds the dependency list (aka stack) of a module.
+ * head: the highest module in the stack (last to insmod, first to rmmod)
+ * tail: the lowest module in the stack (first to insmod, last to rmmod)
+ */
+static void check_dep ( char *mod, struct mod_list_t **head, struct mod_list_t **tail )
+{
+	struct mod_list_t *find;
+	struct dep_t *dt;
+	struct mod_opt_t *opt = 0;
+	char *path = 0;
+
+	/* Search for the given module name amongst all dependency rules.
+	 * The module name in a dependency rule can be a shell pattern,
+	 * so try to match the given module name against such a pattern.
+	 * Of course if the name in the dependency rule is a plain string,
+	 * then we consider it a pattern, and matching will still work. */
+	for ( dt = depend; dt; dt = dt-> m_next ) {
+		if ( fnmatch ( dt-> m_name, mod, 0 ) == 0) {
+			break;
+		}
+	}
+
+	if( !dt ) {
+		bb_error_msg ("module %s not found.", mod);
+		return;
+	}
+
+	// resolve alias names
+	while ( dt-> m_isalias ) {
+		if ( dt-> m_depcnt == 1 ) {
+			struct dep_t *adt;
+
+			for ( adt = depend; adt; adt = adt-> m_next ) {
+				if ( strcmp ( adt-> m_name, dt-> m_deparr [0] ) == 0 )
+					break;
+			}
+			if ( adt ) {
+				/* This is the module we are aliased to */
+				struct mod_opt_t *opts = dt-> m_options;
+				/* Option of the alias are appended to the options of the module */
+				while( opts ) {
+					adt-> m_options = append_option( adt-> m_options, opts-> m_opt_val );
+					opts = opts-> m_next;
+				}
+				dt = adt;
+			}
+			else {
+				bb_error_msg ("module %s not found.", mod);
+				return;
+			}
+		}
+		else {
+			bb_error_msg ("Bad alias %s", dt-> m_name);
+			return;
+		}
+	}
+
+	mod = dt-> m_name;
+	path = dt-> m_path;
+	opt = dt-> m_options;
+
+	// search for duplicates
+	for ( find = *head; find; find = find-> m_next ) {
+		if ( !strcmp ( mod, find-> m_name )) {
+			// found -> dequeue it
+
+			if ( find-> m_prev )
+				find-> m_prev-> m_next = find-> m_next;
+			else
+				*head = find-> m_next;
+
+			if ( find-> m_next )
+				find-> m_next-> m_prev = find-> m_prev;
+			else
+				*tail = find-> m_prev;
+
+			break; // there can be only one duplicate
+		}
+	}
+
+	if ( !find ) { // did not find a duplicate
+		find = (struct mod_list_t *) xmalloc ( sizeof(struct mod_list_t));
+		find-> m_name = mod;
+		find-> m_path = path;
+		find-> m_options = opt;
+	}
+
+	// enqueue at tail
+	if ( *tail )
+		(*tail)-> m_next = find;
+	find-> m_prev   = *tail;
+	find-> m_next   = 0;
+
+	if ( !*head )
+		*head = find;
+	*tail = find;
+
+	if ( dt ) {
+		int i;
+
+		/* Add all dependable module for that new module */
+		for ( i = 0; i < dt-> m_depcnt; i++ )
+			check_dep ( dt-> m_deparr [i], head, tail );
+	}
+}
+
+static int mod_insert ( char *mod, int argc, char **argv )
+{
+	struct mod_list_t *tail = 0;
+	struct mod_list_t *head = 0;
+	int rc;
+
+	// get dep list for module mod
+	check_dep ( mod, &head, &tail );
+
+	if ( head && tail ) {
+		if( argc ) {
+			int i;
+			// append module args
+			for ( i = 0; i < argc; i++ )
+				head->m_options = append_option( head->m_options, argv[i] );
+		}
+
+		// process tail ---> head
+		rc = mod_process ( tail, 1 );
+	}
+	else
+		rc = 1;
+
+	return rc;
+}
+
+static int mod_remove ( char *mod )
+{
+	int rc;
+	static struct mod_list_t rm_a_dummy = { "-a", NULL, NULL, NULL, NULL };
+
+	struct mod_list_t *head = 0;
+	struct mod_list_t *tail = 0;
+
+	if ( mod )
+		check_dep ( mod, &head, &tail );
+	else  // autoclean
+		head = tail = &rm_a_dummy;
+
+	if ( head && tail )
+		rc = mod_process ( head, 0 );  // process head ---> tail
+	else
+		rc = 1;
+	return rc;
+
+}
+
+int modprobe_main(int argc, char** argv)
+{
+	int rc = EXIT_SUCCESS;
+	char *unused;
+
+	bb_opt_complementally = "?V-:q-v:v-q";
+	main_opts = bb_getopt_ulflags(argc, argv, "acdklnqrst:vVC:",
+							&unused, &unused);
+	if((main_opts & (DUMP_CONF_EXIT | LIST_ALL)))
+				return EXIT_SUCCESS;
+	if((main_opts & (RESTRICT_DIR | CONFIG_FILE)))
+				bb_error_msg_and_die("-t and -C not supported");
+
+	depend = build_dep ( );
+
+	if ( !depend )
+		bb_error_msg_and_die ( "could not parse modules.dep" );
+
+	if (remove_opt) {
+		do {
+			if (mod_remove ( optind < argc ?
+						argv [optind] : NULL )) {
+				bb_error_msg ("failed to remove module %s",
+						argv [optind] );
+				rc = EXIT_FAILURE;
+			}
+		} while ( ++optind < argc );
+	} else {
+		if (optind >= argc)
+			bb_error_msg_and_die ( "No module or pattern provided" );
+
+		if ( mod_insert ( argv [optind], argc - optind - 1, argv + optind + 1 ))
+			bb_error_msg_and_die ( "failed to load module %s", argv [optind] );
+	}
+
+	/* Here would be a good place to free up memory allocated during the dependencies build. */
+
+	return rc;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/rmmod.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/rmmod.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/modutils/rmmod.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,109 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini rmmod implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/utsname.h>
+#include <sys/syscall.h>
+
+#ifdef CONFIG_FEATURE_2_6_MODULES
+static inline void filename2modname(char *modname, const char *afterslash)
+{
+	unsigned int i;
+
+#if ENABLE_FEATURE_2_4_MODULES
+	int kr_chk = 1;
+	if (get_linux_version_code() <= KERNEL_VERSION(2,6,0))
+		kr_chk = 0;
+#else
+#define kr_chk 1
+#endif
+
+	/* Convert to underscores, stop at first . */
+	for (i = 0; afterslash[i] && afterslash[i] != '.'; i++) {
+		if (kr_chk && (afterslash[i] == '-'))
+			modname[i] = '_';
+		else
+			modname[i] = afterslash[i];
+	}
+	modname[i] = '\0';
+}
+#endif
+
+int rmmod_main(int argc, char **argv)
+{
+	int n, ret = EXIT_SUCCESS;
+	unsigned int flags = O_NONBLOCK|O_EXCL;
+#ifdef CONFIG_FEATURE_QUERY_MODULE_INTERFACE
+	/* bb_common_bufsiz1 hold the module names which we ignore
+	   but must get */
+	size_t bufsize = sizeof(bb_common_bufsiz1);
+#endif
+
+	/* Parse command line. */
+	n = bb_getopt_ulflags(argc, argv, "wfa");
+	if((n & 1))	// --wait
+		flags &= ~O_NONBLOCK;
+	if((n & 2))	// --force
+		flags |= O_TRUNC;
+	if((n & 4)) {
+		/* Unload _all_ unused modules via NULL delete_module() call */
+		/* until the number of modules does not change */
+		size_t nmod = 0; /* number of modules */
+		size_t pnmod = -1; /* previous number of modules */
+
+		while (nmod != pnmod) {
+			if (syscall(__NR_delete_module, NULL, flags) != 0) {
+				if (errno==EFAULT)
+					return(ret);
+				bb_perror_msg_and_die("rmmod");
+			}
+			pnmod = nmod;
+#ifdef CONFIG_FEATURE_QUERY_MODULE_INTERFACE
+			/* 1 == QM_MODULES */
+			if (my_query_module(NULL, 1, &bb_common_bufsiz1, &bufsize, &nmod)) {
+				bb_perror_msg_and_die("QM_MODULES");
+			}
+#endif
+		}
+		return EXIT_SUCCESS;
+	}
+
+	if (optind == argc)
+		bb_show_usage();
+
+	for (n = optind; n < argc; n++) {
+#ifdef CONFIG_FEATURE_2_6_MODULES
+		const char *afterslash;
+		char *module_name;
+
+		afterslash = strrchr(argv[n], '/');
+		if (!afterslash)
+			afterslash = argv[n];
+		else
+			afterslash++;
+		module_name = alloca(strlen(afterslash) + 1);
+		filename2modname(module_name, afterslash);
+#else
+#define module_name		argv[n]
+#endif
+		if (syscall(__NR_delete_module, module_name, flags) != 0) {
+			bb_perror_msg("%s", argv[n]);
+			ret = EXIT_FAILURE;
+		}
+	}
+
+	return(ret);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,704 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Networking Utilities"
+
+config CONFIG_FEATURE_IPV6
+	bool "Enable IPv6 support"
+	default n
+	help
+	  Enable IPv6 support in busybox.
+	  This adds IPv6 support in the networking applets.
+
+config CONFIG_ARPING
+	bool "arping"
+	default n
+	help
+	  Ping hosts by ARP packets
+
+config CONFIG_DNSD
+	bool "dnsd"
+	default n
+	help
+	  Small and static DNS server daemon. 
+
+config CONFIG_ETHER_WAKE
+	bool "ether-wake"
+	default n
+	help
+	  Send a magic packet to wake up sleeping machines.
+
+config CONFIG_FAKEIDENTD
+	bool "fakeidentd"
+	default n
+	help
+	  fakeidentd listens on the ident port and returns a predefined
+	  fake value on any query.
+
+config CONFIG_FTPGET
+	bool "ftpget"
+	default n
+	help
+	  Retrieve a remote file via FTP.
+
+config CONFIG_FTPPUT
+	bool "ftpput"
+	default n
+	help
+	  Store a remote file via FTP.
+
+config CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS
+	bool "Enable long options in ftpget/ftpput"
+	default n
+	depends on CONFIG_GETOPT_LONG && (CONFIG_FTPGET || CONFIG_FTPPUT)
+	help
+	  Support long options for the ftpget/ftpput applet.
+
+config CONFIG_HOSTNAME
+	bool "hostname"
+	default n
+	help
+	  Show or set the system's host name
+
+config CONFIG_HTTPD
+	bool "httpd"
+	default n
+	help
+	  Serve web pages via an HTTP server.
+
+config CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+	bool "Support using httpd as a daemon (not from inetd)"
+	default n
+	depends on CONFIG_HTTPD
+	help
+	  This option enables uid and port options for the httpd applet,
+	  and eliminates the need to be called from the inetd server daemon.
+
+config CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
+	bool "Support reloading the global config file using hup signal"
+	default n
+	depends on CONFIG_HTTPD && CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+	help
+	  This option enables processing of SIGHUP to reload cached
+	  configuration settings.
+
+config CONFIG_FEATURE_HTTPD_SETUID
+	bool "Enable support -u <user> option"
+	default n
+	depends on CONFIG_HTTPD && CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+	help
+	  This option allows the server to run as a specific user
+	  rather than defaulting to the user that starts the server.
+	  Use of this option requires special privileges to change to a
+	  different user.
+
+config CONFIG_FEATURE_HTTPD_BASIC_AUTH
+	bool "Enable Basic http Authentication"
+	default y
+	depends on CONFIG_HTTPD
+	help
+	  Utilizes password settings from /etc/httpd.conf for basic
+	  authentication on a per url basis.
+
+config CONFIG_FEATURE_HTTPD_AUTH_MD5
+	bool "Support MD5 crypted passwords for http Authentication"
+	default n
+	depends on CONFIG_FEATURE_HTTPD_BASIC_AUTH
+	help
+	  Enables basic per URL authentication from /etc/httpd.conf
+	  using md5 passwords.
+
+config CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
+	bool "Support loading additional MIME types at run-time"
+	default n
+	depends on CONFIG_HTTPD
+	help
+	  This option enables support for additional MIME types at
+	  run-time to be specified in the configuration file.
+
+config CONFIG_FEATURE_HTTPD_CGI
+	bool "Support Common Gateway Interface (CGI)"
+	default y
+	depends on CONFIG_HTTPD
+	help
+	  This option allows scripts and executables to be invoked
+	  when specific URLs are requested.
+
+config CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
+	bool "Enable support for running scripts through an interpreter"
+	default n
+	depends on CONFIG_FEATURE_HTTPD_CGI
+	help
+	  This option enables support for running scripts through an 
+	  interpreter. Turn this on if you want PHP scripts to work 
+	  properly. You need to supply an addition line in your httpd 
+	  config file:
+	  *.php:/path/to/your/php
+
+config CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
+	bool "Support the REMOTE_PORT environment variable for CGI"
+	default n
+	depends on CONFIG_FEATURE_HTTPD_CGI
+	help
+	  Use of this option can assist scripts in generating
+	  references that contain a unique port number.
+
+config CONFIG_FEATURE_HTTPD_ENCODE_URL_STR
+	bool "Enable the -e option for shell script CGI simplification."
+	default y
+	depends on CONFIG_HTTPD
+	help
+	  This option allows html encoding arbitrary
+	  strings for display of the browser.  Output goes to stdout.
+	  For example, httpd -e "<Hello World>" as
+	  "&#60Hello&#32World&#62".
+
+config CONFIG_IFCONFIG
+	bool "ifconfig"
+	default n
+	help
+	  Ifconfig is used to configure the kernel-resident network interfaces.
+
+config CONFIG_FEATURE_IFCONFIG_STATUS
+	bool "Enable status reporting output (+7k)"
+	default y
+	depends on CONFIG_IFCONFIG
+	help
+	  If ifconfig is called with no arguments it will display the status
+	  of the currently active interfaces.
+
+config CONFIG_FEATURE_IFCONFIG_SLIP
+	bool "Enable slip-specific options \"keepalive\" and \"outfill\""
+	default n
+	depends on CONFIG_IFCONFIG
+	help
+	  Allow "keepalive" and "outfill" support for SLIP.  If you're not
+	  planning on using serial lines, leave this unchecked.
+
+config CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
+	bool "Enable options \"mem_start\", \"io_addr\", and \"irq\""
+	default n
+	depends on CONFIG_IFCONFIG
+	help
+	  Allow the start address for shared memory, start address for I/O,
+	  and/or the interrupt line used by the specified device.
+
+config CONFIG_FEATURE_IFCONFIG_HW
+	bool "Enable option \"hw\" (ether only)"
+	default y
+	depends on CONFIG_IFCONFIG
+	help
+	  Set the hardware address of this interface, if the device driver
+	  supports  this  operation.  Currently, we only support the 'ether'
+	  class.
+
+config CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS
+	bool "Set the broadcast automatically"
+	default n
+	depends on CONFIG_IFCONFIG
+	help
+	  Setting this will make ifconfig attempt to find the broadcast
+	  automatically if the value '+' is used.
+
+config CONFIG_IFUPDOWN
+	bool "ifupdown"
+	default n
+	select CONFIG_RUN_PARTS
+	help
+	  Activate or deactivate the specified interfaces.  This applet makes
+	  use of either "ifconfig" and "route" or the "ip" command to actually
+	  configure network interfaces.  Therefore, you will probably also want
+	  to enable either CONFIG_IFCONFIG and CONFIG_ROUTE, or enable
+	  CONFIG_FEATURE_IFUPDOWN_IP and the various CONFIG_IP options.  Of
+	  course you could use non-busybox versions of these programs, so
+	  against my better judgement (since this will surely result in plenty
+	  of support questions on the mailing list), I do not force you to
+	  enable these additional options.  It is up to you to supply either
+	  "ifconfig" and "route" or the "ip" command, either via busybox or via
+	  standalone utilities.
+
+config CONFIG_FEATURE_IFUPDOWN_IP
+	bool "Use ip applet"
+	default n
+	depends on CONFIG_IFUPDOWN
+	help
+	  Use the iproute "ip" command to implement "ifup" and "ifdown", rather
+	  than the default of using the older 'ifconfig' and 'route' utilities.
+
+config CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN
+	bool "Use busybox ip applet"
+	default y
+	depends on CONFIG_FEATURE_IFUPDOWN_IP
+	select CONFIG_IP
+	select CONFIG_FEATURE_IP_ADDRESS
+	select CONFIG_FEATURE_IP_LINK
+	select CONFIG_FEATURE_IP_ROUTE
+	help
+	  Use the busybox iproute "ip" applet to implement "ifupdown".
+
+	  If leave this disabled, you must install the full-blown iproute2
+	  utility or the  "ifup" and "ifdown" applets will not work.
+
+config CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN
+	bool "Use busybox ifconfig and route applets"
+	default y
+	depends on CONFIG_IFUPDOWN && !CONFIG_FEATURE_IFUPDOWN_IP
+	select CONFIG_IFCONFIG
+	select CONFIG_ROUTE
+	help
+	  Use the busybox iproute "ifconfig" and "route" applets to
+	  implement the "ifup" and "ifdown" utilities.
+
+	  If leave this disabled, you must install the full-blown ifconfig
+	  and route utilities, or the  "ifup" and "ifdown" applets will not
+	  work.
+
+config CONFIG_FEATURE_IFUPDOWN_IPV4
+	bool "Enable support for IPv4"
+	default y
+	depends on CONFIG_IFUPDOWN
+	help
+	  If you want busybox to talk IPv4, leave this on.
+
+config CONFIG_FEATURE_IFUPDOWN_IPV6
+	bool "Enable support for IPv6"
+	default n
+	depends on CONFIG_IFUPDOWN && CONFIG_FEATURE_IPV6
+	help
+	  If you need support for IPv6, turn this option on.
+
+config CONFIG_FEATURE_IFUPDOWN_IPX
+	bool "Enable support for IPX"
+	default n
+	depends on CONFIG_IFUPDOWN
+	help
+	  If this option is selected you can use busybox to work with IPX
+	  networks.
+
+config CONFIG_FEATURE_IFUPDOWN_MAPPING
+	bool "Enable mapping support"
+	default n
+	depends on CONFIG_IFUPDOWN
+	help
+	  This enables support for the "mapping" stanza, unless you have
+	  a weird network setup you don't need it.
+
+config CONFIG_INETD
+	bool "inetd"
+	default n
+	help
+	  Internet superserver daemon
+
+config CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
+	bool "Support echo service"
+	default y
+	depends on CONFIG_INETD
+	help
+	  Echo received data internal inetd service
+
+config CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
+	bool "Support discard service"
+	default y
+	depends on CONFIG_INETD
+	help
+	  Internet /dev/null internal inetd service
+
+config CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME
+	bool "Support time service"
+	default y
+	depends on CONFIG_INETD
+	help
+	  Return 32 bit time since 1900 internal inetd service
+
+config CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
+	bool "Support daytime service"
+	default y
+	depends on CONFIG_INETD
+	help
+	  Return human-readable time internal inetd service
+
+config CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+	bool "Support chargen service"
+	default y
+	depends on CONFIG_INETD
+	help
+	  Familiar character generator internal inetd service
+
+config CONFIG_FEATURE_INETD_RPC
+	bool "Support RPC services"
+	default n
+	depends on CONFIG_INETD
+	help
+	  Suuport Sun-RPC based services
+
+
+config CONFIG_IP
+	bool "ip"
+	default n
+	help
+	  The "ip" applet is a TCP/IP interface configuration and routing
+	  utility.  You generally don't need "ip" to use busybox with
+	  TCP/IP.
+
+config CONFIG_FEATURE_IP_ADDRESS
+	bool "ip address"
+	default y
+	depends on CONFIG_IP
+	help
+	  Address manipulation support for the "ip" applet.
+
+config CONFIG_FEATURE_IP_LINK
+	bool "ip link"
+	default y
+	depends on CONFIG_IP
+	help
+	  Configure network devices with "ip".
+
+config CONFIG_FEATURE_IP_ROUTE
+	bool "ip route"
+	default y
+	depends on CONFIG_IP
+	help
+	  Add support for routing table management to "ip".
+
+config CONFIG_FEATURE_IP_TUNNEL
+	bool "ip tunnel"
+	default n
+	depends on CONFIG_IP
+	help
+	  Add support for tunneling commands to "ip".
+
+config CONFIG_FEATURE_IP_SHORT_FORMS
+	bool "Support short forms of ip commands."
+	default n
+	depends on CONFIG_IP
+	help
+	  Also support short-form of ip <OBJECT> commands:
+	  ip addr   -> ipaddr
+	  ip link   -> iplink
+	  ip route  -> iproute
+	  ip tunnel -> iptunnel
+
+	  Say N unless you desparately need the short form of the ip
+	  object commands.
+
+config CONFIG_IPADDR
+	bool
+	default y
+	depends on CONFIG_FEATURE_IP_SHORT_FORMS && CONFIG_FEATURE_IP_ADDRESS
+
+config CONFIG_IPLINK
+	bool
+	default y
+	depends on CONFIG_FEATURE_IP_SHORT_FORMS && CONFIG_FEATURE_IP_LINK
+
+config CONFIG_IPROUTE
+	bool
+	default y
+	depends on CONFIG_FEATURE_IP_SHORT_FORMS && CONFIG_FEATURE_IP_ROUTE
+
+config CONFIG_IPTUNNEL
+	bool
+	default y
+	depends on CONFIG_FEATURE_IP_SHORT_FORMS && CONFIG_FEATURE_IP_TUNNEL
+
+config CONFIG_IPCALC
+	bool "ipcalc"
+	default n
+	help
+	  ipcalc takes an IP address and netmask and calculates the
+	  resulting broadcast, network, and host range.
+
+config CONFIG_FEATURE_IPCALC_FANCY
+	bool "Fancy IPCALC, more options, adds 1 kbyte"
+	default y
+	depends on CONFIG_IPCALC
+	help
+	  Adds the options hostname, prefix and silent to the output of "ipcalc".
+
+config CONFIG_FEATURE_IPCALC_LONG_OPTIONS
+	bool "Enable long options"
+	default n
+	depends on CONFIG_IPCALC && CONFIG_GETOPT_LONG
+	help
+	  Support long options for the ipcalc applet.
+
+config CONFIG_NAMEIF
+	bool "nameif"
+	default n
+	help
+	  nameif is used to rename network interface by its MAC address.
+	  Renamed interfaces MUST be in the down state.
+	  It is possible to use a file (default: /etc/mactab)
+	  with list of new interface names and MACs.
+	  Maximum interface name length: IF_NAMESIZE = 16
+	  File fields are separated by space or tab.
+	  File format:
+	  # Comment
+	  new_interface_name    XX:XX:XX:XX:XX:XX
+
+config CONFIG_NC
+	bool "nc"
+	default n
+	help
+	  A simple Unix utility which reads and writes data across network
+	  connections.
+
+config CONFIG_NC_GAPING_SECURITY_HOLE
+	bool "gaping security hole"
+	default n
+	depends on CONFIG_NC
+	help
+	  Add support for executing a program after making or receiving a
+	  successful connection (-e option).
+
+config CONFIG_NETSTAT
+	bool "netstat"
+	default n
+	help
+	  netstat prints information about the Linux networking subsystem.
+
+config CONFIG_NSLOOKUP
+	bool "nslookup"
+	default n
+	help
+	  nslookup is a tool to query Internet name servers.
+
+config CONFIG_PING
+	bool "ping"
+	default n
+	help
+	  ping uses the ICMP protocol's mandatory ECHO_REQUEST datagram to
+	  elicit an ICMP ECHO_RESPONSE from a host or gateway.
+
+config CONFIG_FEATURE_FANCY_PING
+	bool "Enable fancy ping output"
+	default y
+	depends on CONFIG_PING
+	help
+	  Make the output from the ping applet include statistics, and at the
+	  same time provide full support for ICMP packets.
+
+config CONFIG_PING6
+	bool "ping6"
+	default n
+	depends on CONFIG_FEATURE_IPV6
+	help
+	  This will give you a ping that can talk IPv6.
+
+config CONFIG_FEATURE_FANCY_PING6
+	bool "Enable fancy ping6 output"
+	default y
+	depends on CONFIG_PING6
+	help
+	  Make the output from the ping6 applet include statistics, and at the
+	  same time provide full support for ICMP packets.
+
+config CONFIG_ROUTE
+	bool "route"
+	default n
+	help
+	  Route displays or manipulates the kernel's IP routing tables.
+
+config CONFIG_TELNET
+	bool "telnet"
+	default n
+	help
+	  Telnet is an interface to the TELNET protocol, but is also commonly
+	  used to test other simple protocols.
+
+config CONFIG_FEATURE_TELNET_TTYPE
+	bool "Pass TERM type to remote host"
+	default y
+	depends on CONFIG_TELNET
+	help
+	  Setting this option will forward the TERM environment variable to the
+	  remote host you are connecting to.  This is useful to make sure that
+	  things like ANSI colors and other control sequences behave.
+
+config CONFIG_FEATURE_TELNET_AUTOLOGIN
+	bool "Pass USER type to remote host"
+	default y
+	depends on CONFIG_TELNET
+	help
+	  Setting this option will forward the USER environment variable to the
+	  remote host you are connecting to. This is useful when you need to
+	  log into a machine without telling the username (autologin). This
+	  option enables `-a' and `-l USER' arguments.
+
+config CONFIG_TELNETD
+	bool "telnetd"
+	default n
+	help
+	  A daemon for the TELNET protocol, allowing you to log onto the host
+	  running the daemon.  Please keep in mind that the TELNET protocol
+	  sends passwords in plain text.  If you can't afford the space for an
+	  SSH daemon and you trust your network, you may say 'y' here.  As a
+	  more secure alternative, you should seriously consider installing the
+	  very small Dropbear SSH daemon instead:
+		http://matt.ucc.asn.au/dropbear/dropbear.html
+
+	  Note that for busybox telnetd to work you need several things:
+	  First of all, your kernel needs:
+		  CONFIG_UNIX98_PTYS=y
+		  CONFIG_DEVPTS_FS=y
+
+	  Next, you need a /dev/pts directory on your root filesystem:
+
+		  $ ls -ld /dev/pts
+		  drwxr-xr-x  2 root root 0 Sep 23 13:21 /dev/pts/
+
+	  Next you need the pseudo terminal master multiplexer /dev/ptmx:
+
+		  $ ls -la /dev/ptmx
+		  crw-rw-rw-  1 root tty 5, 2 Sep 23 13:55 /dev/ptmx
+
+	  Any /dev/ttyp[0-9]* files you may have can be removed.
+	  Next, you need to mount the devpts filesystem on /dev/pts using:
+
+		  mount -t devpts devpts /dev/pts
+
+	  You need to be sure that Busybox has CONFIG_LOGIN and
+	  CONFIG_FEATURE_SUID enabled.  And finally, you should make
+	  certain that Busybox has been installed setuid root:
+
+		chown root.root /bin/busybox
+		chmod 4755 /bin/busybox
+
+	  with all that done, telnetd _should_ work....
+
+
+config CONFIG_FEATURE_TELNETD_INETD
+	bool "Support call from inetd only"
+	default n
+	depends on CONFIG_TELNETD
+	help
+	  Selecting this will make telnetd only callable from inetd,
+	  removing the standalone support.
+
+config CONFIG_TFTP
+	bool "tftp"
+	default n
+	help
+	  This enables the Trivial File Transfer Protocol client program.  TFTP
+	  is usually used for simple, small transfers such as a root image
+	  for a network-enabled bootloader.
+
+config CONFIG_FEATURE_TFTP_GET
+	bool "Enable \"get\" command"
+	default y
+	depends on CONFIG_TFTP
+	help
+	  Add support for the GET command within the TFTP client.  This allows
+	  a client to retrieve a file from a TFTP server.
+
+config CONFIG_FEATURE_TFTP_PUT
+	bool "Enable \"put\" command"
+	default y
+	depends on CONFIG_TFTP
+	help
+	  Add support for the PUT command within the TFTP client.  This allows
+	  a client to transfer a file to a TFTP server.
+
+config CONFIG_FEATURE_TFTP_BLOCKSIZE
+	bool "Enable \"blocksize\" command"
+	default n
+	depends on CONFIG_TFTP
+	help
+	  Allow the client to specify the desired block size for transfers.
+
+config CONFIG_DEBUG_TFTP
+	bool "Enable debug"
+	default n
+	depends on CONFIG_TFTP
+	help
+	  Enable debug settings for tftp.  This is useful if you're running
+	  into problems with tftp as the protocol doesn't help you much when
+	  you run into problems.
+
+config CONFIG_TRACEROUTE
+	bool "traceroute"
+	default n
+	help
+	  Utility to trace the route of IP packets
+
+config CONFIG_FEATURE_TRACEROUTE_VERBOSE
+	bool "Enable verbose output"
+	default n
+	depends on CONFIG_TRACEROUTE
+	help
+	  Add some verbosity to traceroute.  This includes amongst other things
+	  hostnames and ICMP response types.
+
+config CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
+	bool "Enable loose source route"
+	default n
+	depends on CONFIG_TRACEROUTE
+	help
+	  Add option to specify a loose source route gateway
+	  (8 maximum).
+
+config CONFIG_FEATURE_TRACEROUTE_USE_ICMP
+	bool "Use ICMP instead of UDP"
+	default n
+	depends on CONFIG_TRACEROUTE
+	help
+	  Add feature to allow for ICMP ECHO instead of UDP datagrams.
+
+source networking/udhcp/Config.in
+
+config CONFIG_VCONFIG
+	bool "vconfig"
+	default n
+	help
+	  Creates, removes, and configures VLAN interfaces
+
+config CONFIG_WGET
+	bool "wget"
+	default n
+	help
+	  wget is a utility for non-interactive download of files from HTTP,
+	  HTTPS, and FTP servers.
+
+config CONFIG_FEATURE_WGET_STATUSBAR
+	bool "Enable a nifty process meter (+2k)"
+	default y
+	depends on CONFIG_WGET
+	help
+	  Enable the transfer progress bar for wget transfers.
+
+config CONFIG_FEATURE_WGET_AUTHENTICATION
+	bool "Enable HTTP authentication"
+	default y
+	depends on CONFIG_WGET
+	help
+	  Support authenticated HTTP transfers.
+
+config CONFIG_FEATURE_WGET_IP6_LITERAL
+	bool "Enable IPv6 literal addresses"
+	default y
+	depends on CONFIG_WGET && CONFIG_FEATURE_IPV6
+	help
+	  Support IPv6 address literal notation in URLs.
+
+config CONFIG_FEATURE_WGET_LONG_OPTIONS
+	bool "Enable long options"
+	default n
+	depends on CONFIG_WGET && CONFIG_GETOPT_LONG
+	help
+	  Support long options for the wget applet.
+
+config CONFIG_ZCIP
+	bool "zcip"
+	default n
+	help
+	  ZCIP provides ZeroConf IPv4 address selection, according to RFC 3927.
+	  It's a daemon that allocates and defends a dynamically assigned
+	  address on the 169.254/16 network, requiring no system administrator.
+
+	  See http://www.zeroconf.org for further details, and "zcip.script"
+	  in the busybox examples.
+
+endmenu

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/networking
+NETWORKING_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,70 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+NETWORKING_AR:=networking.a
+ifndef $(NETWORKING_DIR)
+NETWORKING_DIR:=$(top_builddir)/networking/
+endif
+srcdir=$(top_srcdir)/networking
+
+NETWORKING-y:=
+NETWORKING-$(CONFIG_ARPING)       += arping.o
+NETWORKING-$(CONFIG_DNSD)         += dnsd.o
+NETWORKING-$(CONFIG_ETHER_WAKE)   += ether-wake.o
+NETWORKING-$(CONFIG_FAKEIDENTD)   += fakeidentd.o
+NETWORKING-$(CONFIG_FTPGET)       += ftpgetput.o
+NETWORKING-$(CONFIG_FTPPUT)       += ftpgetput.o
+NETWORKING-$(CONFIG_HOSTNAME)     += hostname.o
+NETWORKING-$(CONFIG_HTTPD)        += httpd.o
+NETWORKING-$(CONFIG_IFCONFIG)     += ifconfig.o interface.o
+NETWORKING-$(CONFIG_IFUPDOWN)     += ifupdown.o
+NETWORKING-$(CONFIG_INETD)        += inetd.o
+NETWORKING-$(CONFIG_IP)           += ip.o
+NETWORKING-$(CONFIG_IPCALC)       += ipcalc.o
+NETWORKING-$(CONFIG_IPADDR)       += ipaddr.o
+NETWORKING-$(CONFIG_IPLINK)       += iplink.o
+NETWORKING-$(CONFIG_IPROUTE)      += iproute.o
+NETWORKING-$(CONFIG_IPTUNNEL)     += iptunnel.o
+NETWORKING-$(CONFIG_NAMEIF)       += nameif.o
+NETWORKING-$(CONFIG_NC)           += nc.o
+NETWORKING-$(CONFIG_NETSTAT)      += netstat.o
+NETWORKING-$(CONFIG_NSLOOKUP)     += nslookup.o
+NETWORKING-$(CONFIG_PING)         += ping.o
+NETWORKING-$(CONFIG_PING6)        += ping6.o
+NETWORKING-$(CONFIG_ROUTE)        += route.o
+NETWORKING-$(CONFIG_TELNET)       += telnet.o
+NETWORKING-$(CONFIG_TELNETD)      += telnetd.o
+NETWORKING-$(CONFIG_TFTP)         += tftp.o
+NETWORKING-$(CONFIG_TRACEROUTE)   += traceroute.o
+NETWORKING-$(CONFIG_VCONFIG)      += vconfig.o
+NETWORKING-$(CONFIG_WGET)         += wget.o
+NETWORKING-$(CONFIG_ZCIP)         += zcip.o
+
+NETWORKING-y:=$(sort $(NETWORKING-y))
+ifneq ($(strip $(NETWORKING-y)),)
+libraries-y+=$(NETWORKING_DIR)$(NETWORKING_AR)
+endif
+
+NETWORKING_SRC-y:=$(patsubst %.o,$(srcdir)/%.c,$(NETWORKING-y))
+NETWORKING_SRC-a:=$(wildcard $(srcdir)/*.c)
+APPLET_SRC-y+=$(NETWORKING_SRC-y)
+APPLET_SRC-a+=$(NETWORKING_SRC-a)
+
+LIBRARY_DEFINE-y+= -I$(top_srcdir)/networking
+LIBRARY_DEFINE-a+= -I$(top_srcdir)/networking
+
+needcrypt-y:=
+needcrypt-$(CONFIG_FEATURE_HTTPD_AUTH_MD5) := y
+
+ifeq ($(needcrypt-y),y)
+	LIBRARIES := -lcrypt $(filter-out -lcrypt,$(LIBRARIES))
+endif
+
+$(NETWORKING_DIR)$(NETWORKING_AR): $(patsubst %,$(NETWORKING_DIR)%, $(NETWORKING-y))
+	$(do_ar)
+
+$(NETWORKING_DIR)%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/arping.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/arping.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/arping.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,469 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * arping.c - Ping hosts by ARP requests/replies
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * Author:	Alexey Kuznetsov <kuznet at ms2.inr.ac.ru>
+ * Busybox port: Nick Fedchik <nick at fedchik.org.ua>
+ */
+
+#include <sys/ioctl.h>
+#include <signal.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/ether.h>
+#include <netpacket/packet.h>
+
+#include "busybox.h"
+
+static struct in_addr src;
+static struct in_addr dst;
+static struct sockaddr_ll me;
+static struct sockaddr_ll he;
+static struct timeval last;
+
+enum cfg_e {
+	dad = 1,
+	unsolicited = 2,
+	advert = 4,
+	quiet = 8,
+	quit_on_reply = 16,
+	broadcast_only = 32,
+	unicasting = 64
+};
+static int cfg;
+
+static int s;
+static int count = -1;
+static int timeout;
+static int sent;
+static int brd_sent;
+static int received;
+static int brd_recv;
+static int req_recv;
+
+
+#define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \
+			   ((tv1).tv_usec-(tv2).tv_usec)/1000 )
+#if 0
+static void set_signal(int signo, void (*handler) (void))
+{
+	struct sigaction sa;
+
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_handler = (void (*)(int)) handler;
+	sa.sa_flags = SA_RESTART;
+	sigaction(signo, &sa, NULL);
+}
+#endif
+
+static int send_pack(int sock, struct in_addr *src_addr,
+					 struct in_addr *dst_addr, struct sockaddr_ll *ME,
+					 struct sockaddr_ll *HE)
+{
+	int err;
+	struct timeval now;
+	RESERVE_CONFIG_UBUFFER(buf, 256);
+	struct arphdr *ah = (struct arphdr *) buf;
+	unsigned char *p = (unsigned char *) (ah + 1);
+
+	ah->ar_hrd = htons(ME->sll_hatype);
+	ah->ar_hrd = htons(ARPHRD_ETHER);
+	ah->ar_pro = htons(ETH_P_IP);
+	ah->ar_hln = ME->sll_halen;
+	ah->ar_pln = 4;
+	ah->ar_op = cfg&advert ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST);
+
+	memcpy(p, &ME->sll_addr, ah->ar_hln);
+	p += ME->sll_halen;
+
+	memcpy(p, src_addr, 4);
+	p += 4;
+
+	if (cfg&advert)
+		memcpy(p, &ME->sll_addr, ah->ar_hln);
+	else
+		memcpy(p, &HE->sll_addr, ah->ar_hln);
+	p += ah->ar_hln;
+
+	memcpy(p, dst_addr, 4);
+	p += 4;
+
+	gettimeofday(&now, NULL);
+	err = sendto(sock, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE));
+	if (err == p - buf) {
+		last = now;
+		sent++;
+		if (!(cfg&unicasting))
+			brd_sent++;
+	}
+	RELEASE_CONFIG_BUFFER(buf);
+	return err;
+}
+
+static void finish(void)
+{
+	if (!(cfg&quiet)) {
+		printf("Sent %d probes (%d broadcast(s))\n"
+			"Received %d repl%s",
+			sent, brd_sent,
+			received, (received > 1) ? "ies" : "y");
+		if (brd_recv || req_recv) {
+			printf(" (");
+			if (req_recv)
+				printf("%d request(s)", req_recv);
+			if (brd_recv)
+				printf("%s%d broadcast(s)", req_recv ? ", " : "", brd_recv);
+			putchar(')');
+		}
+		putchar('\n');
+		fflush(stdout);
+	}
+	if (cfg&dad)
+		exit(!!received);
+	if (cfg&unsolicited)
+		exit(0);
+	exit(!received);
+}
+
+static void catcher(void)
+{
+	struct timeval tv;
+	static struct timeval start;
+
+	gettimeofday(&tv, NULL);
+
+	if (start.tv_sec == 0)
+		start = tv;
+
+	if (count-- == 0
+		|| (timeout && MS_TDIFF(tv, start) > timeout * 1000 + 500))
+		finish();
+
+	if (last.tv_sec == 0 || MS_TDIFF(tv, last) > 500) {
+		send_pack(s, &src, &dst, &me, &he);
+		if (count == 0 && cfg&unsolicited)
+			finish();
+	}
+	alarm(1);
+}
+
+static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
+{
+	struct arphdr *ah = (struct arphdr *) buf;
+	unsigned char *p = (unsigned char *) (ah + 1);
+	struct in_addr src_ip, dst_ip;
+
+	/* Filter out wild packets */
+	if (FROM->sll_pkttype != PACKET_HOST &&
+		FROM->sll_pkttype != PACKET_BROADCAST &&
+		FROM->sll_pkttype != PACKET_MULTICAST)
+		return 0;
+
+	/* Only these types are recognised */
+	if (ah->ar_op != htons(ARPOP_REQUEST) && ah->ar_op != htons(ARPOP_REPLY))
+		return 0;
+
+	/* ARPHRD check and this darned FDDI hack here :-( */
+	if (ah->ar_hrd != htons(FROM->sll_hatype) &&
+		(FROM->sll_hatype != ARPHRD_FDDI
+		 || ah->ar_hrd != htons(ARPHRD_ETHER)))
+		return 0;
+
+	/* Protocol must be IP. */
+	if (ah->ar_pro != htons(ETH_P_IP))
+		return 0;
+	if (ah->ar_pln != 4)
+		return 0;
+	if (ah->ar_hln != me.sll_halen)
+		return 0;
+	if (len < sizeof(*ah) + 2 * (4 + ah->ar_hln))
+		return 0;
+	memcpy(&src_ip, p + ah->ar_hln, 4);
+	memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4);
+	if (!(cfg&dad)) {
+		if (src_ip.s_addr != dst.s_addr)
+			return 0;
+		if (src.s_addr != dst_ip.s_addr)
+			return 0;
+		if (memcmp(p + ah->ar_hln + 4, &me.sll_addr, ah->ar_hln))
+			return 0;
+	} else {
+		/* DAD packet was:
+		   src_ip = 0 (or some src)
+		   src_hw = ME
+		   dst_ip = tested address
+		   dst_hw = <unspec>
+
+		   We fail, if receive request/reply with:
+		   src_ip = tested_address
+		   src_hw != ME
+		   if src_ip in request was not zero, check
+		   also that it matches to dst_ip, otherwise
+		   dst_ip/dst_hw do not matter.
+		 */
+		if (src_ip.s_addr != dst.s_addr)
+			return 0;
+		if (memcmp(p, &me.sll_addr, me.sll_halen) == 0)
+			return 0;
+		if (src.s_addr && src.s_addr != dst_ip.s_addr)
+			return 0;
+	}
+	if (!(cfg&quiet)) {
+		int s_printed = 0;
+		struct timeval tv;
+
+		gettimeofday(&tv, NULL);
+
+		printf("%s %s from %s [%s]",
+			FROM->sll_pkttype == PACKET_HOST ? "Unicast" : "Broadcast",
+			ah->ar_op == htons(ARPOP_REPLY) ? "reply" : "request",
+			inet_ntoa(src_ip),
+			ether_ntoa((struct ether_addr *) p));
+		if (dst_ip.s_addr != src.s_addr) {
+			printf("for %s ", inet_ntoa(dst_ip));
+			s_printed = 1;
+		}
+		if (memcmp(p + ah->ar_hln + 4, me.sll_addr, ah->ar_hln)) {
+			if (!s_printed)
+				printf("for ");
+			printf("[%s]",
+				   ether_ntoa((struct ether_addr *) p + ah->ar_hln + 4));
+		}
+
+		if (last.tv_sec) {
+			long usecs = (tv.tv_sec - last.tv_sec) * 1000000 +
+				tv.tv_usec - last.tv_usec;
+			long msecs = (usecs + 500) / 1000;
+
+			usecs -= msecs * 1000 - 500;
+			printf(" %ld.%03ldms\n", msecs, usecs);
+		} else {
+			printf(" UNSOLICITED?\n");
+		}
+		fflush(stdout);
+	}
+	received++;
+	if (FROM->sll_pkttype != PACKET_HOST)
+		brd_recv++;
+	if (ah->ar_op == htons(ARPOP_REQUEST))
+		req_recv++;
+	if (cfg&quit_on_reply)
+		finish();
+	if (!(cfg&broadcast_only)) {
+		memcpy(he.sll_addr, p, me.sll_halen);
+		cfg |= unicasting;
+	}
+	return 1;
+}
+
+int arping_main(int argc, char **argv)
+{
+	char *device = "eth0";
+	int ifindex;
+	char *source = NULL;
+	char *target;
+
+	s = socket(PF_PACKET, SOCK_DGRAM, 0);
+	ifindex = errno;
+
+	// Drop suid root privileges
+	xsetuid(getuid());
+
+	{
+		unsigned long opt;
+		char *_count, *_timeout, *_device;
+
+		/* Dad also sets quit_on_reply.
+		 * Advert also sets unsolicited.
+		 */
+		bb_opt_complementally = "Df:AU";
+		opt = bb_getopt_ulflags(argc, argv, "DUAqfbc:w:i:s:",
+						&_count, &_timeout, &_device);
+		cfg |= opt & 63; /* set respective flags */
+		if (opt & 64) /* count */
+			count = atoi(_count);
+		if (opt & 128) /* timeout */
+			timeout = atoi(_timeout);
+		if (opt & 256) { /* interface */
+			if (strlen(_device) > IF_NAMESIZE) {
+				bb_error_msg_and_die("Interface name `%s' must be less than %d",
+								_device, IF_NAMESIZE);
+			}
+			device = _device;
+		}
+		if (opt & 512) /* source */
+			source = optarg;
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc != 1)
+		bb_show_usage();
+
+	target = *argv;
+
+
+	if (s < 0) {
+		bb_default_error_retval = ifindex;
+		bb_perror_msg_and_die("socket");
+	}
+	bb_default_error_retval = 2;
+
+	{
+		struct ifreq ifr;
+
+		memset(&ifr, 0, sizeof(ifr));
+		strncpy(ifr.ifr_name, device, IFNAMSIZ - 1);
+		if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
+			bb_error_msg_and_die("Interface %s not found", device);
+		}
+		ifindex = ifr.ifr_ifindex;
+
+		if (ioctl(s, SIOCGIFFLAGS, (char *) &ifr)) {
+			bb_error_msg_and_die("SIOCGIFFLAGS");
+		}
+		if (!(ifr.ifr_flags & IFF_UP)) {
+			bb_error_msg_and_die("Interface %s is down", device);
+		}
+		if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) {
+			bb_error_msg("Interface %s is not ARPable", device);
+			exit(cfg&dad ? 0 : 2);
+		}
+	}
+
+	if (!inet_aton(target, &dst)) {
+		struct hostent *hp;
+
+		hp = gethostbyname2(target, AF_INET);
+		if (!hp) {
+			bb_error_msg_and_die("invalid or unknown target %s", target);
+		}
+		memcpy(&dst, hp->h_addr, 4);
+	}
+
+	if (source && !inet_aton(source, &src)) {
+		bb_error_msg_and_die("invalid source address %s", source);
+	}
+
+	if (!(cfg&dad) && cfg&unsolicited && src.s_addr == 0)
+		src = dst;
+
+	if (!(cfg&dad) || src.s_addr) {
+		struct sockaddr_in saddr;
+		int probe_fd = socket(AF_INET, SOCK_DGRAM, 0); /* maybe use bb_xsocket? */
+
+		if (probe_fd < 0) {
+			bb_error_msg_and_die("socket");
+		}
+		if (device) {
+			if (setsockopt
+				(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device,
+				 strlen(device) + 1) == -1)
+				bb_error_msg("WARNING: interface %s is ignored", device);
+		}
+		memset(&saddr, 0, sizeof(saddr));
+		saddr.sin_family = AF_INET;
+		if (src.s_addr) {
+			saddr.sin_addr = src;
+			if (bind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)) == -1) {
+				bb_error_msg_and_die("bind");
+			}
+		} else if (!(cfg&dad)) {
+			int on = 1;
+			socklen_t alen = sizeof(saddr);
+
+			saddr.sin_port = htons(1025);
+			saddr.sin_addr = dst;
+
+			if (setsockopt
+				(probe_fd, SOL_SOCKET, SO_DONTROUTE, (char *) &on,
+				 sizeof(on)) == -1)
+				bb_perror_msg("WARNING: setsockopt(SO_DONTROUTE)");
+			if (connect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr))
+				== -1) {
+				bb_error_msg_and_die("connect");
+			}
+			if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) ==
+				-1) {
+				bb_error_msg_and_die("getsockname");
+			}
+			src = saddr.sin_addr;
+		}
+		close(probe_fd);
+	};
+
+	me.sll_family = AF_PACKET;
+	me.sll_ifindex = ifindex;
+	me.sll_protocol = htons(ETH_P_ARP);
+	if (bind(s, (struct sockaddr *) &me, sizeof(me)) == -1) {
+		bb_error_msg_and_die("bind");
+	}
+
+	{
+		socklen_t alen = sizeof(me);
+
+		if (getsockname(s, (struct sockaddr *) &me, &alen) == -1) {
+			bb_error_msg_and_die("getsockname");
+		}
+	}
+	if (me.sll_halen == 0) {
+		bb_error_msg("Interface \"%s\" is not ARPable (no ll address)", device);
+		exit(cfg&dad ? 0 : 2);
+	}
+	he = me;
+	memset(he.sll_addr, -1, he.sll_halen);
+
+	if (!(cfg&quiet)) {
+		printf("ARPING to %s from %s via %s\n",
+			inet_ntoa(dst), inet_ntoa(src),
+			device ? device : "unknown");
+	}
+
+	if (!src.s_addr && !(cfg&dad)) {
+		bb_error_msg_and_die("no src address in the non-DAD mode");
+	}
+
+	{
+		struct sigaction sa;
+
+		memset(&sa, 0, sizeof(sa));
+		sa.sa_flags = SA_RESTART;
+
+		sa.sa_handler = (void (*)(int)) finish;
+		sigaction(SIGINT, &sa, NULL);
+
+		sa.sa_handler = (void (*)(int)) catcher;
+		sigaction(SIGALRM, &sa, NULL);
+	}
+
+	catcher();
+
+	while (1) {
+		sigset_t sset, osset;
+		RESERVE_CONFIG_UBUFFER(packet, 4096);
+		struct sockaddr_ll from;
+		socklen_t alen = sizeof(from);
+		int cc;
+
+		if ((cc = recvfrom(s, packet, 4096, 0,
+						   (struct sockaddr *) &from, &alen)) < 0) {
+			perror("recvfrom");
+			continue;
+		}
+		sigemptyset(&sset);
+		sigaddset(&sset, SIGALRM);
+		sigaddset(&sset, SIGINT);
+		sigprocmask(SIG_BLOCK, &sset, &osset);
+		recv_pack(packet, cc, &from);
+		sigprocmask(SIG_SETMASK, &osset, NULL);
+		RELEASE_CONFIG_BUFFER(packet);
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/dnsd.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/dnsd.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/dnsd.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,459 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini DNS server implementation for busybox
+ *
+ * Copyright (C) 2005 Roberto A. Foglietta (me at roberto.foglietta.name)
+ * Copyright (C) 2005 Odd Arild Olsen (oao at fibula dot no)
+ * Copyright (C) 2003 Paul Sheer
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * Odd Arild Olsen started out with the sheerdns [1] of Paul Sheer and rewrote
+ * it into a shape which I believe is both easier to understand and maintain.
+ * I also reused the input buffer for output and removed services he did not
+ * need.  [1] http://threading.2038bug.com/sheerdns/
+ *
+ * Some bugfix and minor changes was applied by Roberto A. Foglietta who made
+ * the first porting of oao' scdns to busybox also.
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <ctype.h>
+#include "busybox.h"
+
+static char *fileconf = "/etc/dnsd.conf";
+#define LOCK_FILE       "/var/run/dnsd.lock"
+#define LOG_FILE        "/var/log/dnsd.log"
+
+enum {
+	MAX_HOST_LEN = 16,      // longest host name allowed is 15
+	IP_STRING_LEN = 18,     // .xxx.xxx.xxx.xxx\0
+
+//must be strlen('.in-addr.arpa') larger than IP_STRING_LEN
+	MAX_NAME_LEN = (IP_STRING_LEN + 13),
+
+/* Cannot get bigger packets than 512 per RFC1035
+   In practice this can be set considerably smaller:
+   Length of response packet is  header (12B) + 2*type(4B) + 2*class(4B) +
+   ttl(4B) + rlen(2B) + r (MAX_NAME_LEN =21B) +
+   2*querystring (2 MAX_NAME_LEN= 42B), all together 90 Byte
+*/
+	MAX_PACK_LEN = 512 + 1,
+
+	DEFAULT_TTL = 30,       // increase this when not testing?
+
+	REQ_A = 1,
+	REQ_PTR = 12
+};
+
+struct dns_repl {		// resource record, add 0 or 1 to accepted dns_msg in resp
+	uint16_t rlen;
+	uint8_t *r;		// resource
+	uint16_t flags;
+};
+
+struct dns_head {		// the message from client and first part of response mag
+	uint16_t id;
+	uint16_t flags;
+	uint16_t nquer;		// accepts 0
+	uint16_t nansw;		// 1 in response
+	uint16_t nauth;		// 0
+	uint16_t nadd;		// 0
+};
+struct dns_prop {
+	uint16_t type;
+	uint16_t class;
+};
+struct dns_entry {		// element of known name, ip address and reversed ip address
+	struct dns_entry *next;
+	char ip[IP_STRING_LEN];		// dotted decimal IP
+	char rip[IP_STRING_LEN];	// length decimal reversed IP
+	char name[MAX_HOST_LEN];
+};
+
+static struct dns_entry *dnsentry = NULL;
+static int daemonmode = 0;
+static uint32_t ttl = DEFAULT_TTL;
+
+/*
+ * Convert host name from C-string to dns length/string.
+ */
+static void convname(char *a, uint8_t *q)
+{
+	int i = (q[0] == '.') ? 0 : 1;
+	for(; i < MAX_HOST_LEN-1 && *q; i++, q++)
+		a[i] = tolower(*q);
+	a[0] = i - 1;
+	a[i] = 0;
+}
+
+/*
+ * Insert length of substrings instead of dots
+ */
+static void undot(uint8_t * rip)
+{
+	int i = 0, s = 0;
+	while(rip[i]) i++;
+	for(--i; i >= 0; i--) {
+		if(rip[i] == '.') {
+			rip[i] = s;
+			s = 0;
+		} else s++;
+	}
+}
+
+/*
+ * Append message to log file
+ */
+static void log_message(char *filename, char *message)
+{
+	FILE *logfile;
+	if (!daemonmode)
+		return;
+	logfile = fopen(filename, "a");
+	if (!logfile)
+		return;
+	fprintf(logfile, "%s\n", message);
+	fclose(logfile);
+}
+
+/*
+ * Read one line of hostname/IP from file
+ * Returns 0 for each valid entry read, -1 at EOF
+ * Assumes all host names are lower case only
+ * Hostnames with more than one label is not handled correctly.
+ * Presently the dot is copied into name without
+ * converting to a length/string substring for that label.
+ */
+
+static int getfileentry(FILE * fp, struct dns_entry *s, int verb)
+{
+	unsigned int a,b,c,d;
+	char *r, *name;
+
+restart:
+	if(!(r = bb_get_line_from_file(fp)))
+		return -1;
+	while(*r == ' ' || *r == '\t') {
+		r++;
+		if(!*r || *r == '#' || *r == '\n')
+			goto restart; /* skipping empty/blank and commented lines  */
+	}
+	name = r;
+	while(*r != ' ' && *r != '\t')
+		r++;
+	*r++ = 0;
+	if(sscanf(r,"%u.%u.%u.%u",&a,&b,&c,&d) != 4)
+			goto restart; /* skipping wrong lines */
+
+	sprintf(s->ip,"%u.%u.%u.%u",a,b,c,d);
+	sprintf(s->rip,".%u.%u.%u.%u",d,c,b,a);
+	undot((uint8_t*)s->rip);
+	convname(s->name,(uint8_t*)name);
+
+	if(verb)
+		fprintf(stderr,"\tname:%s, ip:%s\n",&(s->name[1]),s->ip);
+
+	return 0; /* warningkiller */
+}
+
+/*
+ * Read hostname/IP records from file
+ */
+static void dnsentryinit(int verb)
+{
+	FILE *fp;
+	struct dns_entry *m, *prev;
+	prev = dnsentry = NULL;
+
+	fp = bb_xfopen(fileconf, "r");
+
+	while (1) {
+		m = xmalloc(sizeof(struct dns_entry));
+
+		m->next = NULL;
+		if (getfileentry(fp, m, verb))
+			break;
+
+		if (prev == NULL)
+			dnsentry = m;
+		else
+			prev->next = m;
+		prev = m;
+	}
+	fclose(fp);
+}
+
+
+/*
+ * Set up UDP socket
+ */
+static int listen_socket(char *iface_addr, int listen_port)
+{
+	struct sockaddr_in a;
+	char msg[100];
+	int s;
+	int yes = 1;
+	s = bb_xsocket(PF_INET, SOCK_DGRAM, 0);
+#ifdef SO_REUSEADDR
+	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0)
+		bb_perror_msg_and_die("setsockopt() failed");
+#endif
+	memset(&a, 0, sizeof(a));
+	a.sin_port = htons(listen_port);
+	a.sin_family = AF_INET;
+	if (!inet_aton(iface_addr, &a.sin_addr))
+		bb_perror_msg_and_die("bad iface address");
+	bb_xbind(s, (struct sockaddr *)&a, sizeof(a));
+	listen(s, 50); /* bb_xlisten? */
+	sprintf(msg, "accepting UDP packets on addr:port %s:%d\n",
+		iface_addr, (int)listen_port);
+	log_message(LOG_FILE, msg);
+	return s;
+}
+
+/*
+ * Look query up in dns records and return answer if found
+ * qs is the query string, first byte the string length
+ */
+static int table_lookup(uint16_t type, uint8_t * as, uint8_t * qs)
+{
+	int i;
+	struct dns_entry *d=dnsentry;
+
+	do {
+#ifdef DEBUG
+		char *p,*q;
+		q = (char *)&(qs[1]);
+		p = &(d->name[1]);
+		fprintf(stderr, "\ntest: %d <%s> <%s> %d", strlen(p), p, q, strlen(q));
+#endif
+		if (type == REQ_A) { /* search by host name */
+			for(i = 1; i <= (int)(d->name[0]); i++)
+				if(tolower(qs[i]) != d->name[i])
+					continue;
+#ifdef DEBUG
+			fprintf(stderr, " OK");
+#endif
+			strcpy((char *)as, d->ip);
+#ifdef DEBUG
+			fprintf(stderr, " %s ", as);
+#endif
+					return 0;
+				}
+		else if (type == REQ_PTR) { /* search by IP-address */
+			if (!strncmp((char*)&d->rip[1], (char*)&qs[1], strlen(d->rip)-1)) {
+				strcpy((char *)as, d->name);
+				return 0;
+			}
+		}
+	} while ((d = d->next) != NULL);
+	return -1;
+}
+
+
+/*
+ * Decode message and generate answer
+ */
+#define eret(s) do { fprintf (stderr, "%s\n", s); return -1; } while (0)
+static int process_packet(uint8_t * buf)
+{
+	struct dns_head *head;
+	struct dns_prop *qprop;
+	struct dns_repl outr;
+	void *next, *from, *answb;
+
+	uint8_t answstr[MAX_NAME_LEN + 1];
+	int lookup_result, type, len, packet_len;
+	uint16_t flags;
+
+	answstr[0] = '\0';
+
+	head = (struct dns_head *)buf;
+	if (head->nquer == 0)
+		eret("no queries");
+
+	if ((head->flags & 0x8000))
+		eret("ignoring response packet");
+
+	from = (void *)&head[1];	//  start of query string
+	next = answb = from + strlen((char *)&head[1]) + 1 + sizeof(struct dns_prop);   // where to append answer block
+
+	outr.rlen = 0;			// may change later
+	outr.r = NULL;
+	outr.flags = 0;
+
+	qprop = (struct dns_prop *)(answb - 4);
+	type = ntohs(qprop->type);
+
+	// only let REQ_A and REQ_PTR pass
+	if (!(type == REQ_A || type == REQ_PTR)) {
+		goto empty_packet;	/* we can't handle the query type */
+	}
+
+	if (ntohs(qprop->class) != 1 /* class INET */ ) {
+		outr.flags = 4; /* not supported */
+		goto empty_packet;
+	}
+	/* we only support standard queries */
+
+	if ((ntohs(head->flags) & 0x7800) != 0)
+		goto empty_packet;
+
+	// We have a standard query
+
+	log_message(LOG_FILE, (char *)head);
+	lookup_result = table_lookup(type, answstr, (uint8_t*)(&head[1]));
+	if (lookup_result != 0) {
+		outr.flags = 3 | 0x0400;	//name do not exist and auth
+		goto empty_packet;
+	}
+	if (type == REQ_A) {    // return an address
+		struct in_addr a;
+		if (!inet_aton((char*)answstr, &a)) {//dotted dec to long conv
+			outr.flags = 1; /* Frmt err */
+			goto empty_packet;
+		}
+		memcpy(answstr, &a.s_addr, 4);	// save before a disappears
+		outr.rlen = 4;			// uint32_t IP
+	}
+	else
+		outr.rlen = strlen((char *)answstr) + 1;	// a host name
+	outr.r = answstr;			// 32 bit ip or a host name
+	outr.flags |= 0x0400;			/* authority-bit */
+	// we have an answer
+	head->nansw = htons(1);
+
+	// copy query block to answer block
+	len = answb - from;
+	memcpy(answb, from, len);
+	next += len;
+
+	// and append answer rr
+	*(uint32_t *) next = htonl(ttl);
+	next += 4;
+	*(uint16_t *) next = htons(outr.rlen);
+	next += 2;
+	memcpy(next, (void *)answstr, outr.rlen);
+	next += outr.rlen;
+
+      empty_packet:
+
+	flags = ntohs(head->flags);
+	// clear rcode and RA, set responsebit and our new flags
+	flags |= (outr.flags & 0xff80) | 0x8000;
+	head->flags = htons(flags);
+	head->nauth = head->nadd = htons(0);
+	head->nquer = htons(1);
+
+	packet_len = next - (void *)buf;
+	return packet_len;
+}
+
+/*
+ * Exit on signal
+ */
+static void interrupt(int x)
+{
+	unlink(LOCK_FILE);
+	write(2, "interrupt exiting\n", 18);
+	exit(2);
+}
+
+#define is_daemon()  (flags&16)
+#define is_verbose() (flags&32)
+//#define DEBUG 1
+
+int dnsd_main(int argc, char **argv)
+{
+	int udps;
+	uint16_t port = 53;
+	uint8_t buf[MAX_PACK_LEN];
+	unsigned long flags = 0;
+	char *listen_interface = "0.0.0.0";
+	char *sttl=NULL, *sport=NULL;
+
+	if(argc > 1)
+		flags = bb_getopt_ulflags(argc, argv, "i:c:t:p:dv", &listen_interface, &fileconf, &sttl, &sport);
+	if(sttl)
+		if(!(ttl = atol(sttl)))
+			bb_show_usage();
+	if(sport)
+		if(!(port = atol(sport)))
+			bb_show_usage();
+
+	if(is_verbose()) {
+		fprintf(stderr,"listen_interface: %s\n", listen_interface);
+		fprintf(stderr,"ttl: %d, port: %d\n", ttl, port);
+		fprintf(stderr,"fileconf: %s\n", fileconf);
+	}
+
+	if(is_daemon())
+#ifdef BB_NOMMU
+		/* reexec for vfork() do continue parent */
+		vfork_daemon_rexec(1, 0, argc, argv, "-d");
+#else
+		bb_xdaemon(1, 0);
+#endif
+
+	dnsentryinit(is_verbose());
+
+	signal(SIGINT, interrupt);
+	signal(SIGPIPE, SIG_IGN);
+	signal(SIGHUP, SIG_IGN);
+#ifdef SIGTSTP
+	signal(SIGTSTP, SIG_IGN);
+#endif
+#ifdef SIGURG
+	signal(SIGURG, SIG_IGN);
+#endif
+
+	udps = listen_socket(listen_interface, port);
+	if (udps < 0)
+		exit(1);
+
+	while (1) {
+		fd_set fdset;
+		int r;
+
+		FD_ZERO(&fdset);
+		FD_SET(udps, &fdset);
+		// Block until a message arrives
+		if((r = select(udps + 1, &fdset, NULL, NULL, NULL)) < 0)
+			bb_perror_msg_and_die("select error");
+		else
+		if(r == 0)
+			bb_perror_msg_and_die("select spurious return");
+
+		/* Can this test ever be false? */
+		if (FD_ISSET(udps, &fdset)) {
+			struct sockaddr_in from;
+			int fromlen = sizeof(from);
+			r = recvfrom(udps, buf, sizeof(buf), 0,
+				     (struct sockaddr *)&from,
+				     (void *)&fromlen);
+			if(is_verbose())
+				fprintf(stderr, "\n--- Got UDP  ");
+			log_message(LOG_FILE, "\n--- Got UDP  ");
+
+			if (r < 12 || r > 512) {
+				bb_error_msg("invalid packet size");
+				continue;
+			}
+			if (r > 0) {
+				r = process_packet(buf);
+				if (r > 0)
+					sendto(udps, buf,
+					       r, 0, (struct sockaddr *)&from,
+					       fromlen);
+			}
+		}		// end if
+	}			// end while
+	return 0;
+}
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ether-wake.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ether-wake.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ether-wake.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,300 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * ether-wake.c - Send a magic packet to wake up sleeping machines.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * Author:      Donald Becker, http://www.scyld.com/"; http://www.scyld.com/wakeonlan.html
+ * Busybox port: Christian Volkmann <haveaniceday at online.de>
+ *               Used version of ether-wake.c: v1.09 11/12/2003 Donald Becker, http://www.scyld.com/";
+ */
+
+/* full usage according Donald Becker
+ * usage: ether-wake [-i <ifname>] [-p aa:bb:cc:dd[:ee:ff]] 00:11:22:33:44:55\n"
+ *
+ *	This program generates and transmits a Wake-On-LAN (WOL)\n"
+ *	\"Magic Packet\", used for restarting machines that have been\n"
+ *	soft-powered-down (ACPI D3-warm state).\n"
+ *	It currently generates the standard AMD Magic Packet format, with\n"
+ *	an optional password appended.\n"
+ *
+ *	The single required parameter is the Ethernet MAC (station) address\n"
+ *	of the machine to wake or a host ID with known NSS 'ethers' entry.\n"
+ *	The MAC address may be found with the 'arp' program while the target\n"
+ *	machine is awake.\n"
+ *
+ *	Options:\n"
+ *		-b	Send wake-up packet to the broadcast address.\n"
+ *		-D	Increase the debug level.\n"
+ *		-i ifname	Use interface IFNAME instead of the default 'eth0'.\n"
+ *		-p <pw>		Append the four or six byte password PW to the packet.\n"
+ *					A password is only required for a few adapter types.\n"
+ *					The password may be specified in ethernet hex format\n"
+ *					or dotted decimal (Internet address)\n"
+ *		-p 00:22:44:66:88:aa\n"
+ *		-p 192.168.1.1\n";
+ *
+ *
+ *	This program generates and transmits a Wake-On-LAN (WOL) "Magic Packet",
+ *	used for restarting machines that have been soft-powered-down
+ *	(ACPI D3-warm state).  It currently generates the standard AMD Magic Packet
+ *	format, with an optional password appended.
+ *
+ *	This software may be used and distributed according to the terms
+ *	of the GNU Public License, incorporated herein by reference.
+ *	Contact the author for use under other terms.
+ *
+ *	This source file was originally part of the network tricks package, and
+ *	is now distributed to support the Scyld Beowulf system.
+ *	Copyright 1999-2003 Donald Becker and Scyld Computing Corporation.
+ *
+ *	The author may be reached as becker at scyld, or C/O
+ *	 Scyld Computing Corporation
+ *	 914 Bay Ridge Road, Suite 220
+ *	 Annapolis MD 21403
+ *
+ *   Notes:
+ *   On some systems dropping root capability allows the process to be
+ *   dumped, traced or debugged.
+ *   If someone traces this program, they get control of a raw socket.
+ *   Linux handles this safely, but beware when porting this program.
+ *
+ *   An alternative to needing 'root' is using a UDP broadcast socket, however
+ *   doing so only works with adapters configured for unicast+broadcast Rx
+ *   filter.  That configuration consumes more power.
+*/
+
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <features.h>
+#include <netpacket/packet.h>
+#include <net/ethernet.h>
+#include <netdb.h>
+#include <netinet/ether.h>
+
+#ifdef __linux__
+#include <linux/if.h>
+#endif
+
+#include "busybox.h"
+
+/* Note: PF_INET, SOCK_DGRAM, IPPROTO_UDP would allow SIOCGIFHWADDR to
+ * work as non-root, but we need SOCK_PACKET to specify the Ethernet
+ * destination address.
+ */
+#ifdef PF_PACKET
+# define whereto_t sockaddr_ll
+# define make_socket() bb_xsocket(PF_PACKET, SOCK_RAW, 0)
+#else
+# define whereto_t sockaddr
+# define make_socket() bb_xsocket(AF_INET, SOCK_PACKET, SOCK_PACKET)
+#endif
+
+#ifdef DEBUG
+# define bb_debug_msg(fmt, args...) fprintf(stderr, fmt, ## args)
+void bb_debug_dump_packet(unsigned char *outpack, int pktsize)
+{
+	int i;
+	printf("packet dump:\n");
+	for (i = 0; i < pktsize; ++i) {
+		printf("%2.2x ", outpack[i]);
+		if (i % 20 == 19) printf("\n");
+	}
+	printf("\n\n");
+}
+#else
+# define bb_debug_msg(fmt, args...)
+# define bb_debug_dump_packet(outpack, pktsize)
+#endif
+
+static inline void get_dest_addr(const char *arg, struct ether_addr *eaddr);
+static inline int get_fill(unsigned char *pkt, struct ether_addr *eaddr, int broadcast);
+static inline int get_wol_pw(const char *ethoptarg, unsigned char *wol_passwd);
+
+int etherwake_main(int argc, char *argv[])
+{
+	char *ifname = "eth0", *pass = NULL;
+	unsigned long flags;
+	unsigned char wol_passwd[6];
+	int wol_passwd_sz = 0;
+
+	int s;						/* Raw socket */
+	int pktsize;
+	unsigned char outpack[1000];
+
+	struct ether_addr eaddr;
+	struct whereto_t whereto;	/* who to wake up */
+
+	/* handle misc user options */
+	flags = bb_getopt_ulflags(argc, argv, "bi:p:", &ifname, &pass);
+	if (optind == argc)
+		bb_show_usage();
+	if (pass)
+		wol_passwd_sz = get_wol_pw(pass, wol_passwd);
+
+	/* create the raw socket */
+	s = make_socket();
+
+	/* now that we have a raw socket we can drop root */
+	xsetuid(getuid());
+
+	/* look up the dest mac address */
+	get_dest_addr(argv[optind], &eaddr);
+
+	/* fill out the header of the packet */
+	pktsize = get_fill(outpack, &eaddr, flags /*& 1 [OPT_BROADCAST]*/);
+
+	bb_debug_dump_packet(outpack, pktsize);
+
+	/* Fill in the source address, if possible. */
+#ifdef __linux__
+	{
+		struct ifreq if_hwaddr;
+
+		strcpy(if_hwaddr.ifr_name, ifname);
+		if (ioctl(s, SIOCGIFHWADDR, &if_hwaddr) < 0)
+			bb_perror_msg_and_die("SIOCGIFHWADDR on %s failed", ifname);
+
+		memcpy(outpack+6, if_hwaddr.ifr_hwaddr.sa_data, 6);
+
+# ifdef DEBUG
+		{
+			unsigned char *hwaddr = if_hwaddr.ifr_hwaddr.sa_data;
+			printf("The hardware address (SIOCGIFHWADDR) of %s is type %d  "
+				   "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n\n", ifname,
+				   if_hwaddr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
+				   hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
+		}
+# endif
+	}
+#endif /* __linux__ */
+
+	bb_debug_dump_packet(outpack, pktsize);
+
+	/* append the password if specified */
+	if (wol_passwd_sz > 0) {
+		memcpy(outpack+pktsize, wol_passwd, wol_passwd_sz);
+		pktsize += wol_passwd_sz;
+	}
+
+	bb_debug_dump_packet(outpack, pktsize);
+
+	/* This is necessary for broadcasts to work */
+	if (flags /*& 1 [OPT_BROADCAST]*/) {
+		int one = 1;
+		if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (void *)&one, sizeof(one)) < 0)
+			bb_perror_msg("SO_BROADCAST");
+	}
+
+#if defined(PF_PACKET)
+	{
+		struct ifreq ifr;
+		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+		if (ioctl(s, SIOCGIFINDEX, &ifr) == -1)
+			bb_perror_msg_and_die("SIOCGIFINDEX");
+		memset(&whereto, 0, sizeof(whereto));
+		whereto.sll_family = AF_PACKET;
+		whereto.sll_ifindex = ifr.ifr_ifindex;
+		/* The manual page incorrectly claims the address must be filled.
+		   We do so because the code may change to match the docs. */
+		whereto.sll_halen = ETH_ALEN;
+		memcpy(whereto.sll_addr, outpack, ETH_ALEN);
+	}
+#else
+	whereto.sa_family = 0;
+	strcpy(whereto.sa_data, ifname);
+#endif
+
+	if (sendto(s, outpack, pktsize, 0, (struct sockaddr *)&whereto, sizeof(whereto)) < 0)
+		bb_perror_msg(bb_msg_write_error);
+
+	close(s);
+
+	return EXIT_SUCCESS;
+}
+
+/* Convert the host ID string to a MAC address.
+ * The string may be a:
+ *    Host name
+ *    IP address string
+ *    MAC address string
+*/
+static inline void get_dest_addr(const char *hostid, struct ether_addr *eaddr)
+{
+	struct ether_addr *eap;
+
+	eap = ether_aton(hostid);
+	if (eap) {
+		*eaddr = *eap;
+		bb_debug_msg("The target station address is %s\n\n", ether_ntoa(eaddr));
+#if !defined(__UCLIBC__)
+	} else if (ether_hostton(hostid, eaddr) == 0) {
+		bb_debug_msg("Station address for hostname %s is %s\n\n", hostid, ether_ntoa(eaddr));
+#else
+# warning Need to implement ether_hostton() for uClibc
+#endif
+	} else
+		bb_show_usage();
+}
+
+static inline int get_fill(unsigned char *pkt, struct ether_addr *eaddr, int broadcast)
+{
+	int offset, i;
+	unsigned char *station_addr = eaddr->ether_addr_octet;
+
+	if (broadcast)
+		memset(pkt+0, 0xff, 6);
+	else
+		memcpy(pkt, station_addr, 6);
+	memcpy(pkt+6, station_addr, 6);
+	pkt[12] = 0x08;				/* Or 0x0806 for ARP, 0x8035 for RARP */
+	pkt[13] = 0x42;
+	offset = 14;
+
+	memset(pkt+offset, 0xff, 6);
+	offset += 6;
+
+	for (i = 0; i < 16; ++i) {
+		memcpy(pkt+offset, station_addr, 6);
+		offset += 6;
+	}
+
+	return offset;
+}
+
+static inline int get_wol_pw(const char *ethoptarg, unsigned char *wol_passwd)
+{
+	int passwd[6];
+	int byte_cnt, i;
+
+	/* handle MAC format */
+	byte_cnt = sscanf(ethoptarg, "%2x:%2x:%2x:%2x:%2x:%2x",
+	                  &passwd[0], &passwd[1], &passwd[2],
+	                  &passwd[3], &passwd[4], &passwd[5]);
+	/* handle IP format */
+	if (byte_cnt < 4)
+		byte_cnt = sscanf(ethoptarg, "%d.%d.%d.%d",
+		                  &passwd[0], &passwd[1], &passwd[2], &passwd[3]);
+	if (byte_cnt < 4) {
+		bb_error_msg("Unable to read the Wake-On-LAN pass");
+		return 0;
+	}
+
+	for (i = 0; i < byte_cnt; ++i)
+		wol_passwd[i] = passwd[i];
+
+	bb_debug_msg("password: %2.2x %2.2x %2.2x %2.2x (%d)\n\n",
+	             wol_passwd[0], wol_passwd[1], wol_passwd[2], wol_passwd[3],
+	             byte_cnt);
+
+	return byte_cnt;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/fakeidentd.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/fakeidentd.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/fakeidentd.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,397 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * A fake identd server
+ *
+ * Adapted to busybox by Thomas Lundquist <thomasez at zelow.no>
+ * Original Author: Tomi Ollila <too at iki.fi>
+ *                  http://www.guru-group.fi/~too/sw/
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/syslog.h>
+
+#include <pwd.h>
+
+#include <sys/syslog.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <sys/uio.h>
+
+
+#define IDENT_PORT  113
+#define MAXCONNS    20
+#define MAXIDLETIME 45
+
+static const char ident_substr[] = " : USERID : UNIX : ";
+enum { ident_substr_len = sizeof(ident_substr) - 1 };
+#define PIDFILE "/var/run/identd.pid"
+
+/*
+ * We have to track the 'first connection socket' so that we
+ * don't go around closing file descriptors for non-clients.
+ *
+ * descriptor setup normally
+ *  0 = server socket
+ *  1 = syslog fd (hopefully -- otherwise this won't work)
+ *  2 = connection socket after detached from tty. standard error before that
+ *  3 - 2 + MAXCONNS = rest connection sockets
+ *
+ * To try to make sure that syslog fd is what is "requested", the that fd
+ * is closed before openlog() call.  It can only severely fail if fd 0
+ * is initially closed.
+ */
+#define FCS 2
+
+/*
+ * FD of the connection is always the index of the connection structure
+ * in `conns' array + FCS
+ */
+static struct {
+	char buf[20];
+	int len;
+	time_t lasttime;
+} conns[MAXCONNS];
+
+/* When using global variables, bind those at least to a structure. */
+static struct {
+	const char *identuser;
+	fd_set readfds;
+	int conncnt;
+} G;
+
+/*
+ * Prototypes
+ */
+static void reply(int s, char *buf);
+static void replyError(int s, char *buf);
+
+static const char *nobodystr = "nobody"; /* this needs to be declared like this */
+static char *bind_ip_address = "0.0.0.0";
+
+static inline void movefd(int from, int to)
+{
+	if (from != to) {
+		dup2(from, to);
+		close(from);
+	}
+}
+
+static void inetbind(void)
+{
+	int s, port;
+	struct sockaddr_in addr;
+	int len = sizeof(addr);
+	int one = 1;
+	struct servent *se;
+
+	if ((se = getservbyname("identd", "tcp")) == NULL)
+		port = IDENT_PORT;
+	else
+		port = se->s_port;
+
+	s = bb_xsocket(AF_INET, SOCK_STREAM, 0);
+
+	setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sin_addr.s_addr = inet_addr(bind_ip_address);
+	addr.sin_family = AF_INET;
+	addr.sin_port = htons(port);
+
+	bb_xbind(s, (struct sockaddr *)&addr, len);
+	bb_xlisten(s, 5);
+
+	movefd(s, 0);
+}
+
+static void handlexitsigs(int signum)
+{
+	if (unlink(PIDFILE) < 0)
+		close(open(PIDFILE, O_WRONLY|O_CREAT|O_TRUNC, 0644));
+	exit(0);
+}
+
+/* May succeed. If not, won't care. */
+static inline void writepid(uid_t nobody, uid_t nogrp)
+{
+	char buf[24];
+	int fd = open(PIDFILE, O_WRONLY|O_CREAT|O_TRUNC, 0664);
+
+	if (fd < 0)
+		return;
+
+	snprintf(buf, 23, "%d\n", getpid());
+	write(fd, buf, strlen(buf));
+	fchown(fd, nobody, nogrp);
+	close(fd);
+
+	/* should this handle ILL, ... (see signal(7)) */
+	signal(SIGTERM, handlexitsigs);
+	signal(SIGINT,  handlexitsigs);
+	signal(SIGQUIT, handlexitsigs);
+}
+
+/* return 0 as parent, 1 as child */
+static int godaemon(void)
+{
+	uid_t nobody, nogrp;
+	struct passwd *pw;
+
+	switch (fork()) {
+	case -1:
+		bb_perror_msg_and_die("Could not fork");
+
+	case 0:
+		pw = getpwnam(nobodystr);
+		if (pw == NULL)
+			bb_error_msg_and_die("Cannot find uid/gid of user '%s'", nobodystr);
+		nobody = pw->pw_uid;
+		nogrp = pw->pw_gid;
+		writepid(nobody, nogrp);
+
+		close(0);
+		inetbind();
+		xsetgid(nogrp);
+		xsetuid(nobody);
+		close(1);
+		close(2);
+
+		signal(SIGHUP, SIG_IGN);
+		signal(SIGPIPE, SIG_IGN); /* connection closed when writing (raises ???) */
+
+		setsid();
+
+		openlog(bb_applet_name, 0, LOG_DAEMON);
+		return 1;
+	}
+
+	return 0;
+}
+
+static void deleteConn(int s)
+{
+	int i = s - FCS;
+
+	close(s);
+
+	G.conncnt--;
+
+	/*
+	 * Most of the time there is 0 connections. Most often that there
+	 * is connections, there is just one connection. When this one connection
+	 * closes, i == G.conncnt = 0 -> no copying.
+	 * When there is more than one connection, the oldest connections closes
+	 * earlier on average. When this happens, the code below starts copying
+	 * the connection structure w/ highest index to the place which which is
+	 * just deleted. This means that the connection structures are no longer
+	 * in chronological order. I'd quess this means that when there is more
+	 * than 1 connection, on average every other connection structure needs
+	 * to be copied over the time all these connections are deleted.
+	 */
+	if (i != G.conncnt) {
+		memcpy(&conns[i], &conns[G.conncnt], sizeof(conns[0]));
+		movefd(G.conncnt + FCS, s);
+	}
+
+	FD_CLR(G.conncnt + FCS, &G.readfds);
+}
+
+static int closeOldest(void)
+{
+	time_t min = conns[0].lasttime;
+	int idx = 0;
+	int i;
+
+	for (i = 1; i < MAXCONNS; i++)
+		if (conns[i].lasttime < min)
+			idx = i;
+
+	replyError(idx + FCS, "X-SERVER-TOO-BUSY");
+	close(idx + FCS);
+
+	return idx;
+}
+
+static int checkInput(char *buf, int len, int l)
+{
+	int i;
+	for (i = len; i < len + l; ++i)
+		if (buf[i] == '\n')
+			return 1;
+	return 0;
+}
+
+int fakeidentd_main(int argc, char **argv)
+{
+	memset(conns, 0, sizeof(conns));
+	memset(&G, 0, sizeof(G));
+	FD_ZERO(&G.readfds);
+	FD_SET(0, &G.readfds);
+
+	/* handle -b <ip> parameter */
+	bb_getopt_ulflags(argc, argv, "b:", &bind_ip_address);
+	/* handle optional REPLY STRING */
+	if (optind < argc)
+		G.identuser = argv[optind];
+	else
+		G.identuser = nobodystr;
+
+	/* daemonize and have the parent return */
+	if (godaemon() == 0)
+		return 0;
+
+	/* main loop where we process all events and never exit */
+	while (1) {
+	fd_set rfds = G.readfds;
+	struct timeval tv = { 15, 0 };
+	int i;
+	int tim = time(NULL);
+
+	select(G.conncnt + FCS, &rfds, NULL, NULL, G.conncnt? &tv: NULL);
+
+	for (i = G.conncnt - 1; i >= 0; i--) {
+		int s = i + FCS;
+
+		if (FD_ISSET(s, &rfds)) {
+			char *buf = conns[i].buf;
+			unsigned int len = conns[i].len;
+			unsigned int l;
+
+			if ((l = read(s, buf + len, sizeof(conns[0].buf) - len)) > 0) {
+				if (checkInput(buf, len, l)) {
+					reply(s, buf);
+					goto deleteconn;
+				} else if (len + l >= sizeof(conns[0].buf)) {
+					replyError(s, "X-INVALID-REQUEST");
+					goto deleteconn;
+				} else {
+					conns[i].len += l;
+				}
+			} else {
+				goto deleteconn;
+			}
+
+			conns[i].lasttime = tim;
+			continue;
+
+deleteconn:
+			deleteConn(s);
+		} else {
+			/* implement as time_after() in linux kernel sources ... */
+			if (conns[i].lasttime + MAXIDLETIME <= tim) {
+				replyError(s, "X-TIMEOUT");
+				deleteConn(s);
+			}
+		}
+	}
+
+	if (FD_ISSET(0, &rfds)) {
+		int s = accept(0, NULL, 0);
+
+		if (s < 0) {
+			if (errno != EINTR) /* EINTR */
+				syslog(LOG_ERR, "accept: %s", strerror(errno));
+		} else {
+			if (G.conncnt == MAXCONNS)
+				i = closeOldest();
+			else
+				i = G.conncnt++;
+
+			movefd(s, i + FCS); /* move if not already there */
+			FD_SET(i + FCS, &G.readfds);
+
+			conns[i].len = 0;
+			conns[i].lasttime = time(NULL);
+		}
+	}
+	} /* end of while(1) */
+
+	return 0;
+}
+
+static int parseAddrs(char *ptr, char **myaddr, char **heraddr);
+static void reply(int s, char *buf)
+{
+	char *myaddr, *heraddr;
+
+	myaddr = heraddr = NULL;
+
+	if (parseAddrs(buf, &myaddr, &heraddr))
+		replyError(s, "X-INVALID-REQUEST");
+	else {
+		struct iovec iv[6];
+		iv[0].iov_base = myaddr;               iv[0].iov_len = strlen(myaddr);
+		iv[1].iov_base = ", ";                 iv[1].iov_len = 2;
+		iv[2].iov_base = heraddr;              iv[2].iov_len = strlen(heraddr);
+		iv[3].iov_base = (void *)ident_substr; iv[3].iov_len = ident_substr_len;
+		iv[4].iov_base = (void *)G.identuser;  iv[4].iov_len = strlen(G.identuser);
+		iv[5].iov_base = "\r\n";               iv[5].iov_len = 2;
+		writev(s, iv, 6);
+	}
+}
+
+static void replyError(int s, char *buf)
+{
+	struct iovec iv[3];
+	iv[0].iov_base = "0, 0 : ERROR : ";   iv[0].iov_len = 15;
+	iv[1].iov_base = buf;                 iv[1].iov_len = strlen(buf);
+	iv[2].iov_base = "\r\n";              iv[2].iov_len = 2;
+	writev(s, iv, 3);
+}
+
+static int chmatch(char c, char *chars)
+{
+	for (; *chars; chars++)
+		if (c == *chars)
+			return 1;
+	return 0;
+}
+
+static int skipchars(char **p, char *chars)
+{
+	while (chmatch(**p, chars))
+		(*p)++;
+	if (**p == '\r' || **p == '\n')
+		return 0;
+	return 1;
+}
+
+static int parseAddrs(char *ptr, char **myaddr, char **heraddr)
+{
+	/* parse <port-on-server> , <port-on-client> */
+
+	if (!skipchars(&ptr, " \t"))
+		return -1;
+
+	*myaddr = ptr;
+
+	if (!skipchars(&ptr, "1234567890"))
+		return -1;
+
+	if (!chmatch(*ptr, " \t,"))
+		return -1;
+
+	*ptr++ = '\0';
+
+	if (!skipchars(&ptr, " \t,") )
+		return -1;
+
+	*heraddr = ptr;
+
+	skipchars(&ptr, "1234567890");
+
+	if (!chmatch(*ptr, " \n\r"))
+		return -1;
+
+	*ptr = '\0';
+
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ftpgetput.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ftpgetput.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ftpgetput.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,350 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * ftpget
+ *
+ * Mini implementation of FTP to retrieve a remote file.
+ *
+ * Copyright (C) 2002 Jeff Angielski, The PTR Group <jeff at theptrgroup.com>
+ * Copyright (C) 2002 Glenn McGrath <bug1 at iinet.net.au>
+ *
+ * Based on wget.c by Chip Rosenthal Covad Communications
+ * <chip at laserlink.net>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <sys/ioctl.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/socket.h>
+
+#include "busybox.h"
+
+typedef struct ftp_host_info_s {
+	char *user;
+	char *password;
+	struct sockaddr_in *s_in;
+} ftp_host_info_t;
+
+static char verbose_flag = 0;
+static char do_continue = 0;
+
+static int ftpcmd(const char *s1, const char *s2, FILE *stream, char *buf)
+{
+	if (verbose_flag) {
+		bb_error_msg("cmd %s%s", s1, s2);
+	}
+
+	if (s1) {
+		if (s2) {
+			fprintf(stream, "%s%s\r\n", s1, s2);
+		} else {
+			fprintf(stream, "%s\r\n", s1);
+		}
+	}
+	do {
+		char *buf_ptr;
+
+		if (fgets(buf, 510, stream) == NULL) {
+			bb_perror_msg_and_die("fgets()");
+		}
+		buf_ptr = strstr(buf, "\r\n");
+		if (buf_ptr) {
+			*buf_ptr = '\0';
+		}
+	} while (! isdigit(buf[0]) || buf[3] != ' ');
+
+	return atoi(buf);
+}
+
+static int xconnect_ftpdata(ftp_host_info_t *server, const char *buf)
+{
+	char *buf_ptr;
+	unsigned short port_num;
+
+	buf_ptr = strrchr(buf, ',');
+	*buf_ptr = '\0';
+	port_num = atoi(buf_ptr + 1);
+
+	buf_ptr = strrchr(buf, ',');
+	*buf_ptr = '\0';
+	port_num += atoi(buf_ptr + 1) * 256;
+
+	server->s_in->sin_port=htons(port_num);
+	return(xconnect(server->s_in));
+}
+
+static FILE *ftp_login(ftp_host_info_t *server)
+{
+	FILE *control_stream;
+	char buf[512];
+
+	/* Connect to the command socket */
+	control_stream = fdopen(xconnect(server->s_in), "r+");
+	if (control_stream == NULL) {
+		bb_perror_msg_and_die("Couldnt open control stream");
+	}
+
+	if (ftpcmd(NULL, NULL, control_stream, buf) != 220) {
+		bb_error_msg_and_die("%s", buf + 4);
+	}
+
+	/*  Login to the server */
+	switch (ftpcmd("USER ", server->user, control_stream, buf)) {
+	case 230:
+		break;
+	case 331:
+		if (ftpcmd("PASS ", server->password, control_stream, buf) != 230) {
+			bb_error_msg_and_die("PASS error: %s", buf + 4);
+		}
+		break;
+	default:
+		bb_error_msg_and_die("USER error: %s", buf + 4);
+	}
+
+	ftpcmd("TYPE I", NULL, control_stream, buf);
+
+	return(control_stream);
+}
+
+#if !ENABLE_FTPGET
+#define ftp_receive 0
+#else
+static int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
+		const char *local_path, char *server_path)
+{
+	char buf[512];
+	off_t filesize = 0;
+	int fd_data;
+	int fd_local = -1;
+	off_t beg_range = 0;
+
+	/* Connect to the data socket */
+	if (ftpcmd("PASV", NULL, control_stream, buf) != 227) {
+		bb_error_msg_and_die("PASV error: %s", buf + 4);
+	}
+	fd_data = xconnect_ftpdata(server, buf);
+
+	if (ftpcmd("SIZE ", server_path, control_stream, buf) == 213) {
+		unsigned long value=filesize;
+		if (safe_strtoul(buf + 4, &value))
+			bb_error_msg_and_die("SIZE error: %s", buf + 4);
+		filesize = value;
+	} else {
+		filesize = -1;
+		do_continue = 0;
+	}
+
+	if ((local_path[0] == '-') && (local_path[1] == '\0')) {
+		fd_local = STDOUT_FILENO;
+		do_continue = 0;
+	}
+
+	if (do_continue) {
+		struct stat sbuf;
+		if (lstat(local_path, &sbuf) < 0) {
+			bb_perror_msg_and_die("fstat()");
+		}
+		if (sbuf.st_size > 0) {
+			beg_range = sbuf.st_size;
+		} else {
+			do_continue = 0;
+		}
+	}
+
+	if (do_continue) {
+		sprintf(buf, "REST %ld", (long)beg_range);
+		if (ftpcmd(buf, NULL, control_stream, buf) != 350) {
+			do_continue = 0;
+		} else {
+			filesize -= beg_range;
+		}
+	}
+
+	if (ftpcmd("RETR ", server_path, control_stream, buf) > 150) {
+		bb_error_msg_and_die("RETR error: %s", buf + 4);
+	}
+
+	/* only make a local file if we know that one exists on the remote server */
+	if (fd_local == -1) {
+		if (do_continue) {
+			fd_local = bb_xopen(local_path, O_APPEND | O_WRONLY);
+		} else {
+			fd_local = bb_xopen(local_path, O_CREAT | O_TRUNC | O_WRONLY);
+		}
+	}
+
+	/* Copy the file */
+	if (filesize != -1) {
+		if (-1 == bb_copyfd_size(fd_data, fd_local, filesize))
+			exit(EXIT_FAILURE);
+	} else {
+		if (-1 == bb_copyfd_eof(fd_data, fd_local))
+			exit(EXIT_FAILURE);
+	}
+
+	/* close it all down */
+	close(fd_data);
+	if (ftpcmd(NULL, NULL, control_stream, buf) != 226) {
+		bb_error_msg_and_die("ftp error: %s", buf + 4);
+	}
+	ftpcmd("QUIT", NULL, control_stream, buf);
+
+	return(EXIT_SUCCESS);
+}
+#endif
+
+#if !ENABLE_FTPPUT
+#define ftp_send 0
+#else
+static int ftp_send(ftp_host_info_t *server, FILE *control_stream,
+		const char *server_path, char *local_path)
+{
+	struct stat sbuf;
+	char buf[512];
+	int fd_data;
+	int fd_local;
+	int response;
+
+	/*  Connect to the data socket */
+	if (ftpcmd("PASV", NULL, control_stream, buf) != 227) {
+		bb_error_msg_and_die("PASV error: %s", buf + 4);
+	}
+	fd_data = xconnect_ftpdata(server, buf);
+
+	/* get the local file */
+	if ((local_path[0] == '-') && (local_path[1] == '\0')) {
+		fd_local = STDIN_FILENO;
+	} else {
+		fd_local = bb_xopen(local_path, O_RDONLY);
+		fstat(fd_local, &sbuf);
+
+		sprintf(buf, "ALLO %lu", (unsigned long)sbuf.st_size);
+		response = ftpcmd(buf, NULL, control_stream, buf);
+		switch (response) {
+		case 200:
+		case 202:
+			break;
+		default:
+			close(fd_local);
+			bb_error_msg_and_die("ALLO error: %s", buf + 4);
+			break;
+		}
+	}
+	response = ftpcmd("STOR ", server_path, control_stream, buf);
+	switch (response) {
+	case 125:
+	case 150:
+		break;
+	default:
+		close(fd_local);
+		bb_error_msg_and_die("STOR error: %s", buf + 4);
+	}
+
+	/* transfer the file  */
+	if (bb_copyfd_eof(fd_local, fd_data) == -1) {
+		exit(EXIT_FAILURE);
+	}
+
+	/* close it all down */
+	close(fd_data);
+	if (ftpcmd(NULL, NULL, control_stream, buf) != 226) {
+		bb_error_msg_and_die("error: %s", buf + 4);
+	}
+	ftpcmd("QUIT", NULL, control_stream, buf);
+
+	return(EXIT_SUCCESS);
+}
+#endif
+
+#define FTPGETPUT_OPT_CONTINUE	1
+#define FTPGETPUT_OPT_VERBOSE	2
+#define FTPGETPUT_OPT_USER	4
+#define FTPGETPUT_OPT_PASSWORD	8
+#define FTPGETPUT_OPT_PORT	16
+
+#if ENABLE_FEATURE_FTPGETPUT_LONG_OPTIONS
+static const struct option ftpgetput_long_options[] = {
+	{"continue", 1, NULL, 'c'},
+	{"verbose", 0, NULL, 'v'},
+	{"username", 1, NULL, 'u'},
+	{"password", 1, NULL, 'p'},
+	{"port", 1, NULL, 'P'},
+	{0, 0, 0, 0}
+};
+#else
+#define ftpgetput_long_options 0
+#endif
+
+int ftpgetput_main(int argc, char **argv)
+{
+	/* content-length of the file */
+	unsigned long opt;
+	char *port = "ftp";
+
+	/* socket to ftp server */
+	FILE *control_stream;
+	struct sockaddr_in s_in;
+
+	/* continue a prev transfer (-c) */
+	ftp_host_info_t *server;
+
+	int (*ftp_action)(ftp_host_info_t *, FILE *, const char *, char *) = NULL;
+
+	/* Check to see if the command is ftpget or ftput */
+	if (ENABLE_FTPPUT && (!ENABLE_FTPGET || bb_applet_name[3] == 'p')) {
+		ftp_action = ftp_send;
+	}
+	if (ENABLE_FTPGET && (!ENABLE_FTPPUT || bb_applet_name[3] == 'g')) {
+		ftp_action = ftp_receive;
+	}
+
+	/* Set default values */
+	server = xmalloc(sizeof(ftp_host_info_t));
+	server->user = "anonymous";
+	server->password = "busybox@";
+	verbose_flag = 0;
+
+	/*
+	 * Decipher the command line
+	 */
+	if (ENABLE_FEATURE_FTPGETPUT_LONG_OPTIONS)
+		bb_applet_long_options = ftpgetput_long_options;
+
+	opt = bb_getopt_ulflags(argc, argv, "cvu:p:P:", &server->user, &server->password, &port);
+
+	/* Process the non-option command line arguments */
+	if (argc - optind != 3) {
+		bb_show_usage();
+	}
+
+	if (opt & FTPGETPUT_OPT_CONTINUE) {
+		do_continue = 1;
+	}
+	if (opt & FTPGETPUT_OPT_VERBOSE) {
+		verbose_flag = 1;
+	}
+
+	/* We want to do exactly _one_ DNS lookup, since some
+	 * sites (i.e. ftp.us.debian.org) use round-robin DNS
+	 * and we want to connect to only one IP... */
+	server->s_in = &s_in;
+	bb_lookup_host(&s_in, argv[optind]);
+	s_in.sin_port = bb_lookup_port(port, "tcp", 21);
+	if (verbose_flag) {
+		printf("Connecting to %s[%s]:%d\n",
+				argv[optind], inet_ntoa(s_in.sin_addr), ntohs(s_in.sin_port));
+	}
+
+	/*  Connect/Setup/Configure the FTP session */
+	control_stream = ftp_login(server);
+
+	return(ftp_action(server, control_stream, argv[optind + 1], argv[optind + 2]));
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/hostname.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/hostname.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/hostname.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,130 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * $Id: hostname.c,v 1.36 2003/07/14 21:21:01 andersen Exp $
+ * Mini hostname implementation for busybox
+ *
+ * Copyright (C) 1999 by Randolph Chung <tausq at debian.org>
+ *
+ * adjusted by Erik Andersen <andersen at codepoet.org> to remove
+ * use of long options and GNU getopt.  Improved the usage info.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <errno.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include "busybox.h"
+
+extern char *optarg; /* in unistd.h */
+extern int  optind, opterr, optopt; /* in unistd.h */
+
+static void do_sethostname(char *s, int isfile)
+{
+	FILE *f;
+	char buf[255];
+
+	if (!s)
+		return;
+	if (!isfile) {
+		if (sethostname(s, strlen(s)) < 0) {
+			if (errno == EPERM)
+				bb_error_msg_and_die("you must be root to change the hostname");
+			else
+				bb_perror_msg_and_die("sethostname");
+		}
+	} else {
+		f = bb_xfopen(s, "r");
+		while (fgets(buf, 255, f) != NULL) {
+			if (buf[0] =='#') {
+				continue;
+			}
+			chomp(buf);
+			do_sethostname(buf, 0);
+		}
+#ifdef CONFIG_FEATURE_CLEAN_UP
+		fclose(f);
+#endif
+	}
+}
+
+int hostname_main(int argc, char **argv)
+{
+	int opt;
+	int type = 0;
+	struct hostent *hp;
+	char *filename = NULL;
+	char buf[255];
+	char *p = NULL;
+
+	if (argc < 1)
+		bb_show_usage();
+
+	while ((opt = getopt(argc, argv, "dfisF:")) > 0) {
+		switch (opt) {
+		case 'd':
+		case 'f':
+		case 'i':
+		case 's':
+			type = opt;
+			break;
+		case 'F':
+			filename = optarg;
+			break;
+		default:
+			bb_show_usage();
+		}
+	}
+
+	/* Output in desired format */
+	if (type != 0) {
+		gethostname(buf, 255);
+		hp = xgethostbyname(buf);
+		p = strchr(hp->h_name, '.');
+		if (type == 'f') {
+			puts(hp->h_name);
+		} else if (type == 's') {
+			if (p != NULL) {
+				*p = 0;
+			}
+			puts(hp->h_name);
+		} else if (type == 'd') {
+			if (p) puts(p + 1);
+		} else if (type == 'i') {
+			while (hp->h_addr_list[0]) {
+				printf("%s ", inet_ntoa(*(struct in_addr *) (*hp->h_addr_list++)));
+			}
+			printf("\n");
+		}
+	}
+	/* Set the hostname */
+	else if (filename != NULL) {
+		do_sethostname(filename, 1);
+	} else if (optind < argc) {
+		do_sethostname(argv[optind], 0);
+	}
+	/* Or if all else fails,
+	 * just print the current hostname */
+	 else {
+		gethostname(buf, 255);
+		puts(buf);
+	}
+	return(0);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/httpd.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/httpd.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/httpd.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2036 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * httpd implementation for busybox
+ *
+ * Copyright (C) 2002,2003 Glenn Engel <glenne at engel.org>
+ * Copyright (C) 2003-2006 Vladimir Oleynik <dzo at simtreas.ru>
+ *
+ * simplify patch stolen from libbb without using strdup
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ *****************************************************************************
+ *
+ * Typical usage:
+ *   for non root user
+ * httpd -p 8080 -h $HOME/public_html
+ *   or for daemon start from rc script with uid=0:
+ * httpd -u www
+ * This is equivalent if www user have uid=80 to
+ * httpd -p 80 -u 80 -h /www -c /etc/httpd.conf -r "Web Server Authentication"
+ *
+ *
+ * When a url contains "cgi-bin" it is assumed to be a cgi script.  The
+ * server changes directory to the location of the script and executes it
+ * after setting QUERY_STRING and other environment variables.
+ *
+ * The server can also be invoked as a url arg decoder and html text encoder
+ * as follows:
+ *  foo=`httpd -d $foo`           # decode "Hello%20World" as "Hello World"
+ *  bar=`httpd -e "<Hello World>"`  # encode as "&#60Hello&#32World&#62"
+ * Note that url encoding for arguments is not the same as html encoding for
+ * presentation.  -d decodes a url-encoded argument while -e encodes in html
+ * for page display.
+ *
+ * httpd.conf has the following format:
+ *
+ * A:172.20.         # Allow address from 172.20.0.0/16
+ * A:10.0.0.0/25     # Allow any address from 10.0.0.0-10.0.0.127
+ * A:10.0.0.0/255.255.255.128  # Allow any address that previous set
+ * A:127.0.0.1       # Allow local loopback connections
+ * D:*               # Deny from other IP connections
+ * /cgi-bin:foo:bar  # Require user foo, pwd bar on urls starting with /cgi-bin/
+ * /adm:admin:setup  # Require user admin, pwd setup on urls starting with /adm/
+ * /adm:toor:PaSsWd  # or user toor, pwd PaSsWd on urls starting with /adm/
+ * .au:audio/basic   # additional mime type for audio.au files
+ * *.php:/path/php   # running cgi.php scripts through an interpreter
+ *
+ * A/D may be as a/d or allow/deny - first char case insensitive
+ * Deny IP rules take precedence over allow rules.
+ *
+ *
+ * The Deny/Allow IP logic:
+ *
+ *  - Default is to allow all.  No addresses are denied unless
+ *         denied with a D: rule.
+ *  - Order of Deny/Allow rules is significant
+ *  - Deny rules take precedence over allow rules.
+ *  - If a deny all rule (D:*) is used it acts as a catch-all for unmatched
+ *       addresses.
+ *  - Specification of Allow all (A:*) is a no-op
+ *
+ * Example:
+ *   1. Allow only specified addresses
+ *     A:172.20          # Allow any address that begins with 172.20.
+ *     A:10.10.          # Allow any address that begins with 10.10.
+ *     A:127.0.0.1       # Allow local loopback connections
+ *     D:*               # Deny from other IP connections
+ *
+ *   2. Only deny specified addresses
+ *     D:1.2.3.        # deny from 1.2.3.0 - 1.2.3.255
+ *     D:2.3.4.        # deny from 2.3.4.0 - 2.3.4.255
+ *     A:*             # (optional line added for clarity)
+ *
+ * If a sub directory contains a config file it is parsed and merged with
+ * any existing settings as if it was appended to the original configuration.
+ *
+ * subdir paths are relative to the containing subdir and thus cannot
+ * affect the parent rules.
+ *
+ * Note that since the sub dir is parsed in the forked thread servicing the
+ * subdir http request, any merge is discarded when the process exits.  As a
+ * result, the subdir settings only have a lifetime of a single request.
+ *
+ *
+ * If -c is not set, an attempt will be made to open the default
+ * root configuration file.  If -c is set and the file is not found, the
+ * server exits with an error.
+ *
+*/
+
+
+#include <stdio.h>
+#include <ctype.h>         /* for isspace           */
+#include <string.h>
+#include <stdlib.h>        /* for malloc            */
+#include <time.h>
+#include <unistd.h>        /* for close             */
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>    /* for connect and socket*/
+#include <netinet/in.h>    /* for sockaddr_in       */
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>         /* for open modes        */
+#include "busybox.h"
+
+
+static const char httpdVersion[] = "busybox httpd/1.35 6-Oct-2004";
+static const char default_path_httpd_conf[] = "/etc";
+static const char httpd_conf[] = "httpd.conf";
+static const char home[] = "./";
+
+#ifdef CONFIG_LFS
+# define cont_l_fmt "%lld"
+# define cont_l_type (long long)
+#else
+# define cont_l_fmt "%ld"
+# define cont_l_type (long)
+#endif
+
+#define TIMEOUT 60
+
+// Note: busybox xfuncs are not used because we want the server to keep running
+//       if something bad happens due to a malformed user request.
+//       As a result, all memory allocation after daemonize
+//       is checked rigorously
+
+//#define DEBUG 1
+
+#ifndef DEBUG
+# define DEBUG 0
+#endif
+
+#define MAX_MEMORY_BUFF 8192    /* IO buffer */
+
+typedef struct HT_ACCESS {
+	char *after_colon;
+	struct HT_ACCESS *next;
+	char before_colon[1];         /* really bigger, must last */
+} Htaccess;
+
+typedef struct HT_ACCESS_IP {
+	unsigned int ip;
+	unsigned int mask;
+	int allow_deny;
+	struct HT_ACCESS_IP *next;
+} Htaccess_IP;
+
+typedef struct
+{
+  char buf[MAX_MEMORY_BUFF];
+
+  USE_FEATURE_HTTPD_BASIC_AUTH(const char *realm;)
+  USE_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;)
+
+  const char *query;
+
+  USE_FEATURE_HTTPD_CGI(char *referer;)
+
+  const char *configFile;
+
+  unsigned int rmt_ip;
+#if defined(CONFIG_FEATURE_HTTPD_CGI) || DEBUG
+  char rmt_ip_str[16];     /* for set env REMOTE_ADDR */
+#endif
+  unsigned port;           /* server initial port and for
+			      set env REMOTE_PORT */
+  union HTTPD_FOUND {
+	const char *found_mime_type;
+	const char *found_moved_temporarily;
+  } httpd_found;
+
+  off_t ContentLength;          /* -1 - unknown */
+  time_t last_mod;
+
+  Htaccess_IP *ip_a_d;          /* config allow/deny lines */
+  int flg_deny_all;
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+  Htaccess *auth;               /* config user:password lines */
+#endif
+#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
+  Htaccess *mime_a;             /* config mime types */
+#endif
+
+#ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+  int accepted_socket;
+# define a_c_r config->accepted_socket
+# define a_c_w config->accepted_socket
+#else
+# define a_c_r 0
+# define a_c_w 1
+#endif
+  volatile int alarm_signaled;
+
+#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
+  Htaccess *script_i;           /* config script interpreters */
+#endif
+} HttpdConfig;
+
+static HttpdConfig *config;
+
+static const char request_GET[] = "GET";    /* size algorithmic optimize */
+
+static const char* const suffixTable [] = {
+/* Warning: shorted equivalent suffix in one line must be first */
+  ".htm.html", "text/html",
+  ".jpg.jpeg", "image/jpeg",
+  ".gif", "image/gif",
+  ".png", "image/png",
+  ".txt.h.c.cc.cpp", "text/plain",
+  ".css", "text/css",
+  ".wav", "audio/wav",
+  ".avi", "video/x-msvideo",
+  ".qt.mov", "video/quicktime",
+  ".mpe.mpeg", "video/mpeg",
+  ".mid.midi", "audio/midi",
+  ".mp3", "audio/mpeg",
+#if 0                        /* unpopular */
+  ".au", "audio/basic",
+  ".pac", "application/x-ns-proxy-autoconfig",
+  ".vrml.wrl", "model/vrml",
+#endif
+  0, "application/octet-stream" /* default */
+  };
+
+typedef enum
+{
+  HTTP_OK = 200,
+  HTTP_MOVED_TEMPORARILY = 302,
+  HTTP_BAD_REQUEST = 400,       /* malformed syntax */
+  HTTP_UNAUTHORIZED = 401, /* authentication needed, respond with auth hdr */
+  HTTP_NOT_FOUND = 404,
+  HTTP_FORBIDDEN = 403,
+  HTTP_REQUEST_TIMEOUT = 408,
+  HTTP_NOT_IMPLEMENTED = 501,   /* used for unrecognized requests */
+  HTTP_INTERNAL_SERVER_ERROR = 500,
+#if 0 /* future use */
+  HTTP_CONTINUE = 100,
+  HTTP_SWITCHING_PROTOCOLS = 101,
+  HTTP_CREATED = 201,
+  HTTP_ACCEPTED = 202,
+  HTTP_NON_AUTHORITATIVE_INFO = 203,
+  HTTP_NO_CONTENT = 204,
+  HTTP_MULTIPLE_CHOICES = 300,
+  HTTP_MOVED_PERMANENTLY = 301,
+  HTTP_NOT_MODIFIED = 304,
+  HTTP_PAYMENT_REQUIRED = 402,
+  HTTP_BAD_GATEWAY = 502,
+  HTTP_SERVICE_UNAVAILABLE = 503, /* overload, maintenance */
+  HTTP_RESPONSE_SETSIZE=0xffffffff
+#endif
+} HttpResponseNum;
+
+typedef struct
+{
+  HttpResponseNum type;
+  const char *name;
+  const char *info;
+} HttpEnumString;
+
+static const HttpEnumString httpResponseNames[] = {
+  { HTTP_OK, "OK", NULL },
+  { HTTP_MOVED_TEMPORARILY, "Found", "Directories must end with a slash." },
+  { HTTP_REQUEST_TIMEOUT, "Request Timeout",
+    "No request appeared within a reasonable time period." },
+  { HTTP_NOT_IMPLEMENTED, "Not Implemented",
+    "The requested method is not recognized by this server." },
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+  { HTTP_UNAUTHORIZED, "Unauthorized", "" },
+#endif
+  { HTTP_NOT_FOUND, "Not Found",
+    "The requested URL was not found on this server." },
+  { HTTP_BAD_REQUEST, "Bad Request", "Unsupported method." },
+  { HTTP_FORBIDDEN, "Forbidden", "" },
+  { HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
+    "Internal Server Error" },
+#if 0                               /* not implemented */
+  { HTTP_CREATED, "Created" },
+  { HTTP_ACCEPTED, "Accepted" },
+  { HTTP_NO_CONTENT, "No Content" },
+  { HTTP_MULTIPLE_CHOICES, "Multiple Choices" },
+  { HTTP_MOVED_PERMANENTLY, "Moved Permanently" },
+  { HTTP_NOT_MODIFIED, "Not Modified" },
+  { HTTP_BAD_GATEWAY, "Bad Gateway", "" },
+  { HTTP_SERVICE_UNAVAILABLE, "Service Unavailable", "" },
+#endif
+};
+
+
+static const char RFC1123FMT[] = "%a, %d %b %Y %H:%M:%S GMT";
+static const char Content_length[] = "Content-length:";
+
+
+static int
+scan_ip (const char **ep, unsigned int *ip, unsigned char endc)
+{
+  const char *p = *ep;
+  int auto_mask = 8;
+  int j;
+
+  *ip = 0;
+  for (j = 0; j < 4; j++) {
+	unsigned int octet;
+
+	if ((*p < '0' || *p > '9') && (*p != '/' || j == 0) && *p != 0)
+	  return -auto_mask;
+	octet = 0;
+	while (*p >= '0' && *p <= '9') {
+	  octet *= 10;
+	  octet += *p - '0';
+	  if (octet > 255)
+		return -auto_mask;
+	  p++;
+	}
+	if (*p == '.')
+	  p++;
+	if (*p != '/' && *p != 0)
+	  auto_mask += 8;
+	*ip = ((*ip) << 8) | octet;
+  }
+  if (*p != 0) {
+	if (*p != endc)
+		return -auto_mask;
+	p++;
+	if(*p == 0)
+		return -auto_mask;
+  }
+  *ep = p;
+  return auto_mask;
+}
+
+static int
+scan_ip_mask (const char *ipm, unsigned int *ip, unsigned int *mask)
+{
+  int i;
+  unsigned int msk;
+
+  i = scan_ip(&ipm, ip, '/');
+  if(i < 0)
+	return i;
+  if(*ipm) {
+	const char *p = ipm;
+
+	i = 0;
+	while (*p) {
+		if (*p < '0' || *p > '9') {
+			if (*p == '.') {
+				i = scan_ip (&ipm, mask, 0);
+				return i != 32;
+			}
+			return -1;
+		}
+		i *= 10;
+		i += *p - '0';
+		p++;
+	}
+  }
+  if (i > 32 || i < 0)
+	  return -1;
+  msk = 0x80000000;
+  *mask = 0;
+  while (i > 0) {
+	*mask |= msk;
+	msk >>= 1;
+	i--;
+  }
+  return 0;
+}
+
+#if defined(CONFIG_FEATURE_HTTPD_BASIC_AUTH) || defined(CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES)
+static void free_config_lines(Htaccess **pprev)
+{
+    Htaccess *prev = *pprev;
+
+    while( prev ) {
+	Htaccess *cur = prev;
+
+	prev = cur->next;
+	free(cur);
+    }
+    *pprev = NULL;
+}
+#endif
+
+/* flag */
+#define FIRST_PARSE          0
+#define SUBDIR_PARSE         1
+#define SIGNALED_PARSE       2
+#define FIND_FROM_HTTPD_ROOT 3
+/****************************************************************************
+ *
+ > $Function: parse_conf()
+ *
+ * $Description: parse configuration file into in-memory linked list.
+ *
+ * The first non-white character is examined to determine if the config line
+ * is one of the following:
+ *    .ext:mime/type   # new mime type not compiled into httpd
+ *    [adAD]:from      # ip address allow/deny, * for wildcard
+ *    /path:user:pass  # username/password
+ *
+ * Any previous IP rules are discarded.
+ * If the flag argument is not SUBDIR_PARSE then all /path and mime rules
+ * are also discarded.  That is, previous settings are retained if flag is
+ * SUBDIR_PARSE.
+ *
+ * $Parameters:
+ *      (const char *) path . . null for ip address checks, path for password
+ *                              checks.
+ *      (int) flag  . . . . . . the source of the parse request.
+ *
+ * $Return: (None)
+ *
+ ****************************************************************************/
+static void parse_conf(const char *path, int flag)
+{
+    FILE *f;
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+    Htaccess *prev, *cur;
+#elif CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
+    Htaccess *cur;
+#endif
+
+    const char *cf = config->configFile;
+    char buf[160];
+    char *p0 = NULL;
+    char *c, *p;
+
+    /* free previous ip setup if present */
+    Htaccess_IP *pip = config->ip_a_d;
+
+    while( pip ) {
+	Htaccess_IP *cur_ipl = pip;
+
+	pip = cur_ipl->next;
+	free(cur_ipl);
+    }
+    config->ip_a_d = NULL;
+
+    config->flg_deny_all = 0;
+
+#if defined(CONFIG_FEATURE_HTTPD_BASIC_AUTH) || defined(CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES) || defined(CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR)
+    /* retain previous auth and mime config only for subdir parse */
+    if(flag != SUBDIR_PARSE) {
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+	free_config_lines(&config->auth);
+#endif
+#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
+	free_config_lines(&config->mime_a);
+#endif
+#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
+	free_config_lines(&config->script_i);
+#endif
+    }
+#endif
+
+    if(flag == SUBDIR_PARSE || cf == NULL) {
+	cf = alloca(strlen(path) + sizeof(httpd_conf) + 2);
+	if(cf == NULL) {
+	    if(flag == FIRST_PARSE)
+		bb_error_msg_and_die(bb_msg_memory_exhausted);
+	    return;
+	}
+	sprintf((char *)cf, "%s/%s", path, httpd_conf);
+    }
+
+    while((f = fopen(cf, "r")) == NULL) {
+	if(flag == SUBDIR_PARSE || flag == FIND_FROM_HTTPD_ROOT) {
+	    /* config file not found, no changes to config */
+	    return;
+	}
+	if(config->configFile && flag == FIRST_PARSE) /* if -c option given */
+	    bb_perror_msg_and_die("%s", cf);
+	flag = FIND_FROM_HTTPD_ROOT;
+	cf = httpd_conf;
+    }
+
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+    prev = config->auth;
+#endif
+    /* This could stand some work */
+    while ( (p0 = fgets(buf, sizeof(buf), f)) != NULL) {
+	c = NULL;
+	for(p = p0; *p0 != 0 && *p0 != '#'; p0++) {
+		if(!isspace(*p0)) {
+		    *p++ = *p0;
+		    if(*p0 == ':' && c == NULL)
+			c = p;
+		}
+	}
+	*p = 0;
+
+	/* test for empty or strange line */
+	if (c == NULL || *c == 0)
+	    continue;
+	p0 = buf;
+	if(*p0 == 'd')
+	    *p0 = 'D';
+	if(*c == '*') {
+	    if(*p0 == 'D') {
+		/* memorize deny all */
+		config->flg_deny_all++;
+	    }
+	    /* skip default other "word:*" config lines */
+	    continue;
+	}
+
+	if(*p0 == 'a')
+	    *p0 = 'A';
+	else if(*p0 != 'D' && *p0 != 'A'
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+	   && *p0 != '/'
+#endif
+#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
+	   && *p0 != '.'
+#endif
+#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
+	   && *p0 != '*'
+#endif
+	  )
+	       continue;
+	if(*p0 == 'A' || *p0 == 'D') {
+		/* storing current config IP line */
+		pip = calloc(1, sizeof(Htaccess_IP));
+		if(pip) {
+		    if(scan_ip_mask (c, &(pip->ip), &(pip->mask))) {
+			/* syntax IP{/mask} error detected, protect all */
+			*p0 = 'D';
+			pip->mask = 0;
+		    }
+		    pip->allow_deny = *p0;
+		    if(*p0 == 'D') {
+			/* Deny:form_IP move top */
+			pip->next = config->ip_a_d;
+			config->ip_a_d = pip;
+		    } else {
+			/* add to bottom A:form_IP config line */
+			Htaccess_IP *prev_IP = config->ip_a_d;
+
+			if(prev_IP == NULL) {
+				config->ip_a_d = pip;
+			} else {
+				while(prev_IP->next)
+					prev_IP = prev_IP->next;
+				prev_IP->next = pip;
+			}
+		    }
+		}
+		continue;
+	}
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+	if(*p0 == '/') {
+	    /* make full path from httpd root / curent_path / config_line_path */
+	    cf = flag == SUBDIR_PARSE ? path : "";
+	    p0 = malloc(strlen(cf) + (c - buf) + 2 + strlen(c));
+	    if(p0 == NULL)
+		continue;
+	    c[-1] = 0;
+	    sprintf(p0, "/%s%s", cf, buf);
+
+	    /* another call bb_simplify_path */
+	    cf = p = p0;
+
+	    do {
+		    if (*p == '/') {
+			if (*cf == '/') {    /* skip duplicate (or initial) slash */
+			    continue;
+			} else if (*cf == '.') {
+			    if (cf[1] == '/' || cf[1] == 0) { /* remove extra '.' */
+				continue;
+			    } else if ((cf[1] == '.') && (cf[2] == '/' || cf[2] == 0)) {
+				++cf;
+				if (p > p0) {
+				    while (*--p != '/');    /* omit previous dir */
+				}
+				continue;
+			    }
+			}
+		    }
+		    *++p = *cf;
+	    } while (*++cf);
+
+	    if ((p == p0) || (*p != '/')) {      /* not a trailing slash */
+		++p;                             /* so keep last character */
+	    }
+	    *p = 0;
+	    sprintf(p0, "%s:%s", p0, c);
+	}
+#endif
+
+#if defined(CONFIG_FEATURE_HTTPD_BASIC_AUTH) || defined(CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES) || defined(CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR)
+	/* storing current config line */
+	cur = calloc(1, sizeof(Htaccess) + strlen(p0));
+	if(cur) {
+	    cf = strcpy(cur->before_colon, p0);
+	    c = strchr(cf, ':');
+	    *c++ = 0;
+	    cur->after_colon = c;
+#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
+	    if(*cf == '.') {
+		/* config .mime line move top for overwrite previous */
+		cur->next = config->mime_a;
+		config->mime_a = cur;
+		continue;
+	    }
+#endif
+#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
+	    if(*cf == '*' && cf[1] == '.') {
+		/* config script interpreter line move top for overwrite previous */
+		cur->next = config->script_i;
+		config->script_i = cur;
+		continue;
+	    }
+#endif
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+	    free(p0);
+	    if(prev == NULL) {
+		/* first line */
+		config->auth = prev = cur;
+	    } else {
+		/* sort path, if current lenght eq or bigger then move up */
+		Htaccess *prev_hti = config->auth;
+		size_t l = strlen(cf);
+		Htaccess *hti;
+
+		for(hti = prev_hti; hti; hti = hti->next) {
+		    if(l >= strlen(hti->before_colon)) {
+			/* insert before hti */
+			cur->next = hti;
+			if(prev_hti != hti) {
+			    prev_hti->next = cur;
+			} else {
+			    /* insert as top */
+			    config->auth = cur;
+			}
+			break;
+		    }
+		    if(prev_hti != hti)
+			    prev_hti = prev_hti->next;
+		}
+		if(!hti)  {       /* not inserted, add to bottom */
+		    prev->next = cur;
+		    prev = cur;
+		}
+	    }
+#endif
+	}
+#endif
+   }
+   fclose(f);
+}
+
+#ifdef CONFIG_FEATURE_HTTPD_ENCODE_URL_STR
+/****************************************************************************
+ *
+ > $Function: encodeString()
+ *
+ * $Description: Given a string, html encode special characters.
+ *   This is used for the -e command line option to provide an easy way
+ *   for scripts to encode result data without confusing browsers.  The
+ *   returned string pointer is memory allocated by malloc().
+ *
+ * $Parameters:
+ *      (const char *) string . . The first string to encode.
+ *
+ * $Return: (char *) . . . .. . . A pointer to the encoded string.
+ *
+ * $Errors: Returns a null string ("") if memory is not available.
+ *
+ ****************************************************************************/
+static char *encodeString(const char *string)
+{
+  /* take the simple route and encode everything */
+  /* could possibly scan once to get length.     */
+  int len = strlen(string);
+  char *out = malloc(len * 6 + 1);
+  char *p=out;
+  char ch;
+
+  if (!out) return "";
+  while ((ch = *string++)) {
+    // very simple check for what to encode
+    if (isalnum(ch)) *p++ = ch;
+    else p += sprintf(p, "&#%d;", (unsigned char) ch);
+  }
+  *p=0;
+  return out;
+}
+#endif          /* CONFIG_FEATURE_HTTPD_ENCODE_URL_STR */
+
+/****************************************************************************
+ *
+ > $Function: decodeString()
+ *
+ * $Description: Given a URL encoded string, convert it to plain ascii.
+ *   Since decoding always makes strings smaller, the decode is done in-place.
+ *   Thus, callers should strdup() the argument if they do not want the
+ *   argument modified.  The return is the original pointer, allowing this
+ *   function to be easily used as arguments to other functions.
+ *
+ * $Parameters:
+ *      (char *) string . . . The first string to decode.
+ *      (int)    flag   . . . 1 if require decode '+' as ' ' for CGI
+ *
+ * $Return: (char *)  . . . . A pointer to the decoded string (same as input).
+ *
+ * $Errors: None
+ *
+ ****************************************************************************/
+static char *decodeString(char *orig, int flag_plus_to_space)
+{
+  /* note that decoded string is always shorter than original */
+  char *string = orig;
+  char *ptr = string;
+
+  while (*ptr)
+  {
+    if (*ptr == '+' && flag_plus_to_space)    { *string++ = ' '; ptr++; }
+    else if (*ptr != '%') *string++ = *ptr++;
+    else  {
+      unsigned int value1, value2;
+
+      ptr++;
+      if(sscanf(ptr, "%1X", &value1) != 1 ||
+				sscanf(ptr+1, "%1X", &value2) != 1) {
+	if(!flag_plus_to_space)
+		return NULL;
+	*string++ = '%';
+      } else {
+	value1 = value1 * 16 + value2;
+	if(value1 == '/' || value1 == 0)
+		return orig+1;
+	*string++ = value1;
+	ptr += 2;
+      }
+    }
+  }
+  *string = '\0';
+  return orig;
+}
+
+
+#ifdef CONFIG_FEATURE_HTTPD_CGI
+/****************************************************************************
+ *
+ > $Function: addEnv()
+ *
+ * $Description: Add an environment variable setting to the global list.
+ *    A NAME=VALUE string is allocated, filled, and added to the list of
+ *    environment settings passed to the cgi execution script.
+ *
+ * $Parameters:
+ *  (char *) name_before_underline - The first part environment variable name.
+ *  (char *) name_after_underline  - The second part environment variable name.
+ *  (char *) value  . . The value to which the env variable is set.
+ *
+ * $Return: (void)
+ *
+ * $Errors: Silently returns if the env runs out of space to hold the new item
+ *
+ ****************************************************************************/
+static void addEnv(const char *name_before_underline,
+			const char *name_after_underline, const char *value)
+{
+  char *s = NULL;
+  const char *underline;
+
+  if (!value)
+	value = "";
+  underline = *name_after_underline ? "_" : "";
+  asprintf(&s, "%s%s%s=%s", name_before_underline, underline,
+					name_after_underline, value);
+  if(s) {
+    putenv(s);
+  }
+}
+
+#if defined(CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV) || defined(CONFIG_FEATURE_HTTPD_WITHOUT_INETD)
+/* set environs SERVER_PORT and REMOTE_PORT */
+static void addEnvPort(const char *port_name)
+{
+      char buf[16];
+
+      sprintf(buf, "%u", config->port);
+      addEnv(port_name, "PORT", buf);
+}
+#endif
+#endif          /* CONFIG_FEATURE_HTTPD_CGI */
+
+
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+/****************************************************************************
+ *
+ > $Function: decodeBase64()
+ *
+ > $Description: Decode a base 64 data stream as per rfc1521.
+ *    Note that the rfc states that none base64 chars are to be ignored.
+ *    Since the decode always results in a shorter size than the input, it is
+ *    OK to pass the input arg as an output arg.
+ *
+ * $Parameter:
+ *      (char *) Data . . . . A pointer to a base64 encoded string.
+ *                            Where to place the decoded data.
+ *
+ * $Return: void
+ *
+ * $Errors: None
+ *
+ ****************************************************************************/
+static void decodeBase64(char *Data)
+{
+
+  const unsigned char *in = (const unsigned char *)Data;
+  // The decoded size will be at most 3/4 the size of the encoded
+  unsigned long ch = 0;
+  int i = 0;
+
+  while (*in) {
+    int t = *in++;
+
+    if(t >= '0' && t <= '9')
+	t = t - '0' + 52;
+    else if(t >= 'A' && t <= 'Z')
+	t = t - 'A';
+    else if(t >= 'a' && t <= 'z')
+	t = t - 'a' + 26;
+    else if(t == '+')
+	t = 62;
+    else if(t == '/')
+	t = 63;
+    else if(t == '=')
+	t = 0;
+    else
+	continue;
+
+    ch = (ch << 6) | t;
+    i++;
+    if (i == 4) {
+	*Data++ = (char) (ch >> 16);
+	*Data++ = (char) (ch >> 8);
+	*Data++ = (char) ch;
+	i = 0;
+    }
+  }
+  *Data = 0;
+}
+#endif
+
+
+#ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+/****************************************************************************
+ *
+ > $Function: openServer()
+ *
+ * $Description: create a listen server socket on the designated port.
+ *
+ * $Return: (int)  . . . A connection socket. -1 for errors.
+ *
+ * $Errors: None
+ *
+ ****************************************************************************/
+static int openServer(void)
+{
+  struct sockaddr_in lsocket;
+  int fd;
+
+  /* create the socket right now */
+  /* inet_addr() returns a value that is already in network order */
+  memset(&lsocket, 0, sizeof(lsocket));
+  lsocket.sin_family = AF_INET;
+  lsocket.sin_addr.s_addr = INADDR_ANY;
+  lsocket.sin_port = htons(config->port);
+  fd = bb_xsocket(AF_INET, SOCK_STREAM, 0);
+  /* tell the OS it's OK to reuse a previous address even though */
+  /* it may still be in a close down state.  Allows bind to succeed. */
+  int on = 1;
+#ifdef SO_REUSEPORT
+  setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (void *)&on, sizeof(on)) ;
+#else
+  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)) ;
+#endif
+  bb_xbind(fd, (struct sockaddr *)&lsocket, sizeof(lsocket));
+  listen(fd, 9); /* bb_xlisten? */
+  signal(SIGCHLD, SIG_IGN);   /* prevent zombie (defunct) processes */
+  return fd;
+}
+#endif  /* CONFIG_FEATURE_HTTPD_WITHOUT_INETD */
+
+/****************************************************************************
+ *
+ > $Function: sendHeaders()
+ *
+ * $Description: Create and send HTTP response headers.
+ *   The arguments are combined and sent as one write operation.  Note that
+ *   IE will puke big-time if the headers are not sent in one packet and the
+ *   second packet is delayed for any reason.
+ *
+ * $Parameter:
+ *      (HttpResponseNum) responseNum . . . The result code to send.
+ *
+ * $Return: (int)  . . . . writing errors
+ *
+ ****************************************************************************/
+static int sendHeaders(HttpResponseNum responseNum)
+{
+  char *buf = config->buf;
+  const char *responseString = "";
+  const char *infoString = 0;
+  const char *mime_type;
+  unsigned int i;
+  time_t timer = time(0);
+  char timeStr[80];
+  int len;
+
+  for (i = 0;
+	i < (sizeof(httpResponseNames)/sizeof(httpResponseNames[0])); i++) {
+		if (httpResponseNames[i].type == responseNum) {
+			responseString = httpResponseNames[i].name;
+			infoString = httpResponseNames[i].info;
+			break;
+		}
+  }
+  /* error message is HTML */
+  mime_type = responseNum == HTTP_OK ?
+		config->httpd_found.found_mime_type : "text/html";
+
+  /* emit the current date */
+  strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer));
+  len = sprintf(buf,
+	"HTTP/1.0 %d %s\r\nContent-type: %s\r\n"
+	"Date: %s\r\nConnection: close\r\n",
+	  responseNum, responseString, mime_type, timeStr);
+
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+  if (responseNum == HTTP_UNAUTHORIZED) {
+    len += sprintf(buf+len, "WWW-Authenticate: Basic realm=\"%s\"\r\n",
+							    config->realm);
+  }
+#endif
+  if(responseNum == HTTP_MOVED_TEMPORARILY) {
+	len += sprintf(buf+len, "Location: %s/%s%s\r\n",
+		config->httpd_found.found_moved_temporarily,
+		(config->query ? "?" : ""),
+		(config->query ? config->query : ""));
+  }
+
+  if (config->ContentLength != -1) {    /* file */
+    strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&config->last_mod));
+    len += sprintf(buf+len, "Last-Modified: %s\r\n%s " cont_l_fmt "\r\n",
+			      timeStr, Content_length, cont_l_type config->ContentLength);
+  }
+  strcat(buf, "\r\n");
+  len += 2;
+  if (infoString) {
+    len += sprintf(buf+len,
+	    "<HEAD><TITLE>%d %s</TITLE></HEAD>\n"
+	    "<BODY><H1>%d %s</H1>\n%s\n</BODY>\n",
+	    responseNum, responseString,
+	    responseNum, responseString, infoString);
+  }
+#if DEBUG
+  fprintf(stderr, "Headers: '%s'", buf);
+#endif
+  return bb_full_write(a_c_w, buf, len);
+}
+
+/****************************************************************************
+ *
+ > $Function: getLine()
+ *
+ * $Description: Read from the socket until an end of line char found.
+ *
+ *   Characters are read one at a time until an eol sequence is found.
+ *
+ * $Return: (int) . . . . number of characters read.  -1 if error.
+ *
+ ****************************************************************************/
+static int getLine(void)
+{
+  int  count = 0;
+  char *buf = config->buf;
+
+  while (read(a_c_r, buf + count, 1) == 1) {
+    if (buf[count] == '\r') continue;
+    if (buf[count] == '\n') {
+      buf[count] = 0;
+      return count;
+    }
+    if(count < (MAX_MEMORY_BUFF-1))      /* check owerflow */
+	count++;
+  }
+  if (count) return count;
+  else return -1;
+}
+
+#ifdef CONFIG_FEATURE_HTTPD_CGI
+/****************************************************************************
+ *
+ > $Function: sendCgi()
+ *
+ * $Description: Execute a CGI script and send it's stdout back
+ *
+ *   Environment variables are set up and the script is invoked with pipes
+ *   for stdin/stdout.  If a post is being done the script is fed the POST
+ *   data in addition to setting the QUERY_STRING variable (for GETs or POSTs).
+ *
+ * $Parameters:
+ *      (const char *) url . . . . . . The requested URL (with leading /).
+ *      (int bodyLen)  . . . . . . . . Length of the post body.
+ *      (const char *cookie) . . . . . For set HTTP_COOKIE.
+ *      (const char *content_type) . . For set CONTENT_TYPE.
+
+ *
+ * $Return: (char *)  . . . . A pointer to the decoded string (same as input).
+ *
+ * $Errors: None
+ *
+ ****************************************************************************/
+static int sendCgi(const char *url,
+		   const char *request, int bodyLen, const char *cookie,
+		   const char *content_type)
+{
+  int fromCgi[2];  /* pipe for reading data from CGI */
+  int toCgi[2];    /* pipe for sending data to CGI */
+
+  static char * argp[] = { 0, 0 };
+  int pid = 0;
+  int inFd;
+  int outFd;
+  int firstLine = 1;
+
+  do {
+    if (pipe(fromCgi) != 0) {
+      break;
+    }
+    if (pipe(toCgi) != 0) {
+      break;
+    }
+
+    pid = fork();
+    if (pid < 0) {
+	pid = 0;
+	break;
+    }
+
+    if (!pid) {
+      /* child process */
+      char *script;
+      char *purl = strdup( url );
+      char realpath_buff[MAXPATHLEN];
+
+      if(purl == NULL)
+	_exit(242);
+
+      inFd  = toCgi[0];
+      outFd = fromCgi[1];
+
+      dup2(inFd, 0);  // replace stdin with the pipe
+      dup2(outFd, 1);  // replace stdout with the pipe
+      if(!DEBUG)
+	dup2(outFd, 2);  // replace stderr with the pipe
+
+      close(toCgi[0]);
+      close(toCgi[1]);
+      close(fromCgi[0]);
+      close(fromCgi[1]);
+
+      /*
+       * Find PATH_INFO.
+       */
+      script = purl;
+      while((script = strchr( script + 1, '/' )) != NULL) {
+	/* have script.cgi/PATH_INFO or dirs/script.cgi[/PATH_INFO] */
+	struct stat sb;
+
+	*script = '\0';
+	if(is_directory(purl + 1, 1, &sb) == 0) {
+		/* not directory, found script.cgi/PATH_INFO */
+		*script = '/';
+		break;
+	}
+	*script = '/';          /* is directory, find next '/' */
+      }
+      addEnv("PATH", "INFO", script);   /* set /PATH_INFO or NULL */
+      addEnv("PATH",           "",         getenv("PATH"));
+      addEnv("REQUEST",        "METHOD",   request);
+      if(config->query) {
+	char *uri = alloca(strlen(purl) + 2 + strlen(config->query));
+	if(uri)
+	    sprintf(uri, "%s?%s", purl, config->query);
+	addEnv("REQUEST",        "URI",   uri);
+      } else {
+	addEnv("REQUEST",        "URI",   purl);
+      }
+      if(script != NULL)
+	*script = '\0';         /* reduce /PATH_INFO */
+       /* SCRIPT_FILENAME required by PHP in CGI mode */
+       if(realpath(purl + 1, realpath_buff))
+	 addEnv("SCRIPT", "FILENAME", realpath_buff);
+       else
+	 *realpath_buff = 0;
+      /* set SCRIPT_NAME as full path: /cgi-bin/dirs/script.cgi */
+      addEnv("SCRIPT_NAME",    "",         purl);
+      addEnv("QUERY_STRING",   "",         config->query);
+      addEnv("SERVER",         "SOFTWARE", httpdVersion);
+      addEnv("SERVER",         "PROTOCOL", "HTTP/1.0");
+      addEnv("GATEWAY_INTERFACE", "",      "CGI/1.1");
+      addEnv("REMOTE",         "ADDR",     config->rmt_ip_str);
+#ifdef CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
+      addEnvPort("REMOTE");
+#endif
+      if(bodyLen) {
+	char sbl[32];
+
+	sprintf(sbl, "%d", bodyLen);
+	addEnv("CONTENT", "LENGTH", sbl);
+      }
+      if(cookie)
+	addEnv("HTTP", "COOKIE", cookie);
+      if(content_type)
+	addEnv("CONTENT", "TYPE", content_type);
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+      if(config->remoteuser) {
+	addEnv("REMOTE", "USER", config->remoteuser);
+	addEnv("AUTH_TYPE", "", "Basic");
+      }
+#endif
+      if(config->referer)
+	addEnv("HTTP", "REFERER", config->referer);
+
+	/* set execve argp[0] without path */
+      argp[0] = strrchr( purl, '/' ) + 1;
+	/* but script argp[0] must have absolute path and chdiring to this */
+      if(*realpath_buff) {
+	    script = strrchr(realpath_buff, '/');
+	    if(script) {
+		*script = '\0';
+		if(chdir(realpath_buff) == 0) {
+		  // now run the program.  If it fails,
+		  // use _exit() so no destructors
+		  // get called and make a mess.
+#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
+		  char *interpr = NULL;
+		  char *suffix = strrchr(purl, '.');
+
+		  if(suffix) {
+			Htaccess * cur;
+			for (cur = config->script_i; cur; cur = cur->next)
+				if(strcmp(cur->before_colon + 1, suffix) == 0) {
+					interpr = cur->after_colon;
+					break;
+				}
+		  }
+#endif
+		  *script = '/';
+#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
+		  if (interpr)
+			execv(interpr, argp);
+		  else
+#endif
+			execv(realpath_buff, argp);
+		}
+	    }
+      }
+#ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+      config->accepted_socket = 1;      /* send to stdout */
+#endif
+      sendHeaders(HTTP_NOT_FOUND);
+      _exit(242);
+    } /* end child */
+
+  } while (0);
+
+  if (pid) {
+    /* parent process */
+    int status;
+    size_t post_readed_size = 0, post_readed_idx = 0;
+
+    inFd  = fromCgi[0];
+    outFd = toCgi[1];
+    close(fromCgi[1]);
+    close(toCgi[0]);
+    signal(SIGPIPE, SIG_IGN);
+
+    while (1) {
+      fd_set readSet;
+      fd_set writeSet;
+      char wbuf[128];
+      int nfound;
+      int count;
+
+      FD_ZERO(&readSet);
+      FD_ZERO(&writeSet);
+      FD_SET(inFd, &readSet);
+      if(bodyLen > 0 || post_readed_size > 0) {
+	FD_SET(outFd, &writeSet);
+	nfound = outFd > inFd ? outFd : inFd;
+	if(post_readed_size == 0) {
+		FD_SET(a_c_r, &readSet);
+		if(nfound < a_c_r)
+			nfound = a_c_r;
+	}
+      /* Now wait on the set of sockets! */
+	nfound = select(nfound + 1, &readSet, &writeSet, 0, NULL);
+      } else {
+	if(!bodyLen) {
+		close(outFd);
+		bodyLen = -1;
+	}
+	nfound = select(inFd + 1, &readSet, 0, 0, NULL);
+      }
+
+      if (nfound <= 0) {
+	if (waitpid(pid, &status, WNOHANG) > 0) {
+	  close(inFd);
+#if DEBUG
+	  if (WIFEXITED(status))
+	      bb_error_msg("piped has exited with status=%d", WEXITSTATUS(status));
+	  if (WIFSIGNALED(status))
+	      bb_error_msg("piped has exited with signal=%d", WTERMSIG(status));
+#endif
+	  break;
+	}
+      } else if(post_readed_size > 0 && FD_ISSET(outFd, &writeSet)) {
+		count = bb_full_write(outFd, wbuf + post_readed_idx, post_readed_size);
+		if(count > 0) {
+			post_readed_size -= count;
+			post_readed_idx += count;
+			if(post_readed_size == 0)
+				post_readed_idx = 0;
+		} else {
+			post_readed_size = post_readed_idx = bodyLen = 0; /* broken pipe to CGI */
+		}
+      } else if(bodyLen > 0 && post_readed_size == 0 && FD_ISSET(a_c_r, &readSet)) {
+		count = bodyLen > (int)sizeof(wbuf) ? (int)sizeof(wbuf) : bodyLen;
+		count = safe_read(a_c_r, wbuf, count);
+		if(count > 0) {
+			post_readed_size += count;
+			bodyLen -= count;
+		} else {
+			bodyLen = 0;    /* closed */
+		}
+      }
+      if(FD_ISSET(inFd, &readSet)) {
+	int s = a_c_w;
+	char *rbuf = config->buf;
+
+#ifndef PIPE_BUF
+# define PIPESIZE 4096          /* amount of buffering in a pipe */
+#else
+# define PIPESIZE PIPE_BUF
+#endif
+#if PIPESIZE >= MAX_MEMORY_BUFF
+# error "PIPESIZE >= MAX_MEMORY_BUFF"
+#endif
+
+	// There is something to read
+	count = safe_read(inFd, rbuf, PIPESIZE);
+	if (count == 0)
+		break;  /* closed */
+	if (count > 0) {
+	  if (firstLine) {
+	    rbuf[count] = 0;
+	    /* check to see if the user script added headers */
+	    if(strncmp(rbuf, "HTTP/1.0 200 OK\r\n", 4) != 0) {
+	      bb_full_write(s, "HTTP/1.0 200 OK\r\n", 17);
+	    }
+	    if (strstr(rbuf, "ontent-") == 0) {
+	      bb_full_write(s, "Content-type: text/plain\r\n\r\n", 28);
+	    }
+	    firstLine = 0;
+	  }
+	  if (bb_full_write(s, rbuf, count) != count)
+	      break;
+
+#if DEBUG
+	  fprintf(stderr, "cgi read %d bytes\n", count);
+#endif
+	}
+      }
+    }
+  }
+  return 0;
+}
+#endif          /* CONFIG_FEATURE_HTTPD_CGI */
+
+/****************************************************************************
+ *
+ > $Function: sendFile()
+ *
+ * $Description: Send a file response to an HTTP request
+ *
+ * $Parameter:
+ *      (const char *) url . . The URL requested.
+ *
+ * $Return: (int)  . . . . . . Always 0.
+ *
+ ****************************************************************************/
+static int sendFile(const char *url)
+{
+  char * suffix;
+  int  f;
+  const char * const * table;
+  const char * try_suffix;
+
+  suffix = strrchr(url, '.');
+
+  for (table = suffixTable; *table; table += 2)
+	if(suffix != NULL && (try_suffix = strstr(*table, suffix)) != 0) {
+		try_suffix += strlen(suffix);
+		if(*try_suffix == 0 || *try_suffix == '.')
+			break;
+	}
+  /* also, if not found, set default as "application/octet-stream";  */
+  config->httpd_found.found_mime_type = *(table+1);
+#ifdef CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
+  if (suffix) {
+    Htaccess * cur;
+
+    for (cur = config->mime_a; cur; cur = cur->next) {
+	if(strcmp(cur->before_colon, suffix) == 0) {
+		config->httpd_found.found_mime_type = cur->after_colon;
+		break;
+	}
+    }
+  }
+#endif  /* CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES */
+
+#if DEBUG
+  fprintf(stderr, "Sending file '%s' Content-type: %s\n",
+			url, config->httpd_found.found_mime_type);
+#endif
+
+  f = open(url, O_RDONLY);
+  if (f >= 0) {
+	int count;
+	char *buf = config->buf;
+
+	sendHeaders(HTTP_OK);
+	while ((count = bb_full_read(f, buf, MAX_MEMORY_BUFF)) > 0) {
+		if (bb_full_write(a_c_w, buf, count) != count)
+			break;
+	}
+	close(f);
+  } else {
+#if DEBUG
+	bb_perror_msg("Unable to open '%s'", url);
+#endif
+	sendHeaders(HTTP_NOT_FOUND);
+  }
+
+  return 0;
+}
+
+static int checkPermIP(void)
+{
+    Htaccess_IP * cur;
+
+    /* This could stand some work */
+    for (cur = config->ip_a_d; cur; cur = cur->next) {
+#if DEBUG
+	fprintf(stderr, "checkPermIP: '%s' ? ", config->rmt_ip_str);
+	fprintf(stderr, "'%u.%u.%u.%u/%u.%u.%u.%u'\n",
+		(unsigned char)(cur->ip >> 24),
+		(unsigned char)(cur->ip >> 16),
+		(unsigned char)(cur->ip >> 8),
+				cur->ip & 0xff,
+		(unsigned char)(cur->mask >> 24),
+		(unsigned char)(cur->mask >> 16),
+		(unsigned char)(cur->mask >> 8),
+				cur->mask & 0xff);
+#endif
+	if((config->rmt_ip & cur->mask) == cur->ip)
+	    return cur->allow_deny == 'A';   /* Allow/Deny */
+    }
+
+    /* if unconfigured, return 1 - access from all */
+    return !config->flg_deny_all;
+}
+
+/****************************************************************************
+ *
+ > $Function: checkPerm()
+ *
+ * $Description: Check the permission file for access password protected.
+ *
+ *   If config file isn't present, everything is allowed.
+ *   Entries are of the form you can see example from header source
+ *
+ * $Parameters:
+ *      (const char *) path  . . . . The file path.
+ *      (const char *) request . . . User information to validate.
+ *
+ * $Return: (int)  . . . . . . . . . 1 if request OK, 0 otherwise.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+static int checkPerm(const char *path, const char *request)
+{
+    Htaccess * cur;
+    const char *p;
+    const char *p0;
+
+    const char *prev = NULL;
+
+    /* This could stand some work */
+    for (cur = config->auth; cur; cur = cur->next) {
+	p0 = cur->before_colon;
+	if(prev != NULL && strcmp(prev, p0) != 0)
+	    continue;       /* find next identical */
+	p = cur->after_colon;
+#if DEBUG
+	fprintf(stderr,"checkPerm: '%s' ? '%s'\n", p0, request);
+#endif
+	{
+	    size_t l = strlen(p0);
+
+	    if(strncmp(p0, path, l) == 0 &&
+			    (l == 1 || path[l] == '/' || path[l] == 0)) {
+		char *u;
+		/* path match found.  Check request */
+		/* for check next /path:user:password */
+		prev = p0;
+		u = strchr(request, ':');
+		if(u == NULL) {
+			/* bad request, ':' required */
+			break;
+			}
+
+#ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5
+		{
+			char *cipher;
+			char *pp;
+
+			if(strncmp(p, request, u-request) != 0) {
+				/* user uncompared */
+				continue;
+			}
+			pp = strchr(p, ':');
+			if(pp && pp[1] == '$' && pp[2] == '1' &&
+						 pp[3] == '$' && pp[4]) {
+				pp++;
+				cipher = pw_encrypt(u+1, pp);
+				if (strcmp(cipher, pp) == 0)
+					goto set_remoteuser_var;   /* Ok */
+				/* unauthorized */
+				continue;
+			}
+		}
+#endif
+		if (strcmp(p, request) == 0) {
+#ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5
+set_remoteuser_var:
+#endif
+		    config->remoteuser = strdup(request);
+		    if(config->remoteuser)
+			config->remoteuser[(u - request)] = 0;
+		    return 1;   /* Ok */
+		}
+		/* unauthorized */
+	    }
+	}
+    }   /* for */
+
+    return prev == NULL;
+}
+
+#endif  /* CONFIG_FEATURE_HTTPD_BASIC_AUTH */
+
+/****************************************************************************
+ *
+ > $Function: handle_sigalrm()
+ *
+ * $Description: Handle timeouts
+ *
+ ****************************************************************************/
+
+static void
+handle_sigalrm( int sig )
+{
+    sendHeaders(HTTP_REQUEST_TIMEOUT);
+    config->alarm_signaled = sig;
+}
+
+/****************************************************************************
+ *
+ > $Function: handleIncoming()
+ *
+ * $Description: Handle an incoming http request.
+ *
+ ****************************************************************************/
+static void handleIncoming(void)
+{
+  char *buf = config->buf;
+  char *url;
+  char *purl;
+  int  blank = -1;
+  char *test;
+  struct stat sb;
+  int ip_allowed;
+#ifdef CONFIG_FEATURE_HTTPD_CGI
+  const char *prequest = request_GET;
+  long length=0;
+  char *cookie = 0;
+  char *content_type = 0;
+#endif
+  fd_set s_fd;
+  struct timeval tv;
+  int retval;
+  struct sigaction sa;
+
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+  int credentials = -1;  /* if not requred this is Ok */
+#endif
+
+  sa.sa_handler = handle_sigalrm;
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = 0; /* no SA_RESTART */
+  sigaction(SIGALRM, &sa, NULL);
+
+  do {
+    int  count;
+
+    (void) alarm( TIMEOUT );
+    if (getLine() <= 0)
+	break;  /* closed */
+
+    purl = strpbrk(buf, " \t");
+    if(purl == NULL) {
+BAD_REQUEST:
+      sendHeaders(HTTP_BAD_REQUEST);
+      break;
+    }
+    *purl = 0;
+#ifdef CONFIG_FEATURE_HTTPD_CGI
+    if(strcasecmp(buf, prequest) != 0) {
+	prequest = "POST";
+	if(strcasecmp(buf, prequest) != 0) {
+	    sendHeaders(HTTP_NOT_IMPLEMENTED);
+	    break;
+	}
+    }
+#else
+    if(strcasecmp(buf, request_GET) != 0) {
+	sendHeaders(HTTP_NOT_IMPLEMENTED);
+	break;
+    }
+#endif
+    *purl = ' ';
+    count = sscanf(purl, " %[^ ] HTTP/%d.%*d", buf, &blank);
+
+    if (count < 1 || buf[0] != '/') {
+      /* Garbled request/URL */
+      goto BAD_REQUEST;
+    }
+    url = alloca(strlen(buf) + 12);      /* + sizeof("/index.html\0") */
+    if(url == NULL) {
+	sendHeaders(HTTP_INTERNAL_SERVER_ERROR);
+	break;
+    }
+    strcpy(url, buf);
+    /* extract url args if present */
+    test = strchr(url, '?');
+    if (test) {
+      *test++ = 0;
+      config->query = test;
+    }
+
+    test = decodeString(url, 0);
+    if(test == NULL)
+	goto BAD_REQUEST;
+    if(test == (buf+1)) {
+	sendHeaders(HTTP_NOT_FOUND);
+	break;
+    }
+    /* algorithm stolen from libbb bb_simplify_path(),
+       but don`t strdup and reducing trailing slash and protect out root */
+    purl = test = url;
+
+    do {
+	if (*purl == '/') {
+	    if (*test == '/') {        /* skip duplicate (or initial) slash */
+		continue;
+	    } else if (*test == '.') {
+		if (test[1] == '/' || test[1] == 0) { /* skip extra '.' */
+		    continue;
+		} else if ((test[1] == '.') && (test[2] == '/' || test[2] == 0)) {
+		    ++test;
+		    if (purl == url) {
+			/* protect out root */
+			goto BAD_REQUEST;
+		    }
+		    while (*--purl != '/');    /* omit previous dir */
+		    continue;
+		}
+	    }
+	}
+	*++purl = *test;
+    } while (*++test);
+
+    *++purl = 0;        /* so keep last character */
+    test = purl;        /* end ptr */
+
+    /* If URL is directory, adding '/' */
+    if(test[-1] != '/') {
+	    if ( is_directory(url + 1, 1, &sb) ) {
+		    config->httpd_found.found_moved_temporarily = url;
+	    }
+    }
+#if DEBUG
+    fprintf(stderr, "url='%s', args=%s\n", url, config->query);
+#endif
+
+    test = url;
+    ip_allowed = checkPermIP();
+    while(ip_allowed && (test = strchr( test + 1, '/' )) != NULL) {
+	/* have path1/path2 */
+	*test = '\0';
+	if( is_directory(url + 1, 1, &sb) ) {
+		/* may be having subdir config */
+		parse_conf(url + 1, SUBDIR_PARSE);
+		ip_allowed = checkPermIP();
+	}
+	*test = '/';
+    }
+    if(blank >= 0) {
+      // read until blank line for HTTP version specified, else parse immediate
+      while(1) {
+	alarm(TIMEOUT);
+	count = getLine();
+	if(count <= 0)
+		break;
+
+#if DEBUG
+	fprintf(stderr, "Header: '%s'\n", buf);
+#endif
+
+#ifdef CONFIG_FEATURE_HTTPD_CGI
+	/* try and do our best to parse more lines */
+	if ((strncasecmp(buf, Content_length, 15) == 0)) {
+	  if(prequest != request_GET)
+		  length = strtol(buf + 15, 0, 0); // extra read only for POST
+	} else if ((strncasecmp(buf, "Cookie:", 7) == 0)) {
+		  for(test = buf + 7; isspace(*test); test++)
+			  ;
+		  cookie = strdup(test);
+	} else if ((strncasecmp(buf, "Content-Type:", 13) == 0)) {
+		  for(test = buf + 13; isspace(*test); test++)
+			  ;
+		  content_type = strdup(test);
+	} else if ((strncasecmp(buf, "Referer:", 8) == 0)) {
+		  for(test = buf + 8; isspace(*test); test++)
+			  ;
+		  config->referer = strdup(test);
+	}
+#endif
+
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+	if (strncasecmp(buf, "Authorization:", 14) == 0) {
+	  /* We only allow Basic credentials.
+	   * It shows up as "Authorization: Basic <userid:password>" where
+	   * the userid:password is base64 encoded.
+	   */
+	  for(test = buf + 14; isspace(*test); test++)
+		  ;
+	  if (strncasecmp(test, "Basic", 5) != 0)
+		  continue;
+
+	  test += 5;  /* decodeBase64() skiping space self */
+	  decodeBase64(test);
+	  credentials = checkPerm(url, test);
+	}
+#endif          /* CONFIG_FEATURE_HTTPD_BASIC_AUTH */
+
+      }   /* while extra header reading */
+    }
+    (void) alarm( 0 );
+    if(config->alarm_signaled)
+	break;
+
+    if (strcmp(strrchr(url, '/') + 1, httpd_conf) == 0 || ip_allowed == 0) {
+		/* protect listing [/path]/httpd_conf or IP deny */
+#ifdef CONFIG_FEATURE_HTTPD_CGI
+FORBIDDEN:      /* protect listing /cgi-bin */
+#endif
+		sendHeaders(HTTP_FORBIDDEN);
+		break;
+    }
+
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+    if (credentials <= 0 && checkPerm(url, ":") == 0) {
+      sendHeaders(HTTP_UNAUTHORIZED);
+      break;
+    }
+#endif
+
+    if(config->httpd_found.found_moved_temporarily) {
+	sendHeaders(HTTP_MOVED_TEMPORARILY);
+#if DEBUG
+	/* clear unforked memory flag */
+	config->httpd_found.found_moved_temporarily = NULL;
+#endif
+	break;
+    }
+
+    test = url + 1;      /* skip first '/' */
+
+#ifdef CONFIG_FEATURE_HTTPD_CGI
+    /* if strange Content-Length */
+    if (length < 0)
+	break;
+
+    if (strncmp(test, "cgi-bin", 7) == 0) {
+		if(test[7] == '/' && test[8] == 0)
+			goto FORBIDDEN;     // protect listing cgi-bin/
+		sendCgi(url, prequest, length, cookie, content_type);
+    } else {
+	if (prequest != request_GET)
+		sendHeaders(HTTP_NOT_IMPLEMENTED);
+	else {
+#endif  /* CONFIG_FEATURE_HTTPD_CGI */
+		if(purl[-1] == '/')
+			strcpy(purl, "index.html");
+		if ( stat(test, &sb ) == 0 ) {
+			config->ContentLength = sb.st_size;
+			config->last_mod = sb.st_mtime;
+		}
+		sendFile(test);
+#ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+		/* unset if non inetd looped */
+		config->ContentLength = -1;
+#endif
+
+#ifdef CONFIG_FEATURE_HTTPD_CGI
+	}
+    }
+#endif
+
+  } while (0);
+
+
+#ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+/* from inetd don`t looping: freeing, closing automatic from exit always */
+# if DEBUG
+  fprintf(stderr, "closing socket\n");
+# endif
+# ifdef CONFIG_FEATURE_HTTPD_CGI
+  free(cookie);
+  free(content_type);
+  free(config->referer);
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+  free(config->remoteuser);
+#endif
+# endif
+#endif  /* CONFIG_FEATURE_HTTPD_WITHOUT_INETD */
+  shutdown(a_c_w, SHUT_WR);
+
+  /* Properly wait for remote to closed */
+  FD_ZERO (&s_fd) ;
+  FD_SET (a_c_r, &s_fd) ;
+
+  do {
+    tv.tv_sec = 2 ;
+    tv.tv_usec = 0 ;
+    retval = select (a_c_r + 1, &s_fd, NULL, NULL, &tv);
+  } while (retval > 0 && (read (a_c_r, buf, sizeof (config->buf)) > 0));
+
+  shutdown(a_c_r, SHUT_RD);
+#ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+  close(config->accepted_socket);
+#endif  /* CONFIG_FEATURE_HTTPD_WITHOUT_INETD */
+}
+
+/****************************************************************************
+ *
+ > $Function: miniHttpd()
+ *
+ * $Description: The main http server function.
+ *
+ *   Given an open socket fildes, listen for new connections and farm out
+ *   the processing as a forked process.
+ *
+ * $Parameters:
+ *      (int) server. . . The server socket fildes.
+ *
+ * $Return: (int) . . . . Always 0.
+ *
+ ****************************************************************************/
+#ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+static int miniHttpd(int server)
+{
+  fd_set readfd, portfd;
+
+  FD_ZERO(&portfd);
+  FD_SET(server, &portfd);
+
+  /* copy the ports we are watching to the readfd set */
+  while (1) {
+    readfd = portfd;
+
+    /* Now wait INDEFINITELY on the set of sockets! */
+    if (select(server + 1, &readfd, 0, 0, 0) > 0) {
+      if (FD_ISSET(server, &readfd)) {
+	int on;
+	struct sockaddr_in fromAddr;
+
+	socklen_t fromAddrLen = sizeof(fromAddr);
+	int s = accept(server,
+		       (struct sockaddr *)&fromAddr, &fromAddrLen);
+
+	if (s < 0) {
+	    continue;
+	}
+	config->accepted_socket = s;
+	config->rmt_ip = ntohl(fromAddr.sin_addr.s_addr);
+#if defined(CONFIG_FEATURE_HTTPD_CGI) || DEBUG
+	sprintf(config->rmt_ip_str, "%u.%u.%u.%u",
+		(unsigned char)(config->rmt_ip >> 24),
+		(unsigned char)(config->rmt_ip >> 16),
+		(unsigned char)(config->rmt_ip >> 8),
+				config->rmt_ip & 0xff);
+	config->port = ntohs(fromAddr.sin_port);
+#if DEBUG
+	bb_error_msg("connection from IP=%s, port %u\n",
+					config->rmt_ip_str, config->port);
+#endif
+#endif /* CONFIG_FEATURE_HTTPD_CGI */
+
+	/*  set the KEEPALIVE option to cull dead connections */
+	on = 1;
+	setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof (on));
+
+#if !DEBUG
+	if (fork() == 0)
+#endif
+	{
+	    /* This is the spawned thread */
+#ifdef CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
+	    /* protect reload config, may be confuse checking */
+	    signal(SIGHUP, SIG_IGN);
+#endif
+	    handleIncoming();
+#if !DEBUG
+	    exit(0);
+#endif
+	}
+	close(s);
+      }
+    }
+  } // while (1)
+  return 0;
+}
+
+#else
+    /* from inetd */
+
+static int miniHttpd(void)
+{
+  struct sockaddr_in fromAddrLen;
+  socklen_t sinlen = sizeof (struct sockaddr_in);
+
+  getpeername (0, (struct sockaddr *)&fromAddrLen, &sinlen);
+  config->rmt_ip = ntohl(fromAddrLen.sin_addr.s_addr);
+#ifdef CONFIG_FEATURE_HTTPD_CGI
+  sprintf(config->rmt_ip_str, "%u.%u.%u.%u",
+		(unsigned char)(config->rmt_ip >> 24),
+		(unsigned char)(config->rmt_ip >> 16),
+		(unsigned char)(config->rmt_ip >> 8),
+				config->rmt_ip & 0xff);
+#endif
+  config->port = ntohs(fromAddrLen.sin_port);
+  handleIncoming();
+  return 0;
+}
+#endif  /* CONFIG_FEATURE_HTTPD_WITHOUT_INETD */
+
+#ifdef CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
+static void sighup_handler(int sig)
+{
+	/* set and reset */
+	struct sigaction sa;
+
+	parse_conf(default_path_httpd_conf,
+		    sig == SIGHUP ? SIGNALED_PARSE : FIRST_PARSE);
+	sa.sa_handler = sighup_handler;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = SA_RESTART;
+	sigaction(SIGHUP, &sa, NULL);
+}
+#endif
+
+enum httpd_opts_nums {
+	c_opt_config_file = 0,
+	d_opt_decode_url,
+	h_opt_home_httpd,
+	USE_FEATURE_HTTPD_ENCODE_URL_STR(e_opt_encode_url,)
+	USE_FEATURE_HTTPD_BASIC_AUTH(r_opt_realm,)
+	USE_FEATURE_HTTPD_AUTH_MD5(m_opt_md5,)
+	USE_FEATURE_HTTPD_SETUID(u_opt_setuid,)
+	USE_FEATURE_HTTPD_WITHOUT_INETD(p_opt_port,)
+};
+
+static const char httpd_opts[]="c:d:h:"
+	USE_FEATURE_HTTPD_ENCODE_URL_STR("e:")
+	USE_FEATURE_HTTPD_BASIC_AUTH("r:")
+	USE_FEATURE_HTTPD_AUTH_MD5("m:")
+	USE_FEATURE_HTTPD_SETUID("u:")
+	USE_FEATURE_HTTPD_WITHOUT_INETD("p:");
+
+#define OPT_CONFIG_FILE (1<<c_opt_config_file)
+#define OPT_DECODE_URL  (1<<d_opt_decode_url)
+#define OPT_HOME_HTTPD  (1<<h_opt_home_httpd)
+
+#define OPT_ENCODE_URL  USE_FEATURE_HTTPD_ENCODE_URL_STR((1<<e_opt_encode_url)) \
+			SKIP_FEATURE_HTTPD_ENCODE_URL_STR(0)
+
+#define OPT_REALM       USE_FEATURE_HTTPD_BASIC_AUTH((1<<r_opt_realm)) \
+			SKIP_FEATURE_HTTPD_BASIC_AUTH(0)
+
+#define OPT_MD5         USE_FEATURE_HTTPD_AUTH_MD5((1<<m_opt_md5)) \
+			SKIP_FEATURE_HTTPD_AUTH_MD5(0)
+
+#define OPT_SETUID      USE_FEATURE_HTTPD_SETUID((1<<u_opt_setuid)) \
+			SKIP_FEATURE_HTTPD_SETUID(0)
+
+#define OPT_PORT        USE_FEATURE_HTTPD_WITHOUT_INETD((1<<p_opt_port)) \
+			SKIP_FEATURE_HTTPD_WITHOUT_INETD(0)
+
+
+int httpd_main(int argc, char *argv[])
+{
+  unsigned long opt;
+  const char *home_httpd = home;
+  char *url_for_decode;
+  USE_FEATURE_HTTPD_ENCODE_URL_STR(const char *url_for_encode;)
+  USE_FEATURE_HTTPD_WITHOUT_INETD(const char *s_port;)
+  USE_FEATURE_HTTPD_WITHOUT_INETD(int server;)
+
+  USE_FEATURE_HTTPD_SETUID(const char *s_uid;)
+  USE_FEATURE_HTTPD_SETUID(long uid = -1;)
+
+  USE_FEATURE_HTTPD_AUTH_MD5(const char *pass;)
+
+  config = xcalloc(1, sizeof(*config));
+#ifdef CONFIG_FEATURE_HTTPD_BASIC_AUTH
+  config->realm = "Web Server Authentication";
+#endif
+
+#ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+  config->port = 80;
+#endif
+
+  config->ContentLength = -1;
+
+  opt = bb_getopt_ulflags(argc, argv, httpd_opts,
+			&(config->configFile), &url_for_decode, &home_httpd
+			USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode)
+			USE_FEATURE_HTTPD_BASIC_AUTH(, &(config->realm))
+			USE_FEATURE_HTTPD_AUTH_MD5(, &pass)
+			USE_FEATURE_HTTPD_SETUID(, &s_uid)
+			USE_FEATURE_HTTPD_WITHOUT_INETD(, &s_port)
+	);
+
+  if(opt & OPT_DECODE_URL) {
+      printf("%s", decodeString(url_for_decode, 1));
+      return 0;
+  }
+#ifdef CONFIG_FEATURE_HTTPD_ENCODE_URL_STR
+  if(opt & OPT_ENCODE_URL) {
+      printf("%s", encodeString(url_for_encode));
+      return 0;
+  }
+#endif
+#ifdef CONFIG_FEATURE_HTTPD_AUTH_MD5
+  if(opt & OPT_MD5) {
+      printf("%s\n", pw_encrypt(pass, "$1$"));
+      return 0;
+  }
+#endif
+#ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+    if(opt & OPT_PORT)
+	config->port = bb_xgetlarg(s_port, 10, 1, 0xffff);
+#ifdef CONFIG_FEATURE_HTTPD_SETUID
+    if(opt & OPT_SETUID) {
+	char *e;
+
+	uid = strtol(s_uid, &e, 0);
+	if(*e != '\0') {
+		/* not integer */
+		uid = bb_xgetpwnam(s_uid);
+	}
+      }
+#endif
+#endif
+
+  bb_xchdir(home_httpd);
+#ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+  server = openServer();
+# ifdef CONFIG_FEATURE_HTTPD_SETUID
+  /* drop privileges */
+  if(uid > 0)
+	setuid(uid);
+# endif
+#endif
+
+#ifdef CONFIG_FEATURE_HTTPD_CGI
+   {
+	char *p = getenv("PATH");
+	if(p) {
+		p = bb_xstrdup(p);
+	}
+	clearenv();
+	if(p)
+		setenv("PATH", p, 1);
+# ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+	addEnvPort("SERVER");
+# endif
+   }
+#endif
+
+#ifdef CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
+  sighup_handler(0);
+#else
+  parse_conf(default_path_httpd_conf, FIRST_PARSE);
+#endif
+
+#ifdef CONFIG_FEATURE_HTTPD_WITHOUT_INETD
+# if !DEBUG
+  bb_xdaemon(1, 0);     /* don`t change curent directory */
+# endif
+  return miniHttpd(server);
+#else
+  return miniHttpd();
+#endif
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ifconfig.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ifconfig.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ifconfig.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,599 @@
+/* vi: set sw=4 ts=4: */
+/* ifconfig
+ *
+ * Similar to the standard Unix ifconfig, but with only the necessary
+ * parts for AF_INET, and without any printing of if info (for now).
+ *
+ * Bjorn Wesen, Axis Communications AB
+ *
+ *
+ * Authors of the original ifconfig was:
+ *              Fred N. van Kempen, <waltje at uwalt.nl.mugnet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/*
+ * Heavily modified by Manuel Novoa III       Mar 6, 2001
+ *
+ * From initial port to busybox, removed most of the redundancy by
+ * converting to a table-driven approach.  Added several (optional)
+ * args missing from initial port.
+ *
+ * Still missing:  media, tunnel.
+ *
+ * 2002-04-20
+ * IPV6 support added by Bart Visscher <magick at linux-fan.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>		/* strcmp and friends */
+#include <ctype.h>		/* isdigit and friends */
+#include <stddef.h>		/* offsetof */
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#if __GLIBC__ >=2 && __GLIBC_MINOR >= 1
+#include <netpacket/packet.h>
+#include <net/ethernet.h>
+#else
+#include <sys/types.h>
+#include <netinet/if_ether.h>
+#endif
+#include "inet_common.h"
+#include "busybox.h"
+
+#ifdef CONFIG_FEATURE_IFCONFIG_SLIP
+# include <net/if_slip.h>
+#endif
+
+/* I don't know if this is needed for busybox or not.  Anyone? */
+#define QUESTIONABLE_ALIAS_CASE
+
+
+/* Defines for glibc2.0 users. */
+#ifndef SIOCSIFTXQLEN
+# define SIOCSIFTXQLEN      0x8943
+# define SIOCGIFTXQLEN      0x8942
+#endif
+
+/* ifr_qlen is ifru_ivalue, but it isn't present in 2.0 kernel headers */
+#ifndef ifr_qlen
+# define ifr_qlen        ifr_ifru.ifru_mtu
+#endif
+
+#ifndef IFF_DYNAMIC
+# define IFF_DYNAMIC     0x8000	/* dialup device with changing addresses */
+#endif
+
+#ifdef CONFIG_FEATURE_IPV6
+struct in6_ifreq {
+	struct in6_addr ifr6_addr;
+	uint32_t ifr6_prefixlen;
+	int ifr6_ifindex;
+};
+#endif
+
+/*
+ * Here are the bit masks for the "flags" member of struct options below.
+ * N_ signifies no arg prefix; M_ signifies arg prefixed by '-'.
+ * CLR clears the flag; SET sets the flag; ARG signifies (optional) arg.
+ */
+#define N_CLR            0x01
+#define M_CLR            0x02
+#define N_SET            0x04
+#define M_SET            0x08
+#define N_ARG            0x10
+#define M_ARG            0x20
+
+#define M_MASK           (M_CLR | M_SET | M_ARG)
+#define N_MASK           (N_CLR | N_SET | N_ARG)
+#define SET_MASK         (N_SET | M_SET)
+#define CLR_MASK         (N_CLR | M_CLR)
+#define SET_CLR_MASK     (SET_MASK | CLR_MASK)
+#define ARG_MASK         (M_ARG | N_ARG)
+
+/*
+ * Here are the bit masks for the "arg_flags" member of struct options below.
+ */
+
+/*
+ * cast type:
+ *   00 int
+ *   01 char *
+ *   02 HOST_COPY in_ether
+ *   03 HOST_COPY INET_resolve
+ */
+#define A_CAST_TYPE      0x03
+/*
+ * map type:
+ *   00 not a map type (mem_start, io_addr, irq)
+ *   04 memstart (unsigned long)
+ *   08 io_addr  (unsigned short)
+ *   0C irq      (unsigned char)
+ */
+#define A_MAP_TYPE       0x0C
+#define A_ARG_REQ        0x10	/* Set if an arg is required. */
+#define A_NETMASK        0x20	/* Set if netmask (check for multiple sets). */
+#define A_SET_AFTER      0x40	/* Set a flag at the end. */
+#define A_COLON_CHK      0x80	/* Is this needed?  See below. */
+#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS
+#define A_HOSTNAME      0x100	/* Set if it is ip addr. */
+#define A_BROADCAST     0x200	/* Set if it is broadcast addr. */
+#else
+#define A_HOSTNAME          0
+#define A_BROADCAST         0
+#endif
+
+/*
+ * These defines are for dealing with the A_CAST_TYPE field.
+ */
+#define A_CAST_CHAR_PTR  0x01
+#define A_CAST_RESOLVE   0x01
+#define A_CAST_HOST_COPY 0x02
+#define A_CAST_HOST_COPY_IN_ETHER    A_CAST_HOST_COPY
+#define A_CAST_HOST_COPY_RESOLVE     (A_CAST_HOST_COPY | A_CAST_RESOLVE)
+
+/*
+ * These defines are for dealing with the A_MAP_TYPE field.
+ */
+#define A_MAP_ULONG      0x04	/* memstart */
+#define A_MAP_USHORT     0x08	/* io_addr */
+#define A_MAP_UCHAR      0x0C	/* irq */
+
+/*
+ * Define the bit masks signifying which operations to perform for each arg.
+ */
+
+#define ARG_METRIC       (A_ARG_REQ /*| A_CAST_INT*/)
+#define ARG_MTU          (A_ARG_REQ /*| A_CAST_INT*/)
+#define ARG_TXQUEUELEN   (A_ARG_REQ /*| A_CAST_INT*/)
+#define ARG_MEM_START    (A_ARG_REQ | A_MAP_ULONG)
+#define ARG_IO_ADDR      (A_ARG_REQ | A_MAP_ULONG)
+#define ARG_IRQ          (A_ARG_REQ | A_MAP_UCHAR)
+#define ARG_DSTADDR      (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE)
+#define ARG_NETMASK      (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE | A_NETMASK)
+#define ARG_BROADCAST    (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER | A_BROADCAST)
+#define ARG_HW           (A_ARG_REQ | A_CAST_HOST_COPY_IN_ETHER)
+#define ARG_POINTOPOINT  (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER)
+#define ARG_KEEPALIVE    (A_ARG_REQ | A_CAST_CHAR_PTR)
+#define ARG_OUTFILL      (A_ARG_REQ | A_CAST_CHAR_PTR)
+#define ARG_HOSTNAME     (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER | A_COLON_CHK | A_HOSTNAME)
+#define ARG_ADD_DEL      (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER)
+
+
+/*
+ * Set up the tables.  Warning!  They must have corresponding order!
+ */
+
+struct arg1opt {
+	const char *name;
+	int selector;
+	unsigned short ifr_offset;
+};
+
+struct options {
+	const char *name;
+#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS
+	const unsigned int flags:6;
+	const unsigned int arg_flags:10;
+#else
+	const unsigned char flags;
+	const unsigned char arg_flags;
+#endif
+	const unsigned short selector;
+};
+
+#define ifreq_offsetof(x)  offsetof(struct ifreq, x)
+
+static const struct arg1opt Arg1Opt[] = {
+	{"SIOCSIFMETRIC",  SIOCSIFMETRIC,  ifreq_offsetof(ifr_metric)},
+	{"SIOCSIFMTU",     SIOCSIFMTU,     ifreq_offsetof(ifr_mtu)},
+	{"SIOCSIFTXQLEN",  SIOCSIFTXQLEN,  ifreq_offsetof(ifr_qlen)},
+	{"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)},
+	{"SIOCSIFNETMASK", SIOCSIFNETMASK, ifreq_offsetof(ifr_netmask)},
+	{"SIOCSIFBRDADDR", SIOCSIFBRDADDR, ifreq_offsetof(ifr_broadaddr)},
+#ifdef CONFIG_FEATURE_IFCONFIG_HW
+	{"SIOCSIFHWADDR",  SIOCSIFHWADDR,  ifreq_offsetof(ifr_hwaddr)},
+#endif
+	{"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)},
+#ifdef SIOCSKEEPALIVE
+	{"SIOCSKEEPALIVE", SIOCSKEEPALIVE, ifreq_offsetof(ifr_data)},
+#endif
+#ifdef SIOCSOUTFILL
+	{"SIOCSOUTFILL",   SIOCSOUTFILL,   ifreq_offsetof(ifr_data)},
+#endif
+#ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
+	{"SIOCSIFMAP",     SIOCSIFMAP,     ifreq_offsetof(ifr_map.mem_start)},
+	{"SIOCSIFMAP",     SIOCSIFMAP,     ifreq_offsetof(ifr_map.base_addr)},
+	{"SIOCSIFMAP",     SIOCSIFMAP,     ifreq_offsetof(ifr_map.irq)},
+#endif
+	/* Last entry if for unmatched (possibly hostname) arg. */
+#ifdef CONFIG_FEATURE_IPV6
+	{"SIOCSIFADDR",    SIOCSIFADDR,    ifreq_offsetof(ifr_addr)}, /* IPv6 version ignores the offset */
+	{"SIOCDIFADDR",    SIOCDIFADDR,    ifreq_offsetof(ifr_addr)}, /* IPv6 version ignores the offset */
+#endif
+	{"SIOCSIFADDR",    SIOCSIFADDR,    ifreq_offsetof(ifr_addr)},
+};
+
+static const struct options OptArray[] = {
+	{"metric",      N_ARG,         ARG_METRIC,      0},
+	{"mtu",         N_ARG,         ARG_MTU,         0},
+	{"txqueuelen",  N_ARG,         ARG_TXQUEUELEN,  0},
+	{"dstaddr",     N_ARG,         ARG_DSTADDR,     0},
+	{"netmask",     N_ARG,         ARG_NETMASK,     0},
+	{"broadcast",   N_ARG | M_CLR, ARG_BROADCAST,   IFF_BROADCAST},
+#ifdef CONFIG_FEATURE_IFCONFIG_HW
+	{"hw",          N_ARG, ARG_HW,                  0},
+#endif
+	{"pointopoint", N_ARG | M_CLR, ARG_POINTOPOINT, IFF_POINTOPOINT},
+#ifdef SIOCSKEEPALIVE
+	{"keepalive",   N_ARG,         ARG_KEEPALIVE,   0},
+#endif
+#ifdef SIOCSOUTFILL
+	{"outfill",     N_ARG,         ARG_OUTFILL,     0},
+#endif
+#ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
+	{"mem_start",   N_ARG,         ARG_MEM_START,   0},
+	{"io_addr",     N_ARG,         ARG_IO_ADDR,     0},
+	{"irq",         N_ARG,         ARG_IRQ,         0},
+#endif
+#ifdef CONFIG_FEATURE_IPV6
+	{"add",         N_ARG,         ARG_ADD_DEL,     0},
+	{"del",         N_ARG,         ARG_ADD_DEL,     0},
+#endif
+	{"arp",         N_CLR | M_SET, 0,               IFF_NOARP},
+	{"trailers",    N_CLR | M_SET, 0,               IFF_NOTRAILERS},
+	{"promisc",     N_SET | M_CLR, 0,               IFF_PROMISC},
+	{"multicast",   N_SET | M_CLR, 0,               IFF_MULTICAST},
+	{"allmulti",    N_SET | M_CLR, 0,               IFF_ALLMULTI},
+	{"dynamic",     N_SET | M_CLR, 0,               IFF_DYNAMIC},
+	{"up",          N_SET,         0,               (IFF_UP | IFF_RUNNING)},
+	{"down",        N_CLR,         0,               IFF_UP},
+	{NULL,          0,             ARG_HOSTNAME,    (IFF_UP | IFF_RUNNING)}
+};
+
+/*
+ * A couple of prototypes.
+ */
+
+#ifdef CONFIG_FEATURE_IFCONFIG_HW
+static int in_ether(char *bufp, struct sockaddr *sap);
+#endif
+
+#ifdef CONFIG_FEATURE_IFCONFIG_STATUS
+extern int interface_opt_a;
+extern int display_interfaces(char *ifname);
+#endif
+
+/*
+ * Our main function.
+ */
+
+int ifconfig_main(int argc, char **argv)
+{
+	struct ifreq ifr;
+	struct sockaddr_in sai;
+#ifdef CONFIG_FEATURE_IPV6
+	struct sockaddr_in6 sai6;
+#endif
+#ifdef CONFIG_FEATURE_IFCONFIG_HW
+	struct sockaddr sa;
+#endif
+	const struct arg1opt *a1op;
+	const struct options *op;
+	int sockfd;			/* socket fd we use to manipulate stuff with */
+	int goterr;
+	int selector;
+#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS
+	unsigned int mask;
+	unsigned int did_flags;
+	unsigned int sai_hostname, sai_netmask;
+#else
+	unsigned char mask;
+	unsigned char did_flags;
+#endif
+	char *p;
+	char host[128];
+
+	goterr = 0;
+	did_flags = 0;
+#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS
+	sai_hostname = 0;
+	sai_netmask = 0;
+#endif
+
+	/* skip argv[0] */
+	++argv;
+	--argc;
+
+#ifdef CONFIG_FEATURE_IFCONFIG_STATUS
+	if ((argc > 0) && (((*argv)[0] == '-') && ((*argv)[1] == 'a') && !(*argv)[2])) {
+		interface_opt_a = 1;
+		--argc;
+		++argv;
+	}
+#endif
+
+	if (argc <= 1) {
+#ifdef CONFIG_FEATURE_IFCONFIG_STATUS
+		return display_interfaces(argc ? *argv : NULL);
+#else
+		bb_error_msg_and_die
+			("ifconfig was not compiled with interface status display support.");
+#endif
+	}
+
+	/* Create a channel to the NET kernel. */
+	sockfd = bb_xsocket(AF_INET, SOCK_DGRAM, 0);
+
+	/* get interface name */
+	safe_strncpy(ifr.ifr_name, *argv, IFNAMSIZ);
+
+	/* Process the remaining arguments. */
+	while (*++argv != (char *) NULL) {
+		p = *argv;
+		mask = N_MASK;
+		if (*p == '-') {	/* If the arg starts with '-'... */
+			++p;		/*    advance past it and */
+			mask = M_MASK;	/*    set the appropriate mask. */
+		}
+		for (op = OptArray; op->name; op++) {	/* Find table entry. */
+			if (strcmp(p, op->name) == 0) {	/* If name matches... */
+				if ((mask &= op->flags)) {	/* set the mask and go. */
+					goto FOUND_ARG;
+				}
+				/* If we get here, there was a valid arg with an */
+				/* invalid '-' prefix. */
+				++goterr;
+				goto LOOP;
+			}
+		}
+
+		/* We fell through, so treat as possible hostname. */
+		a1op = Arg1Opt + (sizeof(Arg1Opt) / sizeof(Arg1Opt[0])) - 1;
+		mask = op->arg_flags;
+		goto HOSTNAME;
+
+	  FOUND_ARG:
+		if (mask & ARG_MASK) {
+			mask = op->arg_flags;
+			a1op = Arg1Opt + (op - OptArray);
+			if (mask & A_NETMASK & did_flags) {
+				bb_show_usage();
+			}
+			if (*++argv == NULL) {
+				if (mask & A_ARG_REQ) {
+					bb_show_usage();
+				} else {
+					--argv;
+					mask &= A_SET_AFTER;	/* just for broadcast */
+				}
+			} else {	/* got an arg so process it */
+			  HOSTNAME:
+				did_flags |= (mask & (A_NETMASK|A_HOSTNAME));
+				if (mask & A_CAST_HOST_COPY) {
+#ifdef CONFIG_FEATURE_IFCONFIG_HW
+					if (mask & A_CAST_RESOLVE) {
+#endif
+#ifdef CONFIG_FEATURE_IPV6
+						char *prefix;
+						int prefix_len = 0;
+#endif
+
+						safe_strncpy(host, *argv, (sizeof host));
+#ifdef CONFIG_FEATURE_IPV6
+						if ((prefix = strchr(host, '/'))) {
+							if (safe_strtoi(prefix + 1, &prefix_len) ||
+								(prefix_len < 0) || (prefix_len > 128))
+							{
+								++goterr;
+								goto LOOP;
+							}
+							*prefix = 0;
+						}
+#endif
+
+						sai.sin_family = AF_INET;
+						sai.sin_port = 0;
+						if (!strcmp(host, bb_INET_default)) {
+							/* Default is special, meaning 0.0.0.0. */
+							sai.sin_addr.s_addr = INADDR_ANY;
+#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS
+						} else if (((host[0] == '+') && !host[1]) && (mask & A_BROADCAST) &&
+								   (did_flags & (A_NETMASK|A_HOSTNAME)) == (A_NETMASK|A_HOSTNAME)) {
+							/* + is special, meaning broadcast is derived. */
+							sai.sin_addr.s_addr = (~sai_netmask) | (sai_hostname & sai_netmask);
+#endif
+#ifdef CONFIG_FEATURE_IPV6
+						} else if (inet_pton(AF_INET6, host, &sai6.sin6_addr) > 0) {
+							int sockfd6;
+							struct in6_ifreq ifr6;
+
+							memcpy((char *) &ifr6.ifr6_addr,
+								   (char *) &sai6.sin6_addr,
+								   sizeof(struct in6_addr));
+
+							/* Create a channel to the NET kernel. */
+							if ((sockfd6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+								bb_perror_msg_and_die("socket6");
+							}
+							if (ioctl(sockfd6, SIOGIFINDEX, &ifr) < 0) {
+								perror("SIOGIFINDEX");
+								++goterr;
+								continue;
+							}
+							ifr6.ifr6_ifindex = ifr.ifr_ifindex;
+							ifr6.ifr6_prefixlen = prefix_len;
+							if (ioctl(sockfd6, a1op->selector, &ifr6) < 0) {
+								perror(a1op->name);
+								++goterr;
+							}
+							continue;
+#endif
+						} else if (inet_aton(host, &sai.sin_addr) == 0) {
+							/* It's not a dotted quad. */
+							struct hostent *hp;
+							if ((hp = gethostbyname(host)) == (struct hostent *)NULL) {
+								++goterr;
+								continue;
+							}
+							memcpy((char *) &sai.sin_addr, (char *) hp->h_addr_list[0],
+							sizeof(struct in_addr));
+						}
+#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS
+						if (mask & A_HOSTNAME) {
+							sai_hostname = sai.sin_addr.s_addr;
+						}
+						if (mask & A_NETMASK) {
+							sai_netmask = sai.sin_addr.s_addr;
+						}
+#endif
+						p = (char *) &sai;
+#ifdef CONFIG_FEATURE_IFCONFIG_HW
+					} else {	/* A_CAST_HOST_COPY_IN_ETHER */
+						/* This is the "hw" arg case. */
+						if (strcmp("ether", *argv) || (*++argv == NULL)) {
+							bb_show_usage();
+						}
+						safe_strncpy(host, *argv, (sizeof host));
+						if (in_ether(host, &sa)) {
+							bb_error_msg("invalid hw-addr %s", host);
+							++goterr;
+							continue;
+						}
+						p = (char *) &sa;
+					}
+#endif
+					memcpy((((char *) (&ifr)) + a1op->ifr_offset),
+						   p, sizeof(struct sockaddr));
+				} else {
+					unsigned long i = strtoul(*argv, NULL, 0);
+
+					p = ((char *) (&ifr)) + a1op->ifr_offset;
+#ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
+					if (mask & A_MAP_TYPE) {
+						if (ioctl(sockfd, SIOCGIFMAP, &ifr) < 0) {
+							++goterr;
+							continue;
+						}
+						if ((mask & A_MAP_UCHAR) == A_MAP_UCHAR) {
+							*((unsigned char *) p) = i;
+						} else if (mask & A_MAP_USHORT) {
+							*((unsigned short *) p) = i;
+						} else {
+							*((unsigned long *) p) = i;
+						}
+					} else
+#endif
+					if (mask & A_CAST_CHAR_PTR) {
+						*((caddr_t *) p) = (caddr_t) i;
+					} else {	/* A_CAST_INT */
+						*((int *) p) = i;
+					}
+				}
+
+				if (ioctl(sockfd, a1op->selector, &ifr) < 0) {
+					perror(a1op->name);
+					++goterr;
+					continue;
+				}
+#ifdef QUESTIONABLE_ALIAS_CASE
+				if (mask & A_COLON_CHK) {
+					/*
+					 * Don't do the set_flag() if the address is an alias with
+					 * a - at the end, since it's deleted already! - Roman
+					 *
+					 * Should really use regex.h here, not sure though how well
+					 * it'll go with the cross-platform support etc.
+					 */
+					char *ptr;
+					short int found_colon = 0;
+
+					for (ptr = ifr.ifr_name; *ptr; ptr++) {
+						if (*ptr == ':') {
+							found_colon++;
+						}
+					}
+
+					if (found_colon && *(ptr - 1) == '-') {
+						continue;
+					}
+				}
+#endif
+			}
+			if (!(mask & A_SET_AFTER)) {
+				continue;
+			}
+			mask = N_SET;
+		}
+
+		if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
+			perror("SIOCGIFFLAGS");
+			++goterr;
+		} else {
+			selector = op->selector;
+			if (mask & SET_MASK) {
+				ifr.ifr_flags |= selector;
+			} else {
+				ifr.ifr_flags &= ~selector;
+			}
+			if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
+				perror("SIOCSIFFLAGS");
+				++goterr;
+			}
+		}
+	  LOOP:
+		continue;
+	}					/* end of while-loop */
+
+	if (ENABLE_FEATURE_CLEAN_UP) close(sockfd);
+	return goterr;
+}
+
+#ifdef CONFIG_FEATURE_IFCONFIG_HW
+/* Input an Ethernet address and convert to binary. */
+static int in_ether(char *bufp, struct sockaddr *sap)
+{
+	char *ptr;
+	int i, j;
+	unsigned char val;
+	unsigned char c;
+
+	sap->sa_family = ARPHRD_ETHER;
+	ptr = sap->sa_data;
+
+	i = 0;
+	do {
+		j = val = 0;
+
+		/* We might get a semicolon here - not required. */
+		if (i && (*bufp == ':')) {
+			bufp++;
+		}
+
+		do {
+			c = *bufp;
+			if (((unsigned char)(c - '0')) <= 9) {
+				c -= '0';
+			} else if (((unsigned char)((c|0x20) - 'a')) <= 5) {
+				c = (c|0x20) - ('a'-10);
+			} else if (j && (c == ':' || c == 0)) {
+				break;
+			} else {
+				return -1;
+			}
+			++bufp;
+			val <<= 4;
+			val += c;
+		} while (++j < 2);
+		*ptr++ = val;
+	} while (++i < ETH_ALEN);
+
+	return (int) (*bufp);	/* Error if we don't end at end of string. */
+}
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ifupdown.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ifupdown.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ifupdown.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1302 @@
+/* vi: set sw=4 ts=4: */
+/*
+ *  ifupdown for busybox
+ *  Copyright (c) 2002 Glenn McGrath <bug1 at iinet.net.au>
+ *  Copyright (c) 2003-2004 Erik Andersen <andersen at codepoet.org>
+ *
+ *  Based on ifupdown v 0.6.4 by Anthony Towns
+ *  Copyright (c) 1999 Anthony Towns <aj at azure.humbug.org.au>
+ *
+ *  Changes to upstream version
+ *  Remove checks for kernel version, assume kernel version 2.2.0 or better.
+ *  Lines in the interfaces file cannot wrap.
+ *  To adhere to the FHS, the default state file is /var/run/ifstate.
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+/* TODO: standardise execute() return codes to return 0 for success and 1 for failure */
+
+#include <sys/stat.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "busybox.h"
+
+#define MAX_OPT_DEPTH 10
+#define EUNBALBRACK 10001
+#define EUNDEFVAR   10002
+#define EUNBALPER   10000
+
+#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
+#define MAX_INTERFACE_LENGTH 10
+#endif
+
+#if 0
+#define debug_noise(fmt, args...) printf(fmt, ## args)
+#else
+#define debug_noise(fmt, args...)
+#endif
+
+/* Forward declaration */
+struct interface_defn_t;
+
+typedef int (execfn)(char *command);
+
+struct method_t
+{
+	char *name;
+	int (*up)(struct interface_defn_t *ifd, execfn *e);
+	int (*down)(struct interface_defn_t *ifd, execfn *e);
+};
+
+struct address_family_t
+{
+	char *name;
+	int n_methods;
+	struct method_t *method;
+};
+
+struct mapping_defn_t
+{
+	struct mapping_defn_t *next;
+
+	int max_matches;
+	int n_matches;
+	char **match;
+
+	char *script;
+
+	int max_mappings;
+	int n_mappings;
+	char **mapping;
+};
+
+struct variable_t
+{
+	char *name;
+	char *value;
+};
+
+struct interface_defn_t
+{
+	struct address_family_t *address_family;
+	struct method_t *method;
+
+	char *iface;
+	int max_options;
+	int n_options;
+	struct variable_t *option;
+};
+
+struct interfaces_file_t
+{
+	llist_t *autointerfaces;
+	llist_t *ifaces;
+	struct mapping_defn_t *mappings;
+};
+
+static char no_act = 0;
+static char verbose = 0;
+static char **__myenviron = NULL;
+
+#if ENABLE_FEATURE_IFUPDOWN_IPV4 || ENABLE_FEATURE_IFUPDOWN_IPV6
+
+#ifdef CONFIG_FEATURE_IFUPDOWN_IP
+
+static unsigned int count_bits(unsigned int a)
+{
+	unsigned int result;
+	result = (a & 0x55) + ((a >> 1) & 0x55);
+	result = (result & 0x33) + ((result >> 2) & 0x33);
+	return((result & 0x0F) + ((result >> 4) & 0x0F));
+}
+
+static int count_netmask_bits(char *dotted_quad)
+{
+	unsigned int result, a, b, c, d;
+	/* Found a netmask...  Check if it is dotted quad */
+	if (sscanf(dotted_quad, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
+		return -1;
+	result = count_bits(a);
+	result += count_bits(b);
+	result += count_bits(c);
+	result += count_bits(d);
+	return ((int)result);
+}
+#endif
+
+static void addstr(char **buf, size_t *len, size_t *pos, char *str, size_t str_length)
+{
+	if (*pos + str_length >= *len) {
+		char *newbuf;
+
+		newbuf = xrealloc(*buf, *len * 2 + str_length + 1);
+		*buf = newbuf;
+		*len = *len * 2 + str_length + 1;
+	}
+
+	while (str_length-- >= 1) {
+		(*buf)[(*pos)++] = *str;
+		str++;
+	}
+	(*buf)[*pos] = '\0';
+}
+
+static int strncmpz(char *l, char *r, size_t llen)
+{
+	int i = strncmp(l, r, llen);
+
+	if (i == 0) {
+		return(-r[llen]);
+	} else {
+		return(i);
+	}
+}
+
+static char *get_var(char *id, size_t idlen, struct interface_defn_t *ifd)
+{
+	int i;
+
+	if (strncmpz(id, "iface", idlen) == 0) {
+		char *result;
+		static char label_buf[20];
+		strncpy(label_buf, ifd->iface, 19);
+		label_buf[19]=0;
+		result = strchr(label_buf, ':');
+		if (result) {
+			*result=0;
+		}
+		return( label_buf);
+	} else if (strncmpz(id, "label", idlen) == 0) {
+		return (ifd->iface);
+	} else {
+		for (i = 0; i < ifd->n_options; i++) {
+			if (strncmpz(id, ifd->option[i].name, idlen) == 0) {
+				return (ifd->option[i].value);
+			}
+		}
+	}
+
+	return(NULL);
+}
+
+static char *parse(char *command, struct interface_defn_t *ifd)
+{
+
+	char *result = NULL;
+	size_t pos = 0, len = 0;
+	size_t old_pos[MAX_OPT_DEPTH] = { 0 };
+	int okay[MAX_OPT_DEPTH] = { 1 };
+	int opt_depth = 1;
+
+	while (*command) {
+		switch (*command) {
+
+			default:
+				addstr(&result, &len, &pos, command, 1);
+				command++;
+				break;
+			case '\\':
+				if (command[1]) {
+					addstr(&result, &len, &pos, command + 1, 1);
+					command += 2;
+				} else {
+					addstr(&result, &len, &pos, command, 1);
+					command++;
+				}
+				break;
+			case '[':
+				if (command[1] == '[' && opt_depth < MAX_OPT_DEPTH) {
+					old_pos[opt_depth] = pos;
+					okay[opt_depth] = 1;
+					opt_depth++;
+					command += 2;
+				} else {
+					addstr(&result, &len, &pos, "[", 1);
+					command++;
+				}
+				break;
+			case ']':
+				if (command[1] == ']' && opt_depth > 1) {
+					opt_depth--;
+					if (!okay[opt_depth]) {
+						pos = old_pos[opt_depth];
+						result[pos] = '\0';
+					}
+					command += 2;
+				} else {
+					addstr(&result, &len, &pos, "]", 1);
+					command++;
+				}
+				break;
+			case '%':
+				{
+					char *nextpercent;
+					char *varvalue;
+
+					command++;
+					nextpercent = strchr(command, '%');
+					if (!nextpercent) {
+						errno = EUNBALPER;
+						free(result);
+						return (NULL);
+					}
+
+					varvalue = get_var(command, nextpercent - command, ifd);
+
+					if (varvalue) {
+						addstr(&result, &len, &pos, varvalue, strlen(varvalue));
+					} else {
+#ifdef CONFIG_FEATURE_IFUPDOWN_IP
+						/* Sigh...  Add a special case for 'ip' to convert from
+						 * dotted quad to bit count style netmasks.  */
+						if (strncmp(command, "bnmask", 6)==0) {
+							int res;
+							varvalue = get_var("netmask", 7, ifd);
+							if (varvalue && (res=count_netmask_bits(varvalue)) > 0) {
+								char argument[255];
+								sprintf(argument, "%d", res);
+								addstr(&result, &len, &pos, argument, strlen(argument));
+								command = nextpercent + 1;
+								break;
+							}
+						}
+#endif
+						okay[opt_depth - 1] = 0;
+					}
+
+					command = nextpercent + 1;
+				}
+				break;
+		}
+	}
+
+	if (opt_depth > 1) {
+		errno = EUNBALBRACK;
+		free(result);
+		return(NULL);
+	}
+
+	if (!okay[0]) {
+		errno = EUNDEFVAR;
+		free(result);
+		return(NULL);
+	}
+
+	return(result);
+}
+
+static int execute(char *command, struct interface_defn_t *ifd, execfn *exec)
+{
+	char *out;
+	int ret;
+
+	out = parse(command, ifd);
+	if (!out) {
+		return(0);
+	}
+	ret = (*exec) (out);
+
+	free(out);
+	if (ret != 1) {
+		return(0);
+	}
+	return(1);
+}
+#endif
+
+#ifdef CONFIG_FEATURE_IFUPDOWN_IPV6
+static int loopback_up6(struct interface_defn_t *ifd, execfn *exec)
+{
+#ifdef CONFIG_FEATURE_IFUPDOWN_IP
+	int result;
+	result =execute("ip addr add ::1 dev %iface%", ifd, exec);
+	result += execute("ip link set %iface% up", ifd, exec);
+	return ((result == 2) ? 2 : 0);
+#else
+	return( execute("ifconfig %iface% add ::1", ifd, exec));
+#endif
+}
+
+static int loopback_down6(struct interface_defn_t *ifd, execfn *exec)
+{
+#ifdef CONFIG_FEATURE_IFUPDOWN_IP
+	return(execute("ip link set %iface% down", ifd, exec));
+#else
+	return(execute("ifconfig %iface% del ::1", ifd, exec));
+#endif
+}
+
+static int static_up6(struct interface_defn_t *ifd, execfn *exec)
+{
+	int result;
+#ifdef CONFIG_FEATURE_IFUPDOWN_IP
+	result = execute("ip addr add %address%/%netmask% dev %iface% [[label %label%]]", ifd, exec);
+	result += execute("ip link set [[mtu %mtu%]] [[address %hwaddress%]] %iface% up", ifd, exec);
+	result += execute("[[ ip route add ::/0 via %gateway% ]]", ifd, exec);
+#else
+	result = execute("ifconfig %iface% [[media %media%]] [[hw %hwaddress%]] [[mtu %mtu%]] up", ifd, exec);
+	result += execute("ifconfig %iface% add %address%/%netmask%", ifd, exec);
+	result += execute("[[ route -A inet6 add ::/0 gw %gateway% ]]", ifd, exec);
+#endif
+	return ((result == 3) ? 3 : 0);
+}
+
+static int static_down6(struct interface_defn_t *ifd, execfn *exec)
+{
+#ifdef CONFIG_FEATURE_IFUPDOWN_IP
+	return(execute("ip link set %iface% down", ifd, exec));
+#else
+	return(execute("ifconfig %iface% down", ifd, exec));
+#endif
+}
+
+#ifdef CONFIG_FEATURE_IFUPDOWN_IP
+static int v4tunnel_up(struct interface_defn_t *ifd, execfn *exec)
+{
+	int result;
+	result = execute("ip tunnel add %iface% mode sit remote "
+				"%endpoint% [[local %local%]] [[ttl %ttl%]]", ifd, exec);
+	result += execute("ip link set %iface% up", ifd, exec);
+	result += execute("ip addr add %address%/%netmask% dev %iface%", ifd, exec);
+	result += execute("[[ ip route add ::/0 via %gateway% ]]", ifd, exec);
+	return ((result == 4) ? 4 : 0);
+}
+
+static int v4tunnel_down(struct interface_defn_t * ifd, execfn * exec)
+{
+	return( execute("ip tunnel del %iface%", ifd, exec));
+}
+#endif
+
+static struct method_t methods6[] = {
+#ifdef CONFIG_FEATURE_IFUPDOWN_IP
+	{ "v4tunnel", v4tunnel_up, v4tunnel_down, },
+#endif
+	{ "static", static_up6, static_down6, },
+	{ "loopback", loopback_up6, loopback_down6, },
+};
+
+static struct address_family_t addr_inet6 = {
+	"inet6",
+	sizeof(methods6) / sizeof(struct method_t),
+	methods6
+};
+#endif /* CONFIG_FEATURE_IFUPDOWN_IPV6 */
+
+#ifdef CONFIG_FEATURE_IFUPDOWN_IPV4
+static int loopback_up(struct interface_defn_t *ifd, execfn *exec)
+{
+#ifdef CONFIG_FEATURE_IFUPDOWN_IP
+	int result;
+	result = execute("ip addr add 127.0.0.1/8 dev %iface%", ifd, exec);
+	result += execute("ip link set %iface% up", ifd, exec);
+	return ((result == 2) ? 2 : 0);
+#else
+	return( execute("ifconfig %iface% 127.0.0.1 up", ifd, exec));
+#endif
+}
+
+static int loopback_down(struct interface_defn_t *ifd, execfn *exec)
+{
+#ifdef CONFIG_FEATURE_IFUPDOWN_IP
+	int result;
+	result = execute("ip addr flush dev %iface%", ifd, exec);
+	result += execute("ip link set %iface% down", ifd, exec);
+	return ((result == 2) ? 2 : 0);
+#else
+	return( execute("ifconfig %iface% 127.0.0.1 down", ifd, exec));
+#endif
+}
+
+static int static_up(struct interface_defn_t *ifd, execfn *exec)
+{
+	int result;
+#ifdef CONFIG_FEATURE_IFUPDOWN_IP
+	result = execute("ip addr add %address%/%bnmask% [[broadcast %broadcast%]] "
+			"dev %iface% [[peer %pointopoint%]] [[label %label%]]", ifd, exec);
+	result += execute("ip link set [[mtu %mtu%]] [[address %hwaddress%]] %iface% up", ifd, exec);
+	result += execute("[[ ip route add default via %gateway% dev %iface% ]]", ifd, exec);
+	return ((result == 3) ? 3 : 0);
+#else
+	result = execute("ifconfig %iface% %address% netmask %netmask% "
+				"[[broadcast %broadcast%]] [[pointopoint %pointopoint%]] "
+				"[[media %media%]] [[mtu %mtu%]] [[hw %hwaddress%]] up",
+				ifd, exec);
+	result += execute("[[ route add default gw %gateway% %iface% ]]", ifd, exec);
+	return ((result == 2) ? 2 : 0);
+#endif
+}
+
+static int static_down(struct interface_defn_t *ifd, execfn *exec)
+{
+	int result;
+#ifdef CONFIG_FEATURE_IFUPDOWN_IP
+	result = execute("ip addr flush dev %iface%", ifd, exec);
+	result += execute("ip link set %iface% down", ifd, exec);
+#else
+	result = execute("[[ route del default gw %gateway% %iface% ]]", ifd, exec);
+	result += execute("ifconfig %iface% down", ifd, exec);
+#endif
+	return ((result == 2) ? 2 : 0);
+}
+
+static int execable(char *program)
+{
+	struct stat buf;
+	if (0 == stat(program, &buf)) {
+		if (S_ISREG(buf.st_mode) && (S_IXUSR & buf.st_mode)) {
+			return(1);
+		}
+	}
+	return(0);
+}
+
+static int dhcp_up(struct interface_defn_t *ifd, execfn *exec)
+{
+	if (execable("/sbin/udhcpc")) {
+		return( execute("udhcpc -n -p /var/run/udhcpc.%iface%.pid -i "
+					"%iface% [[-H %hostname%]] [[-c %clientid%]]", ifd, exec));
+	} else if (execable("/sbin/pump")) {
+		return( execute("pump -i %iface% [[-h %hostname%]] [[-l %leasehours%]]", ifd, exec));
+	} else if (execable("/sbin/dhclient")) {
+		return( execute("dhclient -pf /var/run/dhclient.%iface%.pid %iface%", ifd, exec));
+	} else if (execable("/sbin/dhcpcd")) {
+		return( execute("dhcpcd [[-h %hostname%]] [[-i %vendor%]] [[-I %clientid%]] "
+					"[[-l %leasetime%]] %iface%", ifd, exec));
+	}
+	return(0);
+}
+
+static int dhcp_down(struct interface_defn_t *ifd, execfn *exec)
+{
+	int result = 0;
+	if (execable("/sbin/udhcpc")) {
+		/* SIGUSR2 forces udhcpc to release the current lease and go inactive,
+		 * and SIGTERM causes udhcpc to exit.  Signals are queued and processed
+		 * sequentially so we don't need to sleep */
+		result = execute("kill -USR2 `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", ifd, exec);
+		result += execute("kill -TERM `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", ifd, exec);
+	} else if (execable("/sbin/pump")) {
+		result = execute("pump -i %iface% -k", ifd, exec);
+	} else if (execable("/sbin/dhclient")) {
+		result = execute("kill -9 `cat /var/run/dhclient.%iface%.pid` 2>/dev/null", ifd, exec);
+	} else if (execable("/sbin/dhcpcd")) {
+		result = execute("dhcpcd -k %iface%", ifd, exec);
+	}
+	return (result || static_down(ifd, exec));
+}
+
+static int bootp_up(struct interface_defn_t *ifd, execfn *exec)
+{
+	return( execute("bootpc [[--bootfile %bootfile%]] --dev %iface% "
+				"[[--server %server%]] [[--hwaddr %hwaddr%]] "
+				"--returniffail --serverbcast", ifd, exec));
+}
+
+static int ppp_up(struct interface_defn_t *ifd, execfn *exec)
+{
+	return( execute("pon [[%provider%]]", ifd, exec));
+}
+
+static int ppp_down(struct interface_defn_t *ifd, execfn *exec)
+{
+	return( execute("poff [[%provider%]]", ifd, exec));
+}
+
+static int wvdial_up(struct interface_defn_t *ifd, execfn *exec)
+{
+	return( execute("/sbin/start-stop-daemon --start -x /usr/bin/wvdial "
+				"-p /var/run/wvdial.%iface% -b -m -- [[ %provider% ]]", ifd, exec));
+}
+
+static int wvdial_down(struct interface_defn_t *ifd, execfn *exec)
+{
+	return( execute("/sbin/start-stop-daemon --stop -x /usr/bin/wvdial "
+				"-p /var/run/wvdial.%iface% -s 2", ifd, exec));
+}
+
+static struct method_t methods[] =
+{
+	{ "wvdial", wvdial_up, wvdial_down, },
+	{ "ppp", ppp_up, ppp_down, },
+	{ "static", static_up, static_down, },
+	{ "bootp", bootp_up, static_down, },
+	{ "dhcp", dhcp_up, dhcp_down, },
+	{ "loopback", loopback_up, loopback_down, },
+};
+
+static struct address_family_t addr_inet =
+{
+	"inet",
+	sizeof(methods) / sizeof(struct method_t),
+	methods
+};
+
+#endif	/* ifdef CONFIG_FEATURE_IFUPDOWN_IPV4 */
+
+static char *next_word(char **buf)
+{
+	unsigned short length;
+	char *word;
+
+	if ((buf == NULL) || (*buf == NULL) || (**buf == '\0')) {
+		return NULL;
+	}
+
+	/* Skip over leading whitespace */
+	word = *buf;
+	while (isspace(*word)) {
+		++word;
+	}
+
+	/* Skip over comments */
+	if (*word == '#') {
+		return(NULL);
+	}
+
+	/* Find the length of this word */
+	length = strcspn(word, " \t\n");
+	if (length == 0) {
+		return(NULL);
+	}
+	*buf = word + length;
+	/*DBU:[dave at cray.com] if we are already at EOL dont't increment beyond it */
+	if (**buf) {
+		**buf = '\0';
+		(*buf)++;
+	}
+
+	return word;
+}
+
+static struct address_family_t *get_address_family(struct address_family_t *af[], char *name)
+{
+	int i;
+
+	for (i = 0; af[i]; i++) {
+		if (strcmp(af[i]->name, name) == 0) {
+			return af[i];
+		}
+	}
+	return NULL;
+}
+
+static struct method_t *get_method(struct address_family_t *af, char *name)
+{
+	int i;
+
+	for (i = 0; i < af->n_methods; i++) {
+		if (strcmp(af->method[i].name, name) == 0) {
+			return &af->method[i];
+		}
+	}
+	return(NULL);
+}
+
+static const llist_t *find_list_string(const llist_t *list, const char *string)
+{
+	while (list) {
+		if (strcmp(list->data, string) == 0) {
+			return(list);
+		}
+		list = list->link;
+	}
+	return(NULL);
+}
+
+static struct interfaces_file_t *read_interfaces(const char *filename)
+{
+#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
+	struct mapping_defn_t *currmap = NULL;
+#endif
+	struct interface_defn_t *currif = NULL;
+	struct interfaces_file_t *defn;
+	FILE *f;
+	char *firstword;
+	char *buf;
+
+	enum { NONE, IFACE, MAPPING } currently_processing = NONE;
+
+	defn = xzalloc(sizeof(struct interfaces_file_t));
+
+	f = bb_xfopen(filename, "r");
+
+	while ((buf = bb_get_chomped_line_from_file(f)) != NULL) {
+		char *buf_ptr = buf;
+
+		firstword = next_word(&buf_ptr);
+		if (firstword == NULL) {
+			free(buf);
+			continue;	/* blank line */
+		}
+
+		if (strcmp(firstword, "mapping") == 0) {
+#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
+			currmap = xzalloc(sizeof(struct mapping_defn_t));
+
+			while ((firstword = next_word(&buf_ptr)) != NULL) {
+				if (currmap->max_matches == currmap->n_matches) {
+					currmap->max_matches = currmap->max_matches * 2 + 1;
+					currmap->match = xrealloc(currmap->match, sizeof(currmap->match) * currmap->max_matches);
+				}
+
+				currmap->match[currmap->n_matches++] = bb_xstrdup(firstword);
+			}
+			currmap->max_mappings = 0;
+			currmap->n_mappings = 0;
+			currmap->mapping = NULL;
+			currmap->script = NULL;
+			{
+				struct mapping_defn_t **where = &defn->mappings;
+				while (*where != NULL) {
+					where = &(*where)->next;
+				}
+				*where = currmap;
+				currmap->next = NULL;
+			}
+			debug_noise("Added mapping\n");
+#endif
+			currently_processing = MAPPING;
+		} else if (strcmp(firstword, "iface") == 0) {
+			{
+				char *iface_name;
+				char *address_family_name;
+				char *method_name;
+				struct address_family_t *addr_fams[] = {
+#ifdef CONFIG_FEATURE_IFUPDOWN_IPV4
+					&addr_inet,
+#endif
+#ifdef CONFIG_FEATURE_IFUPDOWN_IPV6
+					&addr_inet6,
+#endif
+					NULL
+				};
+
+				currif = xzalloc(sizeof(struct interface_defn_t));
+				iface_name = next_word(&buf_ptr);
+				address_family_name = next_word(&buf_ptr);
+				method_name = next_word(&buf_ptr);
+
+				if (buf_ptr == NULL) {
+					bb_error_msg("too few parameters for line \"%s\"", buf);
+					return NULL;
+				}
+
+				/* ship any trailing whitespace */
+				while (isspace(*buf_ptr)) {
+					++buf_ptr;
+				}
+
+				if (buf_ptr[0] != '\0') {
+					bb_error_msg("too many parameters \"%s\"", buf);
+					return NULL;
+				}
+
+				currif->iface = bb_xstrdup(iface_name);
+
+				currif->address_family = get_address_family(addr_fams, address_family_name);
+				if (!currif->address_family) {
+					bb_error_msg("unknown address type \"%s\"", address_family_name);
+					return NULL;
+				}
+
+				currif->method = get_method(currif->address_family, method_name);
+				if (!currif->method) {
+					bb_error_msg("unknown method \"%s\"", method_name);
+					return NULL;
+				}
+
+
+				{
+					llist_t *iface_list;
+					for (iface_list = defn->ifaces; iface_list; iface_list = iface_list->link) {
+						struct interface_defn_t *tmp = (struct interface_defn_t *) iface_list->data;
+						if ((strcmp(tmp->iface, currif->iface) == 0) && 
+							(tmp->address_family == currif->address_family)) {
+							bb_error_msg("duplicate interface \"%s\"", tmp->iface);
+							return NULL;
+						}
+					}
+
+					llist_add_to_end(&(defn->ifaces), (char*)currif);
+				}
+				debug_noise("iface %s %s %s\n", currif->iface, address_family_name, method_name);
+			}
+			currently_processing = IFACE;
+		} else if (strcmp(firstword, "auto") == 0) {
+			while ((firstword = next_word(&buf_ptr)) != NULL) {
+
+				/* Check the interface isnt already listed */
+				if (find_list_string(defn->autointerfaces, firstword)) {
+					bb_perror_msg_and_die("interface declared auto twice \"%s\"", buf);
+				}
+
+				/* Add the interface to the list */
+				llist_add_to_end(&(defn->autointerfaces), bb_xstrdup(firstword));
+				debug_noise("\nauto %s\n", firstword);
+			}
+			currently_processing = NONE;
+		} else {
+			switch (currently_processing) {
+				case IFACE:
+					{
+						int i;
+
+						if (strlen(buf_ptr) == 0) {
+							bb_error_msg("option with empty value \"%s\"", buf);
+							return NULL;
+						}
+
+						if (strcmp(firstword, "up") != 0
+								&& strcmp(firstword, "down") != 0
+								&& strcmp(firstword, "pre-up") != 0
+								&& strcmp(firstword, "post-down") != 0) {
+							for (i = 0; i < currif->n_options; i++) {
+								if (strcmp(currif->option[i].name, firstword) == 0) {
+									bb_error_msg("duplicate option \"%s\"", buf);
+									return NULL;
+								}
+							}
+						}
+					}
+					if (currif->n_options >= currif->max_options) {
+						struct variable_t *opt;
+
+						currif->max_options = currif->max_options + 10;
+						opt = xrealloc(currif->option, sizeof(*opt) * currif->max_options);
+						currif->option = opt;
+					}
+					currif->option[currif->n_options].name = bb_xstrdup(firstword);
+					currif->option[currif->n_options].value = bb_xstrdup(buf_ptr);
+					if (!currif->option[currif->n_options].name) {
+						perror(filename);
+						return NULL;
+					}
+					if (!currif->option[currif->n_options].value) {
+						perror(filename);
+						return NULL;
+					}
+					debug_noise("\t%s=%s\n", currif->option[currif->n_options].name,
+							currif->option[currif->n_options].value);
+					currif->n_options++;
+					break;
+				case MAPPING:
+#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
+					if (strcmp(firstword, "script") == 0) {
+						if (currmap->script != NULL) {
+							bb_error_msg("duplicate script in mapping \"%s\"", buf);
+							return NULL;
+						} else {
+							currmap->script = bb_xstrdup(next_word(&buf_ptr));
+						}
+					} else if (strcmp(firstword, "map") == 0) {
+						if (currmap->max_mappings == currmap->n_mappings) {
+							currmap->max_mappings = currmap->max_mappings * 2 + 1;
+							currmap->mapping = xrealloc(currmap->mapping, sizeof(char *) * currmap->max_mappings);
+						}
+						currmap->mapping[currmap->n_mappings] = bb_xstrdup(next_word(&buf_ptr));
+						currmap->n_mappings++;
+					} else {
+						bb_error_msg("misplaced option \"%s\"", buf);
+						return NULL;
+					}
+#endif
+					break;
+				case NONE:
+				default:
+					bb_error_msg("misplaced option \"%s\"", buf);
+					return NULL;
+			}
+		}
+		free(buf);
+	}
+	if (ferror(f) != 0) {
+		bb_perror_msg_and_die("%s", filename);
+	}
+	fclose(f);
+
+	return defn;
+}
+
+static char *setlocalenv(char *format, const char *name, const char *value)
+{
+	char *result;
+	char *here;
+	char *there;
+
+	result = bb_xasprintf(format, name, value);
+
+	for (here = there = result; *there != '=' && *there; there++) {
+		if (*there == '-')
+			*there = '_';
+		if (isalpha(*there))
+			*there = toupper(*there);
+
+		if (isalnum(*there) || *there == '_') {
+			*here = *there;
+			here++;
+		}
+	}
+	memmove(here, there, strlen(there) + 1);
+
+	return result;
+}
+
+static void set_environ(struct interface_defn_t *iface, const char *mode)
+{
+	char **environend;
+	int i;
+	const int n_env_entries = iface->n_options + 5;
+	char **ppch;
+
+	if (__myenviron != NULL) {
+		for (ppch = __myenviron; *ppch; ppch++) {
+			free(*ppch);
+			*ppch = NULL;
+		}
+		free(__myenviron);
+	}
+	__myenviron = xzalloc(sizeof(char *) * (n_env_entries + 1 /* for final NULL */ ));
+	environend = __myenviron;
+
+	for (i = 0; i < iface->n_options; i++) {
+		if (strcmp(iface->option[i].name, "up") == 0
+				|| strcmp(iface->option[i].name, "down") == 0
+				|| strcmp(iface->option[i].name, "pre-up") == 0
+				|| strcmp(iface->option[i].name, "post-down") == 0) {
+			continue;
+		}
+		*(environend++) = setlocalenv("IF_%s=%s", iface->option[i].name, iface->option[i].value);
+	}
+
+	*(environend++) = setlocalenv("%s=%s", "IFACE", iface->iface);
+	*(environend++) = setlocalenv("%s=%s", "ADDRFAM", iface->address_family->name);
+	*(environend++) = setlocalenv("%s=%s", "METHOD", iface->method->name);
+	*(environend++) = setlocalenv("%s=%s", "MODE", mode);
+	*(environend++) = setlocalenv("%s=%s", "PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
+}
+
+static int doit(char *str)
+{
+	if (verbose || no_act) {
+		printf("%s\n", str);
+	}
+	if (!no_act) {
+		pid_t child;
+		int status;
+
+		fflush(NULL);
+		switch (child = fork()) {
+			case -1:		/* failure */
+				return 0;
+			case 0:		/* child */
+				execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, NULL, __myenviron);
+				exit(127);
+		}
+		waitpid(child, &status, 0);
+		if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+			return 0;
+		}
+	}
+	return (1);
+}
+
+static int execute_all(struct interface_defn_t *ifd, const char *opt)
+{
+	int i;
+	char *buf;
+	for (i = 0; i < ifd->n_options; i++) {
+		if (strcmp(ifd->option[i].name, opt) == 0) {
+			if (!doit(ifd->option[i].value)) {
+				return 0;
+			}
+		}
+	}
+
+	buf = bb_xasprintf("run-parts /etc/network/if-%s.d", opt);
+	if (doit(buf) != 1) {
+		return 0;
+	}
+	return 1;
+}
+
+static int check(char *str) {
+	return str != NULL;
+}
+
+static int iface_up(struct interface_defn_t *iface)
+{
+	if (!iface->method->up(iface,check)) return -1;
+	set_environ(iface, "start");
+	if (!execute_all(iface, "pre-up")) return 0;
+	if (!iface->method->up(iface, doit)) return 0;
+	if (!execute_all(iface, "up")) return 0;
+	return 1;
+}
+
+static int iface_down(struct interface_defn_t *iface)
+{
+	if (!iface->method->down(iface,check)) return -1;
+	set_environ(iface, "stop");
+	if (!execute_all(iface, "down")) return 0;
+	if (!iface->method->down(iface, doit)) return 0;
+	if (!execute_all(iface, "post-down")) return 0;
+	return 1;
+}
+
+#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
+static int popen2(FILE **in, FILE **out, char *command, ...)
+{
+	va_list ap;
+	char *argv[11] = { command };
+	int argc;
+	int infd[2], outfd[2];
+	pid_t pid;
+
+	argc = 1;
+	va_start(ap, command);
+	while ((argc < 10) && (argv[argc] = va_arg(ap, char *))) {
+		argc++;
+	}
+	argv[argc] = NULL;	/* make sure */
+	va_end(ap);
+
+	if (pipe(infd) != 0) {
+		return 0;
+	}
+
+	if (pipe(outfd) != 0) {
+		close(infd[0]);
+		close(infd[1]);
+		return 0;
+	}
+
+	fflush(NULL);
+	switch (pid = fork()) {
+		case -1:			/* failure */
+			close(infd[0]);
+			close(infd[1]);
+			close(outfd[0]);
+			close(outfd[1]);
+			return 0;
+		case 0:			/* child */
+			dup2(infd[0], 0);
+			dup2(outfd[1], 1);
+			close(infd[0]);
+			close(infd[1]);
+			close(outfd[0]);
+			close(outfd[1]);
+			execvp(command, argv);
+			exit(127);
+		default:			/* parent */
+			*in = fdopen(infd[1], "w");
+			*out = fdopen(outfd[0], "r");
+			close(infd[0]);
+			close(outfd[1]);
+			return pid;
+	}
+	/* unreached */
+}
+
+static char *run_mapping(char *physical, struct mapping_defn_t * map)
+{
+	FILE *in, *out;
+	int i, status;
+	pid_t pid;
+
+	char *logical = bb_xstrdup(physical);
+
+	/* Run the mapping script. */
+	pid = popen2(&in, &out, map->script, physical, NULL);
+
+	/* popen2() returns 0 on failure. */
+	if (pid == 0)
+		return logical;
+
+	/* Write mappings to stdin of mapping script. */
+	for (i = 0; i < map->n_mappings; i++) {
+		fprintf(in, "%s\n", map->mapping[i]);
+	}
+	fclose(in);
+	waitpid(pid, &status, 0);
+
+	if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+		/* If the mapping script exited successfully, try to
+		 * grab a line of output and use that as the name of the
+		 * logical interface. */
+		char *new_logical = (char *)xmalloc(MAX_INTERFACE_LENGTH);
+
+		if (fgets(new_logical, MAX_INTERFACE_LENGTH, out)) {
+			/* If we are able to read a line of output from the script,
+			 * remove any trailing whitespace and use this value
+			 * as the name of the logical interface. */
+			char *pch = new_logical + strlen(new_logical) - 1;
+
+			while (pch >= new_logical && isspace(*pch))
+				*(pch--) = '\0';
+
+			free(logical);
+			logical = new_logical;
+		} else {
+			/* If we are UNABLE to read a line of output, discard our
+			 * freshly allocated memory. */
+			free(new_logical);
+		}
+	}
+
+	fclose(out);
+
+	return logical;
+}
+#endif /* CONFIG_FEATURE_IFUPDOWN_MAPPING */
+
+static llist_t *find_iface_state(llist_t *state_list, const char *iface)
+{
+	unsigned short iface_len = strlen(iface);
+	llist_t *search = state_list;
+
+	while (search) {
+		if ((strncmp(search->data, iface, iface_len) == 0) &&
+				(search->data[iface_len] == '=')) {
+			return(search);
+		}
+		search = search->link;
+	}
+	return(NULL);
+}
+
+int ifupdown_main(int argc, char **argv)
+{
+	int (*cmds) (struct interface_defn_t *) = NULL;
+	struct interfaces_file_t *defn;
+	llist_t *state_list = NULL;
+	llist_t *target_list = NULL;
+	const char *interfaces = "/etc/network/interfaces";
+	const char *statefile = "/var/run/ifstate";
+
+#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
+	int run_mappings = 1;
+#endif
+	int do_all = 0;
+	int force = 0;
+	int any_failures = 0;
+	int i;
+
+	if (bb_applet_name[2] == 'u') {
+		/* ifup command */
+		cmds = iface_up;
+	} else {
+		/* ifdown command */
+		cmds = iface_down;
+	}
+
+#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
+	while ((i = getopt(argc, argv, "i:hvnamf")) != -1)
+#else
+		while ((i = getopt(argc, argv, "i:hvnaf")) != -1)
+#endif
+		{
+			switch (i) {
+				case 'i':	/* interfaces */
+					interfaces = optarg;
+					break;
+				case 'v':	/* verbose */
+					verbose = 1;
+					break;
+				case 'a':	/* all */
+					do_all = 1;
+					break;
+				case 'n':	/* no-act */
+					no_act = 1;
+					break;
+#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
+				case 'm':	/* no-mappings */
+					run_mappings = 0;
+					break;
+#endif
+				case 'f':	/* force */
+					force = 1;
+					break;
+				default:
+					bb_show_usage();
+					break;
+			}
+		}
+
+	if (argc - optind > 0) {
+		if (do_all) {
+			bb_show_usage();
+		}
+	} else {
+		if (!do_all) {
+			bb_show_usage();
+		}
+	}
+
+	debug_noise("reading %s file:\n", interfaces);
+	defn = read_interfaces(interfaces);
+	debug_noise("\ndone reading %s\n\n", interfaces);
+
+	if (!defn) {
+		exit(EXIT_FAILURE);
+	}
+
+	/* Create a list of interfaces to work on */
+	if (do_all) {
+		if (cmds == iface_up) {
+			target_list = defn->autointerfaces;
+		} else {
+			/* iface_down */
+			const llist_t *list = state_list;
+			while (list) {
+				llist_add_to_end(&target_list, bb_xstrdup(list->data));
+				list = list->link;
+			}
+			target_list = defn->autointerfaces;
+		}
+	} else {
+		llist_add_to_end(&target_list, argv[optind]);
+	}
+
+
+	/* Update the interfaces */
+	while (target_list) {
+		llist_t *iface_list;
+		struct interface_defn_t *currif;
+		char *iface;
+		char *liface;
+		char *pch;
+		int okay = 0;
+		int cmds_ret;
+
+		iface = bb_xstrdup(target_list->data);
+		target_list = target_list->link;
+
+		pch = strchr(iface, '=');
+		if (pch) {
+			*pch = '\0';
+			liface = bb_xstrdup(pch + 1);
+		} else {
+			liface = bb_xstrdup(iface);
+		}
+
+		if (!force) {
+			const llist_t *iface_state = find_iface_state(state_list, iface);
+
+			if (cmds == iface_up) {
+				/* ifup */
+				if (iface_state) {
+					bb_error_msg("interface %s already configured", iface);
+					continue;
+				}
+			} else {
+				/* ifdown */
+				if (iface_state) {
+					bb_error_msg("interface %s not configured", iface);
+					continue;
+				}
+			}
+		}
+
+#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
+		if ((cmds == iface_up) && run_mappings) {
+			struct mapping_defn_t *currmap;
+
+			for (currmap = defn->mappings; currmap; currmap = currmap->next) {
+
+				for (i = 0; i < currmap->n_matches; i++) {
+					if (fnmatch(currmap->match[i], liface, 0) != 0)
+						continue;
+					if (verbose) {
+						printf("Running mapping script %s on %s\n", currmap->script, liface);
+					}
+					liface = run_mapping(iface, currmap);
+					break;
+				}
+			}
+		}
+#endif
+
+
+		iface_list = defn->ifaces;
+		while (iface_list) {
+			currif = (struct interface_defn_t *) iface_list->data;
+			if (strcmp(liface, currif->iface) == 0) {
+				char *oldiface = currif->iface;
+
+				okay = 1;
+				currif->iface = iface;
+
+				debug_noise("\nConfiguring interface %s (%s)\n", liface, currif->address_family->name);
+
+				/* Call the cmds function pointer, does either iface_up() or iface_down() */
+				cmds_ret = cmds(currif);
+				if (cmds_ret == -1) {
+					bb_error_msg("Don't seem to have all the variables for %s/%s.",
+							liface, currif->address_family->name);
+					any_failures += 1;
+				} else if (cmds_ret == 0) {
+					any_failures += 1;
+				}
+
+				currif->iface = oldiface;
+			}
+			iface_list = iface_list->link;
+		}
+		if (verbose) {
+			printf("\n");
+		}
+
+		if (!okay && !force) {
+			bb_error_msg("Ignoring unknown interface %s", liface);
+			any_failures += 1;
+		} else {
+			llist_t *iface_state = find_iface_state(state_list, iface);
+
+			if (cmds == iface_up) {
+				char *newiface = bb_xasprintf("%s=%s", iface, liface);
+				if (iface_state == NULL) {
+					llist_add_to_end(&state_list, newiface);
+				} else {
+					free(iface_state->data);
+					iface_state->data = newiface;
+				}
+			} else {
+				/* Remove an interface from the linked list */
+				free(llist_pop(&iface_state));
+			}
+		}
+	}
+
+	/* Actually write the new state */
+	if (!no_act) {
+		FILE *state_fp = NULL;
+
+		state_fp = bb_xfopen(statefile, "w");
+		while (state_list) {
+			if (state_list->data) {
+				fputs(state_list->data, state_fp);
+				fputc('\n', state_fp);
+			}
+			state_list = state_list->link;
+		}
+		fclose(state_fp);
+	}
+
+	if (any_failures)
+		return 1;
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/inetd.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/inetd.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/inetd.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1804 @@
+/*      $Slackware: inetd.c 1.79s 2001/02/06 13:18:00 volkerdi Exp $    */
+/*      $OpenBSD: inetd.c,v 1.79 2001/01/30 08:30:57 deraadt Exp $      */
+/*      $NetBSD: inetd.c,v 1.11 1996/02/22 11:14:41 mycroft Exp $       */
+/* Busybox port by Vladimir Oleynik (C) 2001-2005 <dzo at simtreas.ru>     */
+/*
+ * Copyright (c) 1983,1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Inetd - Internet super-server
+ *
+ * This program invokes all internet services as needed.
+ * connection-oriented services are invoked each time a
+ * connection is made, by creating a process.  This process
+ * is passed the connection as file descriptor 0 and is
+ * expected to do a getpeername to find out the source host
+ * and port.
+ *
+ * Datagram oriented services are invoked when a datagram
+ * arrives; a process is created and passed a pending message
+ * on file descriptor 0.  Datagram servers may either connect
+ * to their peer, freeing up the original socket for inetd
+ * to receive further messages on, or ``take over the socket'',
+ * processing all arriving datagrams and, eventually, timing
+ * out.  The first type of server is said to be ``multi-threaded'';
+ * the second type of server ``single-threaded''.
+ *
+ * Inetd uses a configuration file which is read at startup
+ * and, possibly, at some later time in response to a hangup signal.
+ * The configuration file is ``free format'' with fields given in the
+ * order shown below.  Continuation lines for an entry must begin with
+ * a space or tab.  All fields must be present in each entry.
+ *
+ *      service name                    must be in /etc/services
+ *      socket type                     stream/dgram/raw/rdm/seqpacket
+ *      protocol                        must be in /etc/protocols
+ *      wait/nowait[.max]               single-threaded/multi-threaded, max #
+ *      user[.group] or user[:group]    user/group to run daemon as
+ *      server program                  full path name
+ *      server program arguments        maximum of MAXARGS (20)
+ *
+ * For RPC services
+ *      service name/version            must be in /etc/rpc
+ *      socket type                     stream/dgram/raw/rdm/seqpacket
+ *      protocol                        must be in /etc/protocols
+ *      wait/nowait[.max]               single-threaded/multi-threaded
+ *      user[.group] or user[:group]    user to run daemon as
+ *      server program                  full path name
+ *      server program arguments        maximum of MAXARGS (20)
+ *
+ * For non-RPC services, the "service name" can be of the form
+ * hostaddress:servicename, in which case the hostaddress is used
+ * as the host portion of the address to listen on.  If hostaddress
+ * consists of a single `*' character, INADDR_ANY is used.
+ *
+ * A line can also consist of just
+ *      hostaddress:
+ * where hostaddress is as in the preceding paragraph.  Such a line must
+ * have no further fields; the specified hostaddress is remembered and
+ * used for all further lines that have no hostaddress specified,
+ * until the next such line (or EOF).  (This is why * is provided to
+ * allow explicit specification of INADDR_ANY.)  A line
+ *      *:
+ * is implicitly in effect at the beginning of the file.
+ *
+ * The hostaddress specifier may (and often will) contain dots;
+ * the service name must not.
+ *
+ * For RPC services, host-address specifiers are accepted and will
+ * work to some extent; however, because of limitations in the
+ * portmapper interface, it will not work to try to give more than
+ * one line for any given RPC service, even if the host-address
+ * specifiers are different.
+ *
+ * Comment lines are indicated by a `#' in column 1.
+ */
+
+/*
+ * Here's the scoop concerning the user[.:]group feature:
+ *
+ * 1) set-group-option off.
+ *
+ *      a) user = root: NO setuid() or setgid() is done
+ *
+ *      b) other:       setgid(primary group as found in passwd)
+ *                      initgroups(name, primary group)
+ *                      setuid()
+ *
+ * 2) set-group-option on.
+ *
+ *      a) user = root: setgid(specified group)
+ *                      NO initgroups()
+ *                      NO setuid()
+ *
+ *      b) other:       setgid(specified group)
+ *                      initgroups(name, specified group)
+ *                      setuid()
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <signal.h>
+#include <netdb.h>
+#include <syslog.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "busybox.h"
+
+//#define CONFIG_FEATURE_INETD_RPC
+//#define CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
+//#define CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
+//#define CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME
+//#define CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
+//#define CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+//#define CONFIG_FEATURE_IPV6
+
+#ifdef CONFIG_FEATURE_INETD_RPC
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#endif
+
+#define _PATH_INETDCONF "/etc/inetd.conf"
+#define _PATH_INETDPID  "/var/run/inetd.pid"
+
+
+#define TOOMANY         0               /* don't start more than TOOMANY */
+
+#define CNT_INTVL       60              /* servers in CNT_INTVL sec. */
+#define RETRYTIME       (60*10)         /* retry after bind or server fail */
+
+#ifndef RLIMIT_NOFILE
+#define RLIMIT_NOFILE   RLIMIT_OFILE
+#endif
+
+#ifndef OPEN_MAX
+#define OPEN_MAX        64
+#endif
+
+/* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
+#define FD_MARGIN       (8)
+static rlim_t rlim_ofile_cur = OPEN_MAX;
+static struct rlimit rlim_ofile;
+
+
+/* Check unsupporting builtin */
+#if defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO || \
+	defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD || \
+	defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME || \
+	defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME || \
+	defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+# define INETD_FEATURE_ENABLED
+#endif
+
+#if defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO || \
+	defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD || \
+	defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+# define INETD_SETPROCTITLE
+#endif
+
+typedef struct servtab
+{
+  char *se_hostaddr;                    /* host address to listen on */
+  char *se_service;                     /* name of service */
+  int se_socktype;                      /* type of socket to use */
+  int se_family;                        /* address family */
+  char *se_proto;                       /* protocol used */
+#ifdef CONFIG_FEATURE_INETD_RPC
+  int se_rpcprog;                       /* rpc program number */
+  int se_rpcversl;                      /* rpc program lowest version */
+  int se_rpcversh;                      /* rpc program highest version */
+#define isrpcservice(sep)       ((sep)->se_rpcversl != 0)
+#else
+#define isrpcservice(sep)       0
+#endif
+  pid_t se_wait;                        /* single threaded server */
+  short se_checked;                     /* looked at during merge */
+  char *se_user;                        /* user name to run as */
+  char *se_group;                       /* group name to run as */
+#ifdef INETD_FEATURE_ENABLED
+  const struct builtin *se_bi;                 /* if built-in, description */
+#endif
+  char *se_server;                      /* server program */
+#define MAXARGV 20
+  char *se_argv[MAXARGV + 1];           /* program arguments */
+  int se_fd;                            /* open descriptor */
+  union
+  {
+	struct sockaddr se_un_ctrladdr;
+	struct sockaddr_in se_un_ctrladdr_in;
+#ifdef CONFIG_FEATURE_IPV6
+	struct sockaddr_in6 se_un_ctrladdr_in6;
+#endif
+	struct sockaddr_un se_un_ctrladdr_un;
+  } se_un;                              /* bound address */
+#define se_ctrladdr     se_un.se_un_ctrladdr
+#define se_ctrladdr_in  se_un.se_un_ctrladdr_in
+#define se_ctrladdr_in6 se_un.se_un_ctrladdr_in6
+#define se_ctrladdr_un  se_un.se_un_ctrladdr_un
+  int se_ctrladdr_size;
+  int se_max;                           /* max # of instances of this service */
+  int se_count;                         /* number started since se_time */
+  struct timeval se_time;               /* start of se_count */
+  struct servtab *se_next;
+} servtab_t;
+
+static servtab_t *servtab;
+
+#ifdef INETD_FEATURE_ENABLED
+struct builtin
+{
+  const char *bi_service;               /* internally provided service name */
+  int bi_socktype;                      /* type of socket supported */
+  short bi_fork;                        /* 1 if should fork before call */
+  short bi_wait;                        /* 1 if should wait for child */
+  void (*bi_fn) (int, servtab_t *);
+};
+
+	/* Echo received data */
+#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
+static void echo_stream (int, servtab_t *);
+static void echo_dg (int, servtab_t *);
+#endif
+	/* Internet /dev/null */
+#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
+static void discard_stream (int, servtab_t *);
+static void discard_dg (int, servtab_t *);
+#endif
+	/* Return 32 bit time since 1900 */
+#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME
+static void machtime_stream (int, servtab_t *);
+static void machtime_dg (int, servtab_t *);
+#endif
+	/* Return human-readable time */
+#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
+static void daytime_stream (int, servtab_t *);
+static void daytime_dg (int, servtab_t *);
+#endif
+	/* Familiar character generator */
+#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+static void chargen_stream (int, servtab_t *);
+static void chargen_dg (int, servtab_t *);
+#endif
+
+static const struct builtin builtins[] = {
+#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
+  /* Echo received data */
+  {"echo", SOCK_STREAM, 1, 0, echo_stream,},
+  {"echo", SOCK_DGRAM, 0, 0, echo_dg,},
+#endif
+#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
+  /* Internet /dev/null */
+  {"discard", SOCK_STREAM, 1, 0, discard_stream,},
+  {"discard", SOCK_DGRAM, 0, 0, discard_dg,},
+#endif
+#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME
+  /* Return 32 bit time since 1900 */
+  {"time", SOCK_STREAM, 0, 0, machtime_stream,},
+  {"time", SOCK_DGRAM, 0, 0, machtime_dg,},
+#endif
+#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
+  /* Return human-readable time */
+  {"daytime", SOCK_STREAM, 0, 0, daytime_stream,},
+  {"daytime", SOCK_DGRAM, 0, 0, daytime_dg,},
+#endif
+#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+  /* Familiar character generator */
+  {"chargen", SOCK_STREAM, 1, 0, chargen_stream,},
+  {"chargen", SOCK_DGRAM, 0, 0, chargen_dg,},
+#endif
+  {NULL, 0, 0, 0, NULL}
+};
+#endif /* INETD_FEATURE_ENABLED */
+
+static int global_queuelen = 128;
+static int nsock, maxsock;
+static fd_set allsock;
+static int toomany = TOOMANY;
+static int timingout;
+static struct servent *sp;
+static uid_t uid;
+
+static char *CONFIG = _PATH_INETDCONF;
+
+static FILE *fconfig;
+static char line[1024];
+static char *defhost;
+
+static char *newstr (char *cp)
+{
+  if ((cp = strdup (cp ? cp : "")))
+	return (cp);
+  syslog (LOG_ERR, "strdup: %m");
+  exit (1);
+}
+
+static int setconfig (void)
+{
+  free (defhost);
+  defhost = newstr ("*");
+  if (fconfig != NULL) {
+	fseek (fconfig, 0L, SEEK_SET);
+	return (1);
+  }
+  fconfig = fopen (CONFIG, "r");
+  return (fconfig != NULL);
+}
+
+static void endconfig (void)
+{
+  if (fconfig) {
+	(void) fclose (fconfig);
+	fconfig = NULL;
+  }
+  free (defhost);
+  defhost = 0;
+}
+
+#ifdef CONFIG_FEATURE_INETD_RPC
+static void register_rpc (servtab_t *sep)
+{
+  int n;
+  struct sockaddr_in ir_sin;
+  struct protoent *pp;
+  socklen_t size;
+
+  if ((pp = getprotobyname (sep->se_proto + 4)) == NULL) {
+	syslog (LOG_ERR, "%s: getproto: %m", sep->se_proto);
+	return;
+  }
+  size = sizeof ir_sin;
+  if (getsockname (sep->se_fd, (struct sockaddr *) &ir_sin, &size) < 0) {
+	syslog (LOG_ERR, "%s/%s: getsockname: %m",
+			sep->se_service, sep->se_proto);
+	return;
+  }
+
+  for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
+	(void) pmap_unset (sep->se_rpcprog, n);
+	if (!pmap_set (sep->se_rpcprog, n, pp->p_proto, ntohs (ir_sin.sin_port)))
+	  syslog (LOG_ERR, "%s %s: pmap_set: %u %u %u %u: %m",
+			  sep->se_service, sep->se_proto,
+			  sep->se_rpcprog, n, pp->p_proto, ntohs (ir_sin.sin_port));
+  }
+}
+
+static void unregister_rpc (servtab_t *sep)
+{
+  int n;
+
+  for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
+	if (!pmap_unset (sep->se_rpcprog, n))
+	  syslog (LOG_ERR, "pmap_unset(%u, %u)", sep->se_rpcprog, n);
+  }
+}
+#endif /* CONFIG_FEATURE_INETD_RPC */
+
+static void freeconfig (servtab_t *cp)
+{
+  int i;
+
+  free (cp->se_hostaddr);
+  free (cp->se_service);
+  free (cp->se_proto);
+  free (cp->se_user);
+  free (cp->se_group);
+  free (cp->se_server);
+  for (i = 0; i < MAXARGV; i++)
+	free (cp->se_argv[i]);
+}
+
+static int bump_nofile (void)
+{
+#define FD_CHUNK        32
+
+  struct rlimit rl;
+
+  if (getrlimit (RLIMIT_NOFILE, &rl) < 0) {
+	syslog (LOG_ERR, "getrlimit: %m");
+	return -1;
+  }
+  rl.rlim_cur = MIN (rl.rlim_max, rl.rlim_cur + FD_CHUNK);
+  rl.rlim_cur = MIN (FD_SETSIZE, rl.rlim_cur + FD_CHUNK);
+  if (rl.rlim_cur <= rlim_ofile_cur) {
+	syslog (LOG_ERR, "bump_nofile: cannot extend file limit, max = %d",
+			(int) rl.rlim_cur);
+	return -1;
+  }
+
+  if (setrlimit (RLIMIT_NOFILE, &rl) < 0) {
+	syslog (LOG_ERR, "setrlimit: %m");
+	return -1;
+  }
+
+  rlim_ofile_cur = rl.rlim_cur;
+  return 0;
+}
+
+static void setup (servtab_t *sep)
+{
+  int on = 1;
+  int r;
+
+  if ((sep->se_fd = socket (sep->se_family, sep->se_socktype, 0)) < 0) {
+	syslog (LOG_ERR, "%s/%s: socket: %m", sep->se_service, sep->se_proto);
+	return;
+  }
+#define turnon(fd, opt) \
+setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
+  if (turnon (sep->se_fd, SO_REUSEADDR) < 0)
+	syslog (LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
+#undef turnon
+
+#ifdef CONFIG_FEATURE_INETD_RPC
+  if (isrpcservice (sep)) {
+	struct passwd *pwd;
+
+	/*
+	 * for RPC services, attempt to use a reserved port
+	 * if they are going to be running as root.
+	 *
+	 * Also, zero out the port for all RPC services; let bind()
+	 * find one.
+	 */
+	sep->se_ctrladdr_in.sin_port = 0;
+	if (sep->se_user && (pwd = getpwnam (sep->se_user)) &&
+		pwd->pw_uid == 0 && uid == 0)
+	  r = bindresvport (sep->se_fd, &sep->se_ctrladdr_in);
+	else {
+	  r = bind (sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size);
+	  if (r == 0) {
+		socklen_t len = sep->se_ctrladdr_size;
+		int saveerrno = errno;
+
+		/* update se_ctrladdr_in.sin_port */
+		r = getsockname (sep->se_fd, &sep->se_ctrladdr, &len);
+		if (r <= 0)
+		  errno = saveerrno;
+	  }
+	}
+  } else
+#endif
+	r = bind (sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size);
+  if (r < 0) {
+	syslog (LOG_ERR, "%s/%s (%d): bind: %m",
+			sep->se_service, sep->se_proto, sep->se_ctrladdr.sa_family);
+	close (sep->se_fd);
+	sep->se_fd = -1;
+	if (!timingout) {
+	  timingout = 1;
+	  alarm (RETRYTIME);
+	}
+	return;
+  }
+  if (sep->se_socktype == SOCK_STREAM)
+	listen (sep->se_fd, global_queuelen);
+
+  FD_SET (sep->se_fd, &allsock);
+  nsock++;
+  if (sep->se_fd > maxsock) {
+	maxsock = sep->se_fd;
+	if ((rlim_t)maxsock > rlim_ofile_cur - FD_MARGIN)
+	  bump_nofile ();
+  }
+}
+
+static char *nextline (void)
+{
+  char *cp;
+  FILE *fd = fconfig;
+
+  if (fgets (line, sizeof (line), fd) == NULL)
+	return (NULL);
+  cp = strchr (line, '\n');
+  if (cp)
+	*cp = '\0';
+  return (line);
+}
+
+static char *skip (char **cpp) /* int report; */
+{
+  char *cp = *cpp;
+  char *start;
+
+/* erp: */
+  if (*cpp == NULL) {
+	/* if (report) */
+	/* syslog(LOG_ERR, "syntax error in inetd config file"); */
+	return (NULL);
+  }
+
+again:
+  while (*cp == ' ' || *cp == '\t')
+	cp++;
+  if (*cp == '\0') {
+	int c;
+
+	c = getc (fconfig);
+	(void) ungetc (c, fconfig);
+	if (c == ' ' || c == '\t')
+	  if ((cp = nextline ()))
+		goto again;
+	*cpp = NULL;
+	/* goto erp; */
+	return (NULL);
+  }
+  start = cp;
+  while (*cp && *cp != ' ' && *cp != '\t')
+	cp++;
+  if (*cp != '\0')
+	*cp++ = '\0';
+  /* if ((*cpp = cp) == NULL) */
+  /* goto erp; */
+
+  *cpp = cp;
+  return (start);
+}
+
+static servtab_t *new_servtab(void)
+{
+  servtab_t *sep;
+
+  sep = (servtab_t *) malloc (sizeof (servtab_t));
+  if (sep == NULL) {
+	syslog (LOG_ERR, bb_msg_memory_exhausted);
+	exit (1);
+  }
+  return sep;
+}
+
+static servtab_t *dupconfig (servtab_t *sep)
+{
+  servtab_t *newtab;
+  int argc;
+
+  newtab = new_servtab();
+  memset (newtab, 0, sizeof (servtab_t));
+  newtab->se_service = sep->se_service ? newstr (sep->se_service) : NULL;
+  newtab->se_socktype = sep->se_socktype;
+  newtab->se_family = sep->se_family;
+  newtab->se_proto = sep->se_proto ? newstr (sep->se_proto) : NULL;
+#ifdef CONFIG_FEATURE_INETD_RPC
+  newtab->se_rpcprog = sep->se_rpcprog;
+  newtab->se_rpcversl = sep->se_rpcversl;
+  newtab->se_rpcversh = sep->se_rpcversh;
+#endif
+  newtab->se_wait = sep->se_wait;
+  newtab->se_user = sep->se_user ? newstr (sep->se_user) : NULL;
+  newtab->se_group = sep->se_group ? newstr (sep->se_group) : NULL;
+#ifdef INETD_FEATURE_ENABLED
+  newtab->se_bi = sep->se_bi;
+#endif
+  newtab->se_server = sep->se_server ? newstr (sep->se_server) : 0;
+
+  for (argc = 0; argc <= MAXARGV; argc++)
+	newtab->se_argv[argc] = sep->se_argv[argc] ?
+	  newstr (sep->se_argv[argc]) : NULL;
+  newtab->se_max = sep->se_max;
+
+  return (newtab);
+}
+
+static servtab_t *getconfigent (void)
+{
+  servtab_t *sep;
+  int argc;
+  char *cp, *arg;
+  char *hostdelim;
+  servtab_t *nsep;
+  servtab_t *psep;
+
+  sep = new_servtab();
+
+  /* memset(sep, 0, sizeof *sep); */
+more:
+  /* freeconfig(sep); */
+
+  while ((cp = nextline ()) && *cp == '#');
+  if (cp == NULL) {
+	/* free(sep); */
+	return (NULL);
+  }
+
+  memset ((char *) sep, 0, sizeof *sep);
+  arg = skip (&cp);
+  if (arg == NULL) {
+	/* A blank line. */
+	goto more;
+  }
+
+  /* Check for a host name. */
+  hostdelim = strrchr (arg, ':');
+  if (hostdelim) {
+	*hostdelim = '\0';
+	sep->se_hostaddr = newstr (arg);
+	arg = hostdelim + 1;
+	/*
+	 * If the line is of the form `host:', then just change the
+	 * default host for the following lines.
+	 */
+	if (*arg == '\0') {
+	  arg = skip (&cp);
+	  if (cp == NULL) {
+		free (defhost);
+		defhost = sep->se_hostaddr;
+		goto more;
+	  }
+	}
+  } else
+	sep->se_hostaddr = newstr (defhost);
+
+  sep->se_service = newstr (arg);
+  arg = skip (&cp);
+
+  if (strcmp (arg, "stream") == 0)
+	sep->se_socktype = SOCK_STREAM;
+  else if (strcmp (arg, "dgram") == 0)
+	sep->se_socktype = SOCK_DGRAM;
+  else if (strcmp (arg, "rdm") == 0)
+	sep->se_socktype = SOCK_RDM;
+  else if (strcmp (arg, "seqpacket") == 0)
+	sep->se_socktype = SOCK_SEQPACKET;
+  else if (strcmp (arg, "raw") == 0)
+	sep->se_socktype = SOCK_RAW;
+  else
+	sep->se_socktype = -1;
+
+  sep->se_proto = newstr (skip (&cp));
+
+  if (strcmp (sep->se_proto, "unix") == 0) {
+	sep->se_family = AF_UNIX;
+  } else {
+	sep->se_family = AF_INET;
+	if (sep->se_proto[strlen (sep->se_proto) - 1] == '6')
+#ifdef CONFIG_FEATURE_IPV6
+	  sep->se_family = AF_INET6;
+#else
+	  syslog (LOG_ERR, "%s: IPV6 not supported", sep->se_proto);
+#endif
+	if (strncmp (sep->se_proto, "rpc/", 4) == 0) {
+#ifdef CONFIG_FEATURE_INETD_RPC
+	  char *p, *ccp;
+	  long l;
+
+	  p = strchr (sep->se_service, '/');
+	  if (p == 0) {
+		syslog (LOG_ERR, "%s: no rpc version", sep->se_service);
+		goto more;
+	  }
+	  *p++ = '\0';
+	  l = strtol (p, &ccp, 0);
+	  if (ccp == p || l < 0 || l > INT_MAX) {
+	  badafterall:
+		syslog (LOG_ERR, "%s/%s: bad rpc version", sep->se_service, p);
+		goto more;
+	  }
+	  sep->se_rpcversl = sep->se_rpcversh = l;
+	  if (*ccp == '-') {
+		p = ccp + 1;
+		l = strtol (p, &ccp, 0);
+		if (ccp == p || l < 0 || l > INT_MAX || l < sep->se_rpcversl || *ccp)
+		  goto badafterall;
+		sep->se_rpcversh = l;
+	  } else if (*ccp != '\0')
+		goto badafterall;
+#else
+	syslog (LOG_ERR, "%s: rpc services not supported", sep->se_service);
+#endif
+	}
+  }
+  arg = skip (&cp);
+  if (arg == NULL)
+	goto more;
+
+  {
+	char *s = strchr (arg, '.');
+	if (s) {
+	  *s++ = '\0';
+	  sep->se_max = atoi (s);
+	} else
+	  sep->se_max = toomany;
+  }
+  sep->se_wait = strcmp (arg, "wait") == 0;
+  /* if ((arg = skip(&cp, 1)) == NULL) */
+  /* goto more; */
+  sep->se_user = newstr (skip (&cp));
+  arg = strchr (sep->se_user, '.');
+  if (arg == NULL)
+	arg = strchr (sep->se_user, ':');
+  if (arg) {
+	*arg++ = '\0';
+	sep->se_group = newstr (arg);
+  }
+  /* if ((arg = skip(&cp, 1)) == NULL) */
+  /* goto more; */
+
+  sep->se_server = newstr (skip (&cp));
+  if (strcmp (sep->se_server, "internal") == 0) {
+#ifdef INETD_FEATURE_ENABLED
+	const struct builtin *bi;
+
+	for (bi = builtins; bi->bi_service; bi++)
+	  if (bi->bi_socktype == sep->se_socktype &&
+		  strcmp (bi->bi_service, sep->se_service) == 0)
+		break;
+	if (bi->bi_service == 0) {
+	  syslog (LOG_ERR, "internal service %s unknown", sep->se_service);
+	  goto more;
+	}
+	sep->se_bi = bi;
+	sep->se_wait = bi->bi_wait;
+#else
+	syslog (LOG_ERR, "internal service %s unknown", sep->se_service);
+	goto more;
+#endif
+  }
+#ifdef INETD_FEATURE_ENABLED
+    else
+	sep->se_bi = NULL;
+#endif
+  argc = 0;
+  for (arg = skip (&cp); cp; arg = skip (&cp)) {
+	if (argc < MAXARGV)
+	  sep->se_argv[argc++] = newstr (arg);
+  }
+  while (argc <= MAXARGV)
+	sep->se_argv[argc++] = NULL;
+
+  /*
+   * Now that we've processed the entire line, check if the hostname
+   * specifier was a comma separated list of hostnames. If so
+   * we'll make new entries for each address.
+   */
+  while ((hostdelim = strrchr (sep->se_hostaddr, ',')) != NULL) {
+	nsep = dupconfig (sep);
+
+	/*
+	 * NULL terminate the hostname field of the existing entry,
+	 * and make a dup for the new entry.
+	 */
+	*hostdelim++ = '\0';
+	nsep->se_hostaddr = newstr (hostdelim);
+
+	nsep->se_next = sep->se_next;
+	sep->se_next = nsep;
+  }
+
+  nsep = sep;
+  while (nsep != NULL) {
+	nsep->se_checked = 1;
+	if (nsep->se_family == AF_INET) {
+	  if (!strcmp (nsep->se_hostaddr, "*"))
+		nsep->se_ctrladdr_in.sin_addr.s_addr = INADDR_ANY;
+	  else if (!inet_aton (nsep->se_hostaddr, &nsep->se_ctrladdr_in.sin_addr)) {
+		struct hostent *hp;
+
+		hp = gethostbyname (nsep->se_hostaddr);
+		if (hp == 0) {
+		  syslog (LOG_ERR, "%s: unknown host", nsep->se_hostaddr);
+		  nsep->se_checked = 0;
+		  goto skip;
+		} else if (hp->h_addrtype != AF_INET) {
+		  syslog (LOG_ERR,
+				  "%s: address isn't an Internet "
+				  "address", nsep->se_hostaddr);
+		  nsep->se_checked = 0;
+		  goto skip;
+		} else {
+		  int i = 1;
+
+		  memmove (&nsep->se_ctrladdr_in.sin_addr,
+				   hp->h_addr_list[0], sizeof (struct in_addr));
+		  while (hp->h_addr_list[i] != NULL) {
+			psep = dupconfig (nsep);
+			psep->se_hostaddr = newstr (nsep->se_hostaddr);
+			psep->se_checked = 1;
+			memmove (&psep->se_ctrladdr_in.sin_addr,
+					 hp->h_addr_list[i], sizeof (struct in_addr));
+			psep->se_ctrladdr_size = sizeof (psep->se_ctrladdr_in);
+			i++;
+			/* Prepend to list, don't want to look up its */
+			/* hostname again. */
+			psep->se_next = sep;
+			sep = psep;
+		  }
+		}
+	  }
+	}
+/* XXX BUG?: is this skip: label supposed to remain? */
+  skip:
+	nsep = nsep->se_next;
+  }
+
+  /*
+   * Finally, free any entries which failed the gethostbyname
+   * check.
+   */
+  psep = NULL;
+  nsep = sep;
+  while (nsep != NULL) {
+	servtab_t *tsep;
+
+	if (nsep->se_checked == 0) {
+	  tsep = nsep;
+	  if (psep == NULL) {
+		sep = nsep->se_next;
+		nsep = sep;
+	  } else {
+		nsep = nsep->se_next;
+		psep->se_next = nsep;
+	  }
+	  freeconfig (tsep);
+	} else {
+	  nsep->se_checked = 0;
+	  psep = nsep;
+	  nsep = nsep->se_next;
+	}
+  }
+
+  return (sep);
+}
+
+#define Block_Using_Signals(m) do {     sigemptyset(&m); \
+					sigaddset(&m, SIGCHLD); \
+					sigaddset(&m, SIGHUP); \
+					sigaddset(&m, SIGALRM); \
+					sigprocmask(SIG_BLOCK, &m, NULL); \
+				} while(0)
+
+
+static servtab_t *enter (servtab_t *cp)
+{
+  servtab_t *sep;
+  sigset_t omask;
+
+  sep = new_servtab();
+  *sep = *cp;
+  sep->se_fd = -1;
+#ifdef CONFIG_FEATURE_INETD_RPC
+  sep->se_rpcprog = -1;
+#endif
+  Block_Using_Signals(omask);
+  sep->se_next = servtab;
+  servtab = sep;
+  sigprocmask(SIG_UNBLOCK, &omask, NULL);
+  return (sep);
+}
+
+static int matchconf (servtab_t *old, servtab_t *new)
+{
+  if (strcmp (old->se_service, new->se_service) != 0)
+	return (0);
+
+  if (strcmp (old->se_hostaddr, new->se_hostaddr) != 0)
+	return (0);
+
+  if (strcmp (old->se_proto, new->se_proto) != 0)
+	return (0);
+
+  /*
+   * If the new servtab is bound to a specific address, check that the
+   * old servtab is bound to the same entry. If the new service is not
+   * bound to a specific address then the check of se_hostaddr above
+   * is sufficient.
+   */
+
+  if (old->se_family == AF_INET && new->se_family == AF_INET &&
+	  memcmp (&old->se_ctrladdr_in.sin_addr,
+			  &new->se_ctrladdr_in.sin_addr,
+			  sizeof (new->se_ctrladdr_in.sin_addr)) != 0)
+	return (0);
+
+#ifdef CONFIG_FEATURE_IPV6
+  if (old->se_family == AF_INET6 && new->se_family == AF_INET6 &&
+	  memcmp (&old->se_ctrladdr_in6.sin6_addr,
+			  &new->se_ctrladdr_in6.sin6_addr,
+			  sizeof (new->se_ctrladdr_in6.sin6_addr)) != 0)
+	return (0);
+#endif
+  return (1);
+}
+
+static void config (int sig ATTRIBUTE_UNUSED)
+{
+  servtab_t *sep, *cp, **sepp;
+  sigset_t omask;
+  int add;
+  size_t n;
+  char protoname[10];
+
+  if (!setconfig ()) {
+	syslog (LOG_ERR, "%s: %m", CONFIG);
+	return;
+  }
+  for (sep = servtab; sep; sep = sep->se_next)
+	sep->se_checked = 0;
+  cp = getconfigent ();
+  while (cp != NULL) {
+	for (sep = servtab; sep; sep = sep->se_next)
+	  if (matchconf (sep, cp))
+		break;
+	add = 0;
+	if (sep != 0) {
+	  int i;
+
+#define SWAP(type, a, b) do {type c=(type)a; a=(type)b; b=(type)c;} while (0)
+
+	  Block_Using_Signals(omask);
+	  /*
+	   * sep->se_wait may be holding the pid of a daemon
+	   * that we're waiting for.  If so, don't overwrite
+	   * it unless the config file explicitly says don't
+	   * wait.
+	   */
+	  if (
+#ifdef INETD_FEATURE_ENABLED
+		   cp->se_bi == 0 &&
+#endif
+		(sep->se_wait == 1 || cp->se_wait == 0))
+		sep->se_wait = cp->se_wait;
+	  SWAP (int, cp->se_max, sep->se_max);
+	  SWAP (char *, sep->se_user, cp->se_user);
+	  SWAP (char *, sep->se_group, cp->se_group);
+	  SWAP (char *, sep->se_server, cp->se_server);
+	  for (i = 0; i < MAXARGV; i++)
+		SWAP (char *, sep->se_argv[i], cp->se_argv[i]);
+#undef SWAP
+
+#ifdef CONFIG_FEATURE_INETD_RPC
+	  if (isrpcservice (sep))
+		unregister_rpc (sep);
+	  sep->se_rpcversl = cp->se_rpcversl;
+	  sep->se_rpcversh = cp->se_rpcversh;
+#endif
+	  sigprocmask(SIG_UNBLOCK, &omask, NULL);
+	  freeconfig (cp);
+	  add = 1;
+	} else {
+	  sep = enter (cp);
+	}
+	sep->se_checked = 1;
+
+	switch (sep->se_family) {
+	case AF_UNIX:
+	  if (sep->se_fd != -1)
+		break;
+	  (void) unlink (sep->se_service);
+	  n = strlen (sep->se_service);
+	  if (n > sizeof sep->se_ctrladdr_un.sun_path - 1)
+		n = sizeof sep->se_ctrladdr_un.sun_path - 1;
+	  safe_strncpy (sep->se_ctrladdr_un.sun_path, sep->se_service, n + 1);
+	  sep->se_ctrladdr_un.sun_family = AF_UNIX;
+	  sep->se_ctrladdr_size = n + sizeof sep->se_ctrladdr_un.sun_family;
+	  setup (sep);
+	  break;
+	case AF_INET:
+	  sep->se_ctrladdr_in.sin_family = AF_INET;
+	  /* se_ctrladdr_in was set in getconfigent */
+	  sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in;
+
+#ifdef CONFIG_FEATURE_INETD_RPC
+	  if (isrpcservice (sep)) {
+		struct rpcent *rp;
+
+		sep->se_rpcprog = atoi (sep->se_service);
+		if (sep->se_rpcprog == 0) {
+		  rp = getrpcbyname (sep->se_service);
+		  if (rp == 0) {
+			syslog (LOG_ERR, "%s: unknown rpc service", sep->se_service);
+			goto serv_unknown;
+		  }
+		  sep->se_rpcprog = rp->r_number;
+		}
+		if (sep->se_fd == -1)
+		  setup (sep);
+		if (sep->se_fd != -1)
+		  register_rpc (sep);
+	  } else
+#endif
+	     {
+		u_short port = htons (atoi (sep->se_service));
+
+		if (!port) {
+		   /*XXX*/ strncpy (protoname, sep->se_proto, sizeof (protoname));
+		  if (isdigit (protoname[strlen (protoname) - 1]))
+			protoname[strlen (protoname) - 1] = '\0';
+		  sp = getservbyname (sep->se_service, protoname);
+		  if (sp == 0) {
+			syslog (LOG_ERR,
+					"%s/%s: unknown service", sep->se_service, sep->se_proto);
+			goto serv_unknown;
+		  }
+		  port = sp->s_port;
+		}
+		if (port != sep->se_ctrladdr_in.sin_port) {
+		  sep->se_ctrladdr_in.sin_port = port;
+		  if (sep->se_fd != -1) {
+			FD_CLR (sep->se_fd, &allsock);
+			nsock--;
+			(void) close (sep->se_fd);
+		  }
+		  sep->se_fd = -1;
+		}
+		if (sep->se_fd == -1)
+		  setup (sep);
+	  }
+	  break;
+#ifdef CONFIG_FEATURE_IPV6
+	case AF_INET6:
+	  sep->se_ctrladdr_in6.sin6_family = AF_INET6;
+	  /* se_ctrladdr_in was set in getconfigent */
+	  sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in6;
+
+#ifdef CONFIG_FEATURE_INETD_RPC
+	  if (isrpcservice (sep)) {
+		struct rpcent *rp;
+
+		sep->se_rpcprog = atoi (sep->se_service);
+		if (sep->se_rpcprog == 0) {
+		  rp = getrpcbyname (sep->se_service);
+		  if (rp == 0) {
+			syslog (LOG_ERR, "%s: unknown rpc service", sep->se_service);
+			goto serv_unknown;
+		  }
+		  sep->se_rpcprog = rp->r_number;
+		}
+		if (sep->se_fd == -1)
+		  setup (sep);
+		if (sep->se_fd != -1)
+		  register_rpc (sep);
+	  } else
+#endif
+		{
+		u_short port = htons (atoi (sep->se_service));
+
+		if (!port) {
+		   /*XXX*/ strncpy (protoname, sep->se_proto, sizeof (protoname));
+		  if (isdigit (protoname[strlen (protoname) - 1]))
+			protoname[strlen (protoname) - 1] = '\0';
+		  sp = getservbyname (sep->se_service, protoname);
+		  if (sp == 0) {
+			syslog (LOG_ERR,
+					"%s/%s: unknown service", sep->se_service, sep->se_proto);
+			goto serv_unknown;
+		  }
+		  port = sp->s_port;
+		}
+		if (port != sep->se_ctrladdr_in6.sin6_port) {
+		  sep->se_ctrladdr_in6.sin6_port = port;
+		  if (sep->se_fd != -1) {
+			FD_CLR (sep->se_fd, &allsock);
+			nsock--;
+			(void) close (sep->se_fd);
+		  }
+		  sep->se_fd = -1;
+		}
+		if (sep->se_fd == -1)
+		  setup (sep);
+	  }
+	  break;
+#endif /* CONFIG_FEATURE_IPV6 */
+	}
+  serv_unknown:
+	if (cp->se_next != NULL) {
+	  servtab_t *tmp = cp;
+
+	  cp = cp->se_next;
+	  free (tmp);
+	} else {
+	  free (cp);
+	  cp = getconfigent ();
+	}
+  }
+  endconfig ();
+  /*
+   * Purge anything not looked at above.
+   */
+  Block_Using_Signals(omask);
+  sepp = &servtab;
+  while ((sep = *sepp)) {
+	if (sep->se_checked) {
+	  sepp = &sep->se_next;
+	  continue;
+	}
+	*sepp = sep->se_next;
+	if (sep->se_fd != -1) {
+	  FD_CLR (sep->se_fd, &allsock);
+	  nsock--;
+	  (void) close (sep->se_fd);
+	}
+#ifdef CONFIG_FEATURE_INETD_RPC
+	if (isrpcservice (sep))
+	  unregister_rpc (sep);
+#endif
+	if (sep->se_family == AF_UNIX)
+	  (void) unlink (sep->se_service);
+	freeconfig (sep);
+	free (sep);
+  }
+  sigprocmask(SIG_UNBLOCK, &omask, NULL);
+}
+
+
+static void reapchild (int sig ATTRIBUTE_UNUSED)
+{
+  pid_t pid;
+  int save_errno = errno, status;
+  servtab_t *sep;
+
+  for (;;) {
+	pid = wait3 (&status, WNOHANG, NULL);
+	if (pid <= 0)
+	  break;
+	for (sep = servtab; sep; sep = sep->se_next)
+	  if (sep->se_wait == pid) {
+		if (WIFEXITED (status) && WEXITSTATUS (status))
+		  syslog (LOG_WARNING,
+				  "%s: exit status 0x%x",
+				  sep->se_server, WEXITSTATUS (status));
+		else if (WIFSIGNALED (status))
+		  syslog (LOG_WARNING,
+				  "%s: exit signal 0x%x", sep->se_server, WTERMSIG (status));
+		sep->se_wait = 1;
+		FD_SET (sep->se_fd, &allsock);
+		nsock++;
+	  }
+  }
+  errno = save_errno;
+}
+
+static void retry (int sig ATTRIBUTE_UNUSED)
+{
+  servtab_t *sep;
+
+  timingout = 0;
+  for (sep = servtab; sep; sep = sep->se_next) {
+	if (sep->se_fd == -1) {
+	  switch (sep->se_family) {
+	  case AF_UNIX:
+	  case AF_INET:
+#ifdef CONFIG_FEATURE_IPV6
+	  case AF_INET6:
+#endif
+		setup (sep);
+#ifdef CONFIG_FEATURE_INETD_RPC
+		if (sep->se_fd != -1 && isrpcservice (sep))
+		  register_rpc (sep);
+#endif
+		break;
+	  }
+	}
+  }
+}
+
+static void goaway (int sig ATTRIBUTE_UNUSED)
+{
+  servtab_t *sep;
+
+  /* XXX signal race walking sep list */
+  for (sep = servtab; sep; sep = sep->se_next) {
+	if (sep->se_fd == -1)
+	  continue;
+
+	switch (sep->se_family) {
+	case AF_UNIX:
+	  (void) unlink (sep->se_service);
+	  break;
+	case AF_INET:
+#ifdef CONFIG_FEATURE_IPV6
+	case AF_INET6:
+#endif
+#ifdef CONFIG_FEATURE_INETD_RPC
+	  if (sep->se_wait == 1 && isrpcservice (sep))
+		unregister_rpc (sep);   /* XXX signal race */
+#endif
+	  break;
+	}
+	(void) close (sep->se_fd);
+  }
+  (void) unlink (_PATH_INETDPID);
+  exit (0);
+}
+
+
+#ifdef INETD_SETPROCTITLE
+static char **Argv;
+static char *LastArg;
+
+static void
+inetd_setproctitle (char *a, int s)
+{
+  socklen_t size;
+  char *cp;
+  struct sockaddr_in prt_sin;
+  char buf[80];
+
+  cp = Argv[0];
+  size = sizeof (prt_sin);
+  (void) snprintf (buf, sizeof buf, "-%s", a);
+  if (getpeername (s, (struct sockaddr *) &prt_sin, &size) == 0) {
+	char *sa = inet_ntoa (prt_sin.sin_addr);
+
+	buf[sizeof (buf) - 1 - strlen (sa) - 3] = '\0';
+	strcat (buf, " [");
+	strcat (buf, sa);
+	strcat (buf, "]");
+  }
+  strncpy (cp, buf, LastArg - cp);
+  cp += strlen (cp);
+  while (cp < LastArg)
+	*cp++ = ' ';
+}
+#endif
+
+
+int
+inetd_main (int argc, char *argv[])
+{
+  servtab_t *sep;
+  struct passwd *pwd;
+  struct group *grp = NULL;
+  int tmpint;
+  struct sigaction sa, sapipe;
+  int opt;
+  pid_t pid;
+  char buf[50];
+  char *stoomany;
+  sigset_t omask, wait_mask;
+
+#ifdef INETD_SETPROCTITLE
+  extern char **environ;
+  char **envp = environ;
+
+  Argv = argv;
+  if (envp == 0 || *envp == 0)
+	envp = argv;
+  while (*envp)
+	envp++;
+  LastArg = envp[-1] + strlen (envp[-1]);
+#endif
+
+  openlog (bb_applet_name, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
+
+  opt = bb_getopt_ulflags (argc, argv, "R:f", &stoomany);
+  if(opt & 1) {
+	char *e;
+
+	toomany = strtoul (stoomany, &e, 0);
+	if (!(toomany >= 0 && *e == '\0')) {
+		toomany = TOOMANY;
+		syslog (LOG_ERR, "-R %s: bad value for service invocation rate", stoomany);
+	}
+  }
+  argc -= optind;
+  argv += optind;
+
+  uid = getuid ();
+  if (uid != 0)
+	CONFIG = NULL;
+  if (argc > 0)
+	CONFIG = argv[0];
+  if (CONFIG == NULL)
+	bb_error_msg_and_die ("non-root must specify a config file");
+
+  if (!(opt & 2)) {
+#ifdef BB_NOMMU
+	/* reexec for vfork() do continue parent */
+	vfork_daemon_rexec (0, 0, argc, argv, "-f");
+#else
+	bb_xdaemon (0, 0);
+#endif
+  } else {
+	setsid ();
+  }
+
+  if (uid == 0) {
+	gid_t gid = getgid ();
+
+	/* If run by hand, ensure groups vector gets trashed */
+	setgroups (1, &gid);
+  }
+
+  {
+	FILE *fp;
+
+	if ((fp = fopen (_PATH_INETDPID, "w")) != NULL) {
+		fprintf (fp, "%u\n", getpid ());
+		(void) fclose (fp);
+	}
+  }
+
+  if (getrlimit (RLIMIT_NOFILE, &rlim_ofile) < 0) {
+	syslog (LOG_ERR, "getrlimit: %m");
+  } else {
+	rlim_ofile_cur = rlim_ofile.rlim_cur;
+	if (rlim_ofile_cur == RLIM_INFINITY)    /* ! */
+	  rlim_ofile_cur = OPEN_MAX;
+  }
+
+  memset ((char *) &sa, 0, sizeof (sa));
+  sigemptyset (&sa.sa_mask);
+  sigaddset (&sa.sa_mask, SIGALRM);
+  sigaddset (&sa.sa_mask, SIGCHLD);
+  sigaddset (&sa.sa_mask, SIGHUP);
+  sa.sa_handler = retry;
+  sigaction (SIGALRM, &sa, NULL);
+  /* doconfig(); */
+  config (SIGHUP);
+  sa.sa_handler = config;
+  sigaction (SIGHUP, &sa, NULL);
+  sa.sa_handler = reapchild;
+  sigaction (SIGCHLD, &sa, NULL);
+  sa.sa_handler = goaway;
+  sigaction (SIGTERM, &sa, NULL);
+  sa.sa_handler = goaway;
+  sigaction (SIGINT, &sa, NULL);
+  sa.sa_handler = SIG_IGN;
+  sigaction (SIGPIPE, &sa, &sapipe);
+  memset(&wait_mask, 0, sizeof(wait_mask));
+  {
+	/* space for daemons to overwrite environment for ps */
+#define DUMMYSIZE       100
+	char dummy[DUMMYSIZE];
+
+	(void) memset (dummy, 'x', DUMMYSIZE - 1);
+	dummy[DUMMYSIZE - 1] = '\0';
+
+	(void) setenv ("inetd_dummy", dummy, 1);
+  }
+
+  for (;;) {
+	int n, ctrl = -1;
+	fd_set readable;
+
+	if (nsock == 0) {
+	  Block_Using_Signals(omask);
+	  while (nsock == 0)
+		sigsuspend (&wait_mask);
+	  sigprocmask(SIG_UNBLOCK, &omask, NULL);
+	}
+
+	readable = allsock;
+	if ((n = select (maxsock + 1, &readable, NULL, NULL, NULL)) <= 0) {
+	  if (n < 0 && errno != EINTR) {
+		syslog (LOG_WARNING, "select: %m");
+		sleep (1);
+	  }
+	  continue;
+	}
+	for (sep = servtab; n && sep; sep = sep->se_next)
+	  if (sep->se_fd != -1 && FD_ISSET (sep->se_fd, &readable)) {
+		n--;
+		if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
+		  ctrl = accept (sep->se_fd, NULL, NULL);
+		  if (ctrl < 0) {
+			if (errno == EINTR)
+			  continue;
+			syslog (LOG_WARNING, "accept (for %s): %m", sep->se_service);
+			continue;
+		  }
+		  if (sep->se_family == AF_INET && sep->se_socktype == SOCK_STREAM) {
+			struct sockaddr_in peer;
+			socklen_t plen = sizeof (peer);
+
+			if (getpeername (ctrl, (struct sockaddr *) &peer, &plen) < 0) {
+			  syslog (LOG_WARNING, "could not getpeername");
+			  close (ctrl);
+			  continue;
+			}
+			if (ntohs (peer.sin_port) == 20) {
+			  /* XXX ftp bounce */
+			  close (ctrl);
+			  continue;
+			}
+		  }
+		} else
+		  ctrl = sep->se_fd;
+		Block_Using_Signals(omask);
+		pid = 0;
+#ifdef INETD_FEATURE_ENABLED
+		if (sep->se_bi == 0 || sep->se_bi->bi_fork)
+#endif
+		{
+		  if (sep->se_count++ == 0)
+			(void) gettimeofday (&sep->se_time, NULL);
+		  else if (toomany > 0 && sep->se_count >= sep->se_max) {
+			struct timeval now;
+
+			(void) gettimeofday (&now, NULL);
+			if (now.tv_sec - sep->se_time.tv_sec > CNT_INTVL) {
+			  sep->se_time = now;
+			  sep->se_count = 1;
+			} else {
+			  if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
+				close (ctrl);
+			  if (sep->se_family == AF_INET &&
+				  ntohs (sep->se_ctrladdr_in.sin_port) >= IPPORT_RESERVED) {
+				/*
+				 * Cannot close it -- there are
+				 * thieves on the system.
+				 * Simply ignore the connection.
+				 */
+				--sep->se_count;
+				continue;
+			  }
+			  syslog (LOG_ERR,
+					  "%s/%s server failing (looping), service terminated",
+					  sep->se_service, sep->se_proto);
+			  if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
+				close (ctrl);
+			  FD_CLR (sep->se_fd, &allsock);
+			  (void) close (sep->se_fd);
+			  sep->se_fd = -1;
+			  sep->se_count = 0;
+			  nsock--;
+			  sigprocmask(SIG_UNBLOCK, &omask, NULL);
+			  if (!timingout) {
+				timingout = 1;
+				alarm (RETRYTIME);
+			  }
+			  continue;
+			}
+		  }
+		  pid = fork ();
+		}
+		if (pid < 0) {
+		  syslog (LOG_ERR, "fork: %m");
+		  if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
+			close (ctrl);
+		  sigprocmask(SIG_UNBLOCK, &omask, NULL);
+		  sleep (1);
+		  continue;
+		}
+		if (pid && sep->se_wait) {
+		  sep->se_wait = pid;
+		  FD_CLR (sep->se_fd, &allsock);
+		  nsock--;
+		}
+		sigprocmask(SIG_UNBLOCK, &omask, NULL);
+		if (pid == 0) {
+#ifdef INETD_FEATURE_ENABLED
+		  if (sep->se_bi) {
+			(*sep->se_bi->bi_fn) (ctrl, sep);
+		  } else
+#endif
+			{
+			if ((pwd = getpwnam (sep->se_user)) == NULL) {
+			  syslog (LOG_ERR, "getpwnam: %s: No such user", sep->se_user);
+			  if (sep->se_socktype != SOCK_STREAM)
+				recv (0, buf, sizeof (buf), 0);
+			  _exit (1);
+			}
+			if (setsid () < 0)
+			  syslog (LOG_ERR, "%s: setsid: %m", sep->se_service);
+			if (sep->se_group && (grp = getgrnam (sep->se_group)) == NULL) {
+			  syslog (LOG_ERR, "getgrnam: %s: No such group", sep->se_group);
+			  if (sep->se_socktype != SOCK_STREAM)
+				recv (0, buf, sizeof (buf), 0);
+			  _exit (1);
+			}
+			if (uid != 0) {
+			  /* a user running private inetd */
+			  if (uid != pwd->pw_uid)
+				_exit (1);
+			} else if (pwd->pw_uid) {
+			  if (sep->se_group) {
+				pwd->pw_gid = grp->gr_gid;
+			  }
+			  xsetgid ((gid_t) pwd->pw_gid);
+			  initgroups (pwd->pw_name, pwd->pw_gid);
+			  xsetuid((uid_t) pwd->pw_uid);
+			} else if (sep->se_group) {
+			  xsetgid(grp->gr_gid);
+			  setgroups (1, &grp->gr_gid);
+			}
+			dup2 (ctrl, 0);
+			close (ctrl);
+			dup2 (0, 1);
+			dup2 (0, 2);
+			if (rlim_ofile.rlim_cur != rlim_ofile_cur)
+			  if (setrlimit (RLIMIT_NOFILE, &rlim_ofile) < 0)
+				syslog (LOG_ERR, "setrlimit: %m");
+			closelog ();
+			for (tmpint = rlim_ofile_cur - 1; --tmpint > 2;)
+			  (void) close (tmpint);
+			sigaction (SIGPIPE, &sapipe, NULL);
+			execv (sep->se_server, sep->se_argv);
+			if (sep->se_socktype != SOCK_STREAM)
+			  recv (0, buf, sizeof (buf), 0);
+			syslog (LOG_ERR, "execv %s: %m", sep->se_server);
+			_exit (1);
+		  }
+		}
+		if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
+		  close (ctrl);
+	  }
+  }
+}
+
+/*
+ * Internet services provided internally by inetd:
+ */
+#define BUFSIZE 4096
+
+#if defined(CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO) || \
+    defined(CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN) || \
+    defined(CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME)
+static int dg_badinput (struct sockaddr_in *dg_sin)
+{
+  if (ntohs (dg_sin->sin_port) < IPPORT_RESERVED)
+	return (1);
+  if (dg_sin->sin_addr.s_addr == htonl (INADDR_BROADCAST))
+	return (1);
+  /* XXX compare against broadcast addresses in SIOCGIFCONF list? */
+  return (0);
+}
+#endif
+
+#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
+/* Echo service -- echo data back */
+/* ARGSUSED */
+static void
+echo_stream (int s, servtab_t *sep)
+{
+  char buffer[BUFSIZE];
+  int i;
+
+  inetd_setproctitle (sep->se_service, s);
+  while ((i = read (s, buffer, sizeof (buffer))) > 0 &&
+		 write (s, buffer, i) > 0);
+  exit (0);
+}
+
+/* Echo service -- echo data back */
+/* ARGSUSED */
+static void
+echo_dg (int s, servtab_t *sep ATTRIBUTE_UNUSED)
+{
+  char buffer[BUFSIZE];
+  int i;
+  socklen_t size;
+  /* struct sockaddr_storage ss; */
+  struct sockaddr sa;
+
+  size = sizeof (sa);
+  if ((i = recvfrom (s, buffer, sizeof (buffer), 0, &sa, &size)) < 0)
+	return;
+  if (dg_badinput ((struct sockaddr_in *) &sa))
+	return;
+  (void) sendto (s, buffer, i, 0, &sa, sizeof (sa));
+}
+#endif  /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO */
+
+#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
+/* Discard service -- ignore data */
+/* ARGSUSED */
+static void
+discard_stream (int s, servtab_t *sep)
+{
+  char buffer[BUFSIZE];
+
+  inetd_setproctitle (sep->se_service, s);
+  while ((errno = 0, read (s, buffer, sizeof (buffer)) > 0) ||
+		 errno == EINTR);
+  exit (0);
+}
+
+/* Discard service -- ignore data */
+/* ARGSUSED */
+static void
+discard_dg (int s, servtab_t *sep ATTRIBUTE_UNUSED)
+{
+  char buffer[BUFSIZE];
+
+  (void) read (s, buffer, sizeof (buffer));
+}
+#endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD */
+
+
+#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+#define LINESIZ 72
+static char ring[128];
+static char *endring;
+
+static void
+initring (void)
+{
+  int i;
+
+  endring = ring;
+
+  for (i = 0; i <= 128; ++i)
+	if (isprint (i))
+	  *endring++ = i;
+}
+
+/* Character generator */
+/* ARGSUSED */
+static void
+chargen_stream (int s, servtab_t *sep)
+{
+  char *rs;
+  int len;
+  char text[LINESIZ + 2];
+
+  inetd_setproctitle (sep->se_service, s);
+
+  if (!endring) {
+	initring ();
+	rs = ring;
+  }
+
+  text[LINESIZ] = '\r';
+  text[LINESIZ + 1] = '\n';
+  for (rs = ring;;) {
+	if ((len = endring - rs) >= LINESIZ)
+	  memmove (text, rs, LINESIZ);
+	else {
+	  memmove (text, rs, len);
+	  memmove (text + len, ring, LINESIZ - len);
+	}
+	if (++rs == endring)
+	  rs = ring;
+	if (write (s, text, sizeof (text)) != sizeof (text))
+	  break;
+  }
+  exit (0);
+}
+
+/* Character generator */
+/* ARGSUSED */
+static void
+chargen_dg (int s, servtab_t *sep ATTRIBUTE_UNUSED)
+{
+  /* struct sockaddr_storage ss; */
+  struct sockaddr sa;
+  static char *rs;
+  int len;
+  char text[LINESIZ + 2];
+  socklen_t size;
+
+  if (endring == 0) {
+	initring ();
+	rs = ring;
+  }
+
+  size = sizeof (sa);
+  if (recvfrom (s, text, sizeof (text), 0, &sa, &size) < 0)
+	return;
+  if (dg_badinput ((struct sockaddr_in *) &sa))
+	return;
+
+  if ((len = endring - rs) >= LINESIZ)
+	memmove (text, rs, LINESIZ);
+  else {
+	memmove (text, rs, len);
+	memmove (text + len, ring, LINESIZ - len);
+  }
+  if (++rs == endring)
+	rs = ring;
+  text[LINESIZ] = '\r';
+  text[LINESIZ + 1] = '\n';
+  (void) sendto (s, text, sizeof (text), 0, &sa, sizeof (sa));
+}
+#endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN */
+
+
+#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME
+/*
+ * Return a machine readable date and time, in the form of the
+ * number of seconds since midnight, Jan 1, 1900.  Since gettimeofday
+ * returns the number of seconds since midnight, Jan 1, 1970,
+ * we must add 2208988800 seconds to this figure to make up for
+ * some seventy years Bell Labs was asleep.
+ */
+
+static u_int machtime (void)
+{
+  struct timeval tv;
+
+  if (gettimeofday (&tv, NULL) < 0) {
+	fprintf (stderr, "Unable to get time of day\n");
+	return (0L);
+  }
+  return (htonl ((u_int) tv.tv_sec + 2208988800UL));
+}
+
+/* ARGSUSED */
+static void
+machtime_stream (int s, servtab_t *sep ATTRIBUTE_UNUSED)
+{
+  u_int result;
+
+  result = machtime ();
+  (void) write (s, (char *) &result, sizeof (result));
+}
+
+/* ARGSUSED */
+static void
+machtime_dg (int s, servtab_t *sep ATTRIBUTE_UNUSED)
+{
+  u_int result;
+  /* struct sockaddr_storage ss; */
+  struct sockaddr sa;
+  struct sockaddr_in *dg_sin;
+  socklen_t size;
+
+  size = sizeof (sa);
+  if (recvfrom (s, (char *) &result, sizeof (result), 0, &sa, &size) < 0)
+	return;
+  /* if (dg_badinput((struct sockaddr *)&ss)) */
+  dg_sin = (struct sockaddr_in *) &sa;
+  if (dg_sin->sin_addr.s_addr == htonl (INADDR_BROADCAST) ||
+	  ntohs (dg_sin->sin_port) < IPPORT_RESERVED / 2)
+	return;
+  result = machtime ();
+  (void) sendto (s, (char *) &result, sizeof (result), 0, &sa, sizeof (sa));
+}
+#endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME */
+
+
+#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
+/* Return human-readable time of day */
+/* ARGSUSED */
+static void daytime_stream (int s, servtab_t *sep ATTRIBUTE_UNUSED)
+{
+  char buffer[256];
+  time_t t;
+
+  t = time (NULL);
+
+  (void) sprintf (buffer, "%.24s\r\n", ctime (&t));
+  (void) write (s, buffer, strlen (buffer));
+}
+
+/* Return human-readable time of day */
+/* ARGSUSED */
+void
+daytime_dg (int s, servtab_t *sep ATTRIBUTE_UNUSED)
+{
+  char buffer[256];
+  time_t t;
+  /* struct sockaddr_storage ss; */
+  struct sockaddr sa;
+  socklen_t size;
+
+  t = time ((time_t *) 0);
+
+  size = sizeof (sa);
+  if (recvfrom (s, buffer, sizeof (buffer), 0, &sa, &size) < 0)
+	return;
+  if (dg_badinput ((struct sockaddr_in *) &sa))
+	return;
+  (void) sprintf (buffer, "%.24s\r\n", ctime (&t));
+  (void) sendto (s, buffer, strlen (buffer), 0, &sa, sizeof (sa));
+}
+#endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME */
+/* vi: set sw=4 ts=4: */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/interface.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/interface.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/interface.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1148 @@
+/*
+ * stolen from net-tools-1.59 and stripped down for busybox by
+ *			Erik Andersen <andersen at codepoet.org>
+ *
+ * Heavily modified by Manuel Novoa III       Mar 12, 2001
+ *
+ * Added print_bytes_scaled function to reduce code size.
+ * Added some (potentially) missing defines.
+ * Improved display support for -a and for a named interface.
+ *
+ * -----------------------------------------------------------
+ *
+ * ifconfig   This file contains an implementation of the command
+ *              that either displays or sets the characteristics of
+ *              one or more of the system's networking interfaces.
+ *
+ * Version:     $Id: interface.c,v 1.25 2004/08/26 21:45:21 andersen Exp $
+ *
+ * Author:      Fred N. van Kempen, <waltje at uwalt.nl.mugnet.org>
+ *              and others.  Copyright 1993 MicroWalt Corporation
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * Patched to support 'add' and 'del' keywords for INET(4) addresses
+ * by Mrs. Brisby <mrs.brisby at nimh.org>
+ *
+ * {1.34} - 19980630 - Arnaldo Carvalho de Melo <acme at conectiva.com.br>
+ *                     - gettext instead of catgets for i18n
+ *          10/1998  - Andi Kleen. Use interface list primitives.
+ *	    20001008 - Bernd Eckenfels, Patch from RH for setting mtu
+ *			(default AF was wrong)
+ */
+
+#include "inet_common.h"
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include "busybox.h"
+
+#ifdef CONFIG_FEATURE_IPV6
+# define HAVE_AFINET6 1
+#else
+# undef HAVE_AFINET6
+#endif
+
+#define _PATH_PROCNET_DEV               "/proc/net/dev"
+#define _PATH_PROCNET_IFINET6           "/proc/net/if_inet6"
+
+#if HAVE_AFINET6
+
+#ifndef _LINUX_IN6_H
+/*
+ *    This is in linux/include/net/ipv6.h.
+ */
+
+struct in6_ifreq {
+	struct in6_addr ifr6_addr;
+	uint32_t ifr6_prefixlen;
+	unsigned int ifr6_ifindex;
+};
+
+#endif
+
+#endif							/* HAVE_AFINET6 */
+
+/* Defines for glibc2.0 users. */
+#ifndef SIOCSIFTXQLEN
+#define SIOCSIFTXQLEN      0x8943
+#define SIOCGIFTXQLEN      0x8942
+#endif
+
+/* ifr_qlen is ifru_ivalue, but it isn't present in 2.0 kernel headers */
+#ifndef ifr_qlen
+#define ifr_qlen        ifr_ifru.ifru_mtu
+#endif
+
+#ifndef HAVE_TXQUEUELEN
+#define HAVE_TXQUEUELEN 1
+#endif
+
+#ifndef IFF_DYNAMIC
+#define IFF_DYNAMIC     0x8000	/* dialup device with changing addresses */
+#endif
+
+/* This structure defines protocol families and their handlers. */
+struct aftype {
+	const char *name;
+	const char *title;
+	int af;
+	int alen;
+	char *(*print) (unsigned char *);
+	char *(*sprint) (struct sockaddr *, int numeric);
+	int (*input) (int type, char *bufp, struct sockaddr *);
+	void (*herror) (char *text);
+	int (*rprint) (int options);
+	int (*rinput) (int typ, int ext, char **argv);
+
+	/* may modify src */
+	int (*getmask) (char *src, struct sockaddr * mask, char *name);
+
+	int fd;
+	char *flag_file;
+};
+
+/* Display an Internet socket address. */
+static char *INET_sprint(struct sockaddr *sap, int numeric)
+{
+	static char buff[128];
+
+	if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
+		return safe_strncpy(buff, "[NONE SET]", sizeof(buff));
+
+	if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap,
+					  numeric, 0xffffff00) != 0)
+		return (NULL);
+
+	return (buff);
+}
+
+static struct aftype inet_aftype = {
+	.name =		"inet",
+	.title =	"DARPA Internet",
+	.af =		AF_INET,
+	.alen =		4,
+	.sprint =	INET_sprint,
+	.fd =		-1
+};
+
+#if HAVE_AFINET6
+
+/* Display an Internet socket address. */
+/* dirty! struct sockaddr usually doesn't suffer for inet6 addresses, fst. */
+static char *INET6_sprint(struct sockaddr *sap, int numeric)
+{
+	static char buff[128];
+
+	if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
+		return safe_strncpy(buff, "[NONE SET]", sizeof(buff));
+	if (INET6_rresolve
+		(buff, sizeof(buff), (struct sockaddr_in6 *) sap, numeric) != 0)
+		return safe_strncpy(buff, "[UNKNOWN]", sizeof(buff));
+	return (buff);
+}
+
+static struct aftype inet6_aftype = {
+	.name =		"inet6",
+	.title =	"IPv6",
+	.af =		AF_INET6,
+	.alen =		sizeof(struct in6_addr),
+	.sprint =	INET6_sprint,
+	.fd =		-1
+};
+
+#endif							/* HAVE_AFINET6 */
+
+/* Display an UNSPEC address. */
+static char *UNSPEC_print(unsigned char *ptr)
+{
+	static char buff[sizeof(struct sockaddr) * 3 + 1];
+	char *pos;
+	unsigned int i;
+
+	pos = buff;
+	for (i = 0; i < sizeof(struct sockaddr); i++) {
+		/* careful -- not every libc's sprintf returns # bytes written */
+		sprintf(pos, "%02X-", (*ptr++ & 0377));
+		pos += 3;
+	}
+	/* Erase trailing "-".  Works as long as sizeof(struct sockaddr) != 0 */
+	*--pos = '\0';
+	return (buff);
+}
+
+/* Display an UNSPEC socket address. */
+static char *UNSPEC_sprint(struct sockaddr *sap, int numeric)
+{
+	static char buf[64];
+
+	if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
+		return safe_strncpy(buf, "[NONE SET]", sizeof(buf));
+	return (UNSPEC_print((unsigned char *)sap->sa_data));
+}
+
+static struct aftype unspec_aftype = {
+	"unspec", "UNSPEC", AF_UNSPEC, 0,
+	UNSPEC_print, UNSPEC_sprint, NULL, NULL,
+	NULL,
+};
+
+static struct aftype * const aftypes[] = {
+	&inet_aftype,
+#if HAVE_AFINET6
+	&inet6_aftype,
+#endif
+	&unspec_aftype,
+	NULL
+};
+
+/* Check our protocol family table for this family. */
+static struct aftype *get_afntype(int af)
+{
+	struct aftype * const *afp;
+
+	afp = aftypes;
+	while (*afp != NULL) {
+		if ((*afp)->af == af)
+			return (*afp);
+		afp++;
+	}
+	return (NULL);
+}
+
+/* Check our protocol family table for this family and return its socket */
+static int get_socket_for_af(int af)
+{
+	struct aftype * const *afp;
+
+	afp = aftypes;
+	while (*afp != NULL) {
+		if ((*afp)->af == af)
+			return (*afp)->fd;
+		afp++;
+	}
+	return -1;
+}
+
+struct user_net_device_stats {
+	unsigned long long rx_packets;	/* total packets received       */
+	unsigned long long tx_packets;	/* total packets transmitted    */
+	unsigned long long rx_bytes;	/* total bytes received         */
+	unsigned long long tx_bytes;	/* total bytes transmitted      */
+	unsigned long rx_errors;	/* bad packets received         */
+	unsigned long tx_errors;	/* packet transmit problems     */
+	unsigned long rx_dropped;	/* no space in linux buffers    */
+	unsigned long tx_dropped;	/* no space available in linux  */
+	unsigned long rx_multicast;	/* multicast packets received   */
+	unsigned long rx_compressed;
+	unsigned long tx_compressed;
+	unsigned long collisions;
+
+	/* detailed rx_errors: */
+	unsigned long rx_length_errors;
+	unsigned long rx_over_errors;	/* receiver ring buff overflow  */
+	unsigned long rx_crc_errors;	/* recved pkt with crc error    */
+	unsigned long rx_frame_errors;	/* recv'd frame alignment error */
+	unsigned long rx_fifo_errors;	/* recv'r fifo overrun          */
+	unsigned long rx_missed_errors;	/* receiver missed packet     */
+	/* detailed tx_errors */
+	unsigned long tx_aborted_errors;
+	unsigned long tx_carrier_errors;
+	unsigned long tx_fifo_errors;
+	unsigned long tx_heartbeat_errors;
+	unsigned long tx_window_errors;
+};
+
+struct interface {
+	struct interface *next, *prev;
+	char name[IFNAMSIZ];	/* interface name        */
+	short type;			/* if type               */
+	short flags;		/* various flags         */
+	int metric;			/* routing metric        */
+	int mtu;			/* MTU value             */
+	int tx_queue_len;	/* transmit queue length */
+	struct ifmap map;	/* hardware setup        */
+	struct sockaddr addr;	/* IP address            */
+	struct sockaddr dstaddr;	/* P-P IP address        */
+	struct sockaddr broadaddr;	/* IP broadcast address  */
+	struct sockaddr netmask;	/* IP network mask       */
+	int has_ip;
+	char hwaddr[32];	/* HW address            */
+	int statistics_valid;
+	struct user_net_device_stats stats;	/* statistics            */
+	int keepalive;		/* keepalive value for SLIP */
+	int outfill;		/* outfill value for SLIP */
+};
+
+
+int interface_opt_a = 0;	/* show all interfaces          */
+
+static struct interface *int_list, *int_last;
+static int skfd = -1;	/* generic raw socket desc.     */
+
+
+static int sockets_open(int family)
+{
+	struct aftype * const *aft;
+	int sfd = -1;
+	static int force = -1;
+
+	if (force < 0) {
+		force = 0;
+		if (get_linux_version_code() < KERNEL_VERSION(2,1,0))
+			force = 1;
+		if (access("/proc/net", R_OK))
+			force = 1;
+	}
+	for (aft = aftypes; *aft; aft++) {
+		struct aftype *af = *aft;
+		int type = SOCK_DGRAM;
+
+		if (af->af == AF_UNSPEC)
+			continue;
+		if (family && family != af->af)
+			continue;
+		if (af->fd != -1) {
+			sfd = af->fd;
+			continue;
+		}
+		/* Check some /proc file first to not stress kmod */
+		if (!family && !force && af->flag_file) {
+			if (access(af->flag_file, R_OK))
+				continue;
+		}
+		af->fd = socket(af->af, type, 0);
+		if (af->fd >= 0)
+			sfd = af->fd;
+	}
+	if (sfd < 0) {
+		bb_error_msg("No usable address families found.");
+	}
+	return sfd;
+}
+
+#ifdef CONFIG_FEATURE_CLEAN_UP
+static void sockets_close(void)
+{
+	struct aftype * const *aft;
+	for (aft = aftypes; *aft != NULL; aft++) {
+		struct aftype *af = *aft;
+		if( af->fd != -1 ) {
+			close(af->fd);
+			af->fd = -1;
+		}
+	}
+}
+#endif
+
+/* like strcmp(), but knows about numbers */
+static int nstrcmp(const char *a, const char *b)
+{
+	const char *a_ptr = a;
+	const char *b_ptr = b;
+
+	while (*a == *b) {
+		if (*a == '\0') {
+			return 0;
+		}
+		if (!isdigit(*a) && isdigit(*(a+1))) {
+			a_ptr = a+1;
+			b_ptr = b+1;
+		}
+		a++;
+		b++;
+	}
+
+	if (isdigit(*a) && isdigit(*b)) {
+		return atoi(a_ptr) > atoi(b_ptr) ? 1 : -1;
+	}
+	return *a - *b;
+}
+
+static struct interface *add_interface(char *name)
+{
+	struct interface *ife, **nextp, *new;
+
+	for (ife = int_last; ife; ife = ife->prev) {
+		int n = nstrcmp(ife->name, name);
+
+		if (n == 0)
+			return ife;
+		if (n < 0)
+			break;
+	}
+
+	new = xzalloc(sizeof(*new));
+	safe_strncpy(new->name, name, IFNAMSIZ);
+	nextp = ife ? &ife->next : &int_list;
+	new->prev = ife;
+	new->next = *nextp;
+	if (new->next)
+		new->next->prev = new;
+	else
+		int_last = new;
+	*nextp = new;
+	return new;
+}
+
+
+static int if_readconf(void)
+{
+	int numreqs = 30;
+	struct ifconf ifc;
+	struct ifreq *ifr;
+	int n, err = -1;
+	int skfd2;
+
+	/* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
+	   (as of 2.1.128) */
+	skfd2 = get_socket_for_af(AF_INET);
+	if (skfd2 < 0) {
+		bb_perror_msg(("warning: no inet socket available"));
+		/* Try to soldier on with whatever socket we can get hold of.  */
+		skfd2 = sockets_open(0);
+		if (skfd2 < 0)
+			return -1;
+	}
+
+	ifc.ifc_buf = NULL;
+	for (;;) {
+		ifc.ifc_len = sizeof(struct ifreq) * numreqs;
+		ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
+
+		if (ioctl(skfd2, SIOCGIFCONF, &ifc) < 0) {
+			perror("SIOCGIFCONF");
+			goto out;
+		}
+		if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
+			/* assume it overflowed and try again */
+			numreqs += 10;
+			continue;
+		}
+		break;
+	}
+
+	ifr = ifc.ifc_req;
+	for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
+		add_interface(ifr->ifr_name);
+		ifr++;
+	}
+	err = 0;
+
+  out:
+	free(ifc.ifc_buf);
+	return err;
+}
+
+static char *get_name(char *name, char *p)
+{
+	/* Extract <name> from nul-terminated p where p matches
+	   <name>: after leading whitespace.
+	   If match is not made, set name empty and return unchanged p */
+	int namestart=0, nameend=0;
+	while (isspace(p[namestart]))
+		namestart++;
+	nameend=namestart;
+	while (p[nameend] && p[nameend]!=':' && !isspace(p[nameend]))
+		nameend++;
+	if (p[nameend]==':') {
+		if ((nameend-namestart)<IFNAMSIZ) {
+			memcpy(name,&p[namestart],nameend-namestart);
+			name[nameend-namestart]='\0';
+			p=&p[nameend];
+		} else {
+			/* Interface name too large */
+			name[0]='\0';
+		}
+	} else {
+		/* trailing ':' not found - return empty */
+		name[0]='\0';
+	}
+	return p + 1;
+}
+
+/* If scanf supports size qualifiers for %n conversions, then we can
+ * use a modified fmt that simply stores the position in the fields
+ * having no associated fields in the proc string.  Of course, we need
+ * to zero them again when we're done.  But that is smaller than the
+ * old approach of multiple scanf occurrences with large numbers of
+ * args. */
+
+/* static const char * const ss_fmt[] = { */
+/*	"%lln%llu%lu%lu%lu%lu%ln%ln%lln%llu%lu%lu%lu%lu%lu", */
+/*	"%llu%llu%lu%lu%lu%lu%ln%ln%llu%llu%lu%lu%lu%lu%lu", */
+/*	"%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" */
+/* }; */
+
+	/* Lie about the size of the int pointed to for %n. */
+#if INT_MAX == LONG_MAX
+static const char * const ss_fmt[] = {
+	"%n%llu%u%u%u%u%n%n%n%llu%u%u%u%u%u",
+	"%llu%llu%u%u%u%u%n%n%llu%llu%u%u%u%u%u",
+	"%llu%llu%u%u%u%u%u%u%llu%llu%u%u%u%u%u%u"
+};
+#else
+static const char * const ss_fmt[] = {
+	"%n%llu%lu%lu%lu%lu%n%n%n%llu%lu%lu%lu%lu%lu",
+	"%llu%llu%lu%lu%lu%lu%n%n%llu%llu%lu%lu%lu%lu%lu",
+	"%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu"
+};
+
+#endif
+
+static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn)
+{
+	memset(&ife->stats, 0, sizeof(struct user_net_device_stats));
+
+	sscanf(bp, ss_fmt[procnetdev_vsn],
+		   &ife->stats.rx_bytes, /* missing for 0 */
+		   &ife->stats.rx_packets,
+		   &ife->stats.rx_errors,
+		   &ife->stats.rx_dropped,
+		   &ife->stats.rx_fifo_errors,
+		   &ife->stats.rx_frame_errors,
+		   &ife->stats.rx_compressed, /* missing for <= 1 */
+		   &ife->stats.rx_multicast, /* missing for <= 1 */
+		   &ife->stats.tx_bytes, /* missing for 0 */
+		   &ife->stats.tx_packets,
+		   &ife->stats.tx_errors,
+		   &ife->stats.tx_dropped,
+		   &ife->stats.tx_fifo_errors,
+		   &ife->stats.collisions,
+		   &ife->stats.tx_carrier_errors,
+		   &ife->stats.tx_compressed /* missing for <= 1 */
+		   );
+
+	if (procnetdev_vsn <= 1) {
+		if (procnetdev_vsn == 0) {
+			ife->stats.rx_bytes = 0;
+			ife->stats.tx_bytes = 0;
+		}
+		ife->stats.rx_multicast = 0;
+		ife->stats.rx_compressed = 0;
+		ife->stats.tx_compressed = 0;
+	}
+}
+
+static inline int procnetdev_version(char *buf)
+{
+	if (strstr(buf, "compressed"))
+		return 2;
+	if (strstr(buf, "bytes"))
+		return 1;
+	return 0;
+}
+
+static int if_readlist_proc(char *target)
+{
+	static int proc_read;
+	FILE *fh;
+	char buf[512];
+	struct interface *ife;
+	int err, procnetdev_vsn;
+
+	if (proc_read)
+		return 0;
+	if (!target)
+		proc_read = 1;
+
+	fh = fopen(_PATH_PROCNET_DEV, "r");
+	if (!fh) {
+		bb_perror_msg("Warning: cannot open %s. Limited output.", _PATH_PROCNET_DEV);
+		return if_readconf();
+	}
+	fgets(buf, sizeof buf, fh);	/* eat line */
+	fgets(buf, sizeof buf, fh);
+
+	procnetdev_vsn = procnetdev_version(buf);
+
+	err = 0;
+	while (fgets(buf, sizeof buf, fh)) {
+		char *s, name[128];
+
+		s = get_name(name, buf);
+		ife = add_interface(name);
+		get_dev_fields(s, ife, procnetdev_vsn);
+		ife->statistics_valid = 1;
+		if (target && !strcmp(target, name))
+			break;
+	}
+	if (ferror(fh)) {
+		perror(_PATH_PROCNET_DEV);
+		err = -1;
+		proc_read = 0;
+	}
+	fclose(fh);
+	return err;
+}
+
+static int if_readlist(void)
+{
+	int err = if_readlist_proc(NULL);
+
+	if (!err)
+		err = if_readconf();
+	return err;
+}
+
+static int for_all_interfaces(int (*doit) (struct interface *, void *),
+							  void *cookie)
+{
+	struct interface *ife;
+
+	if (!int_list && (if_readlist() < 0))
+		return -1;
+	for (ife = int_list; ife; ife = ife->next) {
+		int err = doit(ife, cookie);
+
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+/* Fetch the interface configuration from the kernel. */
+static int if_fetch(struct interface *ife)
+{
+	struct ifreq ifr;
+	int fd;
+	char *ifname = ife->name;
+
+	strcpy(ifr.ifr_name, ifname);
+	if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
+		return (-1);
+	ife->flags = ifr.ifr_flags;
+
+	strcpy(ifr.ifr_name, ifname);
+	if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
+		memset(ife->hwaddr, 0, 32);
+	else
+		memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
+
+	ife->type = ifr.ifr_hwaddr.sa_family;
+
+	strcpy(ifr.ifr_name, ifname);
+	if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0)
+		ife->metric = 0;
+	else
+		ife->metric = ifr.ifr_metric;
+
+	strcpy(ifr.ifr_name, ifname);
+	if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
+		ife->mtu = 0;
+	else
+		ife->mtu = ifr.ifr_mtu;
+
+#ifdef SIOCGIFMAP
+	strcpy(ifr.ifr_name, ifname);
+	if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0)
+		ife->map = ifr.ifr_map;
+	else
+#endif
+		memset(&ife->map, 0, sizeof(struct ifmap));
+
+#ifdef HAVE_TXQUEUELEN
+	strcpy(ifr.ifr_name, ifname);
+	if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0)
+		ife->tx_queue_len = -1;	/* unknown value */
+	else
+		ife->tx_queue_len = ifr.ifr_qlen;
+#else
+	ife->tx_queue_len = -1;	/* unknown value */
+#endif
+
+	/* IPv4 address? */
+	fd = get_socket_for_af(AF_INET);
+	if (fd >= 0) {
+		strcpy(ifr.ifr_name, ifname);
+		ifr.ifr_addr.sa_family = AF_INET;
+		if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
+			ife->has_ip = 1;
+			ife->addr = ifr.ifr_addr;
+			strcpy(ifr.ifr_name, ifname);
+			if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)
+				memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
+			else
+				ife->dstaddr = ifr.ifr_dstaddr;
+
+			strcpy(ifr.ifr_name, ifname);
+			if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
+				memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
+			else
+				ife->broadaddr = ifr.ifr_broadaddr;
+
+			strcpy(ifr.ifr_name, ifname);
+			if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
+				memset(&ife->netmask, 0, sizeof(struct sockaddr));
+			else
+				ife->netmask = ifr.ifr_netmask;
+		} else
+			memset(&ife->addr, 0, sizeof(struct sockaddr));
+	}
+
+	return 0;
+}
+
+
+static int do_if_fetch(struct interface *ife)
+{
+	if (if_fetch(ife) < 0) {
+		char *errmsg;
+
+		if (errno == ENODEV) {
+			/* Give better error message for this case. */
+			errmsg = "Device not found";
+		} else {
+			errmsg = strerror(errno);
+		}
+		bb_error_msg("%s: error fetching interface information: %s",
+				ife->name, errmsg);
+		return -1;
+	}
+	return 0;
+}
+
+/* This structure defines hardware protocols and their handlers. */
+struct hwtype {
+	const char * const name;
+	const char *title;
+	int type;
+	int alen;
+	char *(*print) (unsigned char *);
+	int (*input) (char *, struct sockaddr *);
+	int (*activate) (int fd);
+	int suppress_null_addr;
+};
+
+static const struct hwtype unspec_hwtype = {
+	.name =		"unspec",
+	.title =	"UNSPEC",
+	.type =		-1,
+	.print =	UNSPEC_print
+};
+
+static const struct hwtype loop_hwtype = {
+	.name =		"loop",
+	.title =	"Local Loopback",
+	.type =		ARPHRD_LOOPBACK
+};
+
+#include <net/if_arp.h>
+
+#if (__GLIBC__ >=2 && __GLIBC_MINOR >= 1) || defined(_NEWLIB_VERSION)
+#include <net/ethernet.h>
+#else
+#include <linux/if_ether.h>
+#endif
+
+/* Display an Ethernet address in readable format. */
+static char *pr_ether(unsigned char *ptr)
+{
+	static char buff[64];
+
+	snprintf(buff, sizeof(buff), "%02X:%02X:%02X:%02X:%02X:%02X",
+			 (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
+			 (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377)
+		);
+	return (buff);
+}
+
+static const struct hwtype ether_hwtype = {
+	.name =		"ether",
+	.title =	"Ethernet",
+	.type =		ARPHRD_ETHER,
+	.alen =		ETH_ALEN,
+	.print =	pr_ether
+};
+
+#include <net/if_arp.h>
+
+static const struct hwtype ppp_hwtype = {
+	.name =		"ppp",
+	.title =	"Point-to-Point Protocol",
+	.type =		ARPHRD_PPP
+};
+
+#ifdef CONFIG_FEATURE_IPV6
+static const struct hwtype sit_hwtype = {
+	.name =			"sit",
+	.title =		"IPv6-in-IPv4",
+	.type =			ARPHRD_SIT,
+	.print =		UNSPEC_print,
+	.suppress_null_addr =	1
+} ;
+#endif
+
+static const struct hwtype * const hwtypes[] = {
+	&loop_hwtype,
+	&ether_hwtype,
+	&ppp_hwtype,
+	&unspec_hwtype,
+#ifdef CONFIG_FEATURE_IPV6
+	&sit_hwtype,
+#endif
+	NULL
+};
+
+#ifdef IFF_PORTSEL
+static const char * const if_port_text[] = {
+	/* Keep in step with <linux/netdevice.h> */
+	"unknown",
+	"10base2",
+	"10baseT",
+	"AUI",
+	"100baseT",
+	"100baseTX",
+	"100baseFX",
+	NULL
+};
+#endif
+
+/* Check our hardware type table for this type. */
+static const struct hwtype *get_hwntype(int type)
+{
+	const struct hwtype * const *hwp;
+
+	hwp = hwtypes;
+	while (*hwp != NULL) {
+		if ((*hwp)->type == type)
+			return (*hwp);
+		hwp++;
+	}
+	return (NULL);
+}
+
+/* return 1 if address is all zeros */
+static int hw_null_address(const struct hwtype *hw, void *ap)
+{
+	unsigned int i;
+	unsigned char *address = (unsigned char *) ap;
+
+	for (i = 0; i < hw->alen; i++)
+		if (address[i])
+			return 0;
+	return 1;
+}
+
+static const char TRext[] = "\0\0\0Ki\0Mi\0Gi\0Ti";
+
+static void print_bytes_scaled(unsigned long long ull, const char *end)
+{
+	unsigned long long int_part;
+	const char *ext;
+	unsigned int frac_part;
+	int i;
+
+	frac_part = 0;
+	ext = TRext;
+	int_part = ull;
+	i = 4;
+	do {
+		if (int_part >= 1024) {
+			frac_part = ((((unsigned int) int_part) & (1024-1)) * 10) / 1024;
+			int_part /= 1024;
+			ext += 3;	/* KiB, MiB, GiB, TiB */
+		}
+		--i;
+	} while (i);
+
+	printf("X bytes:%llu (%llu.%u %sB)%s", ull, int_part, frac_part, ext, end);
+}
+
+static const char * const ife_print_flags_strs[] = {
+	"UP ",
+	"BROADCAST ",
+	"DEBUG ",
+	"LOOPBACK ",
+	"POINTOPOINT ",
+	"NOTRAILERS ",
+	"RUNNING ",
+	"NOARP ",
+	"PROMISC ",
+	"ALLMULTI ",
+	"SLAVE ",
+	"MASTER ",
+	"MULTICAST ",
+#ifdef HAVE_DYNAMIC
+	"DYNAMIC "
+#endif
+};
+
+static const unsigned short ife_print_flags_mask[] = {
+	IFF_UP,
+	IFF_BROADCAST,
+	IFF_DEBUG,
+	IFF_LOOPBACK,
+	IFF_POINTOPOINT,
+	IFF_NOTRAILERS,
+	IFF_RUNNING,
+	IFF_NOARP,
+	IFF_PROMISC,
+	IFF_ALLMULTI,
+	IFF_SLAVE,
+	IFF_MASTER,
+	IFF_MULTICAST,
+#ifdef HAVE_DYNAMIC
+	IFF_DYNAMIC
+#endif
+	0
+};
+
+static void ife_print(struct interface *ptr)
+{
+	struct aftype *ap;
+	const struct hwtype *hw;
+	int hf;
+	int can_compress = 0;
+
+#if HAVE_AFINET6
+	FILE *f;
+	char addr6[40], devname[20];
+	struct sockaddr_in6 sap;
+	int plen, scope, dad_status, if_idx;
+	char addr6p[8][5];
+#endif
+
+	ap = get_afntype(ptr->addr.sa_family);
+	if (ap == NULL)
+		ap = get_afntype(0);
+
+	hf = ptr->type;
+
+	if (hf == ARPHRD_CSLIP || hf == ARPHRD_CSLIP6)
+		can_compress = 1;
+
+	hw = get_hwntype(hf);
+	if (hw == NULL)
+		hw = get_hwntype(-1);
+
+	printf("%-9.9s Link encap:%s  ", ptr->name, hw->title);
+	/* For some hardware types (eg Ash, ATM) we don't print the
+	   hardware address if it's null.  */
+	if (hw->print != NULL && (!(hw_null_address(hw, ptr->hwaddr) &&
+								hw->suppress_null_addr)))
+		printf("HWaddr %s  ", hw->print((unsigned char *)ptr->hwaddr));
+#ifdef IFF_PORTSEL
+	if (ptr->flags & IFF_PORTSEL) {
+		printf("Media:%s", if_port_text[ptr->map.port] /* [0] */);
+		if (ptr->flags & IFF_AUTOMEDIA)
+			printf("(auto)");
+	}
+#endif
+	printf("\n");
+
+	if (ptr->has_ip) {
+		printf("          %s addr:%s ", ap->name,
+			   ap->sprint(&ptr->addr, 1));
+		if (ptr->flags & IFF_POINTOPOINT) {
+			printf(" P-t-P:%s ", ap->sprint(&ptr->dstaddr, 1));
+		}
+		if (ptr->flags & IFF_BROADCAST) {
+			printf(" Bcast:%s ", ap->sprint(&ptr->broadaddr, 1));
+		}
+		printf(" Mask:%s\n", ap->sprint(&ptr->netmask, 1));
+	}
+
+#if HAVE_AFINET6
+
+#define IPV6_ADDR_ANY           0x0000U
+
+#define IPV6_ADDR_UNICAST       0x0001U
+#define IPV6_ADDR_MULTICAST     0x0002U
+#define IPV6_ADDR_ANYCAST       0x0004U
+
+#define IPV6_ADDR_LOOPBACK      0x0010U
+#define IPV6_ADDR_LINKLOCAL     0x0020U
+#define IPV6_ADDR_SITELOCAL     0x0040U
+
+#define IPV6_ADDR_COMPATv4      0x0080U
+
+#define IPV6_ADDR_SCOPE_MASK    0x00f0U
+
+#define IPV6_ADDR_MAPPED        0x1000U
+#define IPV6_ADDR_RESERVED      0x2000U	/* reserved address space */
+
+	if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
+		while (fscanf
+			   (f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
+				addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4],
+				addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope,
+				&dad_status, devname) != EOF) {
+			if (!strcmp(devname, ptr->name)) {
+				sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
+						addr6p[0], addr6p[1], addr6p[2], addr6p[3],
+						addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
+				inet_pton(AF_INET6, addr6,
+						  (struct sockaddr *) &sap.sin6_addr);
+				sap.sin6_family = AF_INET6;
+				printf("          inet6 addr: %s/%d",
+					   inet6_aftype.sprint((struct sockaddr *) &sap, 1),
+					   plen);
+				printf(" Scope:");
+				switch (scope & IPV6_ADDR_SCOPE_MASK) {
+				case 0:
+					printf("Global");
+					break;
+				case IPV6_ADDR_LINKLOCAL:
+					printf("Link");
+					break;
+				case IPV6_ADDR_SITELOCAL:
+					printf("Site");
+					break;
+				case IPV6_ADDR_COMPATv4:
+					printf("Compat");
+					break;
+				case IPV6_ADDR_LOOPBACK:
+					printf("Host");
+					break;
+				default:
+					printf("Unknown");
+				}
+				printf("\n");
+			}
+		}
+		fclose(f);
+	}
+#endif
+
+	printf("          ");
+	/* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */
+
+	if (ptr->flags == 0) {
+		printf("[NO FLAGS] ");
+	} else {
+		int i = 0;
+		do {
+			if (ptr->flags & ife_print_flags_mask[i]) {
+				printf(ife_print_flags_strs[i]);
+			}
+		} while (ife_print_flags_mask[++i]);
+	}
+
+	/* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
+	printf(" MTU:%d  Metric:%d", ptr->mtu, ptr->metric ? ptr->metric : 1);
+#ifdef SIOCSKEEPALIVE
+	if (ptr->outfill || ptr->keepalive)
+		printf("  Outfill:%d  Keepalive:%d", ptr->outfill, ptr->keepalive);
+#endif
+	printf("\n");
+
+	/* If needed, display the interface statistics. */
+
+	if (ptr->statistics_valid) {
+		/* XXX: statistics are currently only printed for the primary address,
+		 *      not for the aliases, although strictly speaking they're shared
+		 *      by all addresses.
+		 */
+		printf("          ");
+
+		printf("RX packets:%llu errors:%lu dropped:%lu overruns:%lu frame:%lu\n",
+			   ptr->stats.rx_packets, ptr->stats.rx_errors,
+			   ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,
+			   ptr->stats.rx_frame_errors);
+		if (can_compress)
+			printf("             compressed:%lu\n",
+				   ptr->stats.rx_compressed);
+		printf("          ");
+		printf("TX packets:%llu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n",
+			   ptr->stats.tx_packets, ptr->stats.tx_errors,
+			   ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
+			   ptr->stats.tx_carrier_errors);
+		printf("          collisions:%lu ", ptr->stats.collisions);
+		if (can_compress)
+			printf("compressed:%lu ", ptr->stats.tx_compressed);
+		if (ptr->tx_queue_len != -1)
+			printf("txqueuelen:%d ", ptr->tx_queue_len);
+		printf("\n          R");
+		print_bytes_scaled(ptr->stats.rx_bytes, "  T");
+		print_bytes_scaled(ptr->stats.tx_bytes, "\n");
+
+	}
+
+	if ((ptr->map.irq || ptr->map.mem_start || ptr->map.dma ||
+		 ptr->map.base_addr)) {
+		printf("          ");
+		if (ptr->map.irq)
+			printf("Interrupt:%d ", ptr->map.irq);
+		if (ptr->map.base_addr >= 0x100)	/* Only print devices using it for
+											   I/O maps */
+			printf("Base address:0x%lx ",
+				   (unsigned long) ptr->map.base_addr);
+		if (ptr->map.mem_start) {
+			printf("Memory:%lx-%lx ", ptr->map.mem_start,
+				   ptr->map.mem_end);
+		}
+		if (ptr->map.dma)
+			printf("DMA chan:%x ", ptr->map.dma);
+		printf("\n");
+	}
+	printf("\n");
+}
+
+
+static int do_if_print(struct interface *ife, void *cookie)
+{
+	int *opt_a = (int *) cookie;
+	int res;
+
+	res = do_if_fetch(ife);
+	if (res >= 0) {
+		if ((ife->flags & IFF_UP) || *opt_a)
+			ife_print(ife);
+	}
+	return res;
+}
+
+static struct interface *lookup_interface(char *name)
+{
+	struct interface *ife = NULL;
+
+	if (if_readlist_proc(name) < 0)
+		return NULL;
+	ife = add_interface(name);
+	return ife;
+}
+
+/* for ipv4 add/del modes */
+static int if_print(char *ifname)
+{
+	int res;
+
+	if (!ifname) {
+		res = for_all_interfaces(do_if_print, &interface_opt_a);
+	} else {
+		struct interface *ife;
+
+		ife = lookup_interface(ifname);
+		res = do_if_fetch(ife);
+		if (res >= 0)
+			ife_print(ife);
+	}
+	return res;
+}
+
+int display_interfaces(char *ifname);
+int display_interfaces(char *ifname)
+{
+	int status;
+
+	/* Create a channel to the NET kernel. */
+	if ((skfd = sockets_open(0)) < 0) {
+		bb_perror_msg_and_die("socket");
+	}
+
+	/* Do we have to show the current setup? */
+	status = if_print(ifname);
+#ifdef CONFIG_FEATURE_CLEAN_UP
+	sockets_close();
+#endif
+	exit(status < 0);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ip.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ip.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ip.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,112 @@
+/*
+ * ip.c		"ip" utility frontend.
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ *
+ *
+ * Changes:
+ *
+ * Rani Assaf <rani at magic.metawire.com> 980929:	resolve addresses
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+
+#include "libiproute/utils.h"
+#include "libiproute/ip_common.h"
+
+#include "busybox.h"
+
+#if 0
+int preferred_family = AF_UNSPEC;
+int oneline = 0;
+char * _SL_ = NULL;
+
+void ip_parse_common_args(int *argcp, char ***argvp)
+{
+	int argc = *argcp;
+	char **argv = *argvp;
+
+	while (argc > 1) {
+		char *opt = argv[1];
+
+		if (strcmp(opt,"--") == 0) {
+			argc--; argv++;
+			break;
+		}
+
+		if (opt[0] != '-')
+			break;
+
+		if (opt[1] == '-')
+			opt++;
+
+		if (matches(opt, "-family") == 0) {
+			argc--;
+			argv++;
+			if (strcmp(argv[1], "inet") == 0)
+				preferred_family = AF_INET;
+			else if (strcmp(argv[1], "inet6") == 0)
+				preferred_family = AF_INET6;
+			else if (strcmp(argv[1], "link") == 0)
+				preferred_family = AF_PACKET;
+			else
+				invarg(bb_msg_invalid_arg, argv[1], "-family");
+		} else if (strcmp(opt, "-4") == 0) {
+			preferred_family = AF_INET;
+		} else if (strcmp(opt, "-6") == 0) {
+			preferred_family = AF_INET6;
+		} else if (strcmp(opt, "-0") == 0) {
+			preferred_family = AF_PACKET;
+		} else if (matches(opt, "-oneline") == 0) {
+			++oneline;
+		} else {
+			bb_show_usage();
+		}
+		argc--;	argv++;
+	}
+	_SL_ = oneline ? "\\" : "\n" ;
+}
+#endif
+
+int ip_main(int argc, char **argv)
+{
+	int ret = EXIT_FAILURE;
+
+	ip_parse_common_args(&argc, &argv);
+
+	if (argc > 1) {
+#ifdef CONFIG_FEATURE_IP_ADDRESS
+		if (matches(argv[1], "address") == 0) {
+			ret = do_ipaddr(argc-2, argv+2);
+		}
+#endif
+#ifdef CONFIG_FEATURE_IP_ROUTE
+		if (matches(argv[1], "route") == 0) {
+			ret = do_iproute(argc-2, argv+2);
+		}
+#endif
+#ifdef CONFIG_FEATURE_IP_LINK
+		if (matches(argv[1], "link") == 0) {
+			ret = do_iplink(argc-2, argv+2);
+		}
+#endif
+#ifdef CONFIG_FEATURE_IP_TUNNEL
+		if (matches(argv[1], "tunnel") == 0 || strcmp(argv[1], "tunl") == 0) {
+			ret = do_iptunnel(argc-2, argv+2);
+		}
+#endif
+	}
+	if (ret) {
+		bb_show_usage();
+	}
+	return(EXIT_SUCCESS);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ipaddr.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ipaddr.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ipaddr.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,24 @@
+/*
+ * ip.c		"ip" utility frontend.
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ *
+ *
+ * Changes:
+ *
+ * Rani Assaf <rani at magic.metawire.com> 980929:	resolve addresses
+ */
+
+#include "libiproute/utils.h"
+#include "libiproute/ip_common.h"
+
+#include "busybox.h"
+
+int ipaddr_main(int argc, char **argv)
+{
+	ip_parse_common_args(&argc, &argv);
+
+	return do_ipaddr(argc-1, argv+1);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ipcalc.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ipcalc.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ipcalc.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,207 @@
+/* vi: set sw=4 ts=4 ai: */
+/*
+ * Mini ipcalc implementation for busybox
+ *
+ * By Jordan Crouse <jordan at cosmicpenguin.net>
+ *    Stephan Linz  <linz at li-pro.net>
+ *
+ * This is a complete reimplementation of the ipcalc program
+ * from Red Hat.  I didn't look at their source code, but there
+ * is no denying that this is a loving reimplementation
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <ctype.h>
+#include <getopt.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#define IPCALC_MSG(CMD,ALTCMD) if (mode & SILENT) {ALTCMD;} else {CMD;}
+
+#define CLASS_A_NETMASK	ntohl(0xFF000000)
+#define CLASS_B_NETMASK	ntohl(0xFFFF0000)
+#define CLASS_C_NETMASK	ntohl(0xFFFFFF00)
+
+static unsigned long get_netmask(unsigned long ipaddr)
+{
+	ipaddr = htonl(ipaddr);
+
+	if ((ipaddr & 0xC0000000) == 0xC0000000)
+		return CLASS_C_NETMASK;
+	else if ((ipaddr & 0x80000000) == 0x80000000)
+		return CLASS_B_NETMASK;
+	else if ((ipaddr & 0x80000000) == 0)
+		return CLASS_A_NETMASK;
+	else
+		return 0;
+}
+
+#ifdef CONFIG_FEATURE_IPCALC_FANCY
+static int get_prefix(unsigned long netmask)
+{
+	unsigned long msk = 0x80000000;
+	int ret = 0;
+
+	netmask = htonl(netmask);
+	while(msk) {
+		if (netmask & msk)
+			ret++;
+		msk >>= 1;
+	}
+	return ret;
+}
+#else
+int get_prefix(unsigned long netmask);
+#endif
+
+#define NETMASK   0x01
+#define BROADCAST 0x02
+#define NETWORK   0x04
+#define NETPREFIX 0x08
+#define HOSTNAME  0x10
+#define SILENT    0x20
+
+#if ENABLE_FEATURE_IPCALC_LONG_OPTIONS
+	static const struct option long_options[] = {
+		{"netmask",		no_argument, NULL, 'm'},
+		{"broadcast",	no_argument, NULL, 'b'},
+		{"network",		no_argument, NULL, 'n'},
+#ifdef CONFIG_FEATURE_IPCALC_FANCY
+		{"prefix",		no_argument, NULL, 'p'},
+		{"hostname",	no_argument, NULL, 'h'},
+		{"silent",		no_argument, NULL, 's'},
+#endif
+		{NULL, 0, NULL, 0}
+	};
+#else
+#define long_options 0
+#endif
+
+
+
+int ipcalc_main(int argc, char **argv)
+{
+	unsigned long mode;
+	int have_netmask = 0;
+	in_addr_t netmask, broadcast, network, ipaddr;
+	struct in_addr a;
+	char *ipstr;
+
+	if (ENABLE_FEATURE_IPCALC_LONG_OPTIONS)
+		bb_applet_long_options = long_options;
+
+	mode = bb_getopt_ulflags(argc, argv, "mbn" USE_FEATURE_IPCALC_FANCY("phs"));
+
+	argc -= optind;
+	argv += optind;
+	if (mode & (BROADCAST | NETWORK | NETPREFIX)) {
+		if (argc > 2 || argc <= 0)
+			bb_show_usage();
+	} else {
+		if (argc != 1)
+			bb_show_usage();
+	}
+
+	ipstr = argv[0];
+	if (ENABLE_FEATURE_IPCALC_FANCY) {
+		unsigned long netprefix = 0;
+		char *prefixstr;
+
+		prefixstr = ipstr;
+
+		while(*prefixstr) {
+			if (*prefixstr == '/') {
+				*prefixstr = (char)0;
+				prefixstr++;
+				if (*prefixstr) {
+					unsigned int msk;
+
+					if (safe_strtoul(prefixstr, &netprefix) || netprefix > 32) {
+						IPCALC_MSG(bb_error_msg_and_die("bad IP prefix: %s\n", prefixstr),
+								exit(EXIT_FAILURE));
+					}
+					netmask = 0;
+					msk = 0x80000000;
+					while (netprefix > 0) {
+						netmask |= msk;
+						msk >>= 1;
+						netprefix--;
+					}
+					netmask = htonl(netmask);
+					/* Even if it was 0, we will signify that we have a netmask. This allows */
+					/* for specification of default routes, etc which have a 0 netmask/prefix */
+					have_netmask = 1;
+				}
+				break;
+			}
+			prefixstr++;
+		}
+	}
+	ipaddr = inet_aton(ipstr, &a);
+
+	if (ipaddr == 0) {
+		IPCALC_MSG(bb_error_msg_and_die("bad IP address: %s", argv[0]),
+				exit(EXIT_FAILURE));
+	}
+	ipaddr = a.s_addr;
+
+	if (argc == 2) {
+		if (ENABLE_FEATURE_IPCALC_FANCY && have_netmask) {
+			IPCALC_MSG(bb_error_msg_and_die("Use prefix or netmask, not both.\n"),
+					exit(EXIT_FAILURE));
+		}
+
+		netmask = inet_aton(argv[1], &a);
+		if (netmask == 0) {
+			IPCALC_MSG(bb_error_msg_and_die("bad netmask: %s", argv[1]),
+					exit(EXIT_FAILURE));
+		}
+		netmask = a.s_addr;
+	} else {
+
+		/* JHC - If the netmask wasn't provided then calculate it */
+		if (!ENABLE_FEATURE_IPCALC_FANCY || !have_netmask)
+			netmask = get_netmask(ipaddr);
+	}
+
+	if (mode & NETMASK) {
+		printf("NETMASK=%s\n", inet_ntoa((*(struct in_addr *) &netmask)));
+	}
+
+	if (mode & BROADCAST) {
+		broadcast = (ipaddr & netmask) | ~netmask;
+		printf("BROADCAST=%s\n", inet_ntoa((*(struct in_addr *) &broadcast)));
+	}
+
+	if (mode & NETWORK) {
+		network = ipaddr & netmask;
+		printf("NETWORK=%s\n", inet_ntoa((*(struct in_addr *) &network)));
+	}
+
+	if (ENABLE_FEATURE_IPCALC_FANCY) {
+		if (mode & NETPREFIX) {
+			printf("PREFIX=%i\n", get_prefix(netmask));
+		}
+
+		if (mode & HOSTNAME) {
+			struct hostent *hostinfo;
+			int x;
+
+			hostinfo = gethostbyaddr((char *) &ipaddr, sizeof(ipaddr), AF_INET);
+			if (!hostinfo) {
+				IPCALC_MSG(bb_herror_msg_and_die(
+							"cannot find hostname for %s", argv[0]),);
+				exit(EXIT_FAILURE);
+			}
+			for (x = 0; hostinfo->h_name[x]; x++) {
+				hostinfo->h_name[x] = tolower(hostinfo->h_name[x]);
+			}
+
+			printf("HOSTNAME=%s\n", hostinfo->h_name);
+		}
+	}
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/iplink.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/iplink.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/iplink.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,24 @@
+/*
+ * ip.c		"ip" utility frontend.
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ *
+ *
+ * Changes:
+ *
+ * Rani Assaf <rani at magic.metawire.com> 980929:	resolve addresses
+ */
+
+#include "libiproute/utils.h"
+#include "libiproute/ip_common.h"
+
+#include "busybox.h"
+
+int iplink_main(int argc, char **argv)
+{
+	ip_parse_common_args(&argc, &argv);
+
+	return do_iplink(argc-1, argv+1);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/iproute.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/iproute.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/iproute.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,24 @@
+/*
+ * ip.c		"ip" utility frontend.
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ *
+ *
+ * Changes:
+ *
+ * Rani Assaf <rani at magic.metawire.com> 980929:	resolve addresses
+ */
+
+#include "libiproute/utils.h"
+#include "libiproute/ip_common.h"
+
+#include "busybox.h"
+
+int iproute_main(int argc, char **argv)
+{
+	ip_parse_common_args(&argc, &argv);
+
+	return do_iproute(argc-1, argv+1);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/iptunnel.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/iptunnel.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/iptunnel.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,24 @@
+/*
+ * ip.c		"ip" utility frontend.
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ *
+ *
+ * Changes:
+ *
+ * Rani Assaf <rani at magic.metawire.com> 980929:	resolve addresses
+ */
+
+#include "libiproute/utils.h"
+#include "libiproute/ip_common.h"
+
+#include "busybox.h"
+
+int iptunnel_main(int argc, char **argv)
+{
+	ip_parse_common_args(&argc, &argv);
+
+	return do_iptunnel(argc-1, argv+1);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,36 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+ifndef top_srcdir
+top_srcdir=../..
+endif
+ifndef top_builddir
+top_builddir=../..
+endif
+srcdir=$(top_srcdir)/networking/libiproute
+LIBIPROUTE_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,83 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+#
+
+LIBIPROUTE_AR:=libiproute.a
+ifndef $(LIBIPROUTE_DIR)
+LIBIPROUTE_DIR:=$(top_builddir)/networking/libiproute
+endif
+srcdir=$(top_srcdir)/networking/libiproute
+
+LIBIPROUTE-y:=
+LIBIPROUTE-$(CONFIG_IP) += \
+	ip_parse_common_args.o \
+	ipaddress.o \
+	iplink.o \
+	iproute.o \
+	iptunnel.o \
+	libnetlink.o \
+	ll_addr.o \
+	ll_map.o \
+	ll_proto.o \
+	ll_types.o \
+	rt_names.o \
+	rtm_map.o \
+	utils.o
+
+LIBIPROUTE-$(CONFIG_IPADDR) += \
+	ip_parse_common_args.o \
+	ipaddress.o \
+	libnetlink.o \
+	ll_addr.o \
+	ll_map.o \
+	ll_types.o \
+	rt_names.o \
+	utils.o
+
+LIBIPROUTE-$(CONFIG_IPLINK) += \
+	ip_parse_common_args.o \
+	ipaddress.o \
+	iplink.o \
+	libnetlink.o \
+	ll_addr.o \
+	ll_map.o \
+	ll_types.o \
+	rt_names.o \
+	utils.o
+
+LIBIPROUTE-$(CONFIG_IPROUTE) += \
+	ip_parse_common_args.o \
+	iproute.o \
+	libnetlink.o \
+	ll_map.o \
+	rt_names.o \
+	rtm_map.o \
+	utils.o
+
+LIBIPROUTE-$(CONFIG_IPTUNNEL) += \
+	ip_parse_common_args.o \
+	iptunnel.o \
+	rt_names.o \
+	utils.o
+
+LIBIPROUTE-y:=$(sort $(LIBIPROUTE-y))
+
+LIBIPROUTE_SRC-y:=$(patsubst %,$(srcdir)/%,$(subst .o,.c,$(LIBIPROUTE-y)))
+LIBIPROUTE_SRC-a:=$(wildcard $(srcdir)/*.c)
+LIBRARY_SRC-y+=$(LIBIPROUTE_SRC-y)
+LIBRARY_SRC-a+=$(LIBIPROUTE_SRC-a)
+
+LIBIPROUTE-obj:=$(LIBIPROUTE_DIR)/$(LIBIPROUTE_AR)
+
+ifneq ($(strip $(LIBIPROUTE-y)),)
+libraries-y+=$(LIBIPROUTE_DIR)/$(LIBIPROUTE_AR)
+endif
+
+$(LIBIPROUTE_DIR)/$(LIBIPROUTE_AR): $(patsubst %,$(LIBIPROUTE_DIR)/%,$(LIBIPROUTE-y))
+	$(do_ar)
+
+$(LIBIPROUTE_DIR)/%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ip_common.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ip_common.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ip_common.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,28 @@
+#ifndef _IP_COMMON_H
+#define _IP_COMMON_H 1
+
+#include "busybox.h"
+#include <asm/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+
+extern int preferred_family;
+extern char * _SL_;
+
+extern void ip_parse_common_args(int *argcp, char ***argvp);
+extern int print_neigh(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
+extern int ipaddr_list_or_flush(int argc, char **argv, int flush);
+extern int iproute_monitor(int argc, char **argv);
+extern void iplink_usage(void) ATTRIBUTE_NORETURN;
+extern void ipneigh_reset_filter(void);
+extern int do_ipaddr(int argc, char **argv);
+extern int do_iproute(int argc, char **argv);
+extern int do_iprule(int argc, char **argv);
+extern int do_ipneigh(int argc, char **argv);
+extern int do_iptunnel(int argc, char **argv);
+extern int do_iplink(int argc, char **argv);
+extern int do_ipmonitor(int argc, char **argv);
+extern int do_multiaddr(int argc, char **argv);
+extern int do_multiroute(int argc, char **argv);
+#endif /* ip_common.h */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ip_parse_common_args.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ip_parse_common_args.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ip_parse_common_args.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,76 @@
+/*
+ * ip.c		"ip" utility frontend.
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ *
+ *
+ * Changes:
+ *
+ * Rani Assaf <rani at magic.metawire.com> 980929:	resolve addresses
+ */
+
+#include <string.h>
+
+#include "libbb.h"
+#include "utils.h"
+#include "ip_common.h"
+
+
+int preferred_family = AF_UNSPEC;
+int oneline = 0;
+char * _SL_ = NULL;
+
+void ip_parse_common_args(int *argcp, char ***argvp)
+{
+	int argc = *argcp;
+	char **argv = *argvp;
+
+	while (argc > 1) {
+		char *opt = argv[1];
+
+		if (strcmp(opt,"--") == 0) {
+			argc--; argv++;
+			break;
+		}
+
+		if (opt[0] != '-')
+			break;
+
+		if (opt[1] == '-')
+			opt++;
+
+		if (matches(opt, "-family") == 0) {
+			argc--;
+			argv++;
+			if (! argv[1])
+			    bb_show_usage();
+			if (strcmp(argv[1], "inet") == 0)
+				preferred_family = AF_INET;
+			else if (strcmp(argv[1], "inet6") == 0)
+				preferred_family = AF_INET6;
+			else if (strcmp(argv[1], "link") == 0)
+				preferred_family = AF_PACKET;
+			else
+				invarg(argv[1], "protocol family");
+		} else if (strcmp(opt, "-4") == 0) {
+			preferred_family = AF_INET;
+		} else if (strcmp(opt, "-6") == 0) {
+			preferred_family = AF_INET6;
+		} else if (strcmp(opt, "-0") == 0) {
+			preferred_family = AF_PACKET;
+		} else if (matches(opt, "-oneline") == 0) {
+			++oneline;
+		} else {
+			bb_show_usage();
+		}
+		argc--;	argv++;
+	}
+	_SL_ = oneline ? "\\" : "\n" ;
+	*argcp = argc;
+	*argvp = argv;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ipaddress.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ipaddress.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ipaddress.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,823 @@
+/*
+ * ipaddress.c		"ip address".
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ *
+ * Changes:
+ *	Laszlo Valko <valko at linux.karinthy.hu> 990223: address label must be zero terminated
+ */
+
+#include "libbb.h"
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <fnmatch.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+
+#include "rt_names.h"
+#include "utils.h"
+#include "ip_common.h"
+
+
+static struct
+{
+	int ifindex;
+	int family;
+	int oneline;
+	int showqueue;
+	inet_prefix pfx;
+	int scope, scopemask;
+	int flags, flagmask;
+	int up;
+	char *label;
+	int flushed;
+	char *flushb;
+	int flushp;
+	int flushe;
+	struct rtnl_handle *rth;
+} filter;
+
+static void print_link_flags(FILE *fp, unsigned flags, unsigned mdown)
+{
+	fprintf(fp, "<");
+	flags &= ~IFF_RUNNING;
+#define _PF(f) if (flags&IFF_##f) { \
+		  flags &= ~IFF_##f ; \
+		  fprintf(fp, #f "%s", flags ? "," : ""); }
+	_PF(LOOPBACK);
+	_PF(BROADCAST);
+	_PF(POINTOPOINT);
+	_PF(MULTICAST);
+	_PF(NOARP);
+#if 0
+	_PF(ALLMULTI);
+	_PF(PROMISC);
+	_PF(MASTER);
+	_PF(SLAVE);
+	_PF(DEBUG);
+	_PF(DYNAMIC);
+	_PF(AUTOMEDIA);
+	_PF(PORTSEL);
+	_PF(NOTRAILERS);
+#endif
+	_PF(UP);
+#undef _PF
+	if (flags)
+		fprintf(fp, "%x", flags);
+	if (mdown)
+		fprintf(fp, ",M-DOWN");
+	fprintf(fp, "> ");
+}
+
+static void print_queuelen(char *name)
+{
+	struct ifreq ifr;
+	int s;
+
+	s = socket(AF_INET, SOCK_STREAM, 0);
+	if (s < 0)
+		return;
+
+	memset(&ifr, 0, sizeof(ifr));
+	strcpy(ifr.ifr_name, name);
+	if (ioctl(s, SIOCGIFTXQLEN, &ifr) < 0) {
+		perror("SIOCGIFXQLEN");
+		close(s);
+		return;
+	}
+	close(s);
+
+	if (ifr.ifr_qlen)
+		printf("qlen %d", ifr.ifr_qlen);
+}
+
+static int print_linkinfo(struct sockaddr_nl ATTRIBUTE_UNUSED *who,
+		struct nlmsghdr *n, void ATTRIBUTE_UNUSED *arg)
+{
+	FILE *fp = (FILE*)arg;
+	struct ifinfomsg *ifi = NLMSG_DATA(n);
+	struct rtattr * tb[IFLA_MAX+1];
+	int len = n->nlmsg_len;
+	unsigned m_flag = 0;
+
+	if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK)
+		return 0;
+
+	len -= NLMSG_LENGTH(sizeof(*ifi));
+	if (len < 0)
+		return -1;
+
+	if (filter.ifindex && ifi->ifi_index != filter.ifindex)
+		return 0;
+	if (filter.up && !(ifi->ifi_flags&IFF_UP))
+		return 0;
+
+	memset(tb, 0, sizeof(tb));
+	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
+	if (tb[IFLA_IFNAME] == NULL) {
+		bb_error_msg("nil ifname");
+		return -1;
+	}
+	if (filter.label &&
+	    (!filter.family || filter.family == AF_PACKET) &&
+	    fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0))
+		return 0;
+
+	if (n->nlmsg_type == RTM_DELLINK)
+		fprintf(fp, "Deleted ");
+
+	fprintf(fp, "%d: %s", ifi->ifi_index,
+		tb[IFLA_IFNAME] ? (char*)RTA_DATA(tb[IFLA_IFNAME]) : "<nil>");
+
+	if (tb[IFLA_LINK]) {
+		SPRINT_BUF(b1);
+		int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]);
+		if (iflink == 0)
+			fprintf(fp, "@NONE: ");
+		else {
+			fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1));
+			m_flag = ll_index_to_flags(iflink);
+			m_flag = !(m_flag & IFF_UP);
+		}
+	} else {
+		fprintf(fp, ": ");
+	}
+	print_link_flags(fp, ifi->ifi_flags, m_flag);
+
+	if (tb[IFLA_MTU])
+		fprintf(fp, "mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU]));
+	if (tb[IFLA_QDISC])
+		fprintf(fp, "qdisc %s ", (char*)RTA_DATA(tb[IFLA_QDISC]));
+#ifdef IFLA_MASTER
+	if (tb[IFLA_MASTER]) {
+		SPRINT_BUF(b1);
+		fprintf(fp, "master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1));
+	}
+#endif
+	if (filter.showqueue)
+		print_queuelen((char*)RTA_DATA(tb[IFLA_IFNAME]));
+
+	if (!filter.family || filter.family == AF_PACKET) {
+		SPRINT_BUF(b1);
+		fprintf(fp, "%s", _SL_);
+		fprintf(fp, "    link/%s ", ll_type_n2a(ifi->ifi_type, b1, sizeof(b1)));
+
+		if (tb[IFLA_ADDRESS]) {
+			fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]),
+						      RTA_PAYLOAD(tb[IFLA_ADDRESS]),
+						      ifi->ifi_type,
+						      b1, sizeof(b1)));
+		}
+		if (tb[IFLA_BROADCAST]) {
+			if (ifi->ifi_flags&IFF_POINTOPOINT)
+				fprintf(fp, " peer ");
+			else
+				fprintf(fp, " brd ");
+			fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]),
+						      RTA_PAYLOAD(tb[IFLA_BROADCAST]),
+						      ifi->ifi_type,
+						      b1, sizeof(b1)));
+		}
+	}
+	fprintf(fp, "\n");
+	fflush(fp);
+	return 0;
+}
+
+static int flush_update(void)
+{
+	if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0) {
+		perror("Failed to send flush request\n");
+		return -1;
+	}
+	filter.flushp = 0;
+	return 0;
+}
+
+static int print_addrinfo(struct sockaddr_nl ATTRIBUTE_UNUSED *who,
+		struct nlmsghdr *n, void ATTRIBUTE_UNUSED *arg)
+{
+	FILE *fp = (FILE*)arg;
+	struct ifaddrmsg *ifa = NLMSG_DATA(n);
+	int len = n->nlmsg_len;
+	struct rtattr * rta_tb[IFA_MAX+1];
+	char abuf[256];
+	SPRINT_BUF(b1);
+
+	if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR)
+		return 0;
+	len -= NLMSG_LENGTH(sizeof(*ifa));
+	if (len < 0) {
+		bb_error_msg("wrong nlmsg len %d", len);
+		return -1;
+	}
+
+	if (filter.flushb && n->nlmsg_type != RTM_NEWADDR)
+		return 0;
+
+	memset(rta_tb, 0, sizeof(rta_tb));
+	parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
+
+	if (!rta_tb[IFA_LOCAL])
+		rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
+	if (!rta_tb[IFA_ADDRESS])
+		rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL];
+
+	if (filter.ifindex && filter.ifindex != ifa->ifa_index)
+		return 0;
+	if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
+		return 0;
+	if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
+		return 0;
+	if (filter.label) {
+		const char *label;
+		if (rta_tb[IFA_LABEL])
+			label = RTA_DATA(rta_tb[IFA_LABEL]);
+		else
+			label = ll_idx_n2a(ifa->ifa_index, b1);
+		if (fnmatch(filter.label, label, 0) != 0)
+			return 0;
+	}
+	if (filter.pfx.family) {
+		if (rta_tb[IFA_LOCAL]) {
+			inet_prefix dst;
+			memset(&dst, 0, sizeof(dst));
+			dst.family = ifa->ifa_family;
+			memcpy(&dst.data, RTA_DATA(rta_tb[IFA_LOCAL]), RTA_PAYLOAD(rta_tb[IFA_LOCAL]));
+			if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
+				return 0;
+		}
+	}
+
+	if (filter.flushb) {
+		struct nlmsghdr *fn;
+		if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) {
+			if (flush_update())
+				return -1;
+		}
+		fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp));
+		memcpy(fn, n, n->nlmsg_len);
+		fn->nlmsg_type = RTM_DELADDR;
+		fn->nlmsg_flags = NLM_F_REQUEST;
+		fn->nlmsg_seq = ++filter.rth->seq;
+		filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb;
+		filter.flushed++;
+		return 0;
+	}
+
+	if (n->nlmsg_type == RTM_DELADDR)
+		fprintf(fp, "Deleted ");
+
+	if (filter.oneline)
+		fprintf(fp, "%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index));
+	if (ifa->ifa_family == AF_INET)
+		fprintf(fp, "    inet ");
+	else if (ifa->ifa_family == AF_INET6)
+		fprintf(fp, "    inet6 ");
+	else
+		fprintf(fp, "    family %d ", ifa->ifa_family);
+
+	if (rta_tb[IFA_LOCAL]) {
+		fprintf(fp, "%s", rt_addr_n2a(ifa->ifa_family,
+					      RTA_PAYLOAD(rta_tb[IFA_LOCAL]),
+					      RTA_DATA(rta_tb[IFA_LOCAL]),
+					      abuf, sizeof(abuf)));
+
+		if (rta_tb[IFA_ADDRESS] == NULL ||
+		    memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0) {
+			fprintf(fp, "/%d ", ifa->ifa_prefixlen);
+		} else {
+			fprintf(fp, " peer %s/%d ",
+				rt_addr_n2a(ifa->ifa_family,
+					    RTA_PAYLOAD(rta_tb[IFA_ADDRESS]),
+					    RTA_DATA(rta_tb[IFA_ADDRESS]),
+					    abuf, sizeof(abuf)),
+				ifa->ifa_prefixlen);
+		}
+	}
+
+	if (rta_tb[IFA_BROADCAST]) {
+		fprintf(fp, "brd %s ",
+			rt_addr_n2a(ifa->ifa_family,
+				    RTA_PAYLOAD(rta_tb[IFA_BROADCAST]),
+				    RTA_DATA(rta_tb[IFA_BROADCAST]),
+				    abuf, sizeof(abuf)));
+	}
+	if (rta_tb[IFA_ANYCAST]) {
+		fprintf(fp, "any %s ",
+			rt_addr_n2a(ifa->ifa_family,
+				    RTA_PAYLOAD(rta_tb[IFA_ANYCAST]),
+				    RTA_DATA(rta_tb[IFA_ANYCAST]),
+				    abuf, sizeof(abuf)));
+	}
+	fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1)));
+	if (ifa->ifa_flags&IFA_F_SECONDARY) {
+		ifa->ifa_flags &= ~IFA_F_SECONDARY;
+		fprintf(fp, "secondary ");
+	}
+	if (ifa->ifa_flags&IFA_F_TENTATIVE) {
+		ifa->ifa_flags &= ~IFA_F_TENTATIVE;
+		fprintf(fp, "tentative ");
+	}
+	if (ifa->ifa_flags&IFA_F_DEPRECATED) {
+		ifa->ifa_flags &= ~IFA_F_DEPRECATED;
+		fprintf(fp, "deprecated ");
+	}
+	if (!(ifa->ifa_flags&IFA_F_PERMANENT)) {
+		fprintf(fp, "dynamic ");
+	} else
+		ifa->ifa_flags &= ~IFA_F_PERMANENT;
+	if (ifa->ifa_flags)
+		fprintf(fp, "flags %02x ", ifa->ifa_flags);
+	if (rta_tb[IFA_LABEL])
+		fprintf(fp, "%s", (char*)RTA_DATA(rta_tb[IFA_LABEL]));
+	if (rta_tb[IFA_CACHEINFO]) {
+		struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]);
+		char buf[128];
+		fprintf(fp, "%s", _SL_);
+		if (ci->ifa_valid == 0xFFFFFFFFU)
+			sprintf(buf, "valid_lft forever");
+		else
+			sprintf(buf, "valid_lft %dsec", ci->ifa_valid);
+		if (ci->ifa_prefered == 0xFFFFFFFFU)
+			sprintf(buf+strlen(buf), " preferred_lft forever");
+		else
+			sprintf(buf+strlen(buf), " preferred_lft %dsec", ci->ifa_prefered);
+		fprintf(fp, "       %s", buf);
+	}
+	fprintf(fp, "\n");
+	fflush(fp);
+	return 0;
+}
+
+
+struct nlmsg_list
+{
+	struct nlmsg_list *next;
+	struct nlmsghdr	  h;
+};
+
+static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE *fp)
+{
+	for ( ;ainfo ;  ainfo = ainfo->next) {
+		struct nlmsghdr *n = &ainfo->h;
+		struct ifaddrmsg *ifa = NLMSG_DATA(n);
+
+		if (n->nlmsg_type != RTM_NEWADDR)
+			continue;
+
+		if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifa)))
+			return -1;
+
+		if (ifa->ifa_index != ifindex ||
+		    (filter.family && filter.family != ifa->ifa_family))
+			continue;
+
+		print_addrinfo(NULL, n, fp);
+	}
+	return 0;
+}
+
+
+static int store_nlmsg(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+{
+	struct nlmsg_list **linfo = (struct nlmsg_list**)arg;
+	struct nlmsg_list *h;
+	struct nlmsg_list **lp;
+
+	h = malloc(n->nlmsg_len+sizeof(void*));
+	if (h == NULL)
+		return -1;
+
+	memcpy(&h->h, n, n->nlmsg_len);
+	h->next = NULL;
+
+	for (lp = linfo; *lp; lp = &(*lp)->next) /* NOTHING */;
+	*lp = h;
+
+	ll_remember_index(who, n, NULL);
+	return 0;
+}
+
+static void ipaddr_reset_filter(int _oneline)
+{
+	memset(&filter, 0, sizeof(filter));
+	filter.oneline = _oneline;
+}
+
+int ipaddr_list_or_flush(int argc, char **argv, int flush)
+{
+	static const char *const option[] = { "to", "scope", "up", "label", "dev", 0 };
+
+	struct nlmsg_list *linfo = NULL;
+	struct nlmsg_list *ainfo = NULL;
+	struct nlmsg_list *l;
+	struct rtnl_handle rth;
+	char *filter_dev = NULL;
+	int no_link = 0;
+
+	ipaddr_reset_filter(oneline);
+	filter.showqueue = 1;
+
+	if (filter.family == AF_UNSPEC)
+		filter.family = preferred_family;
+
+	if (flush) {
+		if (argc <= 0) {
+			bb_error_msg(bb_msg_requires_arg, "flush");
+			return -1;
+		}
+		if (filter.family == AF_PACKET) {
+			bb_error_msg("Cannot flush link addresses.");
+			return -1;
+		}
+	}
+
+	while (argc > 0) {
+		const int option_num = compare_string_array(option, *argv);
+		switch (option_num) {
+			case 0: /* to */
+				NEXT_ARG();
+				get_prefix(&filter.pfx, *argv, filter.family);
+				if (filter.family == AF_UNSPEC) {
+					filter.family = filter.pfx.family;
+				}
+				break;
+			case 1: /* scope */
+			{
+				uint32_t scope = 0;
+				NEXT_ARG();
+				filter.scopemask = -1;
+				if (rtnl_rtscope_a2n(&scope, *argv)) {
+					if (strcmp(*argv, "all") != 0) {
+						invarg(*argv, "scope");
+					}
+					scope = RT_SCOPE_NOWHERE;
+					filter.scopemask = 0;
+				}
+				filter.scope = scope;
+				break;
+			}
+			case 2: /* up */
+				filter.up = 1;
+				break;
+			case 3: /* label */
+				NEXT_ARG();
+				filter.label = *argv;
+				break;
+			case 4: /* dev */
+				NEXT_ARG();
+			default:
+				if (filter_dev) {
+					duparg2("dev", *argv);
+				}
+				filter_dev = *argv;
+		}
+		argv++;
+		argc--;
+	}
+
+	if (rtnl_open(&rth, 0) < 0)
+		exit(1);
+
+	if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) {
+		bb_perror_msg_and_die("Cannot send dump request");
+	}
+
+	if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) {
+		bb_error_msg_and_die("Dump terminated");
+	}
+
+	if (filter_dev) {
+		filter.ifindex = ll_name_to_index(filter_dev);
+		if (filter.ifindex <= 0) {
+			bb_error_msg("Device \"%s\" does not exist", filter_dev);
+			return -1;
+		}
+	}
+
+	if (flush) {
+		char flushb[4096-512];
+
+		filter.flushb = flushb;
+		filter.flushp = 0;
+		filter.flushe = sizeof(flushb);
+		filter.rth = &rth;
+
+		for (;;) {
+			if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
+				perror("Cannot send dump request");
+				exit(1);
+			}
+			filter.flushed = 0;
+			if (rtnl_dump_filter(&rth, print_addrinfo, stdout, NULL, NULL) < 0) {
+				fprintf(stderr, "Flush terminated\n");
+				exit(1);
+			}
+			if (filter.flushed == 0) {
+				fflush(stdout);
+				return 0;
+			}
+			if (flush_update() < 0)
+				exit(1);
+		}
+	}
+
+	if (filter.family != AF_PACKET) {
+		if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
+			bb_perror_msg_and_die("Cannot send dump request");
+		}
+
+		if (rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL) < 0) {
+			bb_error_msg_and_die("Dump terminated");
+		}
+	}
+
+
+	if (filter.family && filter.family != AF_PACKET) {
+		struct nlmsg_list **lp;
+		lp=&linfo;
+
+		if (filter.oneline)
+			no_link = 1;
+
+		while ((l=*lp)!=NULL) {
+			int ok = 0;
+			struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
+			struct nlmsg_list *a;
+
+			for (a=ainfo; a; a=a->next) {
+				struct nlmsghdr *n = &a->h;
+				struct ifaddrmsg *ifa = NLMSG_DATA(n);
+
+				if (ifa->ifa_index != ifi->ifi_index ||
+				    (filter.family && filter.family != ifa->ifa_family))
+					continue;
+				if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
+					continue;
+				if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
+					continue;
+				if (filter.pfx.family || filter.label) {
+					struct rtattr *tb[IFA_MAX+1];
+					memset(tb, 0, sizeof(tb));
+					parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n));
+					if (!tb[IFA_LOCAL])
+						tb[IFA_LOCAL] = tb[IFA_ADDRESS];
+
+					if (filter.pfx.family && tb[IFA_LOCAL]) {
+						inet_prefix dst;
+						memset(&dst, 0, sizeof(dst));
+						dst.family = ifa->ifa_family;
+						memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL]));
+						if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
+							continue;
+					}
+					if (filter.label) {
+						SPRINT_BUF(b1);
+						const char *label;
+						if (tb[IFA_LABEL])
+							label = RTA_DATA(tb[IFA_LABEL]);
+						else
+							label = ll_idx_n2a(ifa->ifa_index, b1);
+						if (fnmatch(filter.label, label, 0) != 0)
+							continue;
+					}
+				}
+
+				ok = 1;
+				break;
+			}
+			if (!ok)
+				*lp = l->next;
+			else
+				lp = &l->next;
+		}
+	}
+
+	for (l=linfo; l; l = l->next) {
+		if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) {
+			struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
+			if (filter.family != AF_PACKET)
+				print_selected_addrinfo(ifi->ifi_index, ainfo, stdout);
+		}
+		fflush(stdout);
+	}
+
+	exit(0);
+}
+
+static int default_scope(inet_prefix *lcl)
+{
+	if (lcl->family == AF_INET) {
+		if (lcl->bytelen >= 1 && *(__u8*)&lcl->data == 127)
+			return RT_SCOPE_HOST;
+	}
+	return 0;
+}
+
+static int ipaddr_modify(int cmd, int argc, char **argv)
+{
+	static const char *const option[] = {
+		"peer", "remote", "broadcast", "brd",
+		"anycast", "scope", "dev", "label", "local", 0
+	};
+
+	struct rtnl_handle rth;
+	struct {
+		struct nlmsghdr		n;
+		struct ifaddrmsg	ifa;
+		char			buf[256];
+	} req;
+	char  *d = NULL;
+	char  *l = NULL;
+	inet_prefix lcl;
+	inet_prefix peer;
+	int local_len = 0;
+	int peer_len = 0;
+	int brd_len = 0;
+	int any_len = 0;
+	int scoped = 0;
+
+	memset(&req, 0, sizeof(req));
+
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = cmd;
+	req.ifa.ifa_family = preferred_family;
+
+	while (argc > 0) {
+		const int option_num = compare_string_array(option, *argv);
+		switch (option_num) {
+			case 0: /* peer */
+			case 1: /* remote */
+				NEXT_ARG();
+
+				if (peer_len) {
+					duparg("peer", *argv);
+				}
+				get_prefix(&peer, *argv, req.ifa.ifa_family);
+				peer_len = peer.bytelen;
+				if (req.ifa.ifa_family == AF_UNSPEC) {
+					req.ifa.ifa_family = peer.family;
+				}
+				addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &peer.data, peer.bytelen);
+				req.ifa.ifa_prefixlen = peer.bitlen;
+				break;
+			case 2: /* broadcast */
+			case 3: /* brd */
+			{
+				inet_prefix addr;
+				NEXT_ARG();
+				if (brd_len) {
+					duparg("broadcast", *argv);
+				}
+				if (strcmp(*argv, "+") == 0) {
+					brd_len = -1;
+				}
+				else if (strcmp(*argv, "-") == 0) {
+					brd_len = -2;
+				} else {
+					get_addr(&addr, *argv, req.ifa.ifa_family);
+					if (req.ifa.ifa_family == AF_UNSPEC)
+						req.ifa.ifa_family = addr.family;
+					addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &addr.data, addr.bytelen);
+					brd_len = addr.bytelen;
+				}
+				break;
+			}
+			case 4: /* anycast */
+			{
+				inet_prefix addr;
+				NEXT_ARG();
+				if (any_len) {
+					duparg("anycast", *argv);
+				}
+				get_addr(&addr, *argv, req.ifa.ifa_family);
+				if (req.ifa.ifa_family == AF_UNSPEC) {
+					req.ifa.ifa_family = addr.family;
+				}
+				addattr_l(&req.n, sizeof(req), IFA_ANYCAST, &addr.data, addr.bytelen);
+				any_len = addr.bytelen;
+				break;
+			}
+			case 5: /* scope */
+			{
+				uint32_t scope = 0;
+				NEXT_ARG();
+				if (rtnl_rtscope_a2n(&scope, *argv)) {
+					invarg(*argv, "scope");
+				}
+				req.ifa.ifa_scope = scope;
+				scoped = 1;
+				break;
+			}
+			case 6: /* dev */
+				NEXT_ARG();
+				d = *argv;
+				break;
+			case 7: /* label */
+				NEXT_ARG();
+				l = *argv;
+				addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l)+1);
+				break;
+			case 8:	/* local */
+				NEXT_ARG();
+			default:
+				if (local_len) {
+					duparg2("local", *argv);
+				}
+				get_prefix(&lcl, *argv, req.ifa.ifa_family);
+				if (req.ifa.ifa_family == AF_UNSPEC) {
+					req.ifa.ifa_family = lcl.family;
+				}
+				addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen);
+				local_len = lcl.bytelen;
+		}
+		argc--;
+		argv++;
+	}
+
+	if (d == NULL) {
+		bb_error_msg(bb_msg_requires_arg,"\"dev\"");
+		return -1;
+	}
+	if (l && matches(d, l) != 0) {
+		bb_error_msg_and_die("\"dev\" (%s) must match \"label\" (%s)", d, l);
+	}
+
+	if (peer_len == 0 && local_len && cmd != RTM_DELADDR) {
+		peer = lcl;
+		addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &lcl.data, lcl.bytelen);
+	}
+	if (req.ifa.ifa_prefixlen == 0)
+		req.ifa.ifa_prefixlen = lcl.bitlen;
+
+	if (brd_len < 0 && cmd != RTM_DELADDR) {
+		inet_prefix brd;
+		int i;
+		if (req.ifa.ifa_family != AF_INET) {
+			bb_error_msg("Broadcast can be set only for IPv4 addresses");
+			return -1;
+		}
+		brd = peer;
+		if (brd.bitlen <= 30) {
+			for (i=31; i>=brd.bitlen; i--) {
+				if (brd_len == -1)
+					brd.data[0] |= htonl(1<<(31-i));
+				else
+					brd.data[0] &= ~htonl(1<<(31-i));
+			}
+			addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &brd.data, brd.bytelen);
+			brd_len = brd.bytelen;
+		}
+	}
+	if (!scoped && cmd != RTM_DELADDR)
+		req.ifa.ifa_scope = default_scope(&lcl);
+
+	if (rtnl_open(&rth, 0) < 0)
+		exit(1);
+
+	ll_init_map(&rth);
+
+	if ((req.ifa.ifa_index = ll_name_to_index(d)) == 0) {
+		bb_error_msg("Cannot find device \"%s\"", d);
+		return -1;
+	}
+
+	if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
+		exit(2);
+
+	exit(0);
+}
+
+int do_ipaddr(int argc, char **argv)
+{
+	static const char *const commands[] = {
+		"add", "delete", "list", "show", "lst", "flush", 0
+	};
+
+	int command_num = 2;
+
+	if (*argv) {
+		command_num = compare_string_array(commands, *argv);
+	}
+	switch (command_num) {
+		case 0: /* add */
+			return ipaddr_modify(RTM_NEWADDR, argc-1, argv+1);
+		case 1: /* delete */
+			return ipaddr_modify(RTM_DELADDR, argc-1, argv+1);
+		case 2: /* list */
+		case 3: /* show */
+		case 4: /* lst */
+			return ipaddr_list_or_flush(argc-1, argv+1, 0);
+		case 5: /* flush */
+			return ipaddr_list_or_flush(argc-1, argv+1, 1);
+	}
+	bb_error_msg_and_die("Unknown command %s", *argv);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/iplink.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/iplink.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/iplink.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,356 @@
+/*
+ * iplink.c		"ip link".
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <net/if.h>
+#include <net/if_packet.h>
+#include <netpacket/packet.h>
+
+#include <net/ethernet.h>
+
+#include "rt_names.h"
+#include "utils.h"
+#include "ip_common.h"
+
+/* take from linux/sockios.h */
+#define SIOCSIFNAME	0x8923		/* set interface name */
+
+static int do_link;
+
+static int on_off(char *msg)
+{
+	bb_error_msg("Error: argument of \"%s\" must be \"on\" or \"off\"", msg);
+	return -1;
+}
+
+static int get_ctl_fd(void)
+{
+	int s_errno;
+	int fd;
+
+	fd = socket(PF_INET, SOCK_DGRAM, 0);
+	if (fd >= 0)
+		return fd;
+	s_errno = errno;
+	fd = socket(PF_PACKET, SOCK_DGRAM, 0);
+	if (fd >= 0)
+		return fd;
+	fd = socket(PF_INET6, SOCK_DGRAM, 0);
+	if (fd >= 0)
+		return fd;
+	errno = s_errno;
+	perror("Cannot create control socket");
+	return -1;
+}
+
+static int do_chflags(char *dev, __u32 flags, __u32 mask)
+{
+	struct ifreq ifr;
+	int fd;
+	int err;
+
+	strcpy(ifr.ifr_name, dev);
+	fd = get_ctl_fd();
+	if (fd < 0)
+		return -1;
+	err = ioctl(fd, SIOCGIFFLAGS, &ifr);
+	if (err) {
+		perror("SIOCGIFFLAGS");
+		close(fd);
+		return -1;
+	}
+	if ((ifr.ifr_flags^flags)&mask) {
+		ifr.ifr_flags &= ~mask;
+		ifr.ifr_flags |= mask&flags;
+		err = ioctl(fd, SIOCSIFFLAGS, &ifr);
+		if (err)
+			perror("SIOCSIFFLAGS");
+	}
+	close(fd);
+	return err;
+}
+
+static int do_changename(char *dev, char *newdev)
+{
+	struct ifreq ifr;
+	int fd;
+	int err;
+
+	strcpy(ifr.ifr_name, dev);
+	strcpy(ifr.ifr_newname, newdev);
+	fd = get_ctl_fd();
+	if (fd < 0)
+		return -1;
+	err = ioctl(fd, SIOCSIFNAME, &ifr);
+	if (err) {
+		perror("SIOCSIFNAME");
+		close(fd);
+		return -1;
+	}
+	close(fd);
+	return err;
+}
+
+static int set_qlen(char *dev, int qlen)
+{
+	struct ifreq ifr;
+	int s;
+
+	s = get_ctl_fd();
+	if (s < 0)
+		return -1;
+
+	memset(&ifr, 0, sizeof(ifr));
+	strcpy(ifr.ifr_name, dev);
+	ifr.ifr_qlen = qlen;
+	if (ioctl(s, SIOCSIFTXQLEN, &ifr) < 0) {
+		perror("SIOCSIFXQLEN");
+		close(s);
+		return -1;
+	}
+	close(s);
+
+	return 0;
+}
+
+static int set_mtu(char *dev, int mtu)
+{
+	struct ifreq ifr;
+	int s;
+
+	s = get_ctl_fd();
+	if (s < 0)
+		return -1;
+
+	memset(&ifr, 0, sizeof(ifr));
+	strcpy(ifr.ifr_name, dev);
+	ifr.ifr_mtu = mtu;
+	if (ioctl(s, SIOCSIFMTU, &ifr) < 0) {
+		perror("SIOCSIFMTU");
+		close(s);
+		return -1;
+	}
+	close(s);
+
+	return 0;
+}
+
+static int get_address(char *dev, int *htype)
+{
+	struct ifreq ifr;
+	struct sockaddr_ll me;
+	socklen_t alen;
+	int s;
+
+	s = socket(PF_PACKET, SOCK_DGRAM, 0);
+	if (s < 0) {
+		perror("socket(PF_PACKET)");
+		return -1;
+	}
+
+	memset(&ifr, 0, sizeof(ifr));
+	strcpy(ifr.ifr_name, dev);
+	if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
+		perror("SIOCGIFINDEX");
+		close(s);
+		return -1;
+	}
+
+	memset(&me, 0, sizeof(me));
+	me.sll_family = AF_PACKET;
+	me.sll_ifindex = ifr.ifr_ifindex;
+	me.sll_protocol = htons(ETH_P_LOOP);
+	if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) {
+		perror("bind");
+		close(s);
+		return -1;
+	}
+
+	alen = sizeof(me);
+	if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) {
+		perror("getsockname");
+		close(s);
+		return -1;
+	}
+	close(s);
+	*htype = me.sll_hatype;
+	return me.sll_halen;
+}
+
+static int parse_address(char *dev, int hatype, int halen, char *lla, struct ifreq *ifr)
+{
+	int alen;
+
+	memset(ifr, 0, sizeof(*ifr));
+	strcpy(ifr->ifr_name, dev);
+	ifr->ifr_hwaddr.sa_family = hatype;
+	alen = ll_addr_a2n((unsigned char *)(ifr->ifr_hwaddr.sa_data), 14, lla);
+	if (alen < 0)
+		return -1;
+	if (alen != halen) {
+		bb_error_msg("Wrong address (%s) length: expected %d bytes", lla, halen);
+		return -1;
+	}
+	return 0;
+}
+
+static int set_address(struct ifreq *ifr, int brd)
+{
+	int s;
+
+	s = get_ctl_fd();
+	if (s < 0)
+		return -1;
+	if (ioctl(s, brd?SIOCSIFHWBROADCAST:SIOCSIFHWADDR, ifr) < 0) {
+		perror(brd?"SIOCSIFHWBROADCAST":"SIOCSIFHWADDR");
+		close(s);
+		return -1;
+	}
+	close(s);
+	return 0;
+}
+
+
+static int do_set(int argc, char **argv)
+{
+	char *dev = NULL;
+	__u32 mask = 0;
+	__u32 flags = 0;
+	int qlen = -1;
+	int mtu = -1;
+	char *newaddr = NULL;
+	char *newbrd = NULL;
+	struct ifreq ifr0, ifr1;
+	char *newname = NULL;
+	int htype, halen;
+
+	while (argc > 0) {
+		if (strcmp(*argv, "up") == 0) {
+			mask |= IFF_UP;
+			flags |= IFF_UP;
+		} else if (strcmp(*argv, "down") == 0) {
+			mask |= IFF_UP;
+			flags &= ~IFF_UP;
+		} else if (strcmp(*argv, "name") == 0) {
+			NEXT_ARG();
+			newname = *argv;
+		} else if (strcmp(*argv, "mtu") == 0) {
+			NEXT_ARG();
+			if (mtu != -1)
+				duparg("mtu", *argv);
+			if (get_integer(&mtu, *argv, 0))
+				invarg(*argv, "mtu");
+		} else if (strcmp(*argv, "multicast") == 0) {
+			NEXT_ARG();
+			mask |= IFF_MULTICAST;
+			if (strcmp(*argv, "on") == 0) {
+				flags |= IFF_MULTICAST;
+			} else if (strcmp(*argv, "off") == 0) {
+				flags &= ~IFF_MULTICAST;
+			} else
+				return on_off("multicast");
+		} else if (strcmp(*argv, "arp") == 0) {
+			NEXT_ARG();
+			mask |= IFF_NOARP;
+			if (strcmp(*argv, "on") == 0) {
+				flags &= ~IFF_NOARP;
+			} else if (strcmp(*argv, "off") == 0) {
+				flags |= IFF_NOARP;
+			} else
+				return on_off("noarp");
+		} else if (strcmp(*argv, "addr") == 0) {
+			NEXT_ARG();
+			newaddr = *argv;
+		} else {
+			if (strcmp(*argv, "dev") == 0) {
+				NEXT_ARG();
+			}
+			if (dev)
+				duparg2("dev", *argv);
+			dev = *argv;
+		}
+		argc--; argv++;
+	}
+
+	if (!dev) {
+		bb_error_msg(bb_msg_requires_arg, "\"dev\"");
+		exit(-1);
+	}
+
+	if (newaddr || newbrd) {
+		halen = get_address(dev, &htype);
+		if (halen < 0)
+			return -1;
+		if (newaddr) {
+			if (parse_address(dev, htype, halen, newaddr, &ifr0) < 0)
+				return -1;
+		}
+		if (newbrd) {
+			if (parse_address(dev, htype, halen, newbrd, &ifr1) < 0)
+				return -1;
+		}
+	}
+
+	if (newname && strcmp(dev, newname)) {
+		if (do_changename(dev, newname) < 0)
+			return -1;
+		dev = newname;
+	}
+	if (qlen != -1) {
+		if (set_qlen(dev, qlen) < 0)
+			return -1;
+	}
+	if (mtu != -1) {
+		if (set_mtu(dev, mtu) < 0)
+			return -1;
+	}
+	if (newaddr || newbrd) {
+		if (newbrd) {
+			if (set_address(&ifr1, 1) < 0)
+				return -1;
+		}
+		if (newaddr) {
+			if (set_address(&ifr0, 0) < 0)
+				return -1;
+		}
+	}
+	if (mask)
+		return do_chflags(dev, flags, mask);
+	return 0;
+}
+
+static int ipaddr_list_link(int argc, char **argv)
+{
+	preferred_family = AF_PACKET;
+	do_link = 1;
+	return ipaddr_list_or_flush(argc, argv, 0);
+}
+
+int do_iplink(int argc, char **argv)
+{
+	if (argc > 0) {
+		if (matches(*argv, "set") == 0)
+			return do_set(argc-1, argv+1);
+		if (matches(*argv, "show") == 0 ||
+		    matches(*argv, "lst") == 0 ||
+		    matches(*argv, "list") == 0)
+			return ipaddr_list_link(argc-1, argv+1);
+	} else
+		return ipaddr_list_link(0, NULL);
+
+	bb_error_msg("Command \"%s\" is unknown.", *argv);
+	exit(-1);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/iproute.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/iproute.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/iproute.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,856 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * iproute.c		"ip route".
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ *
+ *
+ * Changes:
+ *
+ * Rani Assaf <rani at magic.metawire.com> 980929:	resolve addresses
+ * Kunihiro Ishiguro <kunihiro at zebra.org> 001102: rtnh_ifindex was not initialized
+ */
+
+#include "libbb.h"
+
+#include <sys/socket.h>
+
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "rt_names.h"
+#include "utils.h"
+#include "ip_common.h"
+
+#ifndef RTAX_RTTVAR
+#define RTAX_RTTVAR RTAX_HOPS
+#endif
+
+
+static struct
+{
+	int tb;
+	int flushed;
+	char *flushb;
+	int flushp;
+	int flushe;
+	struct rtnl_handle *rth;
+	int protocol, protocolmask;
+	int scope, scopemask;
+	int type, typemask;
+	int tos, tosmask;
+	int iif, iifmask;
+	int oif, oifmask;
+	int realm, realmmask;
+	inet_prefix rprefsrc;
+	inet_prefix rvia;
+	inet_prefix rdst;
+	inet_prefix mdst;
+	inet_prefix rsrc;
+	inet_prefix msrc;
+} filter;
+
+static int flush_update(void)
+{
+	if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0) {
+		perror("Failed to send flush request\n");
+		return -1;
+	}
+	filter.flushp = 0;
+	return 0;
+}
+
+static int print_route(struct sockaddr_nl *who ATTRIBUTE_UNUSED,
+		struct nlmsghdr *n, void *arg)
+{
+	FILE *fp = (FILE*)arg;
+	struct rtmsg *r = NLMSG_DATA(n);
+	int len = n->nlmsg_len;
+	struct rtattr * tb[RTA_MAX+1];
+	char abuf[256];
+	inet_prefix dst;
+	inet_prefix src;
+	int host_len = -1;
+	SPRINT_BUF(b1);
+
+
+	if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) {
+		fprintf(stderr, "Not a route: %08x %08x %08x\n",
+			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
+		return 0;
+	}
+	if (filter.flushb && n->nlmsg_type != RTM_NEWROUTE)
+		return 0;
+	len -= NLMSG_LENGTH(sizeof(*r));
+	if (len < 0) {
+		bb_error_msg("wrong nlmsg len %d", len);
+		return -1;
+	}
+
+	if (r->rtm_family == AF_INET6)
+		host_len = 128;
+	else if (r->rtm_family == AF_INET)
+		host_len = 32;
+
+	if (r->rtm_family == AF_INET6) {
+		if (filter.tb) {
+			if (filter.tb < 0) {
+				if (!(r->rtm_flags&RTM_F_CLONED)) {
+					return 0;
+				}
+			} else {
+				if (r->rtm_flags&RTM_F_CLONED) {
+					return 0;
+				}
+				if (filter.tb == RT_TABLE_LOCAL) {
+					if (r->rtm_type != RTN_LOCAL) {
+						return 0;
+					}
+				} else if (filter.tb == RT_TABLE_MAIN) {
+					if (r->rtm_type == RTN_LOCAL) {
+						return 0;
+					}
+				} else {
+					return 0;
+				}
+			}
+		}
+	} else {
+		if (filter.tb > 0 && filter.tb != r->rtm_table) {
+			return 0;
+		}
+	}
+	if (filter.rdst.family &&
+	    (r->rtm_family != filter.rdst.family || filter.rdst.bitlen > r->rtm_dst_len)) {
+		return 0;
+	}
+	if (filter.mdst.family &&
+	    (r->rtm_family != filter.mdst.family ||
+	     (filter.mdst.bitlen >= 0 && filter.mdst.bitlen < r->rtm_dst_len))) {
+		return 0;
+	}
+	if (filter.rsrc.family &&
+	    (r->rtm_family != filter.rsrc.family || filter.rsrc.bitlen > r->rtm_src_len)) {
+		return 0;
+	}
+	if (filter.msrc.family &&
+	    (r->rtm_family != filter.msrc.family ||
+	     (filter.msrc.bitlen >= 0 && filter.msrc.bitlen < r->rtm_src_len))) {
+		return 0;
+	}
+
+	memset(tb, 0, sizeof(tb));
+	parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
+
+	if (filter.rdst.family && inet_addr_match(&dst, &filter.rdst, filter.rdst.bitlen))
+		return 0;
+	if (filter.mdst.family && filter.mdst.bitlen >= 0 &&
+	    inet_addr_match(&dst, &filter.mdst, r->rtm_dst_len))
+		return 0;
+
+	if (filter.rsrc.family && inet_addr_match(&src, &filter.rsrc, filter.rsrc.bitlen))
+		return 0;
+	if (filter.msrc.family && filter.msrc.bitlen >= 0 &&
+	    inet_addr_match(&src, &filter.msrc, r->rtm_src_len))
+		return 0;
+
+	if (filter.flushb &&
+	    r->rtm_family == AF_INET6 &&
+	    r->rtm_dst_len == 0 &&
+	    r->rtm_type == RTN_UNREACHABLE &&
+	    tb[RTA_PRIORITY] &&
+	    *(int*)RTA_DATA(tb[RTA_PRIORITY]) == -1)
+		return 0;
+
+	if (filter.flushb) {
+		struct nlmsghdr *fn;
+		if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) {
+			if (flush_update())
+				return -1;
+		}
+		fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp));
+		memcpy(fn, n, n->nlmsg_len);
+		fn->nlmsg_type = RTM_DELROUTE;
+		fn->nlmsg_flags = NLM_F_REQUEST;
+		fn->nlmsg_seq = ++filter.rth->seq;
+		filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb;
+		filter.flushed++;
+		return 0;
+	}
+
+	if (n->nlmsg_type == RTM_DELROUTE) {
+		fprintf(fp, "Deleted ");
+	}
+	if (r->rtm_type != RTN_UNICAST && !filter.type) {
+		fprintf(fp, "%s ", rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
+	}
+
+	if (tb[RTA_DST]) {
+		if (r->rtm_dst_len != host_len) {
+			fprintf(fp, "%s/%u ", rt_addr_n2a(r->rtm_family,
+							 RTA_PAYLOAD(tb[RTA_DST]),
+							 RTA_DATA(tb[RTA_DST]),
+							 abuf, sizeof(abuf)),
+				r->rtm_dst_len
+				);
+		} else {
+			fprintf(fp, "%s ", format_host(r->rtm_family,
+						       RTA_PAYLOAD(tb[RTA_DST]),
+						       RTA_DATA(tb[RTA_DST]),
+						       abuf, sizeof(abuf))
+				);
+		}
+	} else if (r->rtm_dst_len) {
+		fprintf(fp, "0/%d ", r->rtm_dst_len);
+	} else {
+		fprintf(fp, "default ");
+	}
+	if (tb[RTA_SRC]) {
+		if (r->rtm_src_len != host_len) {
+			fprintf(fp, "from %s/%u ", rt_addr_n2a(r->rtm_family,
+							 RTA_PAYLOAD(tb[RTA_SRC]),
+							 RTA_DATA(tb[RTA_SRC]),
+							 abuf, sizeof(abuf)),
+				r->rtm_src_len
+				);
+		} else {
+			fprintf(fp, "from %s ", format_host(r->rtm_family,
+						       RTA_PAYLOAD(tb[RTA_SRC]),
+						       RTA_DATA(tb[RTA_SRC]),
+						       abuf, sizeof(abuf))
+				);
+		}
+	} else if (r->rtm_src_len) {
+		fprintf(fp, "from 0/%u ", r->rtm_src_len);
+	}
+	if (tb[RTA_GATEWAY] && filter.rvia.bitlen != host_len) {
+		fprintf(fp, "via %s ",
+			format_host(r->rtm_family,
+				    RTA_PAYLOAD(tb[RTA_GATEWAY]),
+				    RTA_DATA(tb[RTA_GATEWAY]),
+				    abuf, sizeof(abuf)));
+	}
+	if (tb[RTA_OIF] && filter.oifmask != -1) {
+		fprintf(fp, "dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF])));
+	}
+
+	if (tb[RTA_PREFSRC] && filter.rprefsrc.bitlen != host_len) {
+		/* Do not use format_host(). It is our local addr
+		   and symbolic name will not be useful.
+		 */
+		fprintf(fp, " src %s ",
+			rt_addr_n2a(r->rtm_family,
+				    RTA_PAYLOAD(tb[RTA_PREFSRC]),
+				    RTA_DATA(tb[RTA_PREFSRC]),
+				    abuf, sizeof(abuf)));
+	}
+	if (tb[RTA_PRIORITY]) {
+		fprintf(fp, " metric %d ", *(__u32*)RTA_DATA(tb[RTA_PRIORITY]));
+	}
+	if (r->rtm_family == AF_INET6) {
+		struct rta_cacheinfo *ci = NULL;
+		if (tb[RTA_CACHEINFO]) {
+			ci = RTA_DATA(tb[RTA_CACHEINFO]);
+		}
+		if ((r->rtm_flags & RTM_F_CLONED) || (ci && ci->rta_expires)) {
+			static int hz;
+			if (!hz) {
+				hz = get_hz();
+			}
+			if (r->rtm_flags & RTM_F_CLONED) {
+				fprintf(fp, "%s    cache ", _SL_);
+			}
+			if (ci->rta_expires) {
+				fprintf(fp, " expires %dsec", ci->rta_expires/hz);
+			}
+			if (ci->rta_error != 0) {
+				fprintf(fp, " error %d", ci->rta_error);
+			}
+		} else if (ci) {
+			if (ci->rta_error != 0)
+				fprintf(fp, " error %d", ci->rta_error);
+		}
+	}
+	if (tb[RTA_IIF] && filter.iifmask != -1) {
+		fprintf(fp, " iif %s", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_IIF])));
+	}
+	fprintf(fp, "\n");
+	fflush(fp);
+	return 0;
+}
+
+static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
+{
+	struct rtnl_handle rth;
+	struct {
+		struct nlmsghdr		n;
+		struct rtmsg		r;
+		char			buf[1024];
+	} req;
+	char  mxbuf[256];
+	struct rtattr * mxrta = (void*)mxbuf;
+	unsigned mxlock = 0;
+	char  *d = NULL;
+	int gw_ok = 0;
+	int dst_ok = 0;
+	int proto_ok = 0;
+	int type_ok = 0;
+
+	memset(&req, 0, sizeof(req));
+
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+	req.n.nlmsg_flags = NLM_F_REQUEST|flags;
+	req.n.nlmsg_type = cmd;
+	req.r.rtm_family = preferred_family;
+	req.r.rtm_table = RT_TABLE_MAIN;
+	req.r.rtm_scope = RT_SCOPE_NOWHERE;
+
+	if (cmd != RTM_DELROUTE) {
+		req.r.rtm_protocol = RTPROT_BOOT;
+		req.r.rtm_scope = RT_SCOPE_UNIVERSE;
+		req.r.rtm_type = RTN_UNICAST;
+	}
+
+	mxrta->rta_type = RTA_METRICS;
+	mxrta->rta_len = RTA_LENGTH(0);
+
+	while (argc > 0) {
+		if (strcmp(*argv, "src") == 0) {
+			inet_prefix addr;
+			NEXT_ARG();
+			get_addr(&addr, *argv, req.r.rtm_family);
+			if (req.r.rtm_family == AF_UNSPEC) {
+				req.r.rtm_family = addr.family;
+			}
+			addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &addr.data, addr.bytelen);
+		} else if (strcmp(*argv, "via") == 0) {
+			inet_prefix addr;
+			gw_ok = 1;
+			NEXT_ARG();
+			get_addr(&addr, *argv, req.r.rtm_family);
+			if (req.r.rtm_family == AF_UNSPEC) {
+				req.r.rtm_family = addr.family;
+			}
+			addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &addr.data, addr.bytelen);
+		} else if (strcmp(*argv, "mtu") == 0) {
+			unsigned mtu;
+			NEXT_ARG();
+			if (strcmp(*argv, "lock") == 0) {
+				mxlock |= (1<<RTAX_MTU);
+				NEXT_ARG();
+			}
+			if (get_unsigned(&mtu, *argv, 0)) {
+				invarg(*argv, "mtu");
+			}
+			rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu);
+		} else if (matches(*argv, "protocol") == 0) {
+			uint32_t prot;
+			NEXT_ARG();
+			if (rtnl_rtprot_a2n(&prot, *argv))
+				invarg(*argv, "protocol");
+			req.r.rtm_protocol = prot;
+			proto_ok =1;
+		} else if (strcmp(*argv, "dev") == 0 ||
+			   strcmp(*argv, "oif") == 0) {
+			NEXT_ARG();
+			d = *argv;
+		} else {
+			int type;
+			inet_prefix dst;
+
+			if (strcmp(*argv, "to") == 0) {
+				NEXT_ARG();
+			}
+			if ((**argv < '0' || **argv > '9') &&
+			    rtnl_rtntype_a2n(&type, *argv) == 0) {
+				NEXT_ARG();
+				req.r.rtm_type = type;
+				type_ok = 1;
+			}
+
+			if (dst_ok) {
+				duparg2("to", *argv);
+			}
+			get_prefix(&dst, *argv, req.r.rtm_family);
+			if (req.r.rtm_family == AF_UNSPEC) {
+				req.r.rtm_family = dst.family;
+			}
+			req.r.rtm_dst_len = dst.bitlen;
+			dst_ok = 1;
+			if (dst.bytelen) {
+				addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen);
+			}
+		}
+		argc--; argv++;
+	}
+
+	if (rtnl_open(&rth, 0) < 0) {
+		exit(1);
+	}
+
+	if (d)  {
+		int idx;
+
+		ll_init_map(&rth);
+
+		if (d) {
+			if ((idx = ll_name_to_index(d)) == 0) {
+				bb_error_msg("Cannot find device \"%s\"", d);
+				return -1;
+			}
+			addattr32(&req.n, sizeof(req), RTA_OIF, idx);
+		}
+	}
+
+	if (mxrta->rta_len > RTA_LENGTH(0)) {
+		if (mxlock) {
+			rta_addattr32(mxrta, sizeof(mxbuf), RTAX_LOCK, mxlock);
+		}
+		addattr_l(&req.n, sizeof(req), RTA_METRICS, RTA_DATA(mxrta), RTA_PAYLOAD(mxrta));
+	}
+
+	if (req.r.rtm_family == AF_UNSPEC) {
+		req.r.rtm_family = AF_INET;
+	}
+
+	if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) {
+		exit(2);
+	}
+
+	return 0;
+}
+
+static int rtnl_rtcache_request(struct rtnl_handle *rth, int family)
+{
+	struct {
+		struct nlmsghdr nlh;
+		struct rtmsg rtm;
+	} req;
+	struct sockaddr_nl nladdr;
+
+	memset(&nladdr, 0, sizeof(nladdr));
+	memset(&req, 0, sizeof(req));
+	nladdr.nl_family = AF_NETLINK;
+
+	req.nlh.nlmsg_len = sizeof(req);
+	req.nlh.nlmsg_type = RTM_GETROUTE;
+	req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_REQUEST;
+	req.nlh.nlmsg_pid = 0;
+	req.nlh.nlmsg_seq = rth->dump = ++rth->seq;
+	req.rtm.rtm_family = family;
+	req.rtm.rtm_flags |= RTM_F_CLONED;
+
+	return sendto(rth->fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr));
+}
+
+static int iproute_flush_cache(void)
+{
+#define ROUTE_FLUSH_PATH "/proc/sys/net/ipv4/route/flush"
+
+	int len;
+	int flush_fd = open (ROUTE_FLUSH_PATH, O_WRONLY);
+	char *buffer = "-1";
+
+	if (flush_fd < 0) {
+		fprintf (stderr, "Cannot open \"%s\"\n", ROUTE_FLUSH_PATH);
+		return -1;
+	}
+
+	len = strlen (buffer);
+
+	if ((write (flush_fd, (void *)buffer, len)) < len) {
+		fprintf (stderr, "Cannot flush routing cache\n");
+		return -1;
+	}
+	close(flush_fd);
+	return 0;
+}
+
+static void iproute_reset_filter(void)
+{
+	memset(&filter, 0, sizeof(filter));
+	filter.mdst.bitlen = -1;
+	filter.msrc.bitlen = -1;
+}
+
+static int iproute_list_or_flush(int argc, char **argv, int flush)
+{
+	int do_ipv6 = preferred_family;
+	struct rtnl_handle rth;
+	char *id = NULL;
+	char *od = NULL;
+
+	iproute_reset_filter();
+	filter.tb = RT_TABLE_MAIN;
+
+	if (flush && argc <= 0) {
+		bb_error_msg(bb_msg_requires_arg, "\"ip route flush\"");
+		return -1;
+	}
+
+	while (argc > 0) {
+		if (matches(*argv, "protocol") == 0) {
+			uint32_t prot = 0;
+			NEXT_ARG();
+			filter.protocolmask = -1;
+			if (rtnl_rtprot_a2n(&prot, *argv)) {
+				if (strcmp(*argv, "all") != 0) {
+					invarg(*argv, "protocol");
+				}
+				prot = 0;
+				filter.protocolmask = 0;
+			}
+			filter.protocol = prot;
+		} else if (strcmp(*argv, "dev") == 0 ||
+			   strcmp(*argv, "oif") == 0) {
+			NEXT_ARG();
+			od = *argv;
+		} else if (strcmp(*argv, "iif") == 0) {
+			NEXT_ARG();
+			id = *argv;
+		} else if (matches(*argv, "from") == 0) {
+			NEXT_ARG();
+			if (matches(*argv, "root") == 0) {
+				NEXT_ARG();
+				get_prefix(&filter.rsrc, *argv, do_ipv6);
+			} else if (matches(*argv, "match") == 0) {
+				NEXT_ARG();
+				get_prefix(&filter.msrc, *argv, do_ipv6);
+			} else {
+				if (matches(*argv, "exact") == 0) {
+					NEXT_ARG();
+				}
+				get_prefix(&filter.msrc, *argv, do_ipv6);
+				filter.rsrc = filter.msrc;
+			}
+		} else {
+			if (matches(*argv, "to") == 0) {
+				NEXT_ARG();
+			}
+			if (matches(*argv, "root") == 0) {
+				NEXT_ARG();
+				get_prefix(&filter.rdst, *argv, do_ipv6);
+			} else if (matches(*argv, "match") == 0) {
+				NEXT_ARG();
+				get_prefix(&filter.mdst, *argv, do_ipv6);
+			} else if (matches(*argv, "table") == 0) {
+				NEXT_ARG();
+				if (matches(*argv, "cache") == 0) {
+					filter.tb = -1;
+				} else if (matches(*argv, "main") != 0) {
+					invarg(*argv, "table");
+				}
+			} else if (matches(*argv, "cache") == 0) {
+				filter.tb = -1;
+			} else {
+				if (matches(*argv, "exact") == 0) {
+					NEXT_ARG();
+				}
+				get_prefix(&filter.mdst, *argv, do_ipv6);
+				filter.rdst = filter.mdst;
+			}
+		}
+		argc--; argv++;
+	}
+
+	if (do_ipv6 == AF_UNSPEC && filter.tb) {
+		do_ipv6 = AF_INET;
+	}
+
+	if (rtnl_open(&rth, 0) < 0) {
+		exit(1);
+	}
+
+	ll_init_map(&rth);
+
+	if (id || od)  {
+		int idx;
+
+		if (id) {
+			if ((idx = ll_name_to_index(id)) == 0) {
+				bb_error_msg("Cannot find device \"%s\"", id);
+				return -1;
+			}
+			filter.iif = idx;
+			filter.iifmask = -1;
+		}
+		if (od) {
+			if ((idx = ll_name_to_index(od)) == 0) {
+				bb_error_msg("Cannot find device \"%s\"", od);
+			}
+			filter.oif = idx;
+			filter.oifmask = -1;
+		}
+	}
+
+	if (flush) {
+		char flushb[4096-512];
+
+		if (filter.tb == -1) {
+			if (do_ipv6 != AF_INET6)
+				iproute_flush_cache();
+			if (do_ipv6 == AF_INET)
+				return 0;
+		}
+
+		filter.flushb = flushb;
+		filter.flushp = 0;
+		filter.flushe = sizeof(flushb);
+		filter.rth = &rth;
+
+		for (;;) {
+			if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) {
+				perror("Cannot send dump request");
+				return -1;
+			}
+			filter.flushed = 0;
+			if (rtnl_dump_filter(&rth, print_route, stdout, NULL, NULL) < 0) {
+				bb_error_msg("Flush terminated\n");
+				return -1;
+			}
+			if (filter.flushed == 0) {
+				fflush(stdout);
+				return 0;
+			}
+			if (flush_update() < 0)
+				exit(1);
+		}
+	}
+
+	if (filter.tb != -1) {
+		if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) {
+			bb_perror_msg_and_die("Cannot send dump request");
+		}
+	} else {
+		if (rtnl_rtcache_request(&rth, do_ipv6) < 0) {
+			bb_perror_msg_and_die("Cannot send dump request");
+		}
+	}
+
+	if (rtnl_dump_filter(&rth, print_route, stdout, NULL, NULL) < 0) {
+		bb_error_msg_and_die("Dump terminated");
+	}
+
+	exit(0);
+}
+
+
+static int iproute_get(int argc, char **argv)
+{
+	struct rtnl_handle rth;
+	struct {
+		struct nlmsghdr		n;
+		struct rtmsg		r;
+		char			buf[1024];
+	} req;
+	char  *idev = NULL;
+	char  *odev = NULL;
+	int connected = 0;
+	int from_ok = 0;
+	static const char * const options[] =
+		{ "from", "iif", "oif", "dev", "notify", "connected", "to", 0 };
+
+	memset(&req, 0, sizeof(req));
+
+	iproute_reset_filter();
+
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = RTM_GETROUTE;
+	req.r.rtm_family = preferred_family;
+	req.r.rtm_table = 0;
+	req.r.rtm_protocol = 0;
+	req.r.rtm_scope = 0;
+	req.r.rtm_type = 0;
+	req.r.rtm_src_len = 0;
+	req.r.rtm_dst_len = 0;
+	req.r.rtm_tos = 0;
+
+	while (argc > 0) {
+		switch (compare_string_array(options, *argv)) {
+			case 0: /* from */
+			{
+				inet_prefix addr;
+				NEXT_ARG();
+				from_ok = 1;
+				get_prefix(&addr, *argv, req.r.rtm_family);
+				if (req.r.rtm_family == AF_UNSPEC) {
+					req.r.rtm_family = addr.family;
+				}
+				if (addr.bytelen) {
+					addattr_l(&req.n, sizeof(req), RTA_SRC, &addr.data, addr.bytelen);
+				}
+				req.r.rtm_src_len = addr.bitlen;
+				break;
+			}
+			case 1: /* iif */
+				NEXT_ARG();
+				idev = *argv;
+				break;
+			case 2: /* oif */
+			case 3: /* dev */
+				NEXT_ARG();
+				odev = *argv;
+				break;
+			case 4: /* notify */
+				req.r.rtm_flags |= RTM_F_NOTIFY;
+				break;
+			case 5: /* connected */
+				connected = 1;
+				break;
+			case 6: /* to */
+				NEXT_ARG();
+			default:
+			{
+				inet_prefix addr;
+				get_prefix(&addr, *argv, req.r.rtm_family);
+				if (req.r.rtm_family == AF_UNSPEC) {
+					req.r.rtm_family = addr.family;
+				}
+				if (addr.bytelen) {
+					addattr_l(&req.n, sizeof(req), RTA_DST, &addr.data, addr.bytelen);
+				}
+				req.r.rtm_dst_len = addr.bitlen;
+			}
+			argc--; argv++;
+		}
+	}
+
+	if (req.r.rtm_dst_len == 0) {
+		bb_error_msg_and_die("need at least destination address");
+	}
+
+	if (rtnl_open(&rth, 0) < 0)
+		exit(1);
+
+	ll_init_map(&rth);
+
+	if (idev || odev)  {
+		int idx;
+
+		if (idev) {
+			if ((idx = ll_name_to_index(idev)) == 0) {
+				bb_error_msg("Cannot find device \"%s\"", idev);
+				return -1;
+			}
+			addattr32(&req.n, sizeof(req), RTA_IIF, idx);
+		}
+		if (odev) {
+			if ((idx = ll_name_to_index(odev)) == 0) {
+				bb_error_msg("Cannot find device \"%s\"", odev);
+				return -1;
+			}
+			addattr32(&req.n, sizeof(req), RTA_OIF, idx);
+		}
+	}
+
+	if (req.r.rtm_family == AF_UNSPEC) {
+		req.r.rtm_family = AF_INET;
+	}
+
+	if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0) {
+		exit(2);
+	}
+
+	if (connected && !from_ok) {
+		struct rtmsg *r = NLMSG_DATA(&req.n);
+		int len = req.n.nlmsg_len;
+		struct rtattr * tb[RTA_MAX+1];
+
+		if (print_route(NULL, &req.n, (void*)stdout) < 0) {
+			bb_error_msg_and_die("An error :-)");
+		}
+
+		if (req.n.nlmsg_type != RTM_NEWROUTE) {
+			bb_error_msg("Not a route?");
+			return -1;
+		}
+		len -= NLMSG_LENGTH(sizeof(*r));
+		if (len < 0) {
+			bb_error_msg("Wrong len %d", len);
+			return -1;
+		}
+
+		memset(tb, 0, sizeof(tb));
+		parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
+
+		if (tb[RTA_PREFSRC]) {
+			tb[RTA_PREFSRC]->rta_type = RTA_SRC;
+			r->rtm_src_len = 8*RTA_PAYLOAD(tb[RTA_PREFSRC]);
+		} else if (!tb[RTA_SRC]) {
+			bb_error_msg("Failed to connect the route");
+			return -1;
+		}
+		if (!odev && tb[RTA_OIF]) {
+			tb[RTA_OIF]->rta_type = 0;
+		}
+		if (tb[RTA_GATEWAY]) {
+			tb[RTA_GATEWAY]->rta_type = 0;
+		}
+		if (!idev && tb[RTA_IIF]) {
+			tb[RTA_IIF]->rta_type = 0;
+		}
+		req.n.nlmsg_flags = NLM_F_REQUEST;
+		req.n.nlmsg_type = RTM_GETROUTE;
+
+		if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0) {
+			exit(2);
+		}
+	}
+
+	if (print_route(NULL, &req.n, (void*)stdout) < 0) {
+		bb_error_msg_and_die("An error :-)");
+	}
+
+	exit(0);
+}
+
+int do_iproute(int argc, char **argv)
+{
+	static const char * const ip_route_commands[] =
+		{ "add", "append", "change", "chg", "delete", "del", "get",
+		"list", "show", "prepend", "replace", "test", "flush", 0 };
+	int command_num = 7;
+	unsigned int flags = 0;
+	int cmd = RTM_NEWROUTE;
+
+	if (*argv) {
+		command_num = compare_string_array(ip_route_commands, *argv);
+	}
+	switch(command_num) {
+		case 0: /* add*/
+			flags = NLM_F_CREATE|NLM_F_EXCL;
+			break;
+		case 1: /* append */
+			flags = NLM_F_CREATE|NLM_F_APPEND;
+			break;
+		case 2: /* change */
+		case 3: /* chg */
+			flags = NLM_F_REPLACE;
+			break;
+		case 4: /* delete */
+		case 5: /* del */
+			cmd = RTM_DELROUTE;
+			break;
+		case 6: /* get */
+			return iproute_get(argc-1, argv+1);
+		case 7: /* list */
+		case 8: /* show */
+			return iproute_list_or_flush(argc-1, argv+1, 0);
+		case 9: /* prepend */
+			flags = NLM_F_CREATE;
+		case 10: /* replace */
+			flags = NLM_F_CREATE|NLM_F_REPLACE;
+		case 11: /* test */
+			flags = NLM_F_EXCL;
+		case 12: /* flush */
+			return iproute_list_or_flush(argc-1, argv+1, 1);
+		default:
+			bb_error_msg_and_die("Unknown command %s", *argv);
+	}
+
+	return iproute_modify(cmd, flags, argc-1, argv+1);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/iptunnel.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/iptunnel.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/iptunnel.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,545 @@
+/*
+ * iptunnel.c	       "ip tunnel"
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ *
+ *
+ * Changes:
+ *
+ * Rani Assaf <rani at magic.metawire.com> 980929:	resolve addresses
+ * Rani Assaf <rani at magic.metawire.com> 980930:	do not allow key for ipip/sit
+ * Phil Karn <karn at ka9q.ampr.org>	990408:	"pmtudisc" flag
+ */
+
+#include "libbb.h"
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <string.h>
+#include <unistd.h>
+
+#include <netinet/ip.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+
+#include <asm/types.h>
+#ifndef __constant_htons
+#define __constant_htons htons
+#endif
+#include <linux/if_tunnel.h>
+
+#include "rt_names.h"
+#include "utils.h"
+#include "ip_common.h"
+
+
+static int do_ioctl_get_ifindex(char *dev)
+{
+	struct ifreq ifr;
+	int fd;
+
+	strcpy(ifr.ifr_name, dev);
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (ioctl(fd, SIOCGIFINDEX, &ifr)) {
+		bb_perror_msg("ioctl");
+		return 0;
+	}
+	close(fd);
+	return ifr.ifr_ifindex;
+}
+
+static int do_ioctl_get_iftype(char *dev)
+{
+	struct ifreq ifr;
+	int fd;
+
+	strcpy(ifr.ifr_name, dev);
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (ioctl(fd, SIOCGIFHWADDR, &ifr)) {
+		bb_perror_msg("ioctl");
+		return -1;
+	}
+	close(fd);
+	return ifr.ifr_addr.sa_family;
+}
+
+
+static char *do_ioctl_get_ifname(int idx)
+{
+	static struct ifreq ifr;
+	int fd;
+
+	ifr.ifr_ifindex = idx;
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (ioctl(fd, SIOCGIFNAME, &ifr)) {
+		bb_perror_msg("ioctl");
+		return NULL;
+	}
+	close(fd);
+	return ifr.ifr_name;
+}
+
+
+
+static int do_get_ioctl(char *basedev, struct ip_tunnel_parm *p)
+{
+	struct ifreq ifr;
+	int fd;
+	int err;
+
+	strcpy(ifr.ifr_name, basedev);
+	ifr.ifr_ifru.ifru_data = (void*)p;
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	err = ioctl(fd, SIOCGETTUNNEL, &ifr);
+	if (err) {
+		bb_perror_msg("ioctl");
+	}
+	close(fd);
+	return err;
+}
+
+static int do_add_ioctl(int cmd, char *basedev, struct ip_tunnel_parm *p)
+{
+	struct ifreq ifr;
+	int fd;
+	int err;
+
+	if (cmd == SIOCCHGTUNNEL && p->name[0]) {
+		strcpy(ifr.ifr_name, p->name);
+	} else {
+		strcpy(ifr.ifr_name, basedev);
+	}
+	ifr.ifr_ifru.ifru_data = (void*)p;
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	err = ioctl(fd, cmd, &ifr);
+	if (err) {
+		bb_perror_msg("ioctl");
+	}
+	close(fd);
+	return err;
+}
+
+static int do_del_ioctl(char *basedev, struct ip_tunnel_parm *p)
+{
+	struct ifreq ifr;
+	int fd;
+	int err;
+
+	if (p->name[0]) {
+		strcpy(ifr.ifr_name, p->name);
+	} else {
+		strcpy(ifr.ifr_name, basedev);
+	}
+	ifr.ifr_ifru.ifru_data = (void*)p;
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	err = ioctl(fd, SIOCDELTUNNEL, &ifr);
+	if (err) {
+		bb_perror_msg("ioctl");
+	}
+	close(fd);
+	return err;
+}
+
+static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
+{
+	int count = 0;
+	char medium[IFNAMSIZ];
+	memset(p, 0, sizeof(*p));
+	memset(&medium, 0, sizeof(medium));
+
+	p->iph.version = 4;
+	p->iph.ihl = 5;
+#ifndef IP_DF
+#define IP_DF		0x4000		/* Flag: "Don't Fragment"	*/
+#endif
+	p->iph.frag_off = htons(IP_DF);
+
+	while (argc > 0) {
+		if (strcmp(*argv, "mode") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "ipip") == 0 ||
+			    strcmp(*argv, "ip/ip") == 0) {
+				if (p->iph.protocol && p->iph.protocol != IPPROTO_IPIP) {
+					bb_error_msg("You managed to ask for more than one tunnel mode.");
+					exit(-1);
+				}
+				p->iph.protocol = IPPROTO_IPIP;
+			} else if (strcmp(*argv, "gre") == 0 ||
+				   strcmp(*argv, "gre/ip") == 0) {
+				if (p->iph.protocol && p->iph.protocol != IPPROTO_GRE) {
+					bb_error_msg("You managed to ask for more than one tunnel mode.");
+					exit(-1);
+				}
+				p->iph.protocol = IPPROTO_GRE;
+			} else if (strcmp(*argv, "sit") == 0 ||
+				   strcmp(*argv, "ipv6/ip") == 0) {
+				if (p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) {
+					bb_error_msg("You managed to ask for more than one tunnel mode.");
+					exit(-1);
+				}
+				p->iph.protocol = IPPROTO_IPV6;
+			} else {
+				bb_error_msg("Cannot guess tunnel mode.");
+				exit(-1);
+			}
+		} else if (strcmp(*argv, "key") == 0) {
+			unsigned uval;
+			NEXT_ARG();
+			p->i_flags |= GRE_KEY;
+			p->o_flags |= GRE_KEY;
+			if (strchr(*argv, '.'))
+				p->i_key = p->o_key = get_addr32(*argv);
+			else {
+				if (get_unsigned(&uval, *argv, 0)<0) {
+					bb_error_msg("invalid value of \"key\"");
+					exit(-1);
+				}
+				p->i_key = p->o_key = htonl(uval);
+			}
+		} else if (strcmp(*argv, "ikey") == 0) {
+			unsigned uval;
+			NEXT_ARG();
+			p->i_flags |= GRE_KEY;
+			if (strchr(*argv, '.'))
+				p->o_key = get_addr32(*argv);
+			else {
+				if (get_unsigned(&uval, *argv, 0)<0) {
+					bb_error_msg("invalid value of \"ikey\"");
+					exit(-1);
+				}
+				p->i_key = htonl(uval);
+			}
+		} else if (strcmp(*argv, "okey") == 0) {
+			unsigned uval;
+			NEXT_ARG();
+			p->o_flags |= GRE_KEY;
+			if (strchr(*argv, '.'))
+				p->o_key = get_addr32(*argv);
+			else {
+				if (get_unsigned(&uval, *argv, 0)<0) {
+					bb_error_msg("invalid value of \"okey\"");
+					exit(-1);
+				}
+				p->o_key = htonl(uval);
+			}
+		} else if (strcmp(*argv, "seq") == 0) {
+			p->i_flags |= GRE_SEQ;
+			p->o_flags |= GRE_SEQ;
+		} else if (strcmp(*argv, "iseq") == 0) {
+			p->i_flags |= GRE_SEQ;
+		} else if (strcmp(*argv, "oseq") == 0) {
+			p->o_flags |= GRE_SEQ;
+		} else if (strcmp(*argv, "csum") == 0) {
+			p->i_flags |= GRE_CSUM;
+			p->o_flags |= GRE_CSUM;
+		} else if (strcmp(*argv, "icsum") == 0) {
+			p->i_flags |= GRE_CSUM;
+		} else if (strcmp(*argv, "ocsum") == 0) {
+			p->o_flags |= GRE_CSUM;
+		} else if (strcmp(*argv, "nopmtudisc") == 0) {
+			p->iph.frag_off = 0;
+		} else if (strcmp(*argv, "pmtudisc") == 0) {
+			p->iph.frag_off = htons(IP_DF);
+		} else if (strcmp(*argv, "remote") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "any"))
+				p->iph.daddr = get_addr32(*argv);
+		} else if (strcmp(*argv, "local") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "any"))
+				p->iph.saddr = get_addr32(*argv);
+		} else if (strcmp(*argv, "dev") == 0) {
+			NEXT_ARG();
+			strncpy(medium, *argv, IFNAMSIZ-1);
+		} else if (strcmp(*argv, "ttl") == 0) {
+			unsigned uval;
+			NEXT_ARG();
+			if (strcmp(*argv, "inherit") != 0) {
+				if (get_unsigned(&uval, *argv, 0))
+					invarg(*argv, "TTL");
+				if (uval > 255)
+					invarg(*argv, "TTL must be <=255");
+				p->iph.ttl = uval;
+			}
+		} else if (strcmp(*argv, "tos") == 0 ||
+			   matches(*argv, "dsfield") == 0) {
+			__u32 uval;
+			NEXT_ARG();
+			if (strcmp(*argv, "inherit") != 0) {
+				if (rtnl_dsfield_a2n(&uval, *argv))
+					invarg(*argv, "TOS");
+				p->iph.tos = uval;
+			} else
+				p->iph.tos = 1;
+		} else {
+			if (strcmp(*argv, "name") == 0) {
+				NEXT_ARG();
+			}
+			if (p->name[0])
+				duparg2("name", *argv);
+			strncpy(p->name, *argv, IFNAMSIZ);
+			if (cmd == SIOCCHGTUNNEL && count == 0) {
+				struct ip_tunnel_parm old_p;
+				memset(&old_p, 0, sizeof(old_p));
+				if (do_get_ioctl(*argv, &old_p))
+					return -1;
+				*p = old_p;
+			}
+		}
+		count++;
+		argc--; argv++;
+	}
+
+
+	if (p->iph.protocol == 0) {
+		if (memcmp(p->name, "gre", 3) == 0)
+			p->iph.protocol = IPPROTO_GRE;
+		else if (memcmp(p->name, "ipip", 4) == 0)
+			p->iph.protocol = IPPROTO_IPIP;
+		else if (memcmp(p->name, "sit", 3) == 0)
+			p->iph.protocol = IPPROTO_IPV6;
+	}
+
+	if (p->iph.protocol == IPPROTO_IPIP || p->iph.protocol == IPPROTO_IPV6) {
+		if ((p->i_flags & GRE_KEY) || (p->o_flags & GRE_KEY)) {
+			bb_error_msg("Keys are not allowed with ipip and sit.");
+			return -1;
+		}
+	}
+
+	if (medium[0]) {
+		p->link = do_ioctl_get_ifindex(medium);
+		if (p->link == 0)
+			return -1;
+	}
+
+	if (p->i_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) {
+		p->i_key = p->iph.daddr;
+		p->i_flags |= GRE_KEY;
+	}
+	if (p->o_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) {
+		p->o_key = p->iph.daddr;
+		p->o_flags |= GRE_KEY;
+	}
+	if (IN_MULTICAST(ntohl(p->iph.daddr)) && !p->iph.saddr) {
+		bb_error_msg("Broadcast tunnel requires a source address.");
+		return -1;
+	}
+	return 0;
+}
+
+
+static int do_add(int cmd, int argc, char **argv)
+{
+	struct ip_tunnel_parm p;
+
+	if (parse_args(argc, argv, cmd, &p) < 0)
+		return -1;
+
+	if (p.iph.ttl && p.iph.frag_off == 0) {
+		bb_error_msg("ttl != 0 and noptmudisc are incompatible");
+		return -1;
+	}
+
+	switch (p.iph.protocol) {
+	case IPPROTO_IPIP:
+		return do_add_ioctl(cmd, "tunl0", &p);
+	case IPPROTO_GRE:
+		return do_add_ioctl(cmd, "gre0", &p);
+	case IPPROTO_IPV6:
+		return do_add_ioctl(cmd, "sit0", &p);
+	default:
+		bb_error_msg("cannot determine tunnel mode (ipip, gre or sit)");
+		return -1;
+	}
+	return -1;
+}
+
+static int do_del(int argc, char **argv)
+{
+	struct ip_tunnel_parm p;
+
+	if (parse_args(argc, argv, SIOCDELTUNNEL, &p) < 0)
+		return -1;
+
+	switch (p.iph.protocol) {
+	case IPPROTO_IPIP:
+		return do_del_ioctl("tunl0", &p);
+	case IPPROTO_GRE:
+		return do_del_ioctl("gre0", &p);
+	case IPPROTO_IPV6:
+		return do_del_ioctl("sit0", &p);
+	default:
+		return do_del_ioctl(p.name, &p);
+	}
+	return -1;
+}
+
+static void print_tunnel(struct ip_tunnel_parm *p)
+{
+	char s1[256];
+	char s2[256];
+	char s3[64];
+	char s4[64];
+
+	format_host(AF_INET, 4, &p->iph.daddr, s1, sizeof(s1));
+	format_host(AF_INET, 4, &p->iph.saddr, s2, sizeof(s2));
+	inet_ntop(AF_INET, &p->i_key, s3, sizeof(s3));
+	inet_ntop(AF_INET, &p->o_key, s4, sizeof(s4));
+
+	printf("%s: %s/ip  remote %s  local %s ",
+	       p->name,
+	       p->iph.protocol == IPPROTO_IPIP ? "ip" :
+	       (p->iph.protocol == IPPROTO_GRE ? "gre" :
+		(p->iph.protocol == IPPROTO_IPV6 ? "ipv6" : "unknown")),
+	       p->iph.daddr ? s1 : "any", p->iph.saddr ? s2 : "any");
+	if (p->link) {
+		char *n = do_ioctl_get_ifname(p->link);
+		if (n)
+			printf(" dev %s ", n);
+	}
+	if (p->iph.ttl)
+		printf(" ttl %d ", p->iph.ttl);
+	else
+		printf(" ttl inherit ");
+	if (p->iph.tos) {
+		SPRINT_BUF(b1);
+		printf(" tos");
+		if (p->iph.tos&1)
+			printf(" inherit");
+		if (p->iph.tos&~1)
+			printf("%c%s ", p->iph.tos&1 ? '/' : ' ',
+			       rtnl_dsfield_n2a(p->iph.tos&~1, b1, sizeof(b1)));
+	}
+	if (!(p->iph.frag_off&htons(IP_DF)))
+		printf(" nopmtudisc");
+
+	if ((p->i_flags&GRE_KEY) && (p->o_flags&GRE_KEY) && p->o_key == p->i_key)
+		printf(" key %s", s3);
+	else if ((p->i_flags|p->o_flags)&GRE_KEY) {
+		if (p->i_flags&GRE_KEY)
+			printf(" ikey %s ", s3);
+		if (p->o_flags&GRE_KEY)
+			printf(" okey %s ", s4);
+	}
+
+	if (p->i_flags&GRE_SEQ)
+		printf("%s  Drop packets out of sequence.\n", _SL_);
+	if (p->i_flags&GRE_CSUM)
+		printf("%s  Checksum in received packet is required.", _SL_);
+	if (p->o_flags&GRE_SEQ)
+		printf("%s  Sequence packets on output.", _SL_);
+	if (p->o_flags&GRE_CSUM)
+		printf("%s  Checksum output packets.", _SL_);
+}
+
+static int do_tunnels_list(struct ip_tunnel_parm *p)
+{
+	char name[IFNAMSIZ];
+	unsigned long  rx_bytes, rx_packets, rx_errs, rx_drops,
+	rx_fifo, rx_frame,
+	tx_bytes, tx_packets, tx_errs, tx_drops,
+	tx_fifo, tx_colls, tx_carrier, rx_multi;
+	int type;
+	struct ip_tunnel_parm p1;
+
+	char buf[512];
+	FILE *fp = fopen("/proc/net/dev", "r");
+	if (fp == NULL) {
+		perror("fopen");
+		return -1;
+	}
+
+	fgets(buf, sizeof(buf), fp);
+	fgets(buf, sizeof(buf), fp);
+
+	while (fgets(buf, sizeof(buf), fp) != NULL) {
+		char *ptr;
+		buf[sizeof(buf) - 1] = 0;
+		if ((ptr = strchr(buf, ':')) == NULL ||
+		    (*ptr++ = 0, sscanf(buf, "%s", name) != 1)) {
+			bb_error_msg("Wrong format of /proc/net/dev. Sorry.");
+			return -1;
+		}
+		if (sscanf(ptr, "%lu%lu%lu%lu%lu%lu%lu%*d%lu%lu%lu%lu%lu%lu%lu",
+			   &rx_bytes, &rx_packets, &rx_errs, &rx_drops,
+			   &rx_fifo, &rx_frame, &rx_multi,
+			   &tx_bytes, &tx_packets, &tx_errs, &tx_drops,
+			   &tx_fifo, &tx_colls, &tx_carrier) != 14)
+			continue;
+		if (p->name[0] && strcmp(p->name, name))
+			continue;
+		type = do_ioctl_get_iftype(name);
+		if (type == -1) {
+			bb_error_msg("Failed to get type of [%s]", name);
+			continue;
+		}
+		if (type != ARPHRD_TUNNEL && type != ARPHRD_IPGRE && type != ARPHRD_SIT)
+			continue;
+		memset(&p1, 0, sizeof(p1));
+		if (do_get_ioctl(name, &p1))
+			continue;
+		if ((p->link && p1.link != p->link) ||
+		    (p->name[0] && strcmp(p1.name, p->name)) ||
+		    (p->iph.daddr && p1.iph.daddr != p->iph.daddr) ||
+		    (p->iph.saddr && p1.iph.saddr != p->iph.saddr) ||
+		    (p->i_key && p1.i_key != p->i_key))
+			continue;
+		print_tunnel(&p1);
+		printf("\n");
+	}
+	return 0;
+}
+
+static int do_show(int argc, char **argv)
+{
+	int err;
+	struct ip_tunnel_parm p;
+
+	if (parse_args(argc, argv, SIOCGETTUNNEL, &p) < 0)
+		return -1;
+
+	switch (p.iph.protocol) {
+	case IPPROTO_IPIP:
+		err = do_get_ioctl(p.name[0] ? p.name : "tunl0", &p);
+		break;
+	case IPPROTO_GRE:
+		err = do_get_ioctl(p.name[0] ? p.name : "gre0", &p);
+		break;
+	case IPPROTO_IPV6:
+		err = do_get_ioctl(p.name[0] ? p.name : "sit0", &p);
+		break;
+	default:
+		do_tunnels_list(&p);
+		return 0;
+	}
+	if (err)
+		return -1;
+
+	print_tunnel(&p);
+	printf("\n");
+	return 0;
+}
+
+int do_iptunnel(int argc, char **argv)
+{
+	if (argc > 0) {
+		if (matches(*argv, "add") == 0)
+			return do_add(SIOCADDTUNNEL, argc-1, argv+1);
+		if (matches(*argv, "change") == 0)
+			return do_add(SIOCCHGTUNNEL, argc-1, argv+1);
+		if (matches(*argv, "del") == 0)
+			return do_del(argc-1, argv+1);
+		if (matches(*argv, "show") == 0 ||
+		    matches(*argv, "lst") == 0 ||
+		    matches(*argv, "list") == 0)
+			return do_show(argc-1, argv+1);
+	} else
+		return do_show(0, NULL);
+
+	bb_error_msg("Command \"%s\" is unknown.", *argv);
+	exit(-1);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/libnetlink.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/libnetlink.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/libnetlink.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,395 @@
+/*
+ * libnetlink.c	RTnetlink service routines.
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ *
+ */
+
+#include "libbb.h"
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sys/uio.h>
+
+#include "libnetlink.h"
+
+void rtnl_close(struct rtnl_handle *rth)
+{
+	close(rth->fd);
+}
+
+int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions)
+{
+	socklen_t addr_len;
+
+	memset(rth, 0, sizeof(rth));
+
+	rth->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+	if (rth->fd < 0) {
+		bb_perror_msg("Cannot open netlink socket");
+		return -1;
+	}
+
+	memset(&rth->local, 0, sizeof(rth->local));
+	rth->local.nl_family = AF_NETLINK;
+	rth->local.nl_groups = subscriptions;
+
+	if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) {
+		bb_perror_msg("Cannot bind netlink socket");
+		return -1;
+	}
+	addr_len = sizeof(rth->local);
+	if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) {
+		bb_perror_msg("Cannot getsockname");
+		return -1;
+	}
+	if (addr_len != sizeof(rth->local)) {
+		bb_error_msg("Wrong address length %d", addr_len);
+		return -1;
+	}
+	if (rth->local.nl_family != AF_NETLINK) {
+		bb_error_msg("Wrong address family %d", rth->local.nl_family);
+		return -1;
+	}
+	rth->seq = time(NULL);
+	return 0;
+}
+
+int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
+{
+	struct {
+		struct nlmsghdr nlh;
+		struct rtgenmsg g;
+	} req;
+	struct sockaddr_nl nladdr;
+
+	memset(&nladdr, 0, sizeof(nladdr));
+	nladdr.nl_family = AF_NETLINK;
+
+	req.nlh.nlmsg_len = sizeof(req);
+	req.nlh.nlmsg_type = type;
+	req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
+	req.nlh.nlmsg_pid = 0;
+	req.nlh.nlmsg_seq = rth->dump = ++rth->seq;
+	req.g.rtgen_family = family;
+
+	return sendto(rth->fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr));
+}
+
+int rtnl_send(struct rtnl_handle *rth, char *buf, int len)
+{
+	struct sockaddr_nl nladdr;
+
+	memset(&nladdr, 0, sizeof(nladdr));
+	nladdr.nl_family = AF_NETLINK;
+
+	return sendto(rth->fd, buf, len, 0, (struct sockaddr*)&nladdr, sizeof(nladdr));
+}
+
+int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len)
+{
+	struct nlmsghdr nlh;
+	struct sockaddr_nl nladdr;
+	struct iovec iov[2] = { { &nlh, sizeof(nlh) }, { req, len } };
+	struct msghdr msg = {
+		(void*)&nladdr, sizeof(nladdr),
+		iov,	2,
+		NULL,	0,
+		0
+	};
+
+	memset(&nladdr, 0, sizeof(nladdr));
+	nladdr.nl_family = AF_NETLINK;
+
+	nlh.nlmsg_len = NLMSG_LENGTH(len);
+	nlh.nlmsg_type = type;
+	nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
+	nlh.nlmsg_pid = 0;
+	nlh.nlmsg_seq = rth->dump = ++rth->seq;
+
+	return sendmsg(rth->fd, &msg, 0);
+}
+
+int rtnl_dump_filter(struct rtnl_handle *rth,
+		     int (*filter)(struct sockaddr_nl *, struct nlmsghdr *n, void *),
+		     void *arg1,
+		     int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
+		     void *arg2)
+{
+	char	buf[8192];
+	struct sockaddr_nl nladdr;
+	struct iovec iov = { buf, sizeof(buf) };
+
+	while (1) {
+		int status;
+		struct nlmsghdr *h;
+
+		struct msghdr msg = {
+			(void*)&nladdr, sizeof(nladdr),
+			&iov,	1,
+			NULL,	0,
+			0
+		};
+
+		status = recvmsg(rth->fd, &msg, 0);
+
+		if (status < 0) {
+			if (errno == EINTR)
+				continue;
+			bb_perror_msg("OVERRUN");
+			continue;
+		}
+		if (status == 0) {
+			bb_error_msg("EOF on netlink");
+			return -1;
+		}
+		if (msg.msg_namelen != sizeof(nladdr)) {
+			bb_error_msg_and_die("sender address length == %d", msg.msg_namelen);
+		}
+
+		h = (struct nlmsghdr*)buf;
+		while (NLMSG_OK(h, status)) {
+			int err;
+
+			if (nladdr.nl_pid != 0 ||
+			    h->nlmsg_pid != rth->local.nl_pid ||
+			    h->nlmsg_seq != rth->dump) {
+				if (junk) {
+					err = junk(&nladdr, h, arg2);
+					if (err < 0) {
+						return err;
+					}
+				}
+				goto skip_it;
+			}
+
+			if (h->nlmsg_type == NLMSG_DONE) {
+				return 0;
+			}
+			if (h->nlmsg_type == NLMSG_ERROR) {
+				struct nlmsgerr *l_err = (struct nlmsgerr*)NLMSG_DATA(h);
+				if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
+					bb_error_msg("ERROR truncated");
+				} else {
+					errno = -l_err->error;
+					bb_perror_msg("RTNETLINK answers");
+				}
+				return -1;
+			}
+			err = filter(&nladdr, h, arg1);
+			if (err < 0) {
+				return err;
+			}
+
+skip_it:
+			h = NLMSG_NEXT(h, status);
+		}
+		if (msg.msg_flags & MSG_TRUNC) {
+			bb_error_msg("Message truncated");
+			continue;
+		}
+		if (status) {
+			bb_error_msg_and_die("!!!Remnant of size %d", status);
+		}
+	}
+}
+
+int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
+	      unsigned groups, struct nlmsghdr *answer,
+	      int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
+	      void *jarg)
+{
+	int status;
+	unsigned seq;
+	struct nlmsghdr *h;
+	struct sockaddr_nl nladdr;
+	struct iovec iov = { (void*)n, n->nlmsg_len };
+	char   buf[8192];
+	struct msghdr msg = {
+		(void*)&nladdr, sizeof(nladdr),
+		&iov,	1,
+		NULL,	0,
+		0
+	};
+
+	memset(&nladdr, 0, sizeof(nladdr));
+	nladdr.nl_family = AF_NETLINK;
+	nladdr.nl_pid = peer;
+	nladdr.nl_groups = groups;
+
+	n->nlmsg_seq = seq = ++rtnl->seq;
+	if (answer == NULL) {
+		n->nlmsg_flags |= NLM_F_ACK;
+	}
+	status = sendmsg(rtnl->fd, &msg, 0);
+
+	if (status < 0) {
+		bb_perror_msg("Cannot talk to rtnetlink");
+		return -1;
+	}
+
+	iov.iov_base = buf;
+
+	while (1) {
+		iov.iov_len = sizeof(buf);
+		status = recvmsg(rtnl->fd, &msg, 0);
+
+		if (status < 0) {
+			if (errno == EINTR) {
+				continue;
+			}
+			bb_perror_msg("OVERRUN");
+			continue;
+		}
+		if (status == 0) {
+			bb_error_msg("EOF on netlink");
+			return -1;
+		}
+		if (msg.msg_namelen != sizeof(nladdr)) {
+			bb_error_msg_and_die("sender address length == %d", msg.msg_namelen);
+		}
+		for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
+			int l_err;
+			int len = h->nlmsg_len;
+			int l = len - sizeof(*h);
+
+			if (l<0 || len>status) {
+				if (msg.msg_flags & MSG_TRUNC) {
+					bb_error_msg("Truncated message");
+					return -1;
+				}
+				bb_error_msg_and_die("!!!malformed message: len=%d", len);
+			}
+
+			if (nladdr.nl_pid != peer ||
+			    h->nlmsg_pid != rtnl->local.nl_pid ||
+			    h->nlmsg_seq != seq) {
+				if (junk) {
+					l_err = junk(&nladdr, h, jarg);
+					if (l_err < 0) {
+						return l_err;
+					}
+				}
+				continue;
+			}
+
+			if (h->nlmsg_type == NLMSG_ERROR) {
+				struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
+				if (l < sizeof(struct nlmsgerr)) {
+					bb_error_msg("ERROR truncated");
+				} else {
+					errno = -err->error;
+					if (errno == 0) {
+						if (answer) {
+							memcpy(answer, h, h->nlmsg_len);
+						}
+						return 0;
+					}
+					bb_perror_msg("RTNETLINK answers");
+				}
+				return -1;
+			}
+			if (answer) {
+				memcpy(answer, h, h->nlmsg_len);
+				return 0;
+			}
+
+			bb_error_msg("Unexpected reply!!!");
+
+			status -= NLMSG_ALIGN(len);
+			h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
+		}
+		if (msg.msg_flags & MSG_TRUNC) {
+			bb_error_msg("Message truncated");
+			continue;
+		}
+		if (status) {
+			bb_error_msg_and_die("!!!Remnant of size %d", status);
+		}
+	}
+}
+
+int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data)
+{
+	int len = RTA_LENGTH(4);
+	struct rtattr *rta;
+	if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
+		return -1;
+	rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len));
+	rta->rta_type = type;
+	rta->rta_len = len;
+	memcpy(RTA_DATA(rta), &data, 4);
+	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
+	return 0;
+}
+
+int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
+{
+	int len = RTA_LENGTH(alen);
+	struct rtattr *rta;
+
+	if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
+		return -1;
+	rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len));
+	rta->rta_type = type;
+	rta->rta_len = len;
+	memcpy(RTA_DATA(rta), data, alen);
+	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
+	return 0;
+}
+
+int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data)
+{
+	int len = RTA_LENGTH(4);
+	struct rtattr *subrta;
+
+	if (RTA_ALIGN(rta->rta_len) + len > maxlen) {
+		return -1;
+	}
+	subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));
+	subrta->rta_type = type;
+	subrta->rta_len = len;
+	memcpy(RTA_DATA(subrta), &data, 4);
+	rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len;
+	return 0;
+}
+
+int rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data, int alen)
+{
+	struct rtattr *subrta;
+	int len = RTA_LENGTH(alen);
+
+	if (RTA_ALIGN(rta->rta_len) + len > maxlen) {
+		return -1;
+	}
+	subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));
+	subrta->rta_type = type;
+	subrta->rta_len = len;
+	memcpy(RTA_DATA(subrta), data, alen);
+	rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len;
+	return 0;
+}
+
+
+int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
+{
+	while (RTA_OK(rta, len)) {
+		if (rta->rta_type <= max) {
+			tb[rta->rta_type] = rta;
+		}
+		rta = RTA_NEXT(rta,len);
+	}
+	if (len) {
+		bb_error_msg("!!!Deficit %d, rta_len=%d", len, rta->rta_len);
+	}
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/libnetlink.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/libnetlink.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/libnetlink.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,42 @@
+#ifndef __LIBNETLINK_H__
+#define __LIBNETLINK_H__ 1
+
+#include <asm/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+struct rtnl_handle
+{
+	int			fd;
+	struct sockaddr_nl	local;
+	struct sockaddr_nl	peer;
+	__u32			seq;
+	__u32			dump;
+};
+
+extern int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions);
+extern void rtnl_close(struct rtnl_handle *rth);
+extern int rtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type);
+extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len);
+extern int rtnl_dump_filter(struct rtnl_handle *rth,
+			    int (*filter)(struct sockaddr_nl *, struct nlmsghdr *n, void *),
+			    void *arg1,
+			    int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
+			    void *arg2);
+extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
+		     unsigned groups, struct nlmsghdr *answer,
+		     int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
+		     void *jarg);
+extern int rtnl_send(struct rtnl_handle *rth, char *buf, int);
+
+
+extern int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data);
+extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen);
+extern int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data);
+extern int rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data, int alen);
+
+extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len);
+
+
+#endif /* __LIBNETLINK_H__ */
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/linux/pkt_sched.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/linux/pkt_sched.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/linux/pkt_sched.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,413 @@
+#ifndef __LINUX_PKT_SCHED_H
+#define __LINUX_PKT_SCHED_H
+
+/* Logical priority bands not depending on specific packet scheduler.
+   Every scheduler will map them to real traffic classes, if it has
+   no more precise mechanism to classify packets.
+
+   These numbers have no special meaning, though their coincidence
+   with obsolete IPv6 values is not occasional :-). New IPv6 drafts
+   preferred full anarchy inspired by diffserv group.
+
+   Note: TC_PRIO_BESTEFFORT does not mean that it is the most unhappy
+   class, actually, as rule it will be handled with more care than
+   filler or even bulk.
+ */
+
+#include <asm/types.h>
+
+#define TC_PRIO_BESTEFFORT		0
+#define TC_PRIO_FILLER			1
+#define TC_PRIO_BULK			2
+#define TC_PRIO_INTERACTIVE_BULK	4
+#define TC_PRIO_INTERACTIVE		6
+#define TC_PRIO_CONTROL			7
+
+#define TC_PRIO_MAX			15
+
+/* Generic queue statistics, available for all the elements.
+   Particular schedulers may have also their private records.
+ */
+
+struct tc_stats
+{
+	__u64	bytes;			/* NUmber of enqueues bytes */
+	__u32	packets;		/* Number of enqueued packets	*/
+	__u32	drops;			/* Packets dropped because of lack of resources */
+	__u32	overlimits;		/* Number of throttle events when this
+					 * flow goes out of allocated bandwidth */
+	__u32	bps;			/* Current flow byte rate */
+	__u32	pps;			/* Current flow packet rate */
+	__u32	qlen;
+	__u32	backlog;
+#ifdef __KERNEL__
+	spinlock_t *lock;
+#endif
+};
+
+struct tc_estimator
+{
+	char		interval;
+	unsigned char	ewma_log;
+};
+
+/* "Handles"
+   ---------
+
+    All the traffic control objects have 32bit identifiers, or "handles".
+
+    They can be considered as opaque numbers from user API viewpoint,
+    but actually they always consist of two fields: major and
+    minor numbers, which are interpreted by kernel specially,
+    that may be used by applications, though not recommended.
+
+    F.e. qdisc handles always have minor number equal to zero,
+    classes (or flows) have major equal to parent qdisc major, and
+    minor uniquely identifying class inside qdisc.
+
+    Macros to manipulate handles:
+ */
+
+#define TC_H_MAJ_MASK (0xFFFF0000U)
+#define TC_H_MIN_MASK (0x0000FFFFU)
+#define TC_H_MAJ(h) ((h)&TC_H_MAJ_MASK)
+#define TC_H_MIN(h) ((h)&TC_H_MIN_MASK)
+#define TC_H_MAKE(maj,min) (((maj)&TC_H_MAJ_MASK)|((min)&TC_H_MIN_MASK))
+
+#define TC_H_UNSPEC	(0U)
+#define TC_H_ROOT	(0xFFFFFFFFU)
+#define TC_H_INGRESS    (0xFFFFFFF1U)
+
+struct tc_ratespec
+{
+	unsigned char	cell_log;
+	unsigned char	__reserved;
+	unsigned short	feature;
+	short		addend;
+	unsigned short	mpu;
+	__u32		rate;
+};
+
+/* FIFO section */
+
+struct tc_fifo_qopt
+{
+	__u32	limit;	/* Queue length: bytes for bfifo, packets for pfifo */
+};
+
+/* PRIO section */
+
+#define TCQ_PRIO_BANDS	16
+
+struct tc_prio_qopt
+{
+	int	bands;			/* Number of bands */
+	__u8	priomap[TC_PRIO_MAX+1];	/* Map: logical priority -> PRIO band */
+};
+
+/* CSZ section */
+
+struct tc_csz_qopt
+{
+	int		flows;		/* Maximal number of guaranteed flows */
+	unsigned char	R_log;		/* Fixed point position for round number */
+	unsigned char	delta_log;	/* Log of maximal managed time interval */
+	__u8		priomap[TC_PRIO_MAX+1];	/* Map: logical priority -> CSZ band */
+};
+
+struct tc_csz_copt
+{
+	struct tc_ratespec slice;
+	struct tc_ratespec rate;
+	struct tc_ratespec peakrate;
+	__u32		limit;
+	__u32		buffer;
+	__u32		mtu;
+};
+
+enum
+{
+	TCA_CSZ_UNSPEC,
+	TCA_CSZ_PARMS,
+	TCA_CSZ_RTAB,
+	TCA_CSZ_PTAB,
+};
+
+/* TBF section */
+
+struct tc_tbf_qopt
+{
+	struct tc_ratespec rate;
+	struct tc_ratespec peakrate;
+	__u32		limit;
+	__u32		buffer;
+	__u32		mtu;
+};
+
+enum
+{
+	TCA_TBF_UNSPEC,
+	TCA_TBF_PARMS,
+	TCA_TBF_RTAB,
+	TCA_TBF_PTAB,
+};
+
+
+/* TEQL section */
+
+/* TEQL does not require any parameters */
+
+/* SFQ section */
+
+struct tc_sfq_qopt
+{
+	unsigned	quantum;	/* Bytes per round allocated to flow */
+	int		perturb_period;	/* Period of hash perturbation */
+	__u32		limit;		/* Maximal packets in queue */
+	unsigned	divisor;	/* Hash divisor  */
+	unsigned	flows;		/* Maximal number of flows  */
+};
+
+/*
+ *  NOTE: limit, divisor and flows are hardwired to code at the moment.
+ *
+ *	limit=flows=128, divisor=1024;
+ *
+ *	The only reason for this is efficiency, it is possible
+ *	to change these parameters in compile time.
+ */
+
+/* RED section */
+
+enum
+{
+	TCA_RED_UNSPEC,
+	TCA_RED_PARMS,
+	TCA_RED_STAB,
+};
+
+struct tc_red_qopt
+{
+	__u32		limit;		/* HARD maximal queue length (bytes)	*/
+	__u32		qth_min;	/* Min average length threshold (bytes) */
+	__u32		qth_max;	/* Max average length threshold (bytes) */
+	unsigned char   Wlog;		/* log(W)		*/
+	unsigned char   Plog;		/* log(P_max/(qth_max-qth_min))	*/
+	unsigned char   Scell_log;	/* cell size for idle damping */
+	unsigned char	flags;
+#define TC_RED_ECN	1
+};
+
+struct tc_red_xstats
+{
+	__u32           early;          /* Early drops */
+	__u32           pdrop;          /* Drops due to queue limits */
+	__u32           other;          /* Drops due to drop() calls */
+	__u32           marked;         /* Marked packets */
+};
+
+/* GRED section */
+
+#define MAX_DPs 16
+
+enum
+{
+       TCA_GRED_UNSPEC,
+       TCA_GRED_PARMS,
+       TCA_GRED_STAB,
+       TCA_GRED_DPS,
+};
+
+#define TCA_SET_OFF TCA_GRED_PARMS
+struct tc_gred_qopt
+{
+       __u32           limit;          /* HARD maximal queue length (bytes)
+*/
+       __u32           qth_min;        /* Min average length threshold (bytes)
+*/
+       __u32           qth_max;        /* Max average length threshold (bytes)
+*/
+       __u32           DP;             /* upto 2^32 DPs */
+       __u32           backlog;
+       __u32           qave;
+       __u32           forced;
+       __u32           early;
+       __u32           other;
+       __u32           pdrop;
+
+       unsigned char   Wlog;           /* log(W)               */
+       unsigned char   Plog;           /* log(P_max/(qth_max-qth_min)) */
+       unsigned char   Scell_log;      /* cell size for idle damping */
+       __u8            prio;		/* prio of this VQ */
+       __u32	packets;
+       __u32	bytesin;
+};
+/* gred setup */
+struct tc_gred_sopt
+{
+       __u32           DPs;
+       __u32           def_DP;
+       __u8            grio;
+};
+
+/* HTB section */
+#define TC_HTB_NUMPRIO		4
+#define TC_HTB_MAXDEPTH		4
+
+struct tc_htb_opt
+{
+	struct tc_ratespec	rate;
+	struct tc_ratespec	ceil;
+	__u32	buffer;
+	__u32	cbuffer;
+	__u32	quantum;	/* out only */
+	__u32	level;		/* out only */
+	__u8	prio;
+	__u8	injectd;	/* inject class distance */
+	__u8	pad[2];
+};
+struct tc_htb_glob
+{
+	__u32 rate2quantum;	/* bps->quantum divisor */
+	__u32 defcls;		/* default class number */
+	__u32 use_dcache;	/* use dequeue cache ? */
+	__u32 debug;		/* debug flags */
+
+
+	/* stats */
+	__u32 deq_rate;	/* dequeue rate */
+	__u32 utilz;	/* dequeue utilization */
+	__u32 trials;	/* deq_prio trials per dequeue */
+	__u32 dcache_hits;
+	__u32 direct_pkts; /* count of non shapped packets */
+};
+enum
+{
+	TCA_HTB_UNSPEC,
+	TCA_HTB_PARMS,
+	TCA_HTB_INIT,
+	TCA_HTB_CTAB,
+	TCA_HTB_RTAB,
+};
+struct tc_htb_xstats
+{
+	__u32 lends;
+	__u32 borrows;
+	__u32 giants;	/* too big packets (rate will not be accurate) */
+	__u32 injects;	/* how many times leaf used injected bw */
+	__u32 tokens;
+	__u32 ctokens;
+};
+
+/* CBQ section */
+
+#define TC_CBQ_MAXPRIO		8
+#define TC_CBQ_MAXLEVEL		8
+#define TC_CBQ_DEF_EWMA		5
+
+struct tc_cbq_lssopt
+{
+	unsigned char	change;
+	unsigned char	flags;
+#define TCF_CBQ_LSS_BOUNDED	1
+#define TCF_CBQ_LSS_ISOLATED	2
+	unsigned char	ewma_log;
+	unsigned char	level;
+#define TCF_CBQ_LSS_FLAGS	1
+#define TCF_CBQ_LSS_EWMA	2
+#define TCF_CBQ_LSS_MAXIDLE	4
+#define TCF_CBQ_LSS_MINIDLE	8
+#define TCF_CBQ_LSS_OFFTIME	0x10
+#define TCF_CBQ_LSS_AVPKT	0x20
+	__u32		maxidle;
+	__u32		minidle;
+	__u32		offtime;
+	__u32		avpkt;
+};
+
+struct tc_cbq_wrropt
+{
+	unsigned char	flags;
+	unsigned char	priority;
+	unsigned char	cpriority;
+	unsigned char	__reserved;
+	__u32		allot;
+	__u32		weight;
+};
+
+struct tc_cbq_ovl
+{
+	unsigned char	strategy;
+#define	TC_CBQ_OVL_CLASSIC	0
+#define	TC_CBQ_OVL_DELAY	1
+#define	TC_CBQ_OVL_LOWPRIO	2
+#define	TC_CBQ_OVL_DROP		3
+#define	TC_CBQ_OVL_RCLASSIC	4
+	unsigned char	priority2;
+	__u32		penalty;
+};
+
+struct tc_cbq_police
+{
+	unsigned char	police;
+	unsigned char	__res1;
+	unsigned short	__res2;
+};
+
+struct tc_cbq_fopt
+{
+	__u32		split;
+	__u32		defmap;
+	__u32		defchange;
+};
+
+struct tc_cbq_xstats
+{
+	__u32		borrows;
+	__u32		overactions;
+	__s32		avgidle;
+	__s32		undertime;
+};
+
+enum
+{
+	TCA_CBQ_UNSPEC,
+	TCA_CBQ_LSSOPT,
+	TCA_CBQ_WRROPT,
+	TCA_CBQ_FOPT,
+	TCA_CBQ_OVL_STRATEGY,
+	TCA_CBQ_RATE,
+	TCA_CBQ_RTAB,
+	TCA_CBQ_POLICE,
+};
+
+#define TCA_CBQ_MAX	TCA_CBQ_POLICE
+
+/* dsmark section */
+
+enum {
+	TCA_DSMARK_UNSPEC,
+	TCA_DSMARK_INDICES,
+	TCA_DSMARK_DEFAULT_INDEX,
+	TCA_DSMARK_SET_TC_INDEX,
+	TCA_DSMARK_MASK,
+	TCA_DSMARK_VALUE
+};
+
+#define TCA_DSMARK_MAX TCA_DSMARK_VALUE
+
+/* ATM  section */
+
+enum {
+	TCA_ATM_UNSPEC,
+	TCA_ATM_FD,		/* file/socket descriptor */
+	TCA_ATM_PTR,		/* pointer to descriptor - later */
+	TCA_ATM_HDR,		/* LL header */
+	TCA_ATM_EXCESS,		/* excess traffic class (0 for CLP)  */
+	TCA_ATM_ADDR,		/* PVC address (for output only) */
+	TCA_ATM_STATE		/* VC state (ATM_VS_*; for output only) */
+};
+
+#define TCA_ATM_MAX	TCA_ATM_STATE
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_addr.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_addr.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_addr.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,84 @@
+/*
+ * ll_addr.c
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ */
+
+#include "libbb.h"
+
+#include <string.h>
+#include <net/if_arp.h>
+
+#include "rt_names.h"
+#include "utils.h"
+
+
+const char *ll_addr_n2a(unsigned char *addr, int alen, int type, char *buf, int blen)
+{
+	int i;
+	int l;
+
+	if (alen == 4 &&
+	    (type == ARPHRD_TUNNEL || type == ARPHRD_SIT || type == ARPHRD_IPGRE)) {
+		return inet_ntop(AF_INET, addr, buf, blen);
+	}
+	l = 0;
+	for (i=0; i<alen; i++) {
+		if (i==0) {
+			snprintf(buf+l, blen, "%02x", addr[i]);
+			blen -= 2;
+			l += 2;
+		} else {
+			snprintf(buf+l, blen, ":%02x", addr[i]);
+			blen -= 3;
+			l += 3;
+		}
+	}
+	return buf;
+}
+
+int ll_addr_a2n(unsigned char *lladdr, int len, char *arg)
+{
+	if (strchr(arg, '.')) {
+		inet_prefix pfx;
+		if (get_addr_1(&pfx, arg, AF_INET)) {
+			bb_error_msg("\"%s\" is invalid lladdr.", arg);
+			return -1;
+		}
+		if (len < 4) {
+			return -1;
+		}
+		memcpy(lladdr, pfx.data, 4);
+		return 4;
+	} else {
+		int i;
+
+		for (i=0; i<len; i++) {
+			int temp;
+			char *cp = strchr(arg, ':');
+			if (cp) {
+				*cp = 0;
+				cp++;
+			}
+			if (sscanf(arg, "%x", &temp) != 1) {
+				bb_error_msg("\"%s\" is invalid lladdr.", arg);
+				return -1;
+			}
+			if (temp < 0 || temp > 255) {
+				bb_error_msg("\"%s\" is invalid lladdr.", arg);
+				return -1;
+			}
+			lladdr[i] = temp;
+			if (!cp) {
+				break;
+			}
+			arg = cp;
+		}
+		return i+1;
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_map.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_map.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_map.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,161 @@
+/*
+ * ll_map.c
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ *
+ */
+
+#include "libbb.h"
+#include <string.h>
+
+#include "libnetlink.h"
+#include "ll_map.h"
+
+struct idxmap
+{
+	struct idxmap * next;
+	int		index;
+	int		type;
+	int		alen;
+	unsigned	flags;
+	unsigned char	addr[8];
+	char		name[16];
+};
+
+static struct idxmap *idxmap[16];
+
+int ll_remember_index(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+{
+	int h;
+	struct ifinfomsg *ifi = NLMSG_DATA(n);
+	struct idxmap *im, **imp;
+	struct rtattr *tb[IFLA_MAX+1];
+
+	if (n->nlmsg_type != RTM_NEWLINK)
+		return 0;
+
+	if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi)))
+		return -1;
+
+
+	memset(tb, 0, sizeof(tb));
+	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n));
+	if (tb[IFLA_IFNAME] == NULL)
+		return 0;
+
+	h = ifi->ifi_index&0xF;
+
+	for (imp=&idxmap[h]; (im=*imp)!=NULL; imp = &im->next)
+		if (im->index == ifi->ifi_index)
+			break;
+
+	if (im == NULL) {
+		im = xmalloc(sizeof(*im));
+		im->next = *imp;
+		im->index = ifi->ifi_index;
+		*imp = im;
+	}
+
+	im->type = ifi->ifi_type;
+	im->flags = ifi->ifi_flags;
+	if (tb[IFLA_ADDRESS]) {
+		int alen;
+		im->alen = alen = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
+		if (alen > sizeof(im->addr))
+			alen = sizeof(im->addr);
+		memcpy(im->addr, RTA_DATA(tb[IFLA_ADDRESS]), alen);
+	} else {
+		im->alen = 0;
+		memset(im->addr, 0, sizeof(im->addr));
+	}
+	strcpy(im->name, RTA_DATA(tb[IFLA_IFNAME]));
+	return 0;
+}
+
+const char *ll_idx_n2a(int idx, char *buf)
+{
+	struct idxmap *im;
+
+	if (idx == 0)
+		return "*";
+	for (im = idxmap[idx&0xF]; im; im = im->next)
+		if (im->index == idx)
+			return im->name;
+	snprintf(buf, 16, "if%d", idx);
+	return buf;
+}
+
+
+const char *ll_index_to_name(int idx)
+{
+	static char nbuf[16];
+
+	return ll_idx_n2a(idx, nbuf);
+}
+
+int ll_index_to_type(int idx)
+{
+	struct idxmap *im;
+
+	if (idx == 0)
+		return -1;
+	for (im = idxmap[idx&0xF]; im; im = im->next)
+		if (im->index == idx)
+			return im->type;
+	return -1;
+}
+
+unsigned ll_index_to_flags(int idx)
+{
+	struct idxmap *im;
+
+	if (idx == 0)
+		return 0;
+
+	for (im = idxmap[idx&0xF]; im; im = im->next)
+		if (im->index == idx)
+			return im->flags;
+	return 0;
+}
+
+int ll_name_to_index(char *name)
+{
+	static char ncache[16];
+	static int icache;
+	struct idxmap *im;
+	int i;
+
+	if (name == NULL)
+		return 0;
+	if (icache && strcmp(name, ncache) == 0)
+		return icache;
+	for (i=0; i<16; i++) {
+		for (im = idxmap[i]; im; im = im->next) {
+			if (strcmp(im->name, name) == 0) {
+				icache = im->index;
+				strcpy(ncache, name);
+				return im->index;
+			}
+		}
+	}
+	return 0;
+}
+
+int ll_init_map(struct rtnl_handle *rth)
+{
+	if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) {
+		perror("Cannot send dump request");
+		exit(1);
+	}
+
+	if (rtnl_dump_filter(rth, ll_remember_index, &idxmap, NULL, NULL) < 0) {
+		fprintf(stderr, "Dump terminated\n");
+		exit(1);
+	}
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_map.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_map.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_map.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,12 @@
+#ifndef __LL_MAP_H__
+#define __LL_MAP_H__ 1
+
+extern int ll_remember_index(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
+extern int ll_init_map(struct rtnl_handle *rth);
+extern int ll_name_to_index(char *name);
+extern const char *ll_index_to_name(int idx);
+extern const char *ll_idx_n2a(int idx, char *buf);
+extern int ll_index_to_type(int idx);
+extern unsigned ll_index_to_flags(int idx);
+
+#endif /* __LL_MAP_H__ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_proto.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_proto.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_proto.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,121 @@
+/*
+ * ll_proto.c
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ */
+
+#include "libbb.h"
+#include <string.h>
+
+#include "rt_names.h"
+#include "utils.h"
+
+#if __GLIBC__ >=2 && __GLIBC_MINOR >= 1
+#include <net/ethernet.h>
+#else
+#include <linux/if_ether.h>
+#endif
+
+#define __PF(f,n) { ETH_P_##f, #n },
+static struct {
+	int id;
+	char *name;
+} llproto_names[] = {
+__PF(LOOP,loop)
+__PF(PUP,pup)
+#ifdef ETH_P_PUPAT
+__PF(PUPAT,pupat)
+#endif
+__PF(IP,ip)
+__PF(X25,x25)
+__PF(ARP,arp)
+__PF(BPQ,bpq)
+#ifdef ETH_P_IEEEPUP
+__PF(IEEEPUP,ieeepup)
+#endif
+#ifdef ETH_P_IEEEPUPAT
+__PF(IEEEPUPAT,ieeepupat)
+#endif
+__PF(DEC,dec)
+__PF(DNA_DL,dna_dl)
+__PF(DNA_RC,dna_rc)
+__PF(DNA_RT,dna_rt)
+__PF(LAT,lat)
+__PF(DIAG,diag)
+__PF(CUST,cust)
+__PF(SCA,sca)
+__PF(RARP,rarp)
+__PF(ATALK,atalk)
+__PF(AARP,aarp)
+__PF(IPX,ipx)
+__PF(IPV6,ipv6)
+#ifdef ETH_P_PPP_DISC
+__PF(PPP_DISC,ppp_disc)
+#endif
+#ifdef ETH_P_PPP_SES
+__PF(PPP_SES,ppp_ses)
+#endif
+#ifdef ETH_P_ATMMPOA
+__PF(ATMMPOA,atmmpoa)
+#endif
+#ifdef ETH_P_ATMFATE
+__PF(ATMFATE,atmfate)
+#endif
+
+__PF(802_3,802_3)
+__PF(AX25,ax25)
+__PF(ALL,all)
+__PF(802_2,802_2)
+__PF(SNAP,snap)
+__PF(DDCMP,ddcmp)
+__PF(WAN_PPP,wan_ppp)
+__PF(PPP_MP,ppp_mp)
+__PF(LOCALTALK,localtalk)
+__PF(PPPTALK,ppptalk)
+__PF(TR_802_2,tr_802_2)
+__PF(MOBITEX,mobitex)
+__PF(CONTROL,control)
+__PF(IRDA,irda)
+#ifdef ETH_P_ECONET
+__PF(ECONET,econet)
+#endif
+
+{ 0x8100, "802.1Q" },
+{ ETH_P_IP, "ipv4" },
+};
+#undef __PF
+
+
+const char * ll_proto_n2a(unsigned short id, char *buf, int len)
+{
+	int i;
+
+	id = ntohs(id);
+
+	for (i=0; i<sizeof(llproto_names)/sizeof(llproto_names[0]); i++) {
+		 if (llproto_names[i].id == id)
+			return llproto_names[i].name;
+	}
+	snprintf(buf, len, "[%d]", id);
+	return buf;
+}
+
+int ll_proto_a2n(unsigned short *id, char *buf)
+{
+	int i;
+	for (i=0; i<sizeof(llproto_names)/sizeof(llproto_names[0]); i++) {
+		 if (strcasecmp(llproto_names[i].name, buf) == 0) {
+			 *id = htons(llproto_names[i].id);
+			 return 0;
+		 }
+	}
+	if (get_u16(id, buf, 0))
+		return -1;
+	*id = htons(*id);
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_types.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_types.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/ll_types.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,117 @@
+/*
+ * ll_types.c
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ */
+#include <stdio.h>
+#include <arpa/inet.h>
+
+#include <linux/if_arp.h>
+
+#include "rt_names.h"
+
+const char * ll_type_n2a(int type, char *buf, int len)
+{
+#define __PF(f,n) { ARPHRD_##f, #n },
+static struct {
+	int type;
+	char *name;
+} arphrd_names[] = {
+{ 0, "generic" },
+__PF(ETHER,ether)
+__PF(EETHER,eether)
+__PF(AX25,ax25)
+__PF(PRONET,pronet)
+__PF(CHAOS,chaos)
+#ifdef ARPHRD_IEEE802_TR
+__PF(IEEE802,ieee802)
+#else
+__PF(IEEE802,tr)
+#endif
+__PF(ARCNET,arcnet)
+__PF(APPLETLK,atalk)
+__PF(DLCI,dlci)
+#ifdef ARPHRD_ATM
+__PF(ATM,atm)
+#endif
+__PF(METRICOM,metricom)
+#ifdef ARPHRD_IEEE1394
+__PF(IEEE1394,ieee1394)
+#endif
+
+__PF(SLIP,slip)
+__PF(CSLIP,cslip)
+__PF(SLIP6,slip6)
+__PF(CSLIP6,cslip6)
+__PF(RSRVD,rsrvd)
+__PF(ADAPT,adapt)
+__PF(ROSE,rose)
+__PF(X25,x25)
+#ifdef ARPHRD_HWX25
+__PF(HWX25,hwx25)
+#endif
+__PF(PPP,ppp)
+__PF(HDLC,hdlc)
+__PF(LAPB,lapb)
+#ifdef ARPHRD_DDCMP
+__PF(DDCMP,ddcmp)
+__PF(RAWHDLC,rawhdlc)
+#endif
+
+__PF(TUNNEL,ipip)
+__PF(TUNNEL6,tunnel6)
+__PF(FRAD,frad)
+__PF(SKIP,skip)
+__PF(LOOPBACK,loopback)
+__PF(LOCALTLK,ltalk)
+__PF(FDDI,fddi)
+__PF(BIF,bif)
+__PF(SIT,sit)
+__PF(IPDDP,ip/ddp)
+__PF(IPGRE,gre)
+__PF(PIMREG,pimreg)
+__PF(HIPPI,hippi)
+__PF(ASH,ash)
+__PF(ECONET,econet)
+__PF(IRDA,irda)
+__PF(FCPP,fcpp)
+__PF(FCAL,fcal)
+__PF(FCPL,fcpl)
+__PF(FCFABRIC,fcfb0)
+__PF(FCFABRIC+1,fcfb1)
+__PF(FCFABRIC+2,fcfb2)
+__PF(FCFABRIC+3,fcfb3)
+__PF(FCFABRIC+4,fcfb4)
+__PF(FCFABRIC+5,fcfb5)
+__PF(FCFABRIC+6,fcfb6)
+__PF(FCFABRIC+7,fcfb7)
+__PF(FCFABRIC+8,fcfb8)
+__PF(FCFABRIC+9,fcfb9)
+__PF(FCFABRIC+10,fcfb10)
+__PF(FCFABRIC+11,fcfb11)
+__PF(FCFABRIC+12,fcfb12)
+#ifdef ARPHRD_IEEE802_TR
+__PF(IEEE802_TR,tr)
+#endif
+#ifdef ARPHRD_IEEE80211
+__PF(IEEE80211,ieee802.11)
+#endif
+#ifdef ARPHRD_VOID
+__PF(VOID,void)
+#endif
+};
+#undef __PF
+
+	int i;
+	for (i=0; i<sizeof(arphrd_names)/sizeof(arphrd_names[0]); i++) {
+		 if (arphrd_names[i].type == type)
+			return arphrd_names[i].name;
+	}
+	snprintf(buf, len, "[%d]", type);
+	return buf;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/rt_names.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/rt_names.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/rt_names.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,305 @@
+/*
+ * rt_names.c		rtnetlink names DB.
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <stdint.h>
+#include "rt_names.h"
+
+static void rtnl_tab_initialize(char *file, char **tab, int size)
+{
+	char buf[512];
+	FILE *fp;
+
+	fp = fopen(file, "r");
+	if (!fp)
+		return;
+	while (fgets(buf, sizeof(buf), fp)) {
+		char *p = buf;
+		int id;
+		char namebuf[512];
+
+		while (*p == ' ' || *p == '\t')
+			p++;
+		if (*p == '#' || *p == '\n' || *p == 0)
+			continue;
+		if (sscanf(p, "0x%x %s\n", &id, namebuf) != 2 &&
+		    sscanf(p, "0x%x %s #", &id, namebuf) != 2 &&
+		    sscanf(p, "%d %s\n", &id, namebuf) != 2 &&
+		    sscanf(p, "%d %s #", &id, namebuf) != 2) {
+			fprintf(stderr, "Database %s is corrupted at %s\n",
+				file, p);
+			return;
+		}
+
+		if (id<0 || id>size)
+			continue;
+
+		tab[id] = strdup(namebuf);
+	}
+	fclose(fp);
+}
+
+
+static char * rtnl_rtprot_tab[256] = {
+	"none",
+	"redirect",
+	"kernel",
+	"boot",
+	"static",
+	NULL,
+	NULL,
+	NULL,
+	"gated",
+	"ra",
+	"mrt",
+	"zebra",
+	"bird",
+};
+
+
+
+static int rtnl_rtprot_init;
+
+static void rtnl_rtprot_initialize(void)
+{
+	rtnl_rtprot_init = 1;
+	rtnl_tab_initialize("/etc/iproute2/rt_protos",
+			    rtnl_rtprot_tab, 256);
+}
+
+const char * rtnl_rtprot_n2a(int id, char *buf, int len)
+{
+	if (id<0 || id>=256) {
+		snprintf(buf, len, "%d", id);
+		return buf;
+	}
+	if (!rtnl_rtprot_tab[id]) {
+		if (!rtnl_rtprot_init)
+			rtnl_rtprot_initialize();
+	}
+	if (rtnl_rtprot_tab[id])
+		return rtnl_rtprot_tab[id];
+	snprintf(buf, len, "%d", id);
+	return buf;
+}
+
+int rtnl_rtprot_a2n(uint32_t *id, char *arg)
+{
+	static char *cache = NULL;
+	static unsigned long res;
+	char *end;
+	int i;
+
+	if (cache && strcmp(cache, arg) == 0) {
+		*id = res;
+		return 0;
+	}
+
+	if (!rtnl_rtprot_init)
+		rtnl_rtprot_initialize();
+
+	for (i=0; i<256; i++) {
+		if (rtnl_rtprot_tab[i] &&
+		    strcmp(rtnl_rtprot_tab[i], arg) == 0) {
+			cache = rtnl_rtprot_tab[i];
+			res = i;
+			*id = res;
+			return 0;
+		}
+	}
+
+	res = strtoul(arg, &end, 0);
+	if (!end || end == arg || *end || res > 255)
+		return -1;
+	*id = res;
+	return 0;
+}
+
+
+
+static char * rtnl_rtscope_tab[256] = {
+	"global",
+};
+
+static int rtnl_rtscope_init;
+
+static void rtnl_rtscope_initialize(void)
+{
+	rtnl_rtscope_init = 1;
+	rtnl_rtscope_tab[255] = "nowhere";
+	rtnl_rtscope_tab[254] = "host";
+	rtnl_rtscope_tab[253] = "link";
+	rtnl_rtscope_tab[200] = "site";
+	rtnl_tab_initialize("/etc/iproute2/rt_scopes",
+			    rtnl_rtscope_tab, 256);
+}
+
+const char * rtnl_rtscope_n2a(int id, char *buf, int len)
+{
+	if (id<0 || id>=256) {
+		snprintf(buf, len, "%d", id);
+		return buf;
+	}
+	if (!rtnl_rtscope_tab[id]) {
+		if (!rtnl_rtscope_init)
+			rtnl_rtscope_initialize();
+	}
+	if (rtnl_rtscope_tab[id])
+		return rtnl_rtscope_tab[id];
+	snprintf(buf, len, "%d", id);
+	return buf;
+}
+
+int rtnl_rtscope_a2n(uint32_t *id, char *arg)
+{
+	static char *cache = NULL;
+	static unsigned long res;
+	char *end;
+	int i;
+
+	if (cache && strcmp(cache, arg) == 0) {
+		*id = res;
+		return 0;
+	}
+
+	if (!rtnl_rtscope_init)
+		rtnl_rtscope_initialize();
+
+	for (i=0; i<256; i++) {
+		if (rtnl_rtscope_tab[i] &&
+		    strcmp(rtnl_rtscope_tab[i], arg) == 0) {
+			cache = rtnl_rtscope_tab[i];
+			res = i;
+			*id = res;
+			return 0;
+		}
+	}
+
+	res = strtoul(arg, &end, 0);
+	if (!end || end == arg || *end || res > 255)
+		return -1;
+	*id = res;
+	return 0;
+}
+
+
+
+static char * rtnl_rtrealm_tab[256] = {
+	"unknown",
+};
+
+static int rtnl_rtrealm_init;
+
+static void rtnl_rtrealm_initialize(void)
+{
+	rtnl_rtrealm_init = 1;
+	rtnl_tab_initialize("/etc/iproute2/rt_realms",
+			    rtnl_rtrealm_tab, 256);
+}
+
+int rtnl_rtrealm_a2n(uint32_t *id, char *arg)
+{
+	static char *cache = NULL;
+	static unsigned long res;
+	char *end;
+	int i;
+
+	if (cache && strcmp(cache, arg) == 0) {
+		*id = res;
+		return 0;
+	}
+
+	if (!rtnl_rtrealm_init)
+		rtnl_rtrealm_initialize();
+
+	for (i=0; i<256; i++) {
+		if (rtnl_rtrealm_tab[i] &&
+		    strcmp(rtnl_rtrealm_tab[i], arg) == 0) {
+			cache = rtnl_rtrealm_tab[i];
+			res = i;
+			*id = res;
+			return 0;
+		}
+	}
+
+	res = strtoul(arg, &end, 0);
+	if (!end || end == arg || *end || res > 255)
+		return -1;
+	*id = res;
+	return 0;
+}
+
+
+
+static char * rtnl_rtdsfield_tab[256] = {
+	"0",
+};
+
+static int rtnl_rtdsfield_init;
+
+static void rtnl_rtdsfield_initialize(void)
+{
+	rtnl_rtdsfield_init = 1;
+	rtnl_tab_initialize("/etc/iproute2/rt_dsfield",
+			    rtnl_rtdsfield_tab, 256);
+}
+
+const char * rtnl_dsfield_n2a(int id, char *buf, int len)
+{
+	if (id<0 || id>=256) {
+		snprintf(buf, len, "%d", id);
+		return buf;
+	}
+	if (!rtnl_rtdsfield_tab[id]) {
+		if (!rtnl_rtdsfield_init)
+			rtnl_rtdsfield_initialize();
+	}
+	if (rtnl_rtdsfield_tab[id])
+		return rtnl_rtdsfield_tab[id];
+	snprintf(buf, len, "0x%02x", id);
+	return buf;
+}
+
+
+int rtnl_dsfield_a2n(uint32_t *id, char *arg)
+{
+	static char *cache = NULL;
+	static unsigned long res;
+	char *end;
+	int i;
+
+	if (cache && strcmp(cache, arg) == 0) {
+		*id = res;
+		return 0;
+	}
+
+	if (!rtnl_rtdsfield_init)
+		rtnl_rtdsfield_initialize();
+
+	for (i=0; i<256; i++) {
+		if (rtnl_rtdsfield_tab[i] &&
+		    strcmp(rtnl_rtdsfield_tab[i], arg) == 0) {
+			cache = rtnl_rtdsfield_tab[i];
+			res = i;
+			*id = res;
+			return 0;
+		}
+	}
+
+	res = strtoul(arg, &end, 16);
+	if (!end || end == arg || *end || res > 255)
+		return -1;
+	*id = res;
+	return 0;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/rt_names.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/rt_names.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/rt_names.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,25 @@
+#ifndef RT_NAMES_H_
+#define RT_NAMES_H_ 1
+
+#include <stdint.h>
+
+extern const char* rtnl_rtprot_n2a(int id, char *buf, int len);
+extern const char* rtnl_rtscope_n2a(int id, char *buf, int len);
+extern const char* rtnl_dsfield_n2a(int id, char *buf, int len);
+extern int rtnl_rtprot_a2n(uint32_t *id, char *arg);
+extern int rtnl_rtscope_a2n(uint32_t *id, char *arg);
+extern int rtnl_rtrealm_a2n(uint32_t *id, char *arg);
+extern int rtnl_dsfield_a2n(uint32_t *id, char *arg);
+
+
+extern const char * ll_type_n2a(int type, char *buf, int len);
+
+extern const char *ll_addr_n2a(unsigned char *addr, int alen, int type,
+				char *buf, int blen);
+extern int ll_addr_a2n(unsigned char *lladdr, int len, char *arg);
+
+extern const char * ll_proto_n2a(unsigned short id, char *buf, int len);
+extern int ll_proto_a2n(unsigned short *id, char *buf);
+
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/rtm_map.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/rtm_map.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/rtm_map.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,110 @@
+/*
+ * rtm_map.c
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "rt_names.h"
+#include "utils.h"
+
+char *rtnl_rtntype_n2a(int id, char *buf, int len)
+{
+	switch (id) {
+	case RTN_UNSPEC:
+		return "none";
+	case RTN_UNICAST:
+		return "unicast";
+	case RTN_LOCAL:
+		return "local";
+	case RTN_BROADCAST:
+		return "broadcast";
+	case RTN_ANYCAST:
+		return "anycast";
+	case RTN_MULTICAST:
+		return "multicast";
+	case RTN_BLACKHOLE:
+		return "blackhole";
+	case RTN_UNREACHABLE:
+		return "unreachable";
+	case RTN_PROHIBIT:
+		return "prohibit";
+	case RTN_THROW:
+		return "throw";
+	case RTN_NAT:
+		return "nat";
+	case RTN_XRESOLVE:
+		return "xresolve";
+	default:
+		snprintf(buf, len, "%d", id);
+		return buf;
+	}
+}
+
+
+int rtnl_rtntype_a2n(int *id, char *arg)
+{
+	char *end;
+	unsigned long res;
+
+	if (strcmp(arg, "local") == 0)
+		res = RTN_LOCAL;
+	else if (strcmp(arg, "nat") == 0)
+		res = RTN_NAT;
+	else if (matches(arg, "broadcast") == 0 ||
+		 strcmp(arg, "brd") == 0)
+		res = RTN_BROADCAST;
+	else if (matches(arg, "anycast") == 0)
+		res = RTN_ANYCAST;
+	else if (matches(arg, "multicast") == 0)
+		res = RTN_MULTICAST;
+	else if (matches(arg, "prohibit") == 0)
+		res = RTN_PROHIBIT;
+	else if (matches(arg, "unreachable") == 0)
+		res = RTN_UNREACHABLE;
+	else if (matches(arg, "blackhole") == 0)
+		res = RTN_BLACKHOLE;
+	else if (matches(arg, "xresolve") == 0)
+		res = RTN_XRESOLVE;
+	else if (matches(arg, "unicast") == 0)
+		res = RTN_UNICAST;
+	else if (strcmp(arg, "throw") == 0)
+		res = RTN_THROW;
+	else {
+		res = strtoul(arg, &end, 0);
+		if (!end || end == arg || *end || res > 255)
+			return -1;
+	}
+	*id = res;
+	return 0;
+}
+
+int get_rt_realms(__u32 *realms, char *arg)
+{
+	__u32 realm = 0;
+	char *p = strchr(arg, '/');
+
+	*realms = 0;
+	if (p) {
+		*p = 0;
+		if (rtnl_rtrealm_a2n(realms, arg)) {
+			*p = '/';
+			return -1;
+		}
+		*realms <<= 16;
+		*p = '/';
+		arg = p+1;
+	}
+	if (*arg && rtnl_rtrealm_a2n(&realm, arg))
+		return -1;
+	*realms |= realm;
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/rtm_map.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/rtm_map.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/rtm_map.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,10 @@
+#ifndef __RTM_MAP_H__
+#define __RTM_MAP_H__ 1
+
+char *rtnl_rtntype_n2a(int id, char *buf, int len);
+int rtnl_rtntype_a2n(int *id, char *arg);
+
+int get_rt_realms(__u32 *realms, char *arg);
+
+
+#endif /* __RTM_MAP_H__ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/utils.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/utils.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/utils.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,356 @@
+/*
+ * utils.c
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ *
+ * Changes:
+ *
+ * Rani Assaf <rani at magic.metawire.com> 980929:	resolve addresses
+ */
+
+#include "libbb.h"
+
+#include <string.h>
+#include <unistd.h>
+
+#include "utils.h"
+#include "inet_common.h"
+
+int get_integer(int *val, char *arg, int base)
+{
+	long res;
+	char *ptr;
+
+	if (!arg || !*arg)
+		return -1;
+	res = strtol(arg, &ptr, base);
+	if (!ptr || ptr == arg || *ptr || res > INT_MAX || res < INT_MIN)
+		return -1;
+	*val = res;
+	return 0;
+}
+
+int get_unsigned(unsigned *val, char *arg, int base)
+{
+	unsigned long res;
+	char *ptr;
+
+	if (!arg || !*arg)
+		return -1;
+	res = strtoul(arg, &ptr, base);
+	if (!ptr || ptr == arg || *ptr || res > UINT_MAX)
+		return -1;
+	*val = res;
+	return 0;
+}
+
+int get_u32(__u32 * val, char *arg, int base)
+{
+	unsigned long res;
+	char *ptr;
+
+	if (!arg || !*arg)
+		return -1;
+	res = strtoul(arg, &ptr, base);
+	if (!ptr || ptr == arg || *ptr || res > 0xFFFFFFFFUL)
+		return -1;
+	*val = res;
+	return 0;
+}
+
+int get_u16(__u16 * val, char *arg, int base)
+{
+	unsigned long res;
+	char *ptr;
+
+	if (!arg || !*arg)
+		return -1;
+	res = strtoul(arg, &ptr, base);
+	if (!ptr || ptr == arg || *ptr || res > 0xFFFF)
+		return -1;
+	*val = res;
+	return 0;
+}
+
+int get_u8(__u8 * val, char *arg, int base)
+{
+	unsigned long res;
+	char *ptr;
+
+	if (!arg || !*arg)
+		return -1;
+	res = strtoul(arg, &ptr, base);
+	if (!ptr || ptr == arg || *ptr || res > 0xFF)
+		return -1;
+	*val = res;
+	return 0;
+}
+
+int get_s16(__s16 * val, char *arg, int base)
+{
+	long res;
+	char *ptr;
+
+	if (!arg || !*arg)
+		return -1;
+	res = strtol(arg, &ptr, base);
+	if (!ptr || ptr == arg || *ptr || res > 0x7FFF || res < -0x8000)
+		return -1;
+	*val = res;
+	return 0;
+}
+
+int get_s8(__s8 * val, char *arg, int base)
+{
+	long res;
+	char *ptr;
+
+	if (!arg || !*arg)
+		return -1;
+	res = strtol(arg, &ptr, base);
+	if (!ptr || ptr == arg || *ptr || res > 0x7F || res < -0x80)
+		return -1;
+	*val = res;
+	return 0;
+}
+
+int get_addr_1(inet_prefix * addr, char *name, int family)
+{
+	char *cp;
+	unsigned char *ap = (unsigned char *) addr->data;
+	int i;
+
+	memset(addr, 0, sizeof(*addr));
+
+	if (strcmp(name, bb_INET_default) == 0 ||
+		strcmp(name, "all") == 0 || strcmp(name, "any") == 0) {
+		addr->family = family;
+		addr->bytelen = (family == AF_INET6 ? 16 : 4);
+		addr->bitlen = -1;
+		return 0;
+	}
+
+	if (strchr(name, ':')) {
+		addr->family = AF_INET6;
+		if (family != AF_UNSPEC && family != AF_INET6)
+			return -1;
+		if (inet_pton(AF_INET6, name, addr->data) <= 0)
+			return -1;
+		addr->bytelen = 16;
+		addr->bitlen = -1;
+		return 0;
+	}
+
+	addr->family = AF_INET;
+	if (family != AF_UNSPEC && family != AF_INET)
+		return -1;
+	addr->bytelen = 4;
+	addr->bitlen = -1;
+	for (cp = name, i = 0; *cp; cp++) {
+		if (*cp <= '9' && *cp >= '0') {
+			ap[i] = 10 * ap[i] + (*cp - '0');
+			continue;
+		}
+		if (*cp == '.' && ++i <= 3)
+			continue;
+		return -1;
+	}
+	return 0;
+}
+
+int get_prefix_1(inet_prefix * dst, char *arg, int family)
+{
+	int err;
+	int plen;
+	char *slash;
+
+	memset(dst, 0, sizeof(*dst));
+
+	if (strcmp(arg, bb_INET_default) == 0 || strcmp(arg, "any") == 0) {
+		dst->family = family;
+		dst->bytelen = 0;
+		dst->bitlen = 0;
+		return 0;
+	}
+
+	slash = strchr(arg, '/');
+	if (slash)
+		*slash = 0;
+	err = get_addr_1(dst, arg, family);
+	if (err == 0) {
+		switch (dst->family) {
+		case AF_INET6:
+			dst->bitlen = 128;
+			break;
+		default:
+		case AF_INET:
+			dst->bitlen = 32;
+		}
+		if (slash) {
+			if (get_integer(&plen, slash + 1, 0) || plen > dst->bitlen) {
+				err = -1;
+				goto done;
+			}
+			dst->bitlen = plen;
+		}
+	}
+  done:
+	if (slash)
+		*slash = '/';
+	return err;
+}
+
+int get_addr(inet_prefix * dst, char *arg, int family)
+{
+	if (family == AF_PACKET) {
+		bb_error_msg_and_die("\"%s\" may be inet address, but it is not allowed in this context.", arg);
+	}
+	if (get_addr_1(dst, arg, family)) {
+		bb_error_msg_and_die("an inet address is expected rather than \"%s\".", arg);
+	}
+	return 0;
+}
+
+int get_prefix(inet_prefix * dst, char *arg, int family)
+{
+	if (family == AF_PACKET) {
+		bb_error_msg_and_die("\"%s\" may be inet address, but it is not allowed in this context.", arg);
+	}
+	if (get_prefix_1(dst, arg, family)) {
+		bb_error_msg_and_die("an inet address is expected rather than \"%s\".", arg);
+	}
+	return 0;
+}
+
+__u32 get_addr32(char *name)
+{
+	inet_prefix addr;
+
+	if (get_addr_1(&addr, name, AF_INET)) {
+		bb_error_msg_and_die("an IP address is expected rather than \"%s\"", name);
+	}
+	return addr.data[0];
+}
+
+void incomplete_command(void)
+{
+	bb_error_msg("Command line is not complete. Try option \"help\"");
+	exit(-1);
+}
+
+void invarg(const char * const arg, const char * const opt)
+{
+	bb_error_msg(bb_msg_invalid_arg, arg, opt);
+	exit(-1);
+}
+
+void duparg(char *key, char *arg)
+{
+	bb_error_msg("duplicate \"%s\": \"%s\" is the second value.", key, arg);
+	exit(-1);
+}
+
+void duparg2(char *key, char *arg)
+{
+	bb_error_msg("either \"%s\" is duplicate, or \"%s\" is a garbage.", key, arg);
+	exit(-1);
+}
+
+int matches(char *cmd, char *pattern)
+{
+	int len = strlen(cmd);
+
+	if (len > strlen(pattern)) {
+		return -1;
+	}
+	return memcmp(pattern, cmd, len);
+}
+
+int inet_addr_match(inet_prefix * a, inet_prefix * b, int bits)
+{
+	__u32 *a1 = a->data;
+	__u32 *a2 = b->data;
+	int words = bits >> 0x05;
+
+	bits &= 0x1f;
+
+	if (words)
+		if (memcmp(a1, a2, words << 2))
+			return -1;
+
+	if (bits) {
+		__u32 w1, w2;
+		__u32 mask;
+
+		w1 = a1[words];
+		w2 = a2[words];
+
+		mask = htonl((0xffffffff) << (0x20 - bits));
+
+		if ((w1 ^ w2) & mask)
+			return 1;
+	}
+
+	return 0;
+}
+
+int __iproute2_hz_internal;
+
+int __get_hz(void)
+{
+	int hz = 0;
+	FILE *fp = fopen("/proc/net/psched", "r");
+
+	if (fp) {
+		unsigned nom, denom;
+
+		if (fscanf(fp, "%*08x%*08x%08x%08x", &nom, &denom) == 2)
+			if (nom == 1000000)
+				hz = denom;
+		fclose(fp);
+	}
+	if (hz)
+		return hz;
+	return sysconf(_SC_CLK_TCK);
+}
+
+const char *rt_addr_n2a(int af, int ATTRIBUTE_UNUSED len,
+		void *addr, char *buf, int buflen)
+{
+	switch (af) {
+	case AF_INET:
+	case AF_INET6:
+		return inet_ntop(af, addr, buf, buflen);
+	default:
+		return "???";
+	}
+}
+
+
+const char *format_host(int af, int len, void *addr, char *buf, int buflen)
+{
+#ifdef RESOLVE_HOSTNAMES
+	if (resolve_hosts) {
+		struct hostent *h_ent;
+
+		if (len <= 0) {
+			switch (af) {
+			case AF_INET:
+				len = 4;
+				break;
+			case AF_INET6:
+				len = 16;
+				break;
+			default:;
+			}
+		}
+		if (len > 0 && (h_ent = gethostbyaddr(addr, len, af)) != NULL) {
+			snprintf(buf, buflen - 1, "%s", h_ent->h_name);
+			return buf;
+		}
+	}
+#endif
+	return rt_addr_n2a(af, len, addr, buf, buflen);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/utils.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/utils.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/libiproute/utils.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,102 @@
+#ifndef __UTILS_H__
+#define __UTILS_H__ 1
+
+#include "libbb.h"
+#include <asm/types.h>
+#include <resolv.h>
+
+#include "libnetlink.h"
+#include "ll_map.h"
+#include "rtm_map.h"
+
+extern int preferred_family;
+extern int show_stats;
+extern int show_details;
+extern int show_raw;
+extern int resolve_hosts;
+extern int oneline;
+extern char * _SL_;
+
+#ifndef IPPROTO_ESP
+#define IPPROTO_ESP	50
+#endif
+#ifndef IPPROTO_AH
+#define IPPROTO_AH	51
+#endif
+
+#define SPRINT_BSIZE 64
+#define SPRINT_BUF(x)	char x[SPRINT_BSIZE]
+
+extern void incomplete_command(void) ATTRIBUTE_NORETURN;
+
+#define NEXT_ARG() do { argv++; if (--argc <= 0) incomplete_command(); } while(0)
+
+typedef struct
+{
+	__u8 family;
+	__u8 bytelen;
+	__s16 bitlen;
+	__u32 data[4];
+} inet_prefix;
+
+#define DN_MAXADDL 20
+#ifndef AF_DECnet
+#define AF_DECnet 12
+#endif
+
+struct dn_naddr
+{
+	unsigned short          a_len;
+	unsigned char a_addr[DN_MAXADDL];
+};
+
+#define IPX_NODE_LEN 6
+
+struct ipx_addr {
+	uint32_t ipx_net;
+	uint8_t  ipx_node[IPX_NODE_LEN];
+};
+
+extern __u32 get_addr32(char *name);
+extern int get_addr_1(inet_prefix *dst, char *arg, int family);
+extern int get_prefix_1(inet_prefix *dst, char *arg, int family);
+extern int get_addr(inet_prefix *dst, char *arg, int family);
+extern int get_prefix(inet_prefix *dst, char *arg, int family);
+
+extern int get_integer(int *val, char *arg, int base);
+extern int get_unsigned(unsigned *val, char *arg, int base);
+#define get_byte get_u8
+#define get_ushort get_u16
+#define get_short get_s16
+extern int get_u32(__u32 *val, char *arg, int base);
+extern int get_u16(__u16 *val, char *arg, int base);
+extern int get_s16(__s16 *val, char *arg, int base);
+extern int get_u8(__u8 *val, char *arg, int base);
+extern int get_s8(__s8 *val, char *arg, int base);
+
+extern const char *format_host(int af, int len, void *addr, char *buf, int buflen);
+extern const char *rt_addr_n2a(int af, int len, void *addr, char *buf, int buflen);
+
+void invarg(const char * const, const char * const) ATTRIBUTE_NORETURN;
+void duparg(char *, char *) ATTRIBUTE_NORETURN;
+void duparg2(char *, char *) ATTRIBUTE_NORETURN;
+int matches(char *arg, char *pattern);
+extern int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits);
+
+const char *dnet_ntop(int af, const void *addr, char *str, size_t len);
+int dnet_pton(int af, const char *src, void *addr);
+
+const char *ipx_ntop(int af, const void *addr, char *str, size_t len);
+int ipx_pton(int af, const char *src, void *addr);
+
+extern int __iproute2_hz_internal;
+extern int __get_hz(void);
+
+static __inline__ int get_hz(void)
+{
+	if (__iproute2_hz_internal == 0)
+		__iproute2_hz_internal = __get_hz();
+	return __iproute2_hz_internal;
+}
+
+#endif /* __UTILS_H__ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/nameif.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/nameif.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/nameif.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,195 @@
+/*
+ * nameif.c - Naming Interfaces based on MAC address for busybox.
+ *
+ * Written 2000 by Andi Kleen.
+ * Busybox port 2002 by Nick Fedchik <nick at fedchik.org.ua>
+ *			Glenn McGrath <bug1 at iinet.net.au>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+
+#include <sys/syslog.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <net/if.h>
+#include <netinet/ether.h>
+
+
+/* Older versions of net/if.h do not appear to define IF_NAMESIZE. */
+#ifndef IF_NAMESIZE
+#  ifdef IFNAMSIZ
+#    define IF_NAMESIZE IFNAMSIZ
+#  else
+#    define IF_NAMESIZE 16
+#  endif
+#endif
+
+/* take from linux/sockios.h */
+#define SIOCSIFNAME	0x8923	/* set interface name */
+
+/* Octets in one Ethernet addr, from <linux/if_ether.h> */
+#define ETH_ALEN	6
+
+#ifndef ifr_newname
+#define ifr_newname ifr_ifru.ifru_slave
+#endif
+
+typedef struct mactable_s {
+	struct mactable_s *next;
+	struct mactable_s *prev;
+	char *ifname;
+	struct ether_addr *mac;
+} mactable_t;
+
+static unsigned long flags;
+
+static void serror(const char *s, ...) ATTRIBUTE_NORETURN;
+
+static void serror(const char *s, ...)
+{
+	va_list ap;
+
+	va_start(ap, s);
+
+	if (flags & 1) {
+		openlog(bb_applet_name, 0, LOG_LOCAL0);
+		vsyslog(LOG_ERR, s, ap);
+		closelog();
+	} else {
+		bb_verror_msg(s, ap);
+		putc('\n', stderr);
+	}
+	va_end(ap);
+
+	exit(EXIT_FAILURE);
+}
+
+/* Check ascii str_macaddr, convert and copy to *mac */
+static struct ether_addr *cc_macaddr(const char *str_macaddr)
+{
+	struct ether_addr *lmac, *mac;
+
+	lmac = ether_aton(str_macaddr);
+	if (lmac == NULL)
+		serror("cannot parse MAC %s", str_macaddr);
+	mac = xmalloc(ETH_ALEN);
+	memcpy(mac, lmac, ETH_ALEN);
+
+	return mac;
+}
+
+int nameif_main(int argc, char **argv)
+{
+	mactable_t *clist = NULL;
+	FILE *ifh;
+	const char *fname = "/etc/mactab";
+	char *line;
+	int ctl_sk;
+	int if_index = 1;
+	mactable_t *ch;
+
+	flags = bb_getopt_ulflags(argc, argv, "sc:", &fname);
+
+	if ((argc - optind) & 1)
+		bb_show_usage();
+
+	if (optind < argc) {
+		char **a = argv + optind;
+
+		while (*a) {
+
+			if (strlen(*a) > IF_NAMESIZE)
+				serror("interface name `%s' too long", *a);
+			ch = xzalloc(sizeof(mactable_t));
+			ch->ifname = bb_xstrdup(*a++);
+			ch->mac = cc_macaddr(*a++);
+			if (clist)
+				clist->prev = ch;
+			ch->next = clist;
+			clist = ch;
+		}
+	} else {
+		ifh = bb_xfopen(fname, "r");
+
+		while ((line = bb_get_line_from_file(ifh)) != NULL) {
+			char *line_ptr;
+			size_t name_length;
+
+			line_ptr = line + strspn(line, " \t");
+			if ((line_ptr[0] == '#') || (line_ptr[0] == '\n')) {
+				free(line);
+				continue;
+			}
+			name_length = strcspn(line_ptr, " \t");
+			ch = xzalloc(sizeof(mactable_t));
+			ch->ifname = bb_xstrndup(line_ptr, name_length);
+			if (name_length > IF_NAMESIZE)
+				serror("interface name `%s' too long", ch->ifname);
+			line_ptr += name_length;
+			line_ptr += strspn(line_ptr, " \t");
+			name_length = strspn(line_ptr, "0123456789ABCDEFabcdef:");
+			line_ptr[name_length] = '\0';
+			ch->mac = cc_macaddr(line_ptr);
+			if (clist)
+				clist->prev = ch;
+			ch->next = clist;
+			clist = ch;
+			free(line);
+		}
+		fclose(ifh);
+	}
+
+	if ((ctl_sk = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
+		serror("socket: %m");
+
+	while (clist) {
+		struct ifreq ifr;
+
+		memset(&ifr, 0, sizeof(struct ifreq));
+		if_index++;
+		ifr.ifr_ifindex = if_index;
+
+		/* Get ifname by index or die */
+		if (ioctl(ctl_sk, SIOCGIFNAME, &ifr))
+			break;
+
+		/* Has this device hwaddr? */
+		if (ioctl(ctl_sk, SIOCGIFHWADDR, &ifr))
+			continue;
+
+		/* Search for mac like in ifr.ifr_hwaddr.sa_data */
+		for (ch = clist; ch; ch = ch->next)
+			if (!memcmp(ch->mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN))
+				break;
+
+		/* Nothing found for current ifr.ifr_hwaddr.sa_data */
+		if (ch == NULL)
+			continue;
+
+		strcpy(ifr.ifr_newname, ch->ifname);
+		if (ioctl(ctl_sk, SIOCSIFNAME, &ifr) < 0)
+			serror("cannot change ifname %s to %s: %m",
+				   ifr.ifr_name, ch->ifname);
+
+		/* Remove list entry of renamed interface */
+		if (ch->prev != NULL) {
+			(ch->prev)->next = ch->next;
+		} else {
+			clist = ch->next;
+		}
+		if (ch->next != NULL)
+			(ch->next)->prev = ch->prev;
+		if (ENABLE_FEATURE_CLEAN_UP) {
+			free(ch->ifname);
+			free(ch->mac);
+			free(ch);
+		}
+	}
+
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/nc.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/nc.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/nc.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,173 @@
+/* vi: set sw=4 ts=4: */
+/*  nc: mini-netcat - built from the ground up for LRP
+    Copyright (C) 1998  Charles P. Wright
+
+    0.0.1   6K      It works.
+    0.0.2   5K      Smaller and you can also check the exit condition if you wish.
+    0.0.3           Uses select()
+
+    19980918 Busy Boxed! Dave Cinege
+    19990512 Uses Select. Charles P. Wright
+    19990513 Fixes stdin stupidity and uses buffers.  Charles P. Wright
+
+    Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/ioctl.h>
+#include "busybox.h"
+
+static void timeout(int signum)
+{
+	bb_error_msg_and_die("Timed out");
+}
+
+int nc_main(int argc, char **argv)
+{
+	int do_listen = 0, lport = 0, delay = 0, wsecs = 0, tmpfd, opt, sfd, x;
+
+#ifdef CONFIG_NC_GAPING_SECURITY_HOLE
+	char *pr00gie = NULL;
+#endif
+
+	struct sockaddr_in address;
+	struct hostent *hostinfo;
+
+	fd_set readfds, testfds;
+
+	while ((opt = getopt(argc, argv, "lp:i:e:w:")) > 0) {
+		switch (opt) {
+			case 'l':
+				do_listen++;
+				break;
+			case 'p':
+				lport = bb_lookup_port(optarg, "tcp", 0);
+				break;
+			case 'i':
+				delay = atoi(optarg);
+				break;
+#ifdef CONFIG_NC_GAPING_SECURITY_HOLE
+			case 'e':
+				pr00gie = optarg;
+				break;
+#endif
+			case 'w':
+				wsecs = atoi(optarg);
+				break;
+			default:
+				bb_show_usage();
+		}
+	}
+
+	if ((do_listen && optind != argc) || (!do_listen && optind + 2 != argc))
+		bb_show_usage();
+
+	sfd = bb_xsocket(AF_INET, SOCK_STREAM, 0);
+	x = 1;
+	if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x)) == -1)
+		bb_perror_msg_and_die("reuseaddr");
+	address.sin_family = AF_INET;
+
+	if (wsecs) {
+		signal(SIGALRM, timeout);
+		alarm(wsecs);
+	}
+
+	if (lport != 0) {
+		memset(&address.sin_addr, 0, sizeof(address.sin_addr));
+		address.sin_port = lport;
+
+		bb_xbind(sfd, (struct sockaddr *) &address, sizeof(address));
+	}
+
+	if (do_listen) {
+		socklen_t addrlen = sizeof(address);
+
+		bb_xlisten(sfd, 1);
+		if ((tmpfd = accept(sfd, (struct sockaddr *) &address, &addrlen)) < 0)
+			bb_perror_msg_and_die("accept");
+
+		close(sfd);
+		sfd = tmpfd;
+	} else {
+		hostinfo = xgethostbyname(argv[optind]);
+
+		address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list;
+		address.sin_port = bb_lookup_port(argv[optind+1], "tcp", 0);
+
+		if (connect(sfd, (struct sockaddr *) &address, sizeof(address)) < 0)
+			bb_perror_msg_and_die("connect");
+	}
+
+	if (wsecs) {
+		alarm(0);
+		signal(SIGALRM, SIG_DFL);
+	}
+
+#ifdef CONFIG_NC_GAPING_SECURITY_HOLE
+	/* -e given? */
+	if (pr00gie) {
+		dup2(sfd, 0);
+		close(sfd);
+		dup2(0, 1);
+		dup2(0, 2);
+		execl(pr00gie, pr00gie, NULL);
+		/* Don't print stuff or it will go over the wire.... */
+		_exit(-1);
+	}
+#endif /* CONFIG_NC_GAPING_SECURITY_HOLE */
+
+	FD_ZERO(&readfds);
+	FD_SET(sfd, &readfds);
+	FD_SET(STDIN_FILENO, &readfds);
+
+	while (1) {
+		int fd;
+		int ofd;
+		int nread;
+
+		testfds = readfds;
+
+		if (select(FD_SETSIZE, &testfds, NULL, NULL, NULL) < 0)
+			bb_perror_msg_and_die("select");
+
+		for (fd = 0; fd < FD_SETSIZE; fd++) {
+			if (FD_ISSET(fd, &testfds)) {
+				if ((nread = safe_read(fd, bb_common_bufsiz1,
+					sizeof(bb_common_bufsiz1))) < 0)
+				{
+					bb_perror_msg_and_die(bb_msg_read_error);
+				}
+
+				if (fd == sfd) {
+					if (nread == 0)
+						exit(0);
+					ofd = STDOUT_FILENO;
+				} else {
+					if (nread <= 0) {
+						shutdown(sfd, 1 /* send */ );
+						close(STDIN_FILENO);
+						FD_CLR(STDIN_FILENO, &readfds);
+					}
+					ofd = sfd;
+				}
+
+				if (bb_full_write(ofd, bb_common_bufsiz1, nread) < 0)
+					bb_perror_msg_and_die(bb_msg_write_error);
+				if (delay > 0) {
+					sleep(delay);
+				}
+			}
+		}
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/netstat.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/netstat.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/netstat.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,661 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini netstat implementation(s) for busybox
+ * based in part on the netstat implementation from net-tools.
+ *
+ * Copyright (C) 2002 by Bart Visscher <magick at linux-fan.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * 2002-04-20
+ * IPV6 support added by Bart Visscher <magick at linux-fan.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+#include "inet_common.h"
+#include "busybox.h"
+#include "pwd_.h"
+
+#ifdef CONFIG_ROUTE
+extern void displayroutes(int noresolve, int netstatfmt);
+#endif
+
+#define NETSTAT_CONNECTED	0x01
+#define NETSTAT_LISTENING	0x02
+#define NETSTAT_NUMERIC		0x04
+#define NETSTAT_TCP			0x10
+#define NETSTAT_UDP			0x20
+#define NETSTAT_RAW			0x40
+#define NETSTAT_UNIX		0x80
+
+static int flags = NETSTAT_CONNECTED |
+			NETSTAT_TCP | NETSTAT_UDP | NETSTAT_RAW | NETSTAT_UNIX;
+
+#define PROGNAME_WIDTHs PROGNAME_WIDTH1(PROGNAME_WIDTH)
+#define PROGNAME_WIDTH1(s) PROGNAME_WIDTH2(s)
+#define PROGNAME_WIDTH2(s) #s
+
+#define PRG_HASH_SIZE 211
+
+enum {
+    TCP_ESTABLISHED = 1,
+    TCP_SYN_SENT,
+    TCP_SYN_RECV,
+    TCP_FIN_WAIT1,
+    TCP_FIN_WAIT2,
+    TCP_TIME_WAIT,
+    TCP_CLOSE,
+    TCP_CLOSE_WAIT,
+    TCP_LAST_ACK,
+    TCP_LISTEN,
+    TCP_CLOSING			/* now a valid state */
+};
+
+static const char * const tcp_state[] =
+{
+    "",
+    "ESTABLISHED",
+    "SYN_SENT",
+    "SYN_RECV",
+    "FIN_WAIT1",
+    "FIN_WAIT2",
+    "TIME_WAIT",
+    "CLOSE",
+    "CLOSE_WAIT",
+    "LAST_ACK",
+    "LISTEN",
+    "CLOSING"
+};
+
+typedef enum {
+    SS_FREE = 0,		/* not allocated                */
+    SS_UNCONNECTED,		/* unconnected to any socket    */
+    SS_CONNECTING,		/* in process of connecting     */
+    SS_CONNECTED,		/* connected to socket          */
+    SS_DISCONNECTING		/* in process of disconnecting  */
+} socket_state;
+
+#define SO_ACCEPTCON    (1<<16)	/* performed a listen           */
+#define SO_WAITDATA     (1<<17)	/* wait data to read            */
+#define SO_NOSPACE      (1<<18)	/* no space to write            */
+
+static char *itoa(unsigned int i)
+{
+	/* 21 digits plus null terminator, good for 64-bit or smaller ints */
+	static char local[22];
+	char *p = &local[21];
+	*p-- = '\0';
+	do {
+		*p-- = '0' + i % 10;
+		i /= 10;
+	} while (i > 0);
+	return p + 1;
+}
+
+static char *get_sname(int port, const char *proto, int num)
+{
+	char *str=itoa(ntohs(port));
+	if (num) {
+	} else {
+		struct servent *se=getservbyport(port,proto);
+		if (se)
+			str=se->s_name;
+	}
+	if (!port) {
+		str="*";
+	}
+	return str;
+}
+
+static void snprint_ip_port(char *ip_port, int size, struct sockaddr *addr, int port, char *proto, int numeric)
+{
+	char *port_name;
+
+#ifdef CONFIG_FEATURE_IPV6
+	if (addr->sa_family == AF_INET6) {
+		INET6_rresolve(ip_port, size, (struct sockaddr_in6 *)addr,
+					   (numeric&NETSTAT_NUMERIC) ? 0x0fff : 0);
+	} else
+#endif
+	{
+	INET_rresolve(ip_port, size, (struct sockaddr_in *)addr,
+		0x4000 | ((numeric&NETSTAT_NUMERIC) ? 0x0fff : 0),
+		0xffffffff);
+	}
+	port_name=get_sname(htons(port), proto, numeric);
+	if ((strlen(ip_port) + strlen(port_name)) > 22)
+		ip_port[22 - strlen(port_name)] = '\0';
+	ip_port+=strlen(ip_port);
+	strcat(ip_port, ":");
+	strcat(ip_port, port_name);
+}
+
+static void tcp_do_one(int lnr, const char *line)
+{
+	char local_addr[64], rem_addr[64];
+	const char *state_str;
+	char more[512];
+	int num, local_port, rem_port, d, state, timer_run, uid, timeout;
+#ifdef CONFIG_FEATURE_IPV6
+	struct sockaddr_in6 localaddr, remaddr;
+	char addr6[INET6_ADDRSTRLEN];
+	struct in6_addr in6;
+#else
+	struct sockaddr_in localaddr, remaddr;
+#endif
+	unsigned long rxq, txq, time_len, retr, inode;
+
+	if (lnr == 0)
+		return;
+
+	more[0] = '\0';
+	num = sscanf(line,
+				 "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
+				 &d, local_addr, &local_port,
+				 rem_addr, &rem_port, &state,
+				 &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
+
+	if (strlen(local_addr) > 8) {
+#ifdef CONFIG_FEATURE_IPV6
+		sscanf(local_addr, "%08X%08X%08X%08X",
+			   &in6.s6_addr32[0], &in6.s6_addr32[1],
+			   &in6.s6_addr32[2], &in6.s6_addr32[3]);
+		inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
+		inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr.sin6_addr);
+		sscanf(rem_addr, "%08X%08X%08X%08X",
+			   &in6.s6_addr32[0], &in6.s6_addr32[1],
+			   &in6.s6_addr32[2], &in6.s6_addr32[3]);
+		inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
+		inet_pton(AF_INET6, addr6, (struct sockaddr *) &remaddr.sin6_addr);
+		localaddr.sin6_family = AF_INET6;
+		remaddr.sin6_family = AF_INET6;
+#endif
+	} else {
+		sscanf(local_addr, "%X",
+			   &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
+		sscanf(rem_addr, "%X",
+			   &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
+		((struct sockaddr *) &localaddr)->sa_family = AF_INET;
+		((struct sockaddr *) &remaddr)->sa_family = AF_INET;
+	}
+
+	if (num < 10) {
+		bb_error_msg("warning, got bogus tcp line.");
+		return;
+	}
+	state_str = tcp_state[state];
+	if ((rem_port && (flags&NETSTAT_CONNECTED)) ||
+		(!rem_port && (flags&NETSTAT_LISTENING)))
+	{
+		snprint_ip_port(local_addr, sizeof(local_addr),
+						(struct sockaddr *) &localaddr, local_port,
+						"tcp", flags&NETSTAT_NUMERIC);
+
+		snprint_ip_port(rem_addr, sizeof(rem_addr),
+						(struct sockaddr *) &remaddr, rem_port,
+						"tcp", flags&NETSTAT_NUMERIC);
+
+		printf("tcp   %6ld %6ld %-23s %-23s %-12s\n",
+			   rxq, txq, local_addr, rem_addr, state_str);
+
+	}
+}
+
+static void udp_do_one(int lnr, const char *line)
+{
+	char local_addr[64], rem_addr[64];
+	char *state_str, more[512];
+	int num, local_port, rem_port, d, state, timer_run, uid, timeout;
+#ifdef CONFIG_FEATURE_IPV6
+	struct sockaddr_in6 localaddr, remaddr;
+	char addr6[INET6_ADDRSTRLEN];
+	struct in6_addr in6;
+#else
+	struct sockaddr_in localaddr, remaddr;
+#endif
+	unsigned long rxq, txq, time_len, retr, inode;
+
+	if (lnr == 0)
+		return;
+
+	more[0] = '\0';
+	num = sscanf(line,
+				 "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
+				 &d, local_addr, &local_port,
+				 rem_addr, &rem_port, &state,
+				 &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
+
+	if (strlen(local_addr) > 8) {
+#ifdef CONFIG_FEATURE_IPV6
+	/* Demangle what the kernel gives us */
+		sscanf(local_addr, "%08X%08X%08X%08X",
+			   &in6.s6_addr32[0], &in6.s6_addr32[1],
+			   &in6.s6_addr32[2], &in6.s6_addr32[3]);
+		inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
+		inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr.sin6_addr);
+		sscanf(rem_addr, "%08X%08X%08X%08X",
+			   &in6.s6_addr32[0], &in6.s6_addr32[1],
+			   &in6.s6_addr32[2], &in6.s6_addr32[3]);
+		inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
+		inet_pton(AF_INET6, addr6, (struct sockaddr *) &remaddr.sin6_addr);
+		localaddr.sin6_family = AF_INET6;
+		remaddr.sin6_family = AF_INET6;
+#endif
+	} else {
+		sscanf(local_addr, "%X",
+			   &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
+		sscanf(rem_addr, "%X",
+			   &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
+		((struct sockaddr *) &localaddr)->sa_family = AF_INET;
+		((struct sockaddr *) &remaddr)->sa_family = AF_INET;
+	}
+
+	if (num < 10) {
+		bb_error_msg("warning, got bogus udp line.");
+		return;
+	}
+	switch (state) {
+		case TCP_ESTABLISHED:
+			state_str = "ESTABLISHED";
+			break;
+
+		case TCP_CLOSE:
+			state_str = "";
+			break;
+
+		default:
+			state_str = "UNKNOWN";
+			break;
+	}
+
+#ifdef CONFIG_FEATURE_IPV6
+# define notnull(A) (((A.sin6_family == AF_INET6) &&            \
+					 ((A.sin6_addr.s6_addr32[0]) ||            \
+					  (A.sin6_addr.s6_addr32[1]) ||            \
+					  (A.sin6_addr.s6_addr32[2]) ||            \
+					  (A.sin6_addr.s6_addr32[3]))) ||          \
+					((A.sin6_family == AF_INET) &&             \
+					 ((struct sockaddr_in *) &A)->sin_addr.s_addr))
+#else
+# define notnull(A) (A.sin_addr.s_addr)
+#endif
+	if ((notnull(remaddr) && (flags&NETSTAT_CONNECTED)) ||
+		(!notnull(remaddr) && (flags&NETSTAT_LISTENING)))
+	{
+		snprint_ip_port(local_addr, sizeof(local_addr),
+						(struct sockaddr *) &localaddr, local_port,
+						"udp", flags&NETSTAT_NUMERIC);
+
+		snprint_ip_port(rem_addr, sizeof(rem_addr),
+						(struct sockaddr *) &remaddr, rem_port,
+						"udp", flags&NETSTAT_NUMERIC);
+
+		printf("udp   %6ld %6ld %-23s %-23s %-12s\n",
+			   rxq, txq, local_addr, rem_addr, state_str);
+
+	}
+}
+
+static void raw_do_one(int lnr, const char *line)
+{
+	char local_addr[64], rem_addr[64];
+	char *state_str, more[512];
+	int num, local_port, rem_port, d, state, timer_run, uid, timeout;
+#ifdef CONFIG_FEATURE_IPV6
+	struct sockaddr_in6 localaddr, remaddr;
+	char addr6[INET6_ADDRSTRLEN];
+	struct in6_addr in6;
+#else
+	struct sockaddr_in localaddr, remaddr;
+#endif
+	unsigned long rxq, txq, time_len, retr, inode;
+
+	if (lnr == 0)
+		return;
+
+	more[0] = '\0';
+	num = sscanf(line,
+				 "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
+				 &d, local_addr, &local_port,
+				 rem_addr, &rem_port, &state,
+				 &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
+
+	if (strlen(local_addr) > 8) {
+#ifdef CONFIG_FEATURE_IPV6
+		sscanf(local_addr, "%08X%08X%08X%08X",
+			   &in6.s6_addr32[0], &in6.s6_addr32[1],
+			   &in6.s6_addr32[2], &in6.s6_addr32[3]);
+		inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
+		inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr.sin6_addr);
+		sscanf(rem_addr, "%08X%08X%08X%08X",
+			   &in6.s6_addr32[0], &in6.s6_addr32[1],
+			   &in6.s6_addr32[2], &in6.s6_addr32[3]);
+		inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
+		inet_pton(AF_INET6, addr6, (struct sockaddr *) &remaddr.sin6_addr);
+		localaddr.sin6_family = AF_INET6;
+		remaddr.sin6_family = AF_INET6;
+#endif
+	} else {
+		sscanf(local_addr, "%X",
+			   &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
+		sscanf(rem_addr, "%X",
+			   &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
+		((struct sockaddr *) &localaddr)->sa_family = AF_INET;
+		((struct sockaddr *) &remaddr)->sa_family = AF_INET;
+	}
+
+	if (num < 10) {
+		bb_error_msg("warning, got bogus raw line.");
+		return;
+	}
+	state_str=itoa(state);
+
+#ifdef CONFIG_FEATURE_IPV6
+# define notnull(A) (((A.sin6_family == AF_INET6) &&            \
+					 ((A.sin6_addr.s6_addr32[0]) ||            \
+					  (A.sin6_addr.s6_addr32[1]) ||            \
+					  (A.sin6_addr.s6_addr32[2]) ||            \
+					  (A.sin6_addr.s6_addr32[3]))) ||          \
+					((A.sin6_family == AF_INET) &&             \
+					 ((struct sockaddr_in *) &A)->sin_addr.s_addr))
+#else
+# define notnull(A) (A.sin_addr.s_addr)
+#endif
+	if ((notnull(remaddr) && (flags&NETSTAT_CONNECTED)) ||
+		(!notnull(remaddr) && (flags&NETSTAT_LISTENING)))
+	{
+		snprint_ip_port(local_addr, sizeof(local_addr),
+						(struct sockaddr *) &localaddr, local_port,
+						"raw", flags&NETSTAT_NUMERIC);
+
+		snprint_ip_port(rem_addr, sizeof(rem_addr),
+						(struct sockaddr *) &remaddr, rem_port,
+						"raw", flags&NETSTAT_NUMERIC);
+
+		printf("raw   %6ld %6ld %-23s %-23s %-12s\n",
+			   rxq, txq, local_addr, rem_addr, state_str);
+
+	}
+}
+
+#define HAS_INODE 1
+
+static void unix_do_one(int nr, const char *line)
+{
+	static int has = 0;
+	char path[PATH_MAX], ss_flags[32];
+	char *ss_proto, *ss_state, *ss_type;
+	int num, state, type, inode;
+	void *d;
+	unsigned long refcnt, proto, unix_flags;
+
+	if (nr == 0) {
+		if (strstr(line, "Inode"))
+			has |= HAS_INODE;
+		return;
+	}
+	path[0] = '\0';
+	num = sscanf(line, "%p: %lX %lX %lX %X %X %d %s",
+				 &d, &refcnt, &proto, &unix_flags, &type, &state, &inode, path);
+	if (num < 6) {
+		bb_error_msg("warning, got bogus unix line.");
+		return;
+	}
+	if (!(has & HAS_INODE))
+		snprintf(path,sizeof(path),"%d",inode);
+
+	if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))!=(NETSTAT_LISTENING|NETSTAT_CONNECTED)) {
+		if ((state == SS_UNCONNECTED) && (unix_flags & SO_ACCEPTCON)) {
+			if (!(flags&NETSTAT_LISTENING))
+				return;
+		} else {
+			if (!(flags&NETSTAT_CONNECTED))
+				return;
+		}
+	}
+
+	switch (proto) {
+		case 0:
+			ss_proto = "unix";
+			break;
+
+		default:
+			ss_proto = "??";
+	}
+
+	switch (type) {
+		case SOCK_STREAM:
+			ss_type = "STREAM";
+			break;
+
+		case SOCK_DGRAM:
+			ss_type = "DGRAM";
+			break;
+
+		case SOCK_RAW:
+			ss_type = "RAW";
+			break;
+
+		case SOCK_RDM:
+			ss_type = "RDM";
+			break;
+
+		case SOCK_SEQPACKET:
+			ss_type = "SEQPACKET";
+			break;
+
+		default:
+			ss_type = "UNKNOWN";
+	}
+
+	switch (state) {
+		case SS_FREE:
+			ss_state = "FREE";
+			break;
+
+		case SS_UNCONNECTED:
+			/*
+			 * Unconnected sockets may be listening
+			 * for something.
+			 */
+			if (unix_flags & SO_ACCEPTCON) {
+				ss_state = "LISTENING";
+			} else {
+				ss_state = "";
+			}
+			break;
+
+		case SS_CONNECTING:
+			ss_state = "CONNECTING";
+			break;
+
+		case SS_CONNECTED:
+			ss_state = "CONNECTED";
+			break;
+
+		case SS_DISCONNECTING:
+			ss_state = "DISCONNECTING";
+			break;
+
+		default:
+			ss_state = "UNKNOWN";
+	}
+
+	strcpy(ss_flags, "[ ");
+	if (unix_flags & SO_ACCEPTCON)
+		strcat(ss_flags, "ACC ");
+	if (unix_flags & SO_WAITDATA)
+		strcat(ss_flags, "W ");
+	if (unix_flags & SO_NOSPACE)
+		strcat(ss_flags, "N ");
+
+	strcat(ss_flags, "]");
+
+	printf("%-5s %-6ld %-11s %-10s %-13s ",
+		   ss_proto, refcnt, ss_flags, ss_type, ss_state);
+	if (has & HAS_INODE)
+		printf("%-6d ",inode);
+	else
+		printf("-      ");
+	puts(path);
+}
+
+#define _PATH_PROCNET_UDP "/proc/net/udp"
+#define _PATH_PROCNET_UDP6 "/proc/net/udp6"
+#define _PATH_PROCNET_TCP "/proc/net/tcp"
+#define _PATH_PROCNET_TCP6 "/proc/net/tcp6"
+#define _PATH_PROCNET_RAW "/proc/net/raw"
+#define _PATH_PROCNET_RAW6 "/proc/net/raw6"
+#define _PATH_PROCNET_UNIX "/proc/net/unix"
+
+static void do_info(const char *file, const char *name, void (*proc)(int, const char *))
+{
+	char buffer[8192];
+	int lnr = 0;
+	FILE *procinfo;
+
+	procinfo = fopen(file, "r");
+	if (procinfo == NULL) {
+		if (errno != ENOENT) {
+			perror(file);
+		} else {
+		bb_error_msg("no support for `%s' on this system.", name);
+		}
+	} else {
+		do {
+			if (fgets(buffer, sizeof(buffer), procinfo))
+				(proc)(lnr++, buffer);
+		} while (!feof(procinfo));
+		fclose(procinfo);
+	}
+}
+
+/*
+ * Our main function.
+ */
+
+int netstat_main(int argc, char **argv)
+{
+	int opt;
+	int new_flags=0;
+	int showroute = 0, extended = 0;
+#ifdef CONFIG_FEATURE_IPV6
+	int inet=1;
+	int inet6=1;
+#else
+# define inet 1
+# define inet6 0
+#endif
+	while ((opt = getopt(argc, argv, "laenrtuwx")) != -1)
+		switch (opt) {
+		case 'l':
+			flags &= ~NETSTAT_CONNECTED;
+			flags |= NETSTAT_LISTENING;
+			break;
+		case 'a':
+			flags |= NETSTAT_LISTENING | NETSTAT_CONNECTED;
+			break;
+		case 'n':
+			flags |= NETSTAT_NUMERIC;
+			break;
+		case 'r':
+			showroute = 1;
+			break;
+		case 'e':
+			extended = 1;
+			break;
+		case 't':
+			new_flags |= NETSTAT_TCP;
+			break;
+		case 'u':
+			new_flags |= NETSTAT_UDP;
+			break;
+		case 'w':
+			new_flags |= NETSTAT_RAW;
+			break;
+		case 'x':
+			new_flags |= NETSTAT_UNIX;
+			break;
+		default:
+			bb_show_usage();
+		}
+	if ( showroute ) {
+#ifdef CONFIG_ROUTE
+		displayroutes ( flags & NETSTAT_NUMERIC, !extended );
+		return 0;
+#else
+		bb_error_msg_and_die( "-r (display routing table) is not compiled in." );
+#endif
+	}
+
+	if (new_flags) {
+		flags &= ~(NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW|NETSTAT_UNIX);
+		flags |= new_flags;
+	}
+	if (flags&(NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW)) {
+		printf("Active Internet connections ");	/* xxx */
+
+		if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))==(NETSTAT_LISTENING|NETSTAT_CONNECTED))
+			printf("(servers and established)");
+		else {
+			if (flags&NETSTAT_LISTENING)
+				printf("(only servers)");
+			else
+				printf("(w/o servers)");
+		}
+		printf("\nProto Recv-Q Send-Q Local Address           Foreign Address         State      \n");
+	}
+	if (inet && flags&NETSTAT_TCP)
+		do_info(_PATH_PROCNET_TCP,"AF INET (tcp)",tcp_do_one);
+#ifdef CONFIG_FEATURE_IPV6
+	if (inet6 && flags&NETSTAT_TCP)
+		do_info(_PATH_PROCNET_TCP6,"AF INET6 (tcp)",tcp_do_one);
+#endif
+	if (inet && flags&NETSTAT_UDP)
+		do_info(_PATH_PROCNET_UDP,"AF INET (udp)",udp_do_one);
+#ifdef CONFIG_FEATURE_IPV6
+	if (inet6 && flags&NETSTAT_UDP)
+		do_info(_PATH_PROCNET_UDP6,"AF INET6 (udp)",udp_do_one);
+#endif
+	if (inet && flags&NETSTAT_RAW)
+		do_info(_PATH_PROCNET_RAW,"AF INET (raw)",raw_do_one);
+#ifdef CONFIG_FEATURE_IPV6
+	if (inet6 && flags&NETSTAT_RAW)
+		do_info(_PATH_PROCNET_RAW6,"AF INET6 (raw)",raw_do_one);
+#endif
+	if (flags&NETSTAT_UNIX) {
+		printf("Active UNIX domain sockets ");
+		if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))==(NETSTAT_LISTENING|NETSTAT_CONNECTED))
+			printf("(servers and established)");
+		else {
+			if (flags&NETSTAT_LISTENING)
+				printf("(only servers)");
+			else
+				printf("(w/o servers)");
+		}
+
+		printf("\nProto RefCnt Flags       Type       State         I-Node Path\n");
+		do_info(_PATH_PROCNET_UNIX,"AF UNIX",unix_do_one);
+	}
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/nslookup.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/nslookup.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/nslookup.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,206 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini nslookup implementation for busybox
+ *
+ * Copyright (C) 1999,2000 by Lineo, inc. and John Beppu
+ * Copyright (C) 1999,2000,2001 by John Beppu <beppu at codepoet.org>
+ *
+ * Correct default name server display and explicit name server option
+ * added by Ben Zeckel <bzeckel at hmc.edu> June 2001
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <stdint.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <resolv.h>
+#include <arpa/inet.h>
+#include "busybox.h"
+
+/*
+ |  I'm only implementing non-interactive mode;
+ |  I totally forgot nslookup even had an interactive mode.
+ */
+
+/* only works for IPv4 */
+static int addr_fprint(char *addr)
+{
+	uint8_t split[4];
+	uint32_t ip;
+	uint32_t *x = (uint32_t *) addr;
+
+	ip = ntohl(*x);
+	split[0] = (ip & 0xff000000) >> 24;
+	split[1] = (ip & 0x00ff0000) >> 16;
+	split[2] = (ip & 0x0000ff00) >> 8;
+	split[3] = (ip & 0x000000ff);
+	printf("%d.%d.%d.%d", split[0], split[1], split[2], split[3]);
+	return 0;
+}
+
+/* takes the NULL-terminated array h_addr_list, and
+ * prints its contents appropriately
+ */
+static int addr_list_fprint(char **h_addr_list)
+{
+	int i, j;
+	char *addr_string = (h_addr_list[1])
+		? "Addresses: " : "Address:   ";
+
+	printf("%s ", addr_string);
+	for (i = 0, j = 0; h_addr_list[i]; i++, j++) {
+		addr_fprint(h_addr_list[i]);
+
+		/* real nslookup does this */
+		if (j == 4) {
+			if (h_addr_list[i + 1]) {
+				printf("\n          ");
+			}
+			j = 0;
+		} else {
+			if (h_addr_list[i + 1]) {
+				printf(", ");
+			}
+		}
+
+	}
+	printf("\n");
+	return 0;
+}
+
+/* print the results as nslookup would */
+static struct hostent *hostent_fprint(struct hostent *host, const char *server_host)
+{
+	if (host) {
+		printf("%s     %s\n", server_host, host->h_name);
+		addr_list_fprint(host->h_addr_list);
+	} else {
+		printf("*** Unknown host\n");
+	}
+	return host;
+}
+
+/* changes a c-string matching the perl regex \d+\.\d+\.\d+\.\d+
+ * into a uint32_t
+ */
+static uint32_t str_to_addr(const char *addr)
+{
+	uint32_t split[4];
+	uint32_t ip;
+
+	sscanf(addr, "%d.%d.%d.%d",
+		   &split[0], &split[1], &split[2], &split[3]);
+
+	/* assuming sscanf worked */
+	ip = (split[0] << 24) |
+		(split[1] << 16) | (split[2] << 8) | (split[3]);
+
+	return htonl(ip);
+}
+
+/* gethostbyaddr wrapper */
+static struct hostent *gethostbyaddr_wrapper(const char *address)
+{
+	struct in_addr addr;
+
+	addr.s_addr = str_to_addr(address);
+	return gethostbyaddr((char *) &addr, 4, AF_INET);	/* IPv4 only for now */
+}
+
+/* lookup the default nameserver and display it */
+static inline void server_print(void)
+{
+	struct sockaddr_in def = _res.nsaddr_list[0];
+	char *ip = inet_ntoa(def.sin_addr);
+
+	hostent_fprint(gethostbyaddr_wrapper(ip), "Server:");
+	printf("\n");
+}
+
+/* alter the global _res nameserver structure to use
+   an explicit dns server instead of what is in /etc/resolv.h */
+static inline void set_default_dns(char *server)
+{
+	struct in_addr server_in_addr;
+
+	if(inet_aton(server,&server_in_addr))
+	{
+		_res.nscount = 1;
+		_res.nsaddr_list[0].sin_addr = server_in_addr;
+	}
+}
+
+/* naive function to check whether char *s is an ip address */
+static int is_ip_address(const char *s)
+{
+	while (*s) {
+		if ((isdigit(*s)) || (*s == '.')) {
+			s++;
+			continue;
+		}
+		return 0;
+	}
+	return 1;
+}
+
+/* ________________________________________________________________________ */
+int nslookup_main(int argc, char **argv)
+{
+	struct hostent *host;
+
+	/*
+	* initialize DNS structure _res used in printing the default
+	* name server and in the explicit name server option feature.
+	*/
+
+	res_init();
+
+	/*
+	* We allow 1 or 2 arguments.
+	* The first is the name to be looked up and the second is an
+	* optional DNS server with which to do the lookup.
+	* More than 3 arguments is an error to follow the pattern of the
+	* standard nslookup
+	*/
+
+	if (argc < 2 || *argv[1]=='-' || argc > 3)
+		bb_show_usage();
+	else if(argc == 3)
+		set_default_dns(argv[2]);
+
+	server_print();
+	if (is_ip_address(argv[1])) {
+		host = gethostbyaddr_wrapper(argv[1]);
+	} else {
+		host = xgethostbyname(argv[1]);
+	}
+	hostent_fprint(host, "Name:  ");
+	if (host) {
+		return EXIT_SUCCESS;
+	}
+	return EXIT_FAILURE;
+}
+
+/* $Id: nslookup.c,v 1.33 2004/10/13 07:25:01 andersen Exp $ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ping.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ping.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ping.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,426 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * $Id: ping.c,v 1.56 2004/03/15 08:28:48 andersen Exp $
+ * Mini ping implementation for busybox
+ *
+ * Copyright (C) 1999 by Randolph Chung <tausq at debian.org>
+ *
+ * Adapted from the ping in netkit-base 0.10:
+ * Copyright (c) 1989 The Regents of the University of California.
+ * Derived from software contributed to Berkeley by Mike Muuss.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/times.h>
+#include <signal.h>
+
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+
+enum {
+	DEFDATALEN = 56,
+	MAXIPLEN = 60,
+	MAXICMPLEN = 76,
+	MAXPACKET = 65468,
+	MAX_DUP_CHK = (8 * 128),
+	MAXWAIT = 10,
+	PINGINTERVAL = 1		/* second */
+};
+
+#define O_QUIET         (1 << 0)
+
+#define	A(bit)		rcvd_tbl[(bit)>>3]	/* identify byte in array */
+#define	B(bit)		(1 << ((bit) & 0x07))	/* identify bit in byte */
+#define	SET(bit)	(A(bit) |= B(bit))
+#define	CLR(bit)	(A(bit) &= (~B(bit)))
+#define	TST(bit)	(A(bit) & B(bit))
+
+static void ping(const char *host);
+
+/* common routines */
+static int in_cksum(unsigned short *buf, int sz)
+{
+	int nleft = sz;
+	int sum = 0;
+	unsigned short *w = buf;
+	unsigned short ans = 0;
+
+	while (nleft > 1) {
+		sum += *w++;
+		nleft -= 2;
+	}
+
+	if (nleft == 1) {
+		*(unsigned char *) (&ans) = *(unsigned char *) w;
+		sum += ans;
+	}
+
+	sum = (sum >> 16) + (sum & 0xFFFF);
+	sum += (sum >> 16);
+	ans = ~sum;
+	return (ans);
+}
+
+/* simple version */
+#ifndef CONFIG_FEATURE_FANCY_PING
+static char *hostname = NULL;
+static void noresp(int ign)
+{
+	printf("No response from %s\n", hostname);
+	exit(EXIT_FAILURE);
+}
+
+static void ping(const char *host)
+{
+	struct hostent *h;
+	struct sockaddr_in pingaddr;
+	struct icmp *pkt;
+	int pingsock, c;
+	char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
+
+	pingsock = create_icmp_socket();
+
+	memset(&pingaddr, 0, sizeof(struct sockaddr_in));
+
+	pingaddr.sin_family = AF_INET;
+	h = xgethostbyname(host);
+	memcpy(&pingaddr.sin_addr, h->h_addr, sizeof(pingaddr.sin_addr));
+	hostname = h->h_name;
+
+	pkt = (struct icmp *) packet;
+	memset(pkt, 0, sizeof(packet));
+	pkt->icmp_type = ICMP_ECHO;
+	pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet));
+
+	c = sendto(pingsock, packet, DEFDATALEN + ICMP_MINLEN, 0,
+			   (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in));
+
+	if (c < 0) {
+		if (ENABLE_FEATURE_CLEAN_UP) close(pingsock);
+		bb_perror_msg_and_die("sendto");
+	}
+
+	signal(SIGALRM, noresp);
+	alarm(5);					/* give the host 5000ms to respond */
+	/* listen for replies */
+	while (1) {
+		struct sockaddr_in from;
+		socklen_t fromlen = sizeof(from);
+
+		if ((c = recvfrom(pingsock, packet, sizeof(packet), 0,
+						  (struct sockaddr *) &from, &fromlen)) < 0) {
+			if (errno == EINTR)
+				continue;
+			bb_perror_msg("recvfrom");
+			continue;
+		}
+		if (c >= 76) {			/* ip + icmp */
+			struct iphdr *iphdr = (struct iphdr *) packet;
+
+			pkt = (struct icmp *) (packet + (iphdr->ihl << 2));	/* skip ip hdr */
+			if (pkt->icmp_type == ICMP_ECHOREPLY)
+				break;
+		}
+	}
+	if (ENABLE_FEATURE_CLEAN_UP) close(pingsock);
+	printf("%s is alive!\n", hostname);
+	return;
+}
+
+int ping_main(int argc, char **argv)
+{
+	argc--;
+	argv++;
+	if (argc < 1)
+		bb_show_usage();
+	ping(*argv);
+	return EXIT_SUCCESS;
+}
+
+#else /* ! CONFIG_FEATURE_FANCY_PING */
+/* full(er) version */
+static struct sockaddr_in pingaddr;
+static int pingsock = -1;
+static int datalen; /* intentionally uninitialized to work around gcc bug */
+
+static long ntransmitted, nreceived, nrepeats, pingcount;
+static int myid, options;
+static unsigned long tmin = ULONG_MAX, tmax, tsum;
+static char rcvd_tbl[MAX_DUP_CHK / 8];
+
+#ifndef CONFIG_FEATURE_FANCY_PING6
+static
+#endif
+	struct hostent *hostent;
+
+static void sendping(int);
+static void pingstats(int);
+static void unpack(char *, int, struct sockaddr_in *);
+
+/**************************************************************************/
+
+static void pingstats(int junk)
+{
+	int status;
+
+	signal(SIGINT, SIG_IGN);
+
+	printf("\n--- %s ping statistics ---\n", hostent->h_name);
+	printf("%ld packets transmitted, ", ntransmitted);
+	printf("%ld packets received, ", nreceived);
+	if (nrepeats)
+		printf("%ld duplicates, ", nrepeats);
+	if (ntransmitted)
+		printf("%ld%% packet loss\n",
+			   (ntransmitted - nreceived) * 100 / ntransmitted);
+	if (nreceived)
+		printf("round-trip min/avg/max = %lu.%lu/%lu.%lu/%lu.%lu ms\n",
+			   tmin / 10, tmin % 10,
+			   (tsum / (nreceived + nrepeats)) / 10,
+			   (tsum / (nreceived + nrepeats)) % 10, tmax / 10, tmax % 10);
+	if (nreceived != 0)
+		status = EXIT_SUCCESS;
+	else
+		status = EXIT_FAILURE;
+	exit(status);
+}
+
+static void sendping(int junk)
+{
+	struct icmp *pkt;
+	int i;
+	char packet[datalen + ICMP_MINLEN];
+
+	pkt = (struct icmp *) packet;
+
+	pkt->icmp_type = ICMP_ECHO;
+	pkt->icmp_code = 0;
+	pkt->icmp_cksum = 0;
+	pkt->icmp_seq = htons(ntransmitted++);
+	pkt->icmp_id = myid;
+	CLR(ntohs(pkt->icmp_seq) % MAX_DUP_CHK);
+
+	gettimeofday((struct timeval *) &pkt->icmp_dun, NULL);
+	pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet));
+
+	i = sendto(pingsock, packet, sizeof(packet), 0,
+			   (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in));
+
+	if (i < 0)
+		bb_perror_msg_and_die("sendto");
+	else if ((size_t)i != sizeof(packet))
+		bb_error_msg_and_die("ping wrote %d chars; %d expected", i,
+			   (int)sizeof(packet));
+
+	signal(SIGALRM, sendping);
+	if (pingcount == 0 || ntransmitted < pingcount) {	/* schedule next in 1s */
+		alarm(PINGINTERVAL);
+	} else {					/* done, wait for the last ping to come back */
+		/* todo, don't necessarily need to wait so long... */
+		signal(SIGALRM, pingstats);
+		alarm(MAXWAIT);
+	}
+}
+
+static char *icmp_type_name (int id)
+{
+	switch (id) {
+	case ICMP_ECHOREPLY:		return "Echo Reply";
+	case ICMP_DEST_UNREACH:		return "Destination Unreachable";
+	case ICMP_SOURCE_QUENCH:	return "Source Quench";
+	case ICMP_REDIRECT:			return "Redirect (change route)";
+	case ICMP_ECHO:				return "Echo Request";
+	case ICMP_TIME_EXCEEDED:	return "Time Exceeded";
+	case ICMP_PARAMETERPROB:	return "Parameter Problem";
+	case ICMP_TIMESTAMP:		return "Timestamp Request";
+	case ICMP_TIMESTAMPREPLY:	return "Timestamp Reply";
+	case ICMP_INFO_REQUEST:		return "Information Request";
+	case ICMP_INFO_REPLY:		return "Information Reply";
+	case ICMP_ADDRESS:			return "Address Mask Request";
+	case ICMP_ADDRESSREPLY:		return "Address Mask Reply";
+	default:					return "unknown ICMP type";
+	}
+}
+
+static void unpack(char *buf, int sz, struct sockaddr_in *from)
+{
+	struct icmp *icmppkt;
+	struct iphdr *iphdr;
+	struct timeval tv, *tp;
+	int hlen, dupflag;
+	unsigned long triptime;
+
+	gettimeofday(&tv, NULL);
+
+	/* check IP header */
+	iphdr = (struct iphdr *) buf;
+	hlen = iphdr->ihl << 2;
+	/* discard if too short */
+	if (sz < (datalen + ICMP_MINLEN))
+		return;
+
+	sz -= hlen;
+	icmppkt = (struct icmp *) (buf + hlen);
+
+	if (icmppkt->icmp_id != myid)
+	    return;				/* not our ping */
+
+	if (icmppkt->icmp_type == ICMP_ECHOREPLY) {
+		u_int16_t recv_seq = ntohs(icmppkt->icmp_seq);
+	    ++nreceived;
+		tp = (struct timeval *) icmppkt->icmp_data;
+
+		if ((tv.tv_usec -= tp->tv_usec) < 0) {
+			--tv.tv_sec;
+			tv.tv_usec += 1000000;
+		}
+		tv.tv_sec -= tp->tv_sec;
+
+		triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100);
+		tsum += triptime;
+		if (triptime < tmin)
+			tmin = triptime;
+		if (triptime > tmax)
+			tmax = triptime;
+
+		if (TST(recv_seq % MAX_DUP_CHK)) {
+			++nrepeats;
+			--nreceived;
+			dupflag = 1;
+		} else {
+			SET(recv_seq % MAX_DUP_CHK);
+			dupflag = 0;
+		}
+
+		if (options & O_QUIET)
+			return;
+
+		printf("%d bytes from %s: icmp_seq=%u", sz,
+			   inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr),
+			   recv_seq);
+		printf(" ttl=%d", iphdr->ttl);
+		printf(" time=%lu.%lu ms", triptime / 10, triptime % 10);
+		if (dupflag)
+			printf(" (DUP!)");
+		printf("\n");
+	} else
+		if (icmppkt->icmp_type != ICMP_ECHO)
+			bb_error_msg("Warning: Got ICMP %d (%s)",
+					icmppkt->icmp_type, icmp_type_name (icmppkt->icmp_type));
+	fflush(stdout);
+}
+
+static void ping(const char *host)
+{
+	char packet[datalen + MAXIPLEN + MAXICMPLEN];
+	int sockopt;
+
+	pingsock = create_icmp_socket();
+
+	memset(&pingaddr, 0, sizeof(struct sockaddr_in));
+
+	pingaddr.sin_family = AF_INET;
+	hostent = xgethostbyname(host);
+	if (hostent->h_addrtype != AF_INET)
+		bb_error_msg_and_die("unknown address type; only AF_INET is currently supported.");
+
+	memcpy(&pingaddr.sin_addr, hostent->h_addr, sizeof(pingaddr.sin_addr));
+
+	/* enable broadcast pings */
+	sockopt = 1;
+	setsockopt(pingsock, SOL_SOCKET, SO_BROADCAST, (char *) &sockopt,
+			   sizeof(sockopt));
+
+	/* set recv buf for broadcast pings */
+	sockopt = 48 * 1024;
+	setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, (char *) &sockopt,
+			   sizeof(sockopt));
+
+	printf("PING %s (%s): %d data bytes\n",
+	           hostent->h_name,
+		   inet_ntoa(*(struct in_addr *) &pingaddr.sin_addr.s_addr),
+		   datalen);
+
+	signal(SIGINT, pingstats);
+
+	/* start the ping's going ... */
+	sendping(0);
+
+	/* listen for replies */
+	while (1) {
+		struct sockaddr_in from;
+		socklen_t fromlen = (socklen_t) sizeof(from);
+		int c;
+
+		if ((c = recvfrom(pingsock, packet, sizeof(packet), 0,
+						  (struct sockaddr *) &from, &fromlen)) < 0) {
+			if (errno == EINTR)
+				continue;
+			bb_perror_msg("recvfrom");
+			continue;
+		}
+		unpack(packet, c, &from);
+		if (pingcount > 0 && nreceived >= pingcount)
+			break;
+	}
+	pingstats(0);
+}
+
+int ping_main(int argc, char **argv)
+{
+	char *thisarg;
+
+	datalen = DEFDATALEN; /* initialized here rather than in global scope to work around gcc bug */
+
+	argc--;
+	argv++;
+	options = 0;
+	/* Parse any options */
+	while (argc >= 1 && **argv == '-') {
+		thisarg = *argv;
+		thisarg++;
+		switch (*thisarg) {
+		case 'q':
+			options |= O_QUIET;
+			break;
+		case 'c':
+			if (--argc <= 0)
+			        bb_show_usage();
+			argv++;
+			pingcount = atoi(*argv);
+			break;
+		case 's':
+			if (--argc <= 0)
+			        bb_show_usage();
+			argv++;
+			datalen = atoi(*argv);
+			break;
+		default:
+			bb_show_usage();
+		}
+		argc--;
+		argv++;
+	}
+	if (argc < 1)
+		bb_show_usage();
+
+	myid = getpid() & 0xFFFF;
+	ping(*argv);
+	return EXIT_SUCCESS;
+}
+#endif /* ! CONFIG_FEATURE_FANCY_PING */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ping6.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ping6.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/ping6.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,527 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * $Id: ping6.c,v 1.6 2004/03/15 08:28:48 andersen Exp $
+ * Mini ping implementation for busybox
+ *
+ * Copyright (C) 1999 by Randolph Chung <tausq at debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This version of ping is adapted from the ping in netkit-base 0.10,
+ * which is:
+ *
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Muuss.
+ *
+ * Original copyright notice is retained at the end of this file.
+ *
+ * This version is an adaptation of ping.c from busybox.
+ * The code was modified by Bart Visscher <magick at linux-fan.com>
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/times.h>
+#include <signal.h>
+
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>				/* offsetof */
+#include "busybox.h"
+
+enum {
+	DEFDATALEN = 56,
+	MAXIPLEN = 60,
+	MAXICMPLEN = 76,
+	MAXPACKET = 65468,
+	MAX_DUP_CHK = (8 * 128),
+	MAXWAIT = 10,
+	PINGINTERVAL = 1		/* second */
+};
+
+#define O_QUIET         (1 << 0)
+#define O_VERBOSE       (1 << 1)
+
+#define	A(bit)		rcvd_tbl[(bit)>>3]	/* identify byte in array */
+#define	B(bit)		(1 << ((bit) & 0x07))	/* identify bit in byte */
+#define	SET(bit)	(A(bit) |= B(bit))
+#define	CLR(bit)	(A(bit) &= (~B(bit)))
+#define	TST(bit)	(A(bit) & B(bit))
+
+static void ping(const char *host);
+
+/* simple version */
+#ifndef CONFIG_FEATURE_FANCY_PING6
+static struct hostent *h;
+
+void noresp(int ign)
+{
+	printf("No response from %s\n", h->h_name);
+	exit(EXIT_FAILURE);
+}
+
+static void ping(const char *host)
+{
+	struct sockaddr_in6 pingaddr;
+	struct icmp6_hdr *pkt;
+	int pingsock, c;
+	int sockopt;
+	char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
+
+	pingsock = create_icmp6_socket();
+
+	memset(&pingaddr, 0, sizeof(struct sockaddr_in));
+
+	pingaddr.sin6_family = AF_INET6;
+	h = xgethostbyname2(host, AF_INET6);
+	memcpy(&pingaddr.sin6_addr, h->h_addr, sizeof(pingaddr.sin6_addr));
+
+	pkt = (struct icmp6_hdr *) packet;
+	memset(pkt, 0, sizeof(packet));
+	pkt->icmp6_type = ICMP6_ECHO_REQUEST;
+
+	sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
+	setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, (char *) &sockopt,
+			   sizeof(sockopt));
+
+	c = sendto(pingsock, packet, DEFDATALEN + sizeof (struct icmp6_hdr), 0,
+			   (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in6));
+
+	if (c < 0 || c != sizeof(packet))
+		bb_perror_msg_and_die("sendto");
+
+	signal(SIGALRM, noresp);
+	alarm(5);					/* give the host 5000ms to respond */
+	/* listen for replies */
+	while (1) {
+		struct sockaddr_in6 from;
+		size_t fromlen = sizeof(from);
+
+		if ((c = recvfrom(pingsock, packet, sizeof(packet), 0,
+						  (struct sockaddr *) &from, &fromlen)) < 0) {
+			if (errno == EINTR)
+				continue;
+			bb_perror_msg("recvfrom");
+			continue;
+		}
+		if (c >= 8) {			/* icmp6_hdr */
+			pkt = (struct icmp6_hdr *) packet;
+			if (pkt->icmp6_type == ICMP6_ECHO_REPLY)
+				break;
+		}
+	}
+	printf("%s is alive!\n", h->h_name);
+	return;
+}
+
+int ping6_main(int argc, char **argv)
+{
+	argc--;
+	argv++;
+	if (argc < 1)
+		bb_show_usage();
+	ping(*argv);
+	return EXIT_SUCCESS;
+}
+
+#else /* ! CONFIG_FEATURE_FANCY_PING6 */
+/* full(er) version */
+static struct sockaddr_in6 pingaddr;
+static int pingsock = -1;
+static int datalen; /* intentionally uninitialized to work around gcc bug */
+static char* ifname;
+
+static long ntransmitted, nreceived, nrepeats, pingcount;
+static int myid, options;
+static unsigned long tmin = ULONG_MAX, tmax, tsum;
+static char rcvd_tbl[MAX_DUP_CHK / 8];
+
+# ifdef CONFIG_FEATURE_FANCY_PING
+extern
+# endif
+	struct hostent *hostent;
+
+static void sendping(int);
+static void pingstats(int);
+static void unpack(char *, int, struct sockaddr_in6 *, int);
+
+/**************************************************************************/
+
+static void pingstats(int junk)
+{
+	int status;
+
+	signal(SIGINT, SIG_IGN);
+
+	printf("\n--- %s ping statistics ---\n", hostent->h_name);
+	printf("%ld packets transmitted, ", ntransmitted);
+	printf("%ld packets received, ", nreceived);
+	if (nrepeats)
+		printf("%ld duplicates, ", nrepeats);
+	if (ntransmitted)
+		printf("%ld%% packet loss\n",
+			   (ntransmitted - nreceived) * 100 / ntransmitted);
+	if (nreceived)
+		printf("round-trip min/avg/max = %lu.%lu/%lu.%lu/%lu.%lu ms\n",
+			   tmin / 10, tmin % 10,
+			   (tsum / (nreceived + nrepeats)) / 10,
+			   (tsum / (nreceived + nrepeats)) % 10, tmax / 10, tmax % 10);
+	if (nreceived != 0)
+		status = EXIT_SUCCESS;
+	else
+		status = EXIT_FAILURE;
+	exit(status);
+}
+
+static void sendping(int junk)
+{
+	struct icmp6_hdr *pkt;
+	int i;
+	char packet[datalen + sizeof (struct icmp6_hdr)];
+
+	pkt = (struct icmp6_hdr *) packet;
+
+	pkt->icmp6_type = ICMP6_ECHO_REQUEST;
+	pkt->icmp6_code = 0;
+	pkt->icmp6_cksum = 0;
+	pkt->icmp6_seq = ntransmitted++;
+	pkt->icmp6_id = myid;
+	CLR(pkt->icmp6_seq % MAX_DUP_CHK);
+
+	gettimeofday((struct timeval *) &pkt->icmp6_data8[4], NULL);
+
+	i = sendto(pingsock, packet, sizeof(packet), 0,
+			   (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in6));
+
+	if (i < 0)
+		bb_perror_msg_and_die("sendto");
+	else if ((size_t)i != sizeof(packet))
+		bb_error_msg_and_die("ping wrote %d chars; %d expected", i,
+			   (int)sizeof(packet));
+
+	signal(SIGALRM, sendping);
+	if (pingcount == 0 || ntransmitted < pingcount) {	/* schedule next in 1s */
+		alarm(PINGINTERVAL);
+	} else {					/* done, wait for the last ping to come back */
+		/* todo, don't necessarily need to wait so long... */
+		signal(SIGALRM, pingstats);
+		alarm(MAXWAIT);
+	}
+}
+
+/* RFC3542 changed some definitions from RFC2292 for no good reason, whee !
+ * the newer 3542 uses a MLD_ prefix where as 2292 uses ICMP6_ prefix */
+#ifndef MLD_LISTENER_QUERY
+# define MLD_LISTENER_QUERY ICMP6_MEMBERSHIP_QUERY
+#endif
+#ifndef MLD_LISTENER_REPORT
+# define MLD_LISTENER_REPORT ICMP6_MEMBERSHIP_REPORT
+#endif
+#ifndef MLD_LISTENER_REDUCTION
+# define MLD_LISTENER_REDUCTION ICMP6_MEMBERSHIP_REDUCTION
+#endif
+static char *icmp6_type_name (int id)
+{
+	switch (id) {
+	case ICMP6_DST_UNREACH:				return "Destination Unreachable";
+	case ICMP6_PACKET_TOO_BIG:			return "Packet too big";
+	case ICMP6_TIME_EXCEEDED:			return "Time Exceeded";
+	case ICMP6_PARAM_PROB:				return "Parameter Problem";
+	case ICMP6_ECHO_REPLY:				return "Echo Reply";
+	case ICMP6_ECHO_REQUEST:			return "Echo Request";
+	case MLD_LISTENER_QUERY:			return "Listener Query";
+	case MLD_LISTENER_REPORT:			return "Listener Report";
+	case MLD_LISTENER_REDUCTION:		return "Listener Reduction";
+	default:							return "unknown ICMP type";
+	}
+}
+
+static void unpack(char *packet, int sz, struct sockaddr_in6 *from, int hoplimit)
+{
+	struct icmp6_hdr *icmppkt;
+	struct timeval tv, *tp;
+	int dupflag;
+	unsigned long triptime;
+	char buf[INET6_ADDRSTRLEN];
+
+	gettimeofday(&tv, NULL);
+
+	/* discard if too short */
+	if (sz < (datalen + sizeof(struct icmp6_hdr)))
+		return;
+
+	icmppkt = (struct icmp6_hdr *) packet;
+
+	if (icmppkt->icmp6_id != myid)
+	    return;				/* not our ping */
+
+	if (icmppkt->icmp6_type == ICMP6_ECHO_REPLY) {
+	    ++nreceived;
+		tp = (struct timeval *) &icmppkt->icmp6_data8[4];
+
+		if ((tv.tv_usec -= tp->tv_usec) < 0) {
+			--tv.tv_sec;
+			tv.tv_usec += 1000000;
+		}
+		tv.tv_sec -= tp->tv_sec;
+
+		triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100);
+		tsum += triptime;
+		if (triptime < tmin)
+			tmin = triptime;
+		if (triptime > tmax)
+			tmax = triptime;
+
+		if (TST(icmppkt->icmp6_seq % MAX_DUP_CHK)) {
+			++nrepeats;
+			--nreceived;
+			dupflag = 1;
+		} else {
+			SET(icmppkt->icmp6_seq % MAX_DUP_CHK);
+			dupflag = 0;
+		}
+
+		if (options & O_QUIET)
+			return;
+
+		printf("%d bytes from %s: icmp6_seq=%u", sz,
+			   inet_ntop(AF_INET6, &pingaddr.sin6_addr,
+						 buf, sizeof(buf)),
+			   icmppkt->icmp6_seq);
+		printf(" ttl=%d time=%lu.%lu ms", hoplimit,
+			   triptime / 10, triptime % 10);
+		if (dupflag)
+			printf(" (DUP!)");
+		printf("\n");
+	} else
+		if (icmppkt->icmp6_type != ICMP6_ECHO_REQUEST)
+			bb_error_msg("Warning: Got ICMP %d (%s)",
+					icmppkt->icmp6_type, icmp6_type_name (icmppkt->icmp6_type));
+}
+
+static void ping(const char *host)
+{
+	char packet[datalen + MAXIPLEN + MAXICMPLEN];
+	char buf[INET6_ADDRSTRLEN];
+	int sockopt;
+	struct msghdr msg;
+	struct sockaddr_in6 from;
+	struct iovec iov;
+	char control_buf[CMSG_SPACE(36)];
+
+	pingsock = create_icmp6_socket();
+
+	memset(&pingaddr, 0, sizeof(struct sockaddr_in));
+
+	pingaddr.sin6_family = AF_INET6;
+	hostent = xgethostbyname2(host, AF_INET6);
+	if (hostent->h_addrtype != AF_INET6)
+		bb_error_msg_and_die("unknown address type; only AF_INET6 is currently supported.");
+
+	memcpy(&pingaddr.sin6_addr, hostent->h_addr, sizeof(pingaddr.sin6_addr));
+
+#ifdef ICMP6_FILTER
+	{
+		struct icmp6_filter filt;
+		if (!(options & O_VERBOSE)) {
+			ICMP6_FILTER_SETBLOCKALL(&filt);
+#if 0
+			if ((options & F_FQDN) || (options & F_FQDNOLD) ||
+				(options & F_NODEADDR) || (options & F_SUPTYPES))
+				ICMP6_FILTER_SETPASS(ICMP6_NI_REPLY, &filt);
+			else
+#endif
+				ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt);
+		} else {
+			ICMP6_FILTER_SETPASSALL(&filt);
+		}
+		if (setsockopt(pingsock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
+					   sizeof(filt)) < 0)
+			bb_error_msg_and_die("setsockopt(ICMP6_FILTER)");
+	}
+#endif /*ICMP6_FILTER*/
+
+	/* enable broadcast pings */
+	sockopt = 1;
+	setsockopt(pingsock, SOL_SOCKET, SO_BROADCAST, (char *) &sockopt,
+			   sizeof(sockopt));
+
+	/* set recv buf for broadcast pings */
+	sockopt = 48 * 1024;
+	setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, (char *) &sockopt,
+			   sizeof(sockopt));
+
+	sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
+	setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, (char *) &sockopt,
+			   sizeof(sockopt));
+
+	sockopt = 1;
+	setsockopt(pingsock, SOL_IPV6, IPV6_HOPLIMIT, (char *) &sockopt,
+			   sizeof(sockopt));
+
+	if (ifname) {
+		if ((pingaddr.sin6_scope_id = if_nametoindex(ifname)) == 0)
+			bb_error_msg_and_die("%s: invalid interface name", ifname);
+	}
+
+	printf("PING %s (%s): %d data bytes\n",
+	           hostent->h_name,
+			   inet_ntop(AF_INET6, &pingaddr.sin6_addr,
+						 buf, sizeof(buf)),
+		   datalen);
+
+	signal(SIGINT, pingstats);
+
+	/* start the ping's going ... */
+	sendping(0);
+
+	/* listen for replies */
+	msg.msg_name=&from;
+	msg.msg_namelen=sizeof(from);
+	msg.msg_iov=&iov;
+	msg.msg_iovlen=1;
+	msg.msg_control=control_buf;
+	iov.iov_base=packet;
+	iov.iov_len=sizeof(packet);
+	while (1) {
+		int c;
+		struct cmsghdr *cmsgptr = NULL;
+		int hoplimit=-1;
+		msg.msg_controllen=sizeof(control_buf);
+
+		if ((c = recvmsg(pingsock, &msg, 0)) < 0) {
+			if (errno == EINTR)
+				continue;
+			bb_perror_msg("recvfrom");
+			continue;
+		}
+		for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
+			 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
+			if (cmsgptr->cmsg_level == SOL_IPV6 &&
+				cmsgptr->cmsg_type == IPV6_HOPLIMIT ) {
+				hoplimit=*(int*)CMSG_DATA(cmsgptr);
+			}
+		}
+		unpack(packet, c, &from, hoplimit);
+		if (pingcount > 0 && nreceived >= pingcount)
+			break;
+	}
+	pingstats(0);
+}
+
+int ping6_main(int argc, char **argv)
+{
+	char *thisarg;
+
+	datalen = DEFDATALEN; /* initialized here rather than in global scope to work around gcc bug */
+
+	argc--;
+	argv++;
+	options = 0;
+	/* Parse any options */
+	while (argc >= 1 && **argv == '-') {
+		thisarg = *argv;
+		thisarg++;
+		switch (*thisarg) {
+		case 'v':
+			options &= ~O_QUIET;
+			options |= O_VERBOSE;
+			break;
+		case 'q':
+			options &= ~O_VERBOSE;
+			options |= O_QUIET;
+			break;
+		case 'c':
+			if (--argc <= 0)
+			        bb_show_usage();
+			argv++;
+			pingcount = atoi(*argv);
+			break;
+		case 's':
+			if (--argc <= 0)
+			        bb_show_usage();
+			argv++;
+			datalen = atoi(*argv);
+			break;
+		case 'I':
+			if (--argc <= 0)
+			        bb_show_usage();
+			argv++;
+			ifname = *argv;
+			break;
+		default:
+			bb_show_usage();
+		}
+		argc--;
+		argv++;
+	}
+	if (argc < 1)
+		bb_show_usage();
+
+	myid = getpid() & 0xFFFF;
+	ping(*argv);
+	return EXIT_SUCCESS;
+}
+#endif /* ! CONFIG_FEATURE_FANCY_PING6 */
+
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Muuss.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
+ *		ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
+ *
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/route.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/route.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/route.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,724 @@
+/* vi: set sw=4 ts=4: */
+/* route
+ *
+ * Similar to the standard Unix route, but with only the necessary
+ * parts for AF_INET and AF_INET6
+ *
+ * Bjorn Wesen, Axis Communications AB
+ *
+ * Author of the original route:
+ *              Fred N. van Kempen, <waltje at uwalt.nl.mugnet.org>
+ *              (derived from FvK's 'route.c     1.70    01/04/94')
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * $Id: route.c,v 1.26 2004/03/19 23:27:08 mjn3 Exp $
+ *
+ * displayroute() code added by Vladimir N. Oleynik <dzo at simtreas.ru>
+ * adjustments by Larry Doolittle  <LRDoolittle at lbl.gov>
+ *
+ * IPV6 support added by Bart Visscher <magick at linux-fan.com>
+ */
+
+/* 2004/03/09  Manuel Novoa III <mjn3 at codepoet.org>
+ *
+ * Rewritten to fix several bugs, add additional error checking, and
+ * remove ridiculous amounts of bloat.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <net/route.h>
+#include <net/if.h>
+#include "busybox.h"
+#include "inet_common.h"
+
+#ifndef RTF_UP
+/* Keep this in sync with /usr/src/linux/include/linux/route.h */
+#define RTF_UP          0x0001	/* route usable                 */
+#define RTF_GATEWAY     0x0002	/* destination is a gateway     */
+#define RTF_HOST        0x0004	/* host entry (net otherwise)   */
+#define RTF_REINSTATE   0x0008	/* reinstate route after tmout  */
+#define RTF_DYNAMIC     0x0010	/* created dyn. (by redirect)   */
+#define RTF_MODIFIED    0x0020	/* modified dyn. (by redirect)  */
+#define RTF_MTU         0x0040	/* specific MTU for this route  */
+#ifndef RTF_MSS
+#define RTF_MSS         RTF_MTU	/* Compatibility :-(            */
+#endif
+#define RTF_WINDOW      0x0080	/* per route window clamping    */
+#define RTF_IRTT        0x0100	/* Initial round trip time      */
+#define RTF_REJECT      0x0200	/* Reject route                 */
+#endif
+
+#if defined (SIOCADDRTOLD) || defined (RTF_IRTT)	/* route */
+#define HAVE_NEW_ADDRT 1
+#endif
+
+#if HAVE_NEW_ADDRT
+#define mask_in_addr(x) (((struct sockaddr_in *)&((x).rt_genmask))->sin_addr.s_addr)
+#define full_mask(x) (x)
+#else
+#define mask_in_addr(x) ((x).rt_genmask)
+#define full_mask(x) (((struct sockaddr_in *)&(x))->sin_addr.s_addr)
+#endif
+
+/* The RTACTION entries must agree with tbl_verb[] below! */
+#define RTACTION_ADD		1
+#define RTACTION_DEL		2
+
+/* For the various tbl_*[] arrays, the 1st byte is the offset to
+ * the next entry and the 2nd byte is return value. */
+
+#define NET_FLAG			1
+#define HOST_FLAG			2
+
+/* We remap '-' to '#' to avoid problems with getopt. */
+static const char tbl_hash_net_host[] =
+	"\007\001#net\0"
+/*	"\010\002#host\0" */
+	"\007\002#host"				/* Since last, we can save a byte. */
+;
+
+#define KW_TAKES_ARG		020
+#define KW_SETS_FLAG		040
+
+#define KW_IPVx_METRIC		020
+#define KW_IPVx_NETMASK		021
+#define KW_IPVx_GATEWAY		022
+#define KW_IPVx_MSS			023
+#define KW_IPVx_WINDOW		024
+#define KW_IPVx_IRTT		025
+#define KW_IPVx_DEVICE		026
+
+#define KW_IPVx_FLAG_ONLY	040
+#define KW_IPVx_REJECT		040
+#define KW_IPVx_MOD			041
+#define KW_IPVx_DYN			042
+#define KW_IPVx_REINSTATE	043
+
+static const char tbl_ipvx[] =
+	/* 020 is the "takes an arg" bit */
+#if HAVE_NEW_ADDRT
+	"\011\020metric\0"
+#endif
+	"\012\021netmask\0"
+	"\005\022gw\0"
+	"\012\022gateway\0"
+	"\006\023mss\0"
+	"\011\024window\0"
+#ifdef RTF_IRTT
+	"\007\025irtt\0"
+#endif
+	"\006\026dev\0"
+	"\011\026device\0"
+	/* 040 is the "sets a flag" bit - MUST match flags_ipvx[] values below. */
+#ifdef RTF_REJECT
+	"\011\040reject\0"
+#endif
+	"\006\041mod\0"
+	"\006\042dyn\0"
+/*	"\014\043reinstate\0" */
+	"\013\043reinstate"			/* Since last, we can save a byte. */
+;
+
+static const int flags_ipvx[] = { /* MUST match tbl_ipvx[] values above. */
+#ifdef RTF_REJECT
+	RTF_REJECT,
+#endif
+	RTF_MODIFIED,
+	RTF_DYNAMIC,
+	RTF_REINSTATE
+};
+
+static int kw_lookup(const char *kwtbl, char ***pargs)
+{
+	if (**pargs) {
+		do {
+			if (strcmp(kwtbl+2, **pargs) == 0) { /* Found a match. */
+				*pargs += 1;
+				if (kwtbl[1] & KW_TAKES_ARG) {
+					if (!**pargs) {	/* No more args! */
+						bb_show_usage();
+					}
+					*pargs += 1; /* Calling routine will use args[-1]. */
+				}
+				return kwtbl[1];
+			}
+			kwtbl += *kwtbl;
+		} while (*kwtbl);
+	}
+	return 0;
+}
+
+/* Add or delete a route, depending on action. */
+
+static void INET_setroute(int action, char **args)
+{
+	struct rtentry rt;
+	const char *netmask = NULL;
+	int skfd, isnet, xflag;
+
+	assert((action == RTACTION_ADD) || (action == RTACTION_DEL));
+
+	/* Grab the -net or -host options.  Remember they were transformed. */
+	xflag = kw_lookup(tbl_hash_net_host, &args);
+
+	/* If we did grab -net or -host, make sure we still have an arg left. */
+	if (*args == NULL) {
+		bb_show_usage();
+	}
+
+	/* Clean out the RTREQ structure. */
+	memset((char *) &rt, 0, sizeof(struct rtentry));
+
+	{
+		const char *target = *args++;
+		char *prefix;
+
+		/* recognize x.x.x.x/mask format. */
+		prefix = strchr(target, '/');
+		if(prefix) {
+			int prefix_len;
+
+			prefix_len = bb_xgetularg10_bnd(prefix+1, 0, 32);
+			mask_in_addr(rt) = htonl( ~ (0xffffffffUL >> prefix_len));
+			*prefix = '\0';
+#if HAVE_NEW_ADDRT
+			rt.rt_genmask.sa_family = AF_INET;
+#endif
+		} else {
+			/* Default netmask. */
+			netmask = bb_INET_default;
+		}
+		/* Prefer hostname lookup is -host flag (xflag==1) was given. */
+		isnet = INET_resolve(target, (struct sockaddr_in *) &rt.rt_dst,
+							 (xflag & HOST_FLAG));
+		if (isnet < 0) {
+			bb_error_msg_and_die("resolving %s", target);
+		}
+		if(prefix) {
+			/* do not destroy prefix for process args */
+			*prefix = '/';
+		}
+	}
+
+	if (xflag) {		/* Reinit isnet if -net or -host was specified. */
+		isnet = (xflag & NET_FLAG);
+	}
+
+	/* Fill in the other fields. */
+	rt.rt_flags = ((isnet) ? RTF_UP : (RTF_UP | RTF_HOST));
+
+	while (*args) {
+		int k = kw_lookup(tbl_ipvx, &args);
+		const char *args_m1 = args[-1];
+
+		if (k & KW_IPVx_FLAG_ONLY) {
+			rt.rt_flags |= flags_ipvx[k & 3];
+			continue;
+		}
+
+#if HAVE_NEW_ADDRT
+		if (k == KW_IPVx_METRIC) {
+			rt.rt_metric = bb_xgetularg10(args_m1) + 1;
+			continue;
+		}
+#endif
+
+		if (k == KW_IPVx_NETMASK) {
+			struct sockaddr mask;
+
+			if (mask_in_addr(rt)) {
+				bb_show_usage();
+			}
+
+			netmask = args_m1;
+			isnet = INET_resolve(netmask, (struct sockaddr_in *) &mask, 0);
+			if (isnet < 0) {
+				bb_error_msg_and_die("resolving %s", netmask);
+			}
+			rt.rt_genmask = full_mask(mask);
+			continue;
+		}
+
+		if (k == KW_IPVx_GATEWAY) {
+			if (rt.rt_flags & RTF_GATEWAY) {
+				bb_show_usage();
+			}
+
+			isnet = INET_resolve(args_m1,
+								 (struct sockaddr_in *) &rt.rt_gateway, 1);
+			rt.rt_flags |= RTF_GATEWAY;
+
+			if (isnet) {
+				if (isnet < 0) {
+					bb_error_msg_and_die("resolving %s", args_m1);
+				}
+				bb_error_msg_and_die("gateway %s is a NETWORK", args_m1);
+			}
+			continue;
+		}
+
+		if (k == KW_IPVx_MSS) {	/* Check valid MSS bounds. */
+			rt.rt_flags |= RTF_MSS;
+			rt.rt_mss = bb_xgetularg10_bnd(args_m1, 64, 32768);
+			continue;
+		}
+
+		if (k == KW_IPVx_WINDOW) {	/* Check valid window bounds. */
+			rt.rt_flags |= RTF_WINDOW;
+			rt.rt_window = bb_xgetularg10_bnd(args_m1, 128, INT_MAX);
+			continue;
+		}
+
+#ifdef RTF_IRTT
+		if (k == KW_IPVx_IRTT) {
+			rt.rt_flags |= RTF_IRTT;
+			rt.rt_irtt = bb_xgetularg10(args_m1);
+			rt.rt_irtt *= (sysconf(_SC_CLK_TCK) / 100);	/* FIXME */
+#if 0					/* FIXME: do we need to check anything of this? */
+			if (rt.rt_irtt < 1 || rt.rt_irtt > (120 * HZ)) {
+				bb_error_msg_and_die("bad irtt");
+			}
+#endif
+			continue;
+		}
+#endif
+
+		/* Device is special in that it can be the last arg specified
+		 * and doesn't requre the dev/device keyword in that case. */
+		if (!rt.rt_dev && ((k == KW_IPVx_DEVICE) || (!k && !*++args))) {
+			/* Don't use args_m1 here since args may have changed! */
+			rt.rt_dev = args[-1];
+			continue;
+		}
+
+		/* Nothing matched. */
+		bb_show_usage();
+	}
+
+#ifdef RTF_REJECT
+	if ((rt.rt_flags & RTF_REJECT) && !rt.rt_dev) {
+		rt.rt_dev = "lo";
+	}
+#endif
+
+	/* sanity checks.. */
+	if (mask_in_addr(rt)) {
+		unsigned long mask = mask_in_addr(rt);
+
+		mask = ~ntohl(mask);
+		if ((rt.rt_flags & RTF_HOST) && mask != 0xffffffff) {
+			bb_error_msg_and_die("netmask %.8x and host route conflict",
+								 (unsigned int) mask);
+		}
+		if (mask & (mask + 1)) {
+			bb_error_msg_and_die("bogus netmask %s", netmask);
+		}
+		mask = ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr;
+		if (mask & ~mask_in_addr(rt)) {
+			bb_error_msg_and_die("netmask and route address conflict");
+		}
+	}
+
+	/* Fill out netmask if still unset */
+	if ((action == RTACTION_ADD) && (rt.rt_flags & RTF_HOST)) {
+		mask_in_addr(rt) = 0xffffffff;
+	}
+
+	/* Create a socket to the INET kernel. */
+	skfd = bb_xsocket(AF_INET, SOCK_DGRAM, 0);
+
+	if (ioctl(skfd, ((action==RTACTION_ADD) ? SIOCADDRT : SIOCDELRT), &rt)<0) {
+		bb_perror_msg_and_die("SIOC[ADD|DEL]RT");
+	}
+
+	if (ENABLE_FEATURE_CLEAN_UP) close(skfd);
+}
+
+#ifdef CONFIG_FEATURE_IPV6
+
+static void INET6_setroute(int action, char **args)
+{
+	struct sockaddr_in6 sa6;
+	struct in6_rtmsg rt;
+	int prefix_len, skfd;
+	const char *devname;
+
+	assert((action == RTACTION_ADD) || (action == RTACTION_DEL));
+
+	{
+		/* We know args isn't NULL from the check in route_main. */
+		const char *target = *args++;
+
+		if (strcmp(target, bb_INET_default) == 0) {
+			prefix_len = 0;
+			memset(&sa6, 0, sizeof(sa6));
+		} else {
+			char *cp;
+			if ((cp = strchr(target, '/'))) { /* Yes... const to non is ok. */
+				*cp = 0;
+				prefix_len = bb_xgetularg10_bnd(cp+1, 0, 128);
+			} else {
+				prefix_len = 128;
+			}
+			if (INET6_resolve(target, (struct sockaddr_in6 *) &sa6) < 0) {
+				bb_error_msg_and_die("resolving %s", target);
+			}
+		}
+	}
+
+	/* Clean out the RTREQ structure. */
+	memset((char *) &rt, 0, sizeof(struct in6_rtmsg));
+
+	memcpy(&rt.rtmsg_dst, sa6.sin6_addr.s6_addr, sizeof(struct in6_addr));
+
+	/* Fill in the other fields. */
+	rt.rtmsg_dst_len = prefix_len;
+	rt.rtmsg_flags = ((prefix_len == 128) ? (RTF_UP|RTF_HOST) : RTF_UP);
+	rt.rtmsg_metric = 1;
+
+	devname = NULL;
+
+	while (*args) {
+		int k = kw_lookup(tbl_ipvx, &args);
+		const char *args_m1 = args[-1];
+
+		if ((k == KW_IPVx_MOD) || (k == KW_IPVx_DYN)) {
+			rt.rtmsg_flags |= flags_ipvx[k & 3];
+			continue;
+		}
+
+		if (k == KW_IPVx_METRIC) {
+			rt.rtmsg_metric = bb_xgetularg10(args_m1);
+			continue;
+		}
+
+		if (k == KW_IPVx_GATEWAY) {
+			if (rt.rtmsg_flags & RTF_GATEWAY) {
+				bb_show_usage();
+			}
+
+			if (INET6_resolve(args_m1, (struct sockaddr_in6 *) &sa6) < 0) {
+				bb_error_msg_and_die("resolving %s", args_m1);
+			}
+			memcpy(&rt.rtmsg_gateway, sa6.sin6_addr.s6_addr,
+				   sizeof(struct in6_addr));
+			rt.rtmsg_flags |= RTF_GATEWAY;
+			continue;
+		}
+
+		/* Device is special in that it can be the last arg specified
+		 * and doesn't requre the dev/device keyword in that case. */
+		if (!devname && ((k == KW_IPVx_DEVICE) || (!k && !*++args))) {
+			/* Don't use args_m1 here since args may have changed! */
+			devname = args[-1];
+			continue;
+		}
+
+		/* Nothing matched. */
+		bb_show_usage();
+	}
+
+	/* Create a socket to the INET6 kernel. */
+	skfd = bb_xsocket(AF_INET6, SOCK_DGRAM, 0);
+
+	rt.rtmsg_ifindex = 0;
+
+	if (devname) {
+		struct ifreq ifr;
+		memset(&ifr, 0, sizeof(ifr));
+		strcpy(ifr.ifr_name, devname);
+
+		if (ioctl(skfd, SIOGIFINDEX, &ifr) < 0) {
+			bb_perror_msg_and_die("SIOGIFINDEX");
+		}
+		rt.rtmsg_ifindex = ifr.ifr_ifindex;
+	}
+
+	/* Tell the kernel to accept this route. */
+	if (ioctl(skfd, ((action==RTACTION_ADD) ? SIOCADDRT : SIOCDELRT), &rt)<0) {
+		bb_perror_msg_and_die("SIOC[ADD|DEL]RT");
+	}
+
+	if (ENABLE_FEATURE_CLEAN_UP) close(skfd);
+}
+#endif
+
+static const unsigned int flagvals[] = { /* Must agree with flagchars[]. */
+	RTF_GATEWAY,
+	RTF_HOST,
+	RTF_REINSTATE,
+	RTF_DYNAMIC,
+	RTF_MODIFIED,
+#ifdef CONFIG_FEATURE_IPV6
+	RTF_DEFAULT,
+	RTF_ADDRCONF,
+	RTF_CACHE
+#endif
+};
+
+#define IPV4_MASK (RTF_GATEWAY|RTF_HOST|RTF_REINSTATE|RTF_DYNAMIC|RTF_MODIFIED)
+#define IPV6_MASK (RTF_GATEWAY|RTF_HOST|RTF_DEFAULT|RTF_ADDRCONF|RTF_CACHE)
+
+static const char flagchars[] =		/* Must agree with flagvals[]. */
+	"GHRDM"
+#ifdef CONFIG_FEATURE_IPV6
+	"DAC"
+#endif
+;
+
+static
+#ifndef CONFIG_FEATURE_IPV6
+__inline
+#endif
+void set_flags(char *flagstr, int flags)
+{
+	int i;
+
+	*flagstr++ = 'U';
+
+	for (i=0 ; (*flagstr = flagchars[i]) != 0 ; i++) {
+		if (flags & flagvals[i]) {
+			++flagstr;
+		}
+	}
+}
+
+/* also used in netstat */
+void displayroutes(int noresolve, int netstatfmt);
+void displayroutes(int noresolve, int netstatfmt)
+{
+	char devname[64], flags[16], sdest[16], sgw[16];
+	unsigned long int d, g, m;
+	int flgs, ref, use, metric, mtu, win, ir;
+	struct sockaddr_in s_addr;
+	struct in_addr mask;
+
+	FILE *fp = bb_xfopen("/proc/net/route", "r");
+
+	bb_printf("Kernel IP routing table\n"
+			  "Destination     Gateway         Genmask"
+			  "         Flags %s Iface\n",
+			  netstatfmt ? "  MSS Window  irtt" : "Metric Ref    Use");
+
+	if (fscanf(fp, "%*[^\n]\n") < 0) { /* Skip the first line. */
+		goto ERROR;		   /* Empty or missing line, or read error. */
+	}
+	while (1) {
+		int r;
+		r = fscanf(fp, "%63s%lx%lx%X%d%d%d%lx%d%d%d\n",
+				   devname, &d, &g, &flgs, &ref, &use, &metric, &m,
+				   &mtu, &win, &ir);
+		if (r != 11) {
+			if ((r < 0) && feof(fp)) { /* EOF with no (nonspace) chars read. */
+				break;
+			}
+		ERROR:
+			bb_error_msg_and_die("fscanf");
+		}
+
+		if (!(flgs & RTF_UP)) { /* Skip interfaces that are down. */
+			continue;
+		}
+
+		set_flags(flags, (flgs & IPV4_MASK));
+#ifdef RTF_REJECT
+		if (flgs & RTF_REJECT) {
+			flags[0] = '!';
+		}
+#endif
+
+		memset(&s_addr, 0, sizeof(struct sockaddr_in));
+		s_addr.sin_family = AF_INET;
+		s_addr.sin_addr.s_addr = d;
+		INET_rresolve(sdest, sizeof(sdest), &s_addr,
+					  (noresolve | 0x8000), m);	/* Default instead of *. */
+
+		s_addr.sin_addr.s_addr = g;
+		INET_rresolve(sgw, sizeof(sgw), &s_addr,
+					  (noresolve | 0x4000), m);	/* Host instead of net. */
+
+		mask.s_addr = m;
+		bb_printf("%-16s%-16s%-16s%-6s", sdest, sgw, inet_ntoa(mask), flags);
+		if (netstatfmt) {
+			bb_printf("%5d %-5d %6d %s\n", mtu, win, ir, devname);
+		} else {
+			bb_printf("%-6d %-2d %7d %s\n", metric, ref, use, devname);
+		}
+	}
+}
+
+#ifdef CONFIG_FEATURE_IPV6
+
+static void INET6_displayroutes(int noresolve)
+{
+	char addr6[128], naddr6[128];
+	/* In addr6x, we store both 40-byte ':'-delimited ipv6 addresses.
+	 * We read the non-delimited strings into the tail of the buffer
+	 * using fscanf and then modify the buffer by shifting forward
+	 * while inserting ':'s and the nul terminator for the first string.
+	 * Hence the strings are at addr6x and addr6x+40.  This generates
+	 * _much_ less code than the previous (upstream) approach. */
+	char addr6x[80];
+	char iface[16], flags[16];
+	int iflags, metric, refcnt, use, prefix_len, slen;
+	struct sockaddr_in6 snaddr6;
+
+	FILE *fp = bb_xfopen("/proc/net/ipv6_route", "r");
+
+	bb_printf("Kernel IPv6 routing table\n%-44s%-40s"
+			  "Flags Metric Ref    Use Iface\n",
+			  "Destination", "Next Hop");
+
+	while (1) {
+		int r;
+		r = fscanf(fp, "%32s%x%*s%x%32s%x%x%x%x%s\n",
+				   addr6x+14, &prefix_len, &slen, addr6x+40+7,
+				   &metric, &use, &refcnt, &iflags, iface);
+		if (r != 9) {
+			if ((r < 0) && feof(fp)) { /* EOF with no (nonspace) chars read. */
+				break;
+			}
+		ERROR:
+			bb_error_msg_and_die("fscanf");
+		}
+
+		/* Do the addr6x shift-and-insert changes to ':'-delimit addresses.
+		 * For now, always do this to validate the proc route format, even
+		 * if the interface is down. */
+		{
+			int i = 0;
+			char *p = addr6x+14;
+
+			do {
+				if (!*p) {
+					if (i==40) { /* nul terminator for 1st address? */
+						addr6x[39] = 0;	/* Fixup... need 0 instead of ':'. */
+						++p;	/* Skip and continue. */
+						continue;
+					}
+					goto ERROR;
+				}
+				addr6x[i++] = *p++;
+				if (!((i+1)%5)) {
+					addr6x[i++] = ':';
+				}
+			} while (i < 40+28+7);
+		}
+
+		if (!(iflags & RTF_UP)) { /* Skip interfaces that are down. */
+			continue;
+		}
+
+		set_flags(flags, (iflags & IPV6_MASK));
+
+		r = 0;
+		do {
+			inet_pton(AF_INET6, addr6x + r,
+					  (struct sockaddr *) &snaddr6.sin6_addr);
+			snaddr6.sin6_family = AF_INET6;
+			INET6_rresolve(naddr6, sizeof(naddr6),
+						   (struct sockaddr_in6 *) &snaddr6,
+#if 0
+						   (noresolve | 0x8000) /* Default instead of *. */
+#else
+						   0x0fff /* Apparently, upstream never resolves. */
+#endif
+						   );
+
+			if (!r) {			/* 1st pass */
+				snprintf(addr6, sizeof(addr6), "%s/%d", naddr6, prefix_len);
+				r += 40;
+			} else {			/* 2nd pass */
+				/* Print the info. */
+				bb_printf("%-43s %-39s %-5s %-6d %-2d %7d %-8s\n",
+						  addr6, naddr6, flags, metric, refcnt, use, iface);
+				break;
+			}
+		} while (1);
+	}
+}
+
+#endif
+
+#define ROUTE_OPT_A			0x01
+#define ROUTE_OPT_n			0x02
+#define ROUTE_OPT_e			0x04
+#define ROUTE_OPT_INET6		0x08 /* Not an actual option. See below. */
+
+/* 1st byte is offset to next entry offset.  2nd byte is return value. */
+static const char tbl_verb[] =	/* 2nd byte matches RTACTION_* code */
+	"\006\001add\0"
+	"\006\002del\0"
+/*	"\011\002delete\0" */
+	"\010\002delete"			/* Since last, we can save a byte. */
+;
+
+int route_main(int argc, char **argv)
+{
+	unsigned long opt;
+	int what;
+	char *family;
+
+	/* First, remap '-net' and '-host' to avoid getopt problems. */
+	{
+		char **p = argv;
+
+		while (*++p) {
+			if ((strcmp(*p, "-net") == 0) || (strcmp(*p, "-host") == 0)) {
+				p[0][0] = '#';
+			}
+		}
+	}
+
+	opt = bb_getopt_ulflags(argc, argv, "A:ne", &family);
+
+	if ((opt & ROUTE_OPT_A) && strcmp(family, "inet")) {
+#ifdef CONFIG_FEATURE_IPV6
+		if (strcmp(family, "inet6") == 0) {
+			opt |= ROUTE_OPT_INET6;	/* Set flag for ipv6. */
+		} else
+#endif
+		bb_show_usage();
+	}
+
+	argv += optind;
+
+	/* No more args means display the routing table. */
+	if (!*argv) {
+		int noresolve = (opt & ROUTE_OPT_n) ? 0x0fff : 0;
+#ifdef CONFIG_FEATURE_IPV6
+		if (opt & ROUTE_OPT_INET6)
+			INET6_displayroutes(noresolve);
+		else
+#endif
+			displayroutes(noresolve, opt & ROUTE_OPT_e);
+
+		bb_xferror_stdout();
+		bb_fflush_stdout_and_exit(EXIT_SUCCESS);
+	}
+
+	/* Check verb.  At the moment, must be add, del, or delete. */
+	what = kw_lookup(tbl_verb, &argv);
+	if (!what || !*argv) {		/* Unknown verb or no more args. */
+		bb_show_usage();
+	}
+
+#ifdef CONFIG_FEATURE_IPV6
+	if (opt & ROUTE_OPT_INET6)
+		INET6_setroute(what, argv);
+	else
+#endif
+		INET_setroute(what, argv);
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/telnet.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/telnet.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/telnet.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,729 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * telnet implementation for busybox
+ *
+ * Author: Tomi Ollila <too at iki.fi>
+ * Copyright (C) 1994-2000 by Tomi Ollila
+ *
+ * Created: Thu Apr  7 13:29:41 1994 too
+ * Last modified: Fri Jun  9 14:34:24 2000 too
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ * HISTORY
+ * Revision 3.1  1994/04/17  11:31:54  too
+ * initial revision
+ * Modified 2000/06/13 for inclusion into BusyBox by Erik Andersen <andersen at codepoet.org>
+ * Modified 2001/05/07 to add ability to pass TTYPE to remote host by Jim McQuillan
+ * <jam at ltsp.org>
+ * Modified 2004/02/11 to add ability to pass the USER variable to remote host
+ * by Fernando Silveira <swrh at gmx.net>
+ *
+ */
+
+#include <termios.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+#include <arpa/telnet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "busybox.h"
+
+#if 0
+enum { DOTRACE = 1 };
+#endif
+
+#ifdef DOTRACE
+#include <arpa/inet.h> /* for inet_ntoa()... */
+#define TRACE(x, y) do { if (x) printf y; } while (0)
+#else
+#define TRACE(x, y)
+#endif
+
+#define DATABUFSIZE  128
+#define IACBUFSIZE   128
+
+enum {
+	CHM_TRY = 0,
+	CHM_ON = 1,
+	CHM_OFF = 2,
+
+	UF_ECHO = 0x01,
+	UF_SGA = 0x02,
+
+	TS_0 = 1,
+	TS_IAC = 2,
+	TS_OPT = 3,
+	TS_SUB1 = 4,
+	TS_SUB2 = 5,
+};
+
+#define WriteCS(fd, str) write(fd, str, sizeof str -1)
+
+typedef unsigned char byte;
+
+/* use globals to reduce size ??? */ /* test this hypothesis later */
+static struct Globalvars {
+	int		netfd; /* console fd:s are 0 and 1 (and 2) */
+    /* same buffer used both for network and console read/write */
+	char    buf[DATABUFSIZE]; /* allocating so static size is smaller */
+	byte	telstate; /* telnet negotiation state from network input */
+	byte	telwish;  /* DO, DONT, WILL, WONT */
+	byte    charmode;
+	byte    telflags;
+	byte	gotsig;
+	byte	do_termios;
+	/* buffer to handle telnet negotiations */
+	char    iacbuf[IACBUFSIZE];
+	short	iaclen; /* could even use byte */
+	struct termios termios_def;
+	struct termios termios_raw;
+} G;
+
+#define xUSE_GLOBALVAR_PTR /* xUSE... -> don't use :D (makes smaller code) */
+
+#ifdef USE_GLOBALVAR_PTR
+struct Globalvars * Gptr;
+#define G (*Gptr)
+#endif
+
+static inline void iacflush(void)
+{
+	write(G.netfd, G.iacbuf, G.iaclen);
+	G.iaclen = 0;
+}
+
+/* Function prototypes */
+static void rawmode(void);
+static void cookmode(void);
+static void do_linemode(void);
+static void will_charmode(void);
+static void telopt(byte c);
+static int subneg(byte c);
+
+/* Some globals */
+static int one = 1;
+
+#ifdef CONFIG_FEATURE_TELNET_TTYPE
+static char *ttype;
+#endif
+
+#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
+static const char *autologin;
+#endif
+
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+static int win_width, win_height;
+#endif
+
+static void doexit(int ev)
+{
+	cookmode();
+	exit(ev);
+}
+
+static void conescape(void)
+{
+	char b;
+
+	if (G.gotsig)	/* came from line  mode... go raw */
+		rawmode();
+
+	WriteCS(1, "\r\nConsole escape. Commands are:\r\n\n"
+			" l	go to line mode\r\n"
+			" c	go to character mode\r\n"
+			" z	suspend telnet\r\n"
+			" e	exit telnet\r\n");
+
+	if (read(0, &b, 1) <= 0)
+		doexit(1);
+
+	switch (b)
+	{
+	case 'l':
+		if (!G.gotsig)
+		{
+			do_linemode();
+			goto rrturn;
+		}
+		break;
+	case 'c':
+		if (G.gotsig)
+		{
+			will_charmode();
+			goto rrturn;
+		}
+		break;
+	case 'z':
+		cookmode();
+		kill(0, SIGTSTP);
+		rawmode();
+		break;
+	case 'e':
+		doexit(0);
+	}
+
+	WriteCS(1, "continuing...\r\n");
+
+	if (G.gotsig)
+		cookmode();
+
+ rrturn:
+	G.gotsig = 0;
+
+}
+static void handlenetoutput(int len)
+{
+	/*	here we could do smart tricks how to handle 0xFF:s in output
+	 *	stream  like writing twice every sequence of FF:s (thus doing
+	 *	many write()s. But I think interactive telnet application does
+	 *	not need to be 100% 8-bit clean, so changing every 0xff:s to
+	 *	0x7f:s
+	 *
+	 *	2002-mar-21, Przemyslaw Czerpak (druzus at polbox.com)
+	 *	I don't agree.
+	 *	first - I cannot use programs like sz/rz
+	 *	second - the 0x0D is sent as one character and if the next
+	 *	         char is 0x0A then it's eaten by a server side.
+	 *	third - whay doy you have to make 'many write()s'?
+	 *	        I don't understand.
+	 *	So I implemented it. It's realy useful for me. I hope that
+	 *	others people will find it interesting to.
+	 */
+
+	int i, j;
+	byte * p = (byte*)G.buf;
+	byte outbuf[4*DATABUFSIZE];
+
+	for (i = len, j = 0; i > 0; i--, p++)
+	{
+		if (*p == 0x1d)
+		{
+			conescape();
+			return;
+		}
+		outbuf[j++] = *p;
+		if (*p == 0xff)
+		    outbuf[j++] = 0xff;
+		else if (*p == 0x0d)
+		    outbuf[j++] = 0x00;
+	}
+	if (j > 0 )
+	    write(G.netfd, outbuf, j);
+}
+
+
+static void handlenetinput(int len)
+{
+	int i;
+	int cstart = 0;
+
+	for (i = 0; i < len; i++)
+	{
+		byte c = G.buf[i];
+
+		if (G.telstate == 0) /* most of the time state == 0 */
+		{
+			if (c == IAC)
+			{
+				cstart = i;
+				G.telstate = TS_IAC;
+			}
+		}
+		else
+			switch (G.telstate)
+			 {
+			 case TS_0:
+				 if (c == IAC)
+					 G.telstate = TS_IAC;
+				 else
+					 G.buf[cstart++] = c;
+				 break;
+
+			 case TS_IAC:
+				 if (c == IAC) /* IAC IAC -> 0xFF */
+				 {
+					 G.buf[cstart++] = c;
+					 G.telstate = TS_0;
+					 break;
+				 }
+				 /* else */
+				 switch (c)
+				 {
+				 case SB:
+					 G.telstate = TS_SUB1;
+					 break;
+				 case DO:
+				 case DONT:
+				 case WILL:
+				 case WONT:
+					 G.telwish =  c;
+					 G.telstate = TS_OPT;
+					 break;
+				 default:
+					 G.telstate = TS_0;	/* DATA MARK must be added later */
+				 }
+				 break;
+			 case TS_OPT: /* WILL, WONT, DO, DONT */
+				 telopt(c);
+				 G.telstate = TS_0;
+				 break;
+			 case TS_SUB1: /* Subnegotiation */
+			 case TS_SUB2: /* Subnegotiation */
+				 if (subneg(c))
+					 G.telstate = TS_0;
+				 break;
+			 }
+	}
+	if (G.telstate)
+	{
+		if (G.iaclen)			iacflush();
+		if (G.telstate == TS_0)	G.telstate = 0;
+
+		len = cstart;
+	}
+
+	if (len)
+		write(1, G.buf, len);
+}
+
+
+/* ******************************* */
+
+static inline void putiac(int c)
+{
+	G.iacbuf[G.iaclen++] = c;
+}
+
+
+static void putiac2(byte wwdd, byte c)
+{
+	if (G.iaclen + 3 > IACBUFSIZE)
+		iacflush();
+
+	putiac(IAC);
+	putiac(wwdd);
+	putiac(c);
+}
+
+#if 0
+static void putiac1(byte c)
+{
+	if (G.iaclen + 2 > IACBUFSIZE)
+		iacflush();
+
+	putiac(IAC);
+	putiac(c);
+}
+#endif
+
+#ifdef CONFIG_FEATURE_TELNET_TTYPE
+static void putiac_subopt(byte c, char *str)
+{
+	int	len = strlen(str) + 6;   // ( 2 + 1 + 1 + strlen + 2 )
+
+	if (G.iaclen + len > IACBUFSIZE)
+		iacflush();
+
+	putiac(IAC);
+	putiac(SB);
+	putiac(c);
+	putiac(0);
+
+	while(*str)
+		putiac(*str++);
+
+	putiac(IAC);
+	putiac(SE);
+}
+#endif
+
+#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
+static void putiac_subopt_autologin(void)
+{
+	int len = strlen(autologin) + 6;	// (2 + 1 + 1 + strlen + 2)
+	char *user = "USER";
+
+	if (G.iaclen + len > IACBUFSIZE)
+		iacflush();
+
+	putiac(IAC);
+	putiac(SB);
+	putiac(TELOPT_NEW_ENVIRON);
+	putiac(TELQUAL_IS);
+	putiac(NEW_ENV_VAR);
+
+	while(*user)
+		putiac(*user++);
+
+	putiac(NEW_ENV_VALUE);
+
+	while(*autologin)
+		putiac(*autologin++);
+
+	putiac(IAC);
+	putiac(SE);
+}
+#endif
+
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+static void putiac_naws(byte c, int x, int y)
+{
+	if (G.iaclen + 9 > IACBUFSIZE)
+		iacflush();
+
+	putiac(IAC);
+	putiac(SB);
+	putiac(c);
+
+	putiac((x >> 8) & 0xff);
+	putiac(x & 0xff);
+	putiac((y >> 8) & 0xff);
+	putiac(y & 0xff);
+
+	putiac(IAC);
+	putiac(SE);
+}
+#endif
+
+/* void putiacstring (subneg strings) */
+
+/* ******************************* */
+
+static char const escapecharis[] = "\r\nEscape character is ";
+
+static void setConMode(void)
+{
+	if (G.telflags & UF_ECHO)
+	{
+		if (G.charmode == CHM_TRY) {
+			G.charmode = CHM_ON;
+			printf("\r\nEntering character mode%s'^]'.\r\n", escapecharis);
+			rawmode();
+		}
+	}
+	else
+	{
+		if (G.charmode != CHM_OFF) {
+			G.charmode = CHM_OFF;
+			printf("\r\nEntering line mode%s'^C'.\r\n", escapecharis);
+			cookmode();
+		}
+	}
+}
+
+/* ******************************* */
+
+static void will_charmode(void)
+{
+	G.charmode = CHM_TRY;
+	G.telflags |= (UF_ECHO | UF_SGA);
+	setConMode();
+
+	putiac2(DO, TELOPT_ECHO);
+	putiac2(DO, TELOPT_SGA);
+	iacflush();
+}
+
+static void do_linemode(void)
+{
+	G.charmode = CHM_TRY;
+	G.telflags &= ~(UF_ECHO | UF_SGA);
+	setConMode();
+
+	putiac2(DONT, TELOPT_ECHO);
+	putiac2(DONT, TELOPT_SGA);
+	iacflush();
+}
+
+/* ******************************* */
+
+static inline void to_notsup(char c)
+{
+	if      (G.telwish == WILL)	putiac2(DONT, c);
+	else if (G.telwish == DO)	putiac2(WONT, c);
+}
+
+static inline void to_echo(void)
+{
+	/* if server requests ECHO, don't agree */
+	if      (G.telwish == DO) {	putiac2(WONT, TELOPT_ECHO);	return; }
+	else if (G.telwish == DONT)	return;
+
+	if (G.telflags & UF_ECHO)
+	{
+		if (G.telwish == WILL)
+			return;
+	}
+	else
+		if (G.telwish == WONT)
+			return;
+
+	if (G.charmode != CHM_OFF)
+		G.telflags ^= UF_ECHO;
+
+	if (G.telflags & UF_ECHO)
+		putiac2(DO, TELOPT_ECHO);
+	else
+		putiac2(DONT, TELOPT_ECHO);
+
+	setConMode();
+	WriteCS(1, "\r\n");  /* sudden modec */
+}
+
+static inline void to_sga(void)
+{
+	/* daemon always sends will/wont, client do/dont */
+
+	if (G.telflags & UF_SGA)
+	{
+		if (G.telwish == WILL)
+			return;
+	}
+	else
+		if (G.telwish == WONT)
+			return;
+
+	if ((G.telflags ^= UF_SGA) & UF_SGA) /* toggle */
+		putiac2(DO, TELOPT_SGA);
+	else
+		putiac2(DONT, TELOPT_SGA);
+
+	return;
+}
+
+#ifdef CONFIG_FEATURE_TELNET_TTYPE
+static inline void to_ttype(void)
+{
+	/* Tell server we will (or won't) do TTYPE */
+
+	if(ttype)
+		putiac2(WILL, TELOPT_TTYPE);
+	else
+		putiac2(WONT, TELOPT_TTYPE);
+
+	return;
+}
+#endif
+
+#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
+static inline void to_new_environ(void)
+{
+	/* Tell server we will (or will not) do AUTOLOGIN */
+
+	if (autologin)
+		putiac2(WILL, TELOPT_NEW_ENVIRON);
+	else
+		putiac2(WONT, TELOPT_NEW_ENVIRON);
+
+	return;
+}
+#endif
+
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+static inline void to_naws(void)
+{
+	/* Tell server we will do NAWS */
+	putiac2(WILL, TELOPT_NAWS);
+	return;
+}
+#endif
+
+static void telopt(byte c)
+{
+	switch (c)
+	{
+		case TELOPT_ECHO:		to_echo();	break;
+		case TELOPT_SGA:		to_sga();	break;
+#ifdef CONFIG_FEATURE_TELNET_TTYPE
+		case TELOPT_TTYPE:		to_ttype();break;
+#endif
+#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
+		case TELOPT_NEW_ENVIRON:	to_new_environ();	break;
+#endif
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+		case TELOPT_NAWS:		to_naws();
+								putiac_naws(c, win_width, win_height);
+								break;
+#endif
+		default:				to_notsup(c);
+								break;
+	}
+}
+
+
+/* ******************************* */
+
+/* subnegotiation -- ignore all (except TTYPE,NAWS) */
+
+static int subneg(byte c)
+{
+	switch (G.telstate)
+	{
+	case TS_SUB1:
+		if (c == IAC)
+			G.telstate = TS_SUB2;
+#ifdef CONFIG_FEATURE_TELNET_TTYPE
+		else
+		if (c == TELOPT_TTYPE)
+			putiac_subopt(TELOPT_TTYPE,ttype);
+#endif
+#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
+		else
+		if (c == TELOPT_NEW_ENVIRON)
+			putiac_subopt_autologin();
+#endif
+		break;
+	case TS_SUB2:
+		if (c == SE)
+			return TRUE;
+		G.telstate = TS_SUB1;
+		/* break; */
+	}
+	return FALSE;
+}
+
+/* ******************************* */
+
+static void fgotsig(int sig)
+{
+	G.gotsig = sig;
+}
+
+
+static void rawmode(void)
+{
+	if (G.do_termios) tcsetattr(0, TCSADRAIN, &G.termios_raw);
+}
+
+static void cookmode(void)
+{
+	if (G.do_termios) tcsetattr(0, TCSADRAIN, &G.termios_def);
+}
+
+int telnet_main(int argc, char** argv)
+{
+	int len;
+	struct sockaddr_in s_in;
+#ifdef USE_POLL
+	struct pollfd ufds[2];
+#else
+	fd_set readfds;
+	int maxfd;
+#endif
+
+#ifdef CONFIG_FEATURE_AUTOWIDTH
+	get_terminal_width_height(0, &win_width, &win_height);
+#endif
+
+#ifdef CONFIG_FEATURE_TELNET_TTYPE
+    ttype = getenv("TERM");
+#endif
+
+	memset(&G, 0, sizeof G);
+
+	if (tcgetattr(0, &G.termios_def) >= 0) {
+		G.do_termios = 1;
+
+		G.termios_raw = G.termios_def;
+		cfmakeraw(&G.termios_raw);
+	}
+
+	if (argc < 2)
+		bb_show_usage();
+
+#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
+	if (1 & bb_getopt_ulflags(argc, argv, "al:", &autologin))
+		autologin = getenv("USER");
+
+	if (optind < argc) {
+		bb_lookup_host(&s_in, argv[optind++]);
+		s_in.sin_port = bb_lookup_port((optind < argc) ? argv[optind++] :
+				"telnet", "tcp", 23);
+		if (optind < argc)
+			bb_show_usage();
+	} else
+		bb_show_usage();
+#else
+	bb_lookup_host(&s_in, argv[1]);
+	s_in.sin_port = bb_lookup_port((argc == 3) ? argv[2] : "telnet", "tcp", 23);
+#endif
+
+	G.netfd = xconnect(&s_in);
+
+	setsockopt(G.netfd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof one);
+
+	signal(SIGINT, fgotsig);
+
+#ifdef USE_POLL
+	ufds[0].fd = 0; ufds[1].fd = G.netfd;
+	ufds[0].events = ufds[1].events = POLLIN;
+#else
+	FD_ZERO(&readfds);
+	FD_SET(0, &readfds);
+	FD_SET(G.netfd, &readfds);
+	maxfd = G.netfd + 1;
+#endif
+
+	while (1)
+	{
+#ifndef USE_POLL
+		fd_set rfds = readfds;
+
+		switch (select(maxfd, &rfds, NULL, NULL, NULL))
+#else
+		switch (poll(ufds, 2, -1))
+#endif
+		{
+		case 0:
+			/* timeout */
+		case -1:
+			/* error, ignore and/or log something, bay go to loop */
+			if (G.gotsig)
+				conescape();
+			else
+				sleep(1);
+			break;
+		default:
+
+#ifdef USE_POLL
+			if (ufds[0].revents) /* well, should check POLLIN, but ... */
+#else
+			if (FD_ISSET(0, &rfds))
+#endif
+			{
+				len = read(0, G.buf, DATABUFSIZE);
+
+				if (len <= 0)
+					doexit(0);
+
+				TRACE(0, ("Read con: %d\n", len));
+
+				handlenetoutput(len);
+			}
+
+#ifdef USE_POLL
+			if (ufds[1].revents) /* well, should check POLLIN, but ... */
+#else
+			if (FD_ISSET(G.netfd, &rfds))
+#endif
+			{
+				len = read(G.netfd, G.buf, DATABUFSIZE);
+
+				if (len <= 0)
+				{
+					WriteCS(1, "Connection closed by foreign host.\r\n");
+					doexit(1);
+				}
+				TRACE(0, ("Read netfd (%d): %d\n", G.netfd, len));
+
+				handlenetinput(len);
+			}
+		}
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/telnetd.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/telnetd.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/telnetd.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,669 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Simple telnet server
+ * Bjorn Wesen, Axis Communications AB (bjornw at axis.com)
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * ---------------------------------------------------------------------------
+ * (C) Copyright 2000, Axis Communications AB, LUND, SWEDEN
+ ****************************************************************************
+ *
+ * The telnetd manpage says it all:
+ *
+ *   Telnetd operates by allocating a pseudo-terminal device (see pty(4))  for
+ *   a client, then creating a login process which has the slave side of the
+ *   pseudo-terminal as stdin, stdout, and stderr. Telnetd manipulates the
+ *   master side of the pseudo-terminal, implementing the telnet protocol and
+ *   passing characters between the remote client and the login process.
+ *
+ * Vladimir Oleynik <dzo at simtreas.ru> 2001
+ *     Set process group corrections, initial busybox port
+ */
+
+/*#define DEBUG 1 */
+#undef DEBUG
+
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <signal.h>
+#include <termios.h>
+#ifdef DEBUG
+#define TELCMDS
+#define TELOPTS
+#endif
+#include <arpa/telnet.h>
+#include <ctype.h>
+#include <sys/syslog.h>
+
+#include "busybox.h"
+
+#define BUFSIZE 4000
+
+#ifdef CONFIG_FEATURE_IPV6
+#define SOCKET_TYPE	AF_INET6
+typedef struct sockaddr_in6 sockaddr_type;
+#else
+#define SOCKET_TYPE	AF_INET
+typedef struct sockaddr_in sockaddr_type;
+#endif
+
+
+#ifdef CONFIG_LOGIN
+static const char *loginpath = "/bin/login";
+#else
+static const char *loginpath;
+#endif
+static const char *issuefile = "/etc/issue.net";
+
+/* shell name and arguments */
+
+static const char *argv_init[] = {NULL, NULL};
+
+/* structure that describes a session */
+
+struct tsession {
+#ifdef CONFIG_FEATURE_TELNETD_INETD
+	int sockfd_read, sockfd_write, ptyfd;
+#else /* CONFIG_FEATURE_TELNETD_INETD */
+	struct tsession *next;
+	int sockfd, ptyfd;
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+	int shell_pid;
+	/* two circular buffers */
+	char *buf1, *buf2;
+	int rdidx1, wridx1, size1;
+	int rdidx2, wridx2, size2;
+};
+
+/*
+
+   This is how the buffers are used. The arrows indicate the movement
+   of data.
+
+   +-------+     wridx1++     +------+     rdidx1++     +----------+
+   |       | <--------------  | buf1 | <--------------  |          |
+   |       |     size1--      +------+     size1++      |          |
+   |  pty  |                                            |  socket  |
+   |       |     rdidx2++     +------+     wridx2++     |          |
+   |       |  --------------> | buf2 |  --------------> |          |
+   +-------+     size2++      +------+     size2--      +----------+
+
+   Each session has got two buffers.
+
+*/
+
+static int maxfd;
+
+static struct tsession *sessions;
+
+
+/*
+
+   Remove all IAC's from the buffer pointed to by bf (received IACs are ignored
+   and must be removed so as to not be interpreted by the terminal).  Make an
+   uninterrupted string of characters fit for the terminal.  Do this by packing
+   all characters meant for the terminal sequentially towards the end of bf.
+
+   Return a pointer to the beginning of the characters meant for the terminal.
+   and make *num_totty the number of characters that should be sent to
+   the terminal.
+
+   Note - If an IAC (3 byte quantity) starts before (bf + len) but extends
+   past (bf + len) then that IAC will be left unprocessed and *processed will be
+   less than len.
+
+   FIXME - if we mean to send 0xFF to the terminal then it will be escaped,
+   what is the escape character?  We aren't handling that situation here.
+
+   CR-LF ->'s CR mapping is also done here, for convenience
+
+  */
+static char *
+remove_iacs(struct tsession *ts, int *pnum_totty) {
+	unsigned char *ptr0 = (unsigned char *)ts->buf1 + ts->wridx1;
+	unsigned char *ptr = ptr0;
+	unsigned char *totty = ptr;
+	unsigned char *end = ptr + MIN(BUFSIZE - ts->wridx1, ts->size1);
+	int processed;
+	int num_totty;
+
+	while (ptr < end) {
+		if (*ptr != IAC) {
+			int c = *ptr;
+			*totty++ = *ptr++;
+			/* We now map \r\n ==> \r for pragmatic reasons.
+			 * Many client implementations send \r\n when
+			 * the user hits the CarriageReturn key.
+			 */
+			if (c == '\r' && (*ptr == '\n' || *ptr == 0) && ptr < end)
+				ptr++;
+		}
+		else {
+			/*
+			 * TELOPT_NAWS support!
+			 */
+			if ((ptr+2) >= end) {
+				/* only the beginning of the IAC is in the
+				buffer we were asked to process, we can't
+				process this char. */
+				break;
+			}
+
+			/*
+			 * IAC -> SB -> TELOPT_NAWS -> 4-byte -> IAC -> SE
+			 */
+			else if (ptr[1] == SB && ptr[2] == TELOPT_NAWS) {
+				struct winsize ws;
+				if ((ptr+8) >= end)
+					break;	/* incomplete, can't process */
+				ws.ws_col = (ptr[3] << 8) | ptr[4];
+				ws.ws_row = (ptr[5] << 8) | ptr[6];
+				(void) ioctl(ts->ptyfd, TIOCSWINSZ, (char *)&ws);
+				ptr += 9;
+			}
+			else {
+				/* skip 3-byte IAC non-SB cmd */
+#ifdef DEBUG
+				fprintf(stderr, "Ignoring IAC %s,%s\n",
+					TELCMD(*(ptr+1)), TELOPT(*(ptr+2)));
+#endif
+				ptr += 3;
+			}
+		}
+	}
+
+	processed = ptr - ptr0;
+	num_totty = totty - ptr0;
+	/* the difference between processed and num_to tty
+	   is all the iacs we removed from the stream.
+	   Adjust buf1 accordingly. */
+	ts->wridx1 += processed - num_totty;
+	ts->size1 -= processed - num_totty;
+	*pnum_totty = num_totty;
+	/* move the chars meant for the terminal towards the end of the
+	buffer. */
+	return memmove(ptr - num_totty, ptr0, num_totty);
+}
+
+
+static int
+getpty(char *line)
+{
+	int p;
+#ifdef CONFIG_FEATURE_DEVPTS
+	p = open("/dev/ptmx", 2);
+	if (p > 0) {
+		grantpt(p);
+		unlockpt(p);
+		strcpy(line, ptsname(p));
+		return(p);
+	}
+#else
+	struct stat stb;
+	int i;
+	int j;
+
+	strcpy(line, "/dev/ptyXX");
+
+	for (i = 0; i < 16; i++) {
+		line[8] = "pqrstuvwxyzabcde"[i];
+		line[9] = '0';
+		if (stat(line, &stb) < 0) {
+			continue;
+		}
+		for (j = 0; j < 16; j++) {
+			line[9] = j < 10 ? j + '0' : j - 10 + 'a';
+#ifdef DEBUG
+			fprintf(stderr, "Trying to open device: %s\n", line);
+#endif
+			if ((p = open(line, O_RDWR | O_NOCTTY)) >= 0) {
+				line[5] = 't';
+				return p;
+			}
+		}
+	}
+#endif /* CONFIG_FEATURE_DEVPTS */
+	return -1;
+}
+
+
+static void
+send_iac(struct tsession *ts, unsigned char command, int option)
+{
+	/* We rely on that there is space in the buffer for now.  */
+	char *b = ts->buf2 + ts->rdidx2;
+	*b++ = IAC;
+	*b++ = command;
+	*b++ = option;
+	ts->rdidx2 += 3;
+	ts->size2 += 3;
+}
+
+
+static struct tsession *
+#ifdef CONFIG_FEATURE_TELNETD_INETD
+make_new_session(void)
+#else /* CONFIG_FEATURE_TELNETD_INETD */
+make_new_session(int sockfd)
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+{
+	struct termios termbuf;
+	int pty, pid;
+	char tty_name[32];
+	struct tsession *ts = xzalloc(sizeof(struct tsession) + BUFSIZE * 2);
+
+	ts->buf1 = (char *)(&ts[1]);
+	ts->buf2 = ts->buf1 + BUFSIZE;
+
+#ifdef CONFIG_FEATURE_TELNETD_INETD
+	ts->sockfd_write = 1;
+#else /* CONFIG_FEATURE_TELNETD_INETD */
+	ts->sockfd = sockfd;
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+
+	/* Got a new connection, set up a tty and spawn a shell.  */
+
+	pty = getpty(tty_name);
+
+	if (pty < 0) {
+		syslog(LOG_ERR, "All terminals in use!");
+		return 0;
+	}
+
+	if (pty > maxfd)
+		maxfd = pty;
+
+	ts->ptyfd = pty;
+
+	/* Make the telnet client understand we will echo characters so it
+	 * should not do it locally. We don't tell the client to run linemode,
+	 * because we want to handle line editing and tab completion and other
+	 * stuff that requires char-by-char support.
+	 */
+
+	send_iac(ts, DO, TELOPT_ECHO);
+	send_iac(ts, DO, TELOPT_NAWS);
+	send_iac(ts, DO, TELOPT_LFLOW);
+	send_iac(ts, WILL, TELOPT_ECHO);
+	send_iac(ts, WILL, TELOPT_SGA);
+
+	if ((pid = fork()) < 0) {
+		syslog(LOG_ERR, "Could not fork");
+	}
+	if (pid == 0) {
+		/* In child, open the child's side of the tty.  */
+		int i;
+
+		for(i = 0; i <= maxfd; i++)
+			close(i);
+		/* make new process group */
+		setsid();
+
+		if (open(tty_name, O_RDWR /*| O_NOCTTY*/) < 0) {
+			syslog(LOG_ERR, "Could not open tty");
+			exit(1);
+		}
+		dup(0);
+		dup(0);
+
+		tcsetpgrp(0, getpid());
+
+		/* The pseudo-terminal allocated to the client is configured to operate in
+		 * cooked mode, and with XTABS CRMOD enabled (see tty(4)).
+		 */
+
+		tcgetattr(0, &termbuf);
+		termbuf.c_lflag |= ECHO; /* if we use readline we dont want this */
+		termbuf.c_oflag |= ONLCR|XTABS;
+		termbuf.c_iflag |= ICRNL;
+		termbuf.c_iflag &= ~IXOFF;
+		/*termbuf.c_lflag &= ~ICANON;*/
+		tcsetattr(0, TCSANOW, &termbuf);
+
+		print_login_issue(issuefile, NULL);
+
+		/* exec shell, with correct argv and env */
+		execv(loginpath, (char *const *)argv_init);
+
+		/* NOT REACHED */
+		syslog(LOG_ERR, "execv error");
+		exit(1);
+	}
+
+	ts->shell_pid = pid;
+
+	return ts;
+}
+
+#ifndef CONFIG_FEATURE_TELNETD_INETD
+static void
+free_session(struct tsession *ts)
+{
+	struct tsession *t = sessions;
+
+	/* Unlink this telnet session from the session list.  */
+	if (t == ts)
+		sessions = ts->next;
+	else {
+		while(t->next != ts)
+			t = t->next;
+		t->next = ts->next;
+	}
+
+	kill(ts->shell_pid, SIGKILL);
+
+	wait4(ts->shell_pid, NULL, 0, NULL);
+
+	close(ts->ptyfd);
+	close(ts->sockfd);
+
+	if (ts->ptyfd == maxfd || ts->sockfd == maxfd)
+		maxfd--;
+	if (ts->ptyfd == maxfd || ts->sockfd == maxfd)
+		maxfd--;
+
+	free(ts);
+}
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+
+int
+telnetd_main(int argc, char **argv)
+{
+#ifndef CONFIG_FEATURE_TELNETD_INETD
+	sockaddr_type sa;
+	int master_fd;
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+	fd_set rdfdset, wrfdset;
+	int selret;
+#ifndef CONFIG_FEATURE_TELNETD_INETD
+	int on = 1;
+	int portnbr = 23;
+	struct in_addr bind_addr = { .s_addr = 0x0 };
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+	int c;
+	static const char options[] =
+#ifdef CONFIG_FEATURE_TELNETD_INETD
+		"f:l:";
+#else /* CONFIG_EATURE_TELNETD_INETD */
+		"f:l:p:b:";
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+	int maxlen, w, r;
+
+#ifndef CONFIG_LOGIN
+	loginpath = DEFAULT_SHELL;
+#endif
+
+	for (;;) {
+		c = getopt( argc, argv, options);
+		if (c == EOF) break;
+		switch (c) {
+			case 'f':
+				issuefile = optarg;
+				break;
+			case 'l':
+				loginpath = optarg;
+				break;
+#ifndef CONFIG_FEATURE_TELNETD_INETD
+			case 'p':
+				portnbr = atoi(optarg);
+				break;
+			case 'b':
+				if (inet_aton(optarg, &bind_addr) == 0)
+					bb_show_usage();
+				break;
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+			default:
+				bb_show_usage();
+		}
+	}
+
+	if (access(loginpath, X_OK) < 0) {
+		bb_error_msg_and_die ("'%s' unavailable.", loginpath);
+	}
+
+	argv_init[0] = loginpath;
+
+	openlog(bb_applet_name, 0, LOG_USER);
+
+#ifdef CONFIG_FEATURE_TELNETD_INETD
+	maxfd = 1;
+	sessions = make_new_session();
+#else /* CONFIG_EATURE_TELNETD_INETD */
+	sessions = 0;
+
+	/* Grab a TCP socket.  */
+
+	master_fd = bb_xsocket(SOCKET_TYPE, SOCK_STREAM, 0);
+	(void)setsockopt(master_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+
+	/* Set it to listen to specified port.  */
+
+	memset((void *)&sa, 0, sizeof(sa));
+#ifdef CONFIG_FEATURE_IPV6
+	sa.sin6_family = AF_INET6;
+	sa.sin6_port = htons(portnbr);
+	/* sa.sin6_addr = bind_addr6; */
+#else
+	sa.sin_family = AF_INET;
+	sa.sin_port = htons(portnbr);
+	sa.sin_addr = bind_addr;
+#endif
+
+	bb_xbind(master_fd, (struct sockaddr *) &sa, sizeof(sa));
+	bb_xlisten(master_fd, 1);
+	bb_xdaemon(0, 0);
+
+	maxfd = master_fd;
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+
+	do {
+		struct tsession *ts;
+
+		FD_ZERO(&rdfdset);
+		FD_ZERO(&wrfdset);
+
+		/* select on the master socket, all telnet sockets and their
+		 * ptys if there is room in their respective session buffers.
+		 */
+
+#ifndef CONFIG_FEATURE_TELNETD_INETD
+		FD_SET(master_fd, &rdfdset);
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+
+		ts = sessions;
+#ifndef CONFIG_FEATURE_TELNETD_INETD
+		while (ts) {
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+			/* buf1 is used from socket to pty
+			 * buf2 is used from pty to socket
+			 */
+			if (ts->size1 > 0) {
+				FD_SET(ts->ptyfd, &wrfdset);  /* can write to pty */
+			}
+			if (ts->size1 < BUFSIZE) {
+#ifdef CONFIG_FEATURE_TELNETD_INETD
+				FD_SET(ts->sockfd_read, &rdfdset); /* can read from socket */
+#else /* CONFIG_FEATURE_TELNETD_INETD */
+				FD_SET(ts->sockfd, &rdfdset); /* can read from socket */
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+			}
+			if (ts->size2 > 0) {
+#ifdef CONFIG_FEATURE_TELNETD_INETD
+				FD_SET(ts->sockfd_write, &wrfdset); /* can write to socket */
+#else /* CONFIG_FEATURE_TELNETD_INETD */
+				FD_SET(ts->sockfd, &wrfdset); /* can write to socket */
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+			}
+			if (ts->size2 < BUFSIZE) {
+				FD_SET(ts->ptyfd, &rdfdset);  /* can read from pty */
+			}
+#ifndef CONFIG_FEATURE_TELNETD_INETD
+			ts = ts->next;
+		}
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+
+		selret = select(maxfd + 1, &rdfdset, &wrfdset, 0, 0);
+
+		if (!selret)
+			break;
+
+#ifndef CONFIG_FEATURE_TELNETD_INETD
+		/* First check for and accept new sessions.  */
+		if (FD_ISSET(master_fd, &rdfdset)) {
+			int fd;
+			socklen_t salen;
+
+			salen = sizeof(sa);
+			if ((fd = accept(master_fd, (struct sockaddr *)&sa,
+						&salen)) < 0) {
+				continue;
+			} else {
+				/* Create a new session and link it into
+					our active list.  */
+				struct tsession *new_ts = make_new_session(fd);
+				if (new_ts) {
+					new_ts->next = sessions;
+					sessions = new_ts;
+					if (fd > maxfd)
+						maxfd = fd;
+				} else {
+					close(fd);
+				}
+			}
+		}
+
+		/* Then check for data tunneling.  */
+
+		ts = sessions;
+		while (ts) { /* For all sessions...  */
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+#ifndef CONFIG_FEATURE_TELNETD_INETD
+			struct tsession *next = ts->next; /* in case we free ts. */
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+
+			if (ts->size1 && FD_ISSET(ts->ptyfd, &wrfdset)) {
+				int num_totty;
+				char *ptr;
+				/* Write to pty from buffer 1.  */
+
+				ptr = remove_iacs(ts, &num_totty);
+
+				w = write(ts->ptyfd, ptr, num_totty);
+				if (w < 0) {
+#ifdef CONFIG_FEATURE_TELNETD_INETD
+					exit(0);
+#else /* CONFIG_FEATURE_TELNETD_INETD */
+					free_session(ts);
+					ts = next;
+					continue;
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+				}
+				ts->wridx1 += w;
+				ts->size1 -= w;
+				if (ts->wridx1 == BUFSIZE)
+					ts->wridx1 = 0;
+			}
+
+#ifdef CONFIG_FEATURE_TELNETD_INETD
+			if (ts->size2 && FD_ISSET(ts->sockfd_write, &wrfdset)) {
+#else /* CONFIG_FEATURE_TELNETD_INETD */
+			if (ts->size2 && FD_ISSET(ts->sockfd, &wrfdset)) {
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+				/* Write to socket from buffer 2.  */
+				maxlen = MIN(BUFSIZE - ts->wridx2, ts->size2);
+#ifdef CONFIG_FEATURE_TELNETD_INETD
+				w = write(ts->sockfd_write, ts->buf2 + ts->wridx2, maxlen);
+				if (w < 0)
+					exit(0);
+#else /* CONFIG_FEATURE_TELNETD_INETD */
+				w = write(ts->sockfd, ts->buf2 + ts->wridx2, maxlen);
+				if (w < 0) {
+					free_session(ts);
+					ts = next;
+					continue;
+				}
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+				ts->wridx2 += w;
+				ts->size2 -= w;
+				if (ts->wridx2 == BUFSIZE)
+					ts->wridx2 = 0;
+			}
+
+#ifdef CONFIG_FEATURE_TELNETD_INETD
+			if (ts->size1 < BUFSIZE && FD_ISSET(ts->sockfd_read, &rdfdset)) {
+#else /* CONFIG_FEATURE_TELNETD_INETD */
+			if (ts->size1 < BUFSIZE && FD_ISSET(ts->sockfd, &rdfdset)) {
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+				/* Read from socket to buffer 1. */
+				maxlen = MIN(BUFSIZE - ts->rdidx1,
+						BUFSIZE - ts->size1);
+#ifdef CONFIG_FEATURE_TELNETD_INETD
+				r = read(ts->sockfd_read, ts->buf1 + ts->rdidx1, maxlen);
+				if (!r || (r < 0 && errno != EINTR))
+					exit(0);
+#else /* CONFIG_FEATURE_TELNETD_INETD */
+				r = read(ts->sockfd, ts->buf1 + ts->rdidx1, maxlen);
+				if (!r || (r < 0 && errno != EINTR)) {
+					free_session(ts);
+					ts = next;
+					continue;
+				}
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+				if (!*(ts->buf1 + ts->rdidx1 + r - 1)) {
+					r--;
+					if (!r)
+						continue;
+				}
+				ts->rdidx1 += r;
+				ts->size1 += r;
+				if (ts->rdidx1 == BUFSIZE)
+					ts->rdidx1 = 0;
+			}
+
+			if (ts->size2 < BUFSIZE && FD_ISSET(ts->ptyfd, &rdfdset)) {
+				/* Read from pty to buffer 2.  */
+				maxlen = MIN(BUFSIZE - ts->rdidx2,
+						BUFSIZE - ts->size2);
+				r = read(ts->ptyfd, ts->buf2 + ts->rdidx2, maxlen);
+				if (!r || (r < 0 && errno != EINTR)) {
+#ifdef CONFIG_FEATURE_TELNETD_INETD
+					exit(0);
+#else /* CONFIG_FEATURE_TELNETD_INETD */
+					free_session(ts);
+					ts = next;
+					continue;
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+				}
+				ts->rdidx2 += r;
+				ts->size2 += r;
+				if (ts->rdidx2 == BUFSIZE)
+					ts->rdidx2 = 0;
+			}
+
+			if (ts->size1 == 0) {
+				ts->rdidx1 = 0;
+				ts->wridx1 = 0;
+			}
+			if (ts->size2 == 0) {
+				ts->rdidx2 = 0;
+				ts->wridx2 = 0;
+			}
+#ifndef CONFIG_FEATURE_TELNETD_INETD
+			ts = next;
+		}
+#endif /* CONFIG_FEATURE_TELNETD_INETD */
+
+	} while (1);
+
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/tftp.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/tftp.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/tftp.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,575 @@
+/* vi: set sw=4 ts=4: */
+/* -------------------------------------------------------------------------
+ * tftp.c
+ *
+ * A simple tftp client for busybox.
+ * Tries to follow RFC1350.
+ * Only "octet" mode supported.
+ * Optional blocksize negotiation (RFC2347 + RFC2348)
+ *
+ * Copyright (C) 2001 Magnus Damm <damm at opensource.se>
+ *
+ * Parts of the code based on:
+ *
+ * atftp:  Copyright (C) 2000 Jean-Pierre Lefebvre <helix at step.polymtl.ca>
+ *                        and Remi Lefebvre <remi at debian.org>
+ *
+ * utftp:  Copyright (C) 1999 Uwe Ohse <uwe at ohse.de>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ * ------------------------------------------------------------------------- */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "busybox.h"
+
+
+#define TFTP_BLOCKSIZE_DEFAULT 512	/* according to RFC 1350, don't change */
+#define TFTP_TIMEOUT 5	/* seconds */
+#define TFTP_NUM_RETRIES 5 /* number of retries */
+
+static const char * const MODE_OCTET = "octet";
+#define MODE_OCTET_LEN 6 /* sizeof(MODE_OCTET)*/
+
+static const char * const OPTION_BLOCKSIZE = "blksize";
+#define OPTION_BLOCKSIZE_LEN 8 /* sizeof(OPTION_BLOCKSIZE) */
+
+/* opcodes we support */
+#define TFTP_RRQ   1
+#define TFTP_WRQ   2
+#define TFTP_DATA  3
+#define TFTP_ACK   4
+#define TFTP_ERROR 5
+#define TFTP_OACK  6
+
+static const char *const tftp_bb_error_msg[] = {
+	"Undefined error",
+	"File not found",
+	"Access violation",
+	"Disk full or allocation error",
+	"Illegal TFTP operation",
+	"Unknown transfer ID",
+	"File already exists",
+	"No such user"
+};
+
+#define tftp_cmd_get ENABLE_FEATURE_TFTP_GET
+
+#if ENABLE_FEATURE_TFTP_PUT
+# define tftp_cmd_put (tftp_cmd_get+ENABLE_FEATURE_TFTP_PUT)
+#else
+# define tftp_cmd_put 0
+#endif
+
+
+#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE
+
+static int tftp_blocksize_check(int blocksize, int bufsize)
+{
+	/* Check if the blocksize is valid:
+	 * RFC2348 says between 8 and 65464,
+	 * but our implementation makes it impossible
+	 * to use blocksizes smaller than 22 octets.
+	 */
+
+	if ((bufsize && (blocksize > bufsize)) ||
+		(blocksize < 8) || (blocksize > 65564)) {
+		bb_error_msg("bad blocksize");
+		return 0;
+	}
+
+	return blocksize;
+}
+
+static char *tftp_option_get(char *buf, int len, const char * const option)
+{
+	int opt_val = 0;
+	int opt_found = 0;
+	int k;
+
+	while (len > 0) {
+
+		/* Make sure the options are terminated correctly */
+
+		for (k = 0; k < len; k++) {
+			if (buf[k] == '\0') {
+				break;
+			}
+		}
+
+		if (k >= len) {
+			break;
+		}
+
+		if (opt_val == 0) {
+			if (strcasecmp(buf, option) == 0) {
+				opt_found = 1;
+			}
+		} else {
+			if (opt_found) {
+				return buf;
+			}
+		}
+
+		k++;
+
+		buf += k;
+		len -= k;
+
+		opt_val ^= 1;
+	}
+
+	return NULL;
+}
+
+#endif
+
+static int tftp(const int cmd, const struct hostent *host,
+		   const char *remotefile, const int localfd,
+		   const unsigned short port, int tftp_bufsize)
+{
+	struct sockaddr_in sa;
+	struct sockaddr_in from;
+	struct timeval tv;
+	socklen_t fromlen;
+	fd_set rfds;
+	int socketfd;
+	int len;
+	int opcode = 0;
+	int finished = 0;
+	int timeout = TFTP_NUM_RETRIES;
+	unsigned short block_nr = 1;
+	unsigned short tmp;
+	char *cp;
+
+	USE_FEATURE_TFTP_BLOCKSIZE(int want_option_ack = 0;)
+
+	/* Can't use RESERVE_CONFIG_BUFFER here since the allocation
+	 * size varies meaning BUFFERS_GO_ON_STACK would fail */
+	char *buf=xmalloc(tftp_bufsize += 4);
+
+	if ((socketfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
+		/* need to unlink the localfile, so don't use bb_xsocket here. */
+		bb_perror_msg("socket");
+		return EXIT_FAILURE;
+	}
+
+	len = sizeof(sa);
+
+	memset(&sa, 0, len);
+	bb_xbind(socketfd, (struct sockaddr *)&sa, len);
+
+	sa.sin_family = host->h_addrtype;
+	sa.sin_port = port;
+	memcpy(&sa.sin_addr, (struct in_addr *) host->h_addr,
+		   sizeof(sa.sin_addr));
+
+	/* build opcode */
+	if (cmd & tftp_cmd_get) {
+		opcode = TFTP_RRQ;
+	}
+	if (cmd & tftp_cmd_put) {
+		opcode = TFTP_WRQ;
+	}
+
+	while (1) {
+
+		cp = buf;
+
+		/* first create the opcode part */
+		*((unsigned short *) cp) = htons(opcode);
+		cp += 2;
+
+		/* add filename and mode */
+		if (((cmd & tftp_cmd_get) && (opcode == TFTP_RRQ)) ||
+			((cmd & tftp_cmd_put) && (opcode == TFTP_WRQ)))
+		{
+			int too_long = 0;
+
+			/* see if the filename fits into buf
+			 * and fill in packet.  */
+			len = strlen(remotefile) + 1;
+
+			if ((cp + len) >= &buf[tftp_bufsize - 1]) {
+				too_long = 1;
+			} else {
+				safe_strncpy(cp, remotefile, len);
+				cp += len;
+			}
+
+			if (too_long || ((&buf[tftp_bufsize - 1] - cp) < MODE_OCTET_LEN)) {
+				bb_error_msg("remote filename too long");
+				break;
+			}
+
+			/* add "mode" part of the package */
+			memcpy(cp, MODE_OCTET, MODE_OCTET_LEN);
+			cp += MODE_OCTET_LEN;
+
+#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE
+
+			len = tftp_bufsize - 4;	/* data block size */
+
+			if (len != TFTP_BLOCKSIZE_DEFAULT) {
+
+				if ((&buf[tftp_bufsize - 1] - cp) < 15) {
+					bb_error_msg("remote filename too long");
+					break;
+				}
+
+				/* add "blksize" + number of blocks  */
+				memcpy(cp, OPTION_BLOCKSIZE, OPTION_BLOCKSIZE_LEN);
+				cp += OPTION_BLOCKSIZE_LEN;
+				cp += snprintf(cp, 6, "%d", len) + 1;
+
+				want_option_ack = 1;
+			}
+#endif
+		}
+
+		/* add ack and data */
+
+		if (((cmd & tftp_cmd_get) && (opcode == TFTP_ACK)) ||
+			((cmd & tftp_cmd_put) && (opcode == TFTP_DATA))) {
+
+			*((unsigned short *) cp) = htons(block_nr);
+
+			cp += 2;
+
+			block_nr++;
+
+			if ((cmd & tftp_cmd_put) && (opcode == TFTP_DATA)) {
+				len = bb_full_read(localfd, cp, tftp_bufsize - 4);
+
+				if (len < 0) {
+					bb_perror_msg(bb_msg_read_error);
+					break;
+				}
+
+				if (len != (tftp_bufsize - 4)) {
+					finished++;
+				}
+
+				cp += len;
+			}
+		}
+
+
+		/* send packet */
+
+
+		timeout = TFTP_NUM_RETRIES;	/* re-initialize */
+		do {
+
+			len = cp - buf;
+
+#ifdef CONFIG_DEBUG_TFTP
+			fprintf(stderr, "sending %u bytes\n", len);
+			for (cp = buf; cp < &buf[len]; cp++)
+				fprintf(stderr, "%02x ", (unsigned char) *cp);
+			fprintf(stderr, "\n");
+#endif
+			if (sendto(socketfd, buf, len, 0,
+					   (struct sockaddr *) &sa, sizeof(sa)) < 0) {
+				bb_perror_msg("send");
+				len = -1;
+				break;
+			}
+
+
+			if (finished && (opcode == TFTP_ACK)) {
+				break;
+			}
+
+			/* receive packet */
+
+			memset(&from, 0, sizeof(from));
+			fromlen = sizeof(from);
+
+			tv.tv_sec = TFTP_TIMEOUT;
+			tv.tv_usec = 0;
+
+			FD_ZERO(&rfds);
+			FD_SET(socketfd, &rfds);
+
+			switch (select(socketfd + 1, &rfds, NULL, NULL, &tv)) {
+			case 1:
+				len = recvfrom(socketfd, buf, tftp_bufsize, 0,
+							   (struct sockaddr *) &from, &fromlen);
+
+				if (len < 0) {
+					bb_perror_msg("recvfrom");
+					break;
+				}
+
+				timeout = 0;
+
+				if (sa.sin_port == port) {
+					sa.sin_port = from.sin_port;
+				}
+				if (sa.sin_port == from.sin_port) {
+					break;
+				}
+
+				/* fall-through for bad packets! */
+				/* discard the packet - treat as timeout */
+				timeout = TFTP_NUM_RETRIES;
+			case 0:
+				bb_error_msg("timeout");
+
+				timeout--;
+				if (timeout == 0) {
+					len = -1;
+					bb_error_msg("last timeout");
+				}
+				break;
+			default:
+				bb_perror_msg("select");
+				len = -1;
+			}
+
+		} while (timeout && (len >= 0));
+
+		if ((finished) || (len < 0)) {
+			break;
+		}
+
+		/* process received packet */
+
+		opcode = ntohs(*((unsigned short *) buf));
+		tmp = ntohs(*((unsigned short *) &buf[2]));
+
+#ifdef CONFIG_DEBUG_TFTP
+		fprintf(stderr, "received %d bytes: %04x %04x\n", len, opcode, tmp);
+#endif
+
+		if (opcode == TFTP_ERROR) {
+			const char *msg = NULL;
+
+			if (buf[4] != '\0') {
+				msg = &buf[4];
+				buf[tftp_bufsize - 1] = '\0';
+			} else if (tmp < (sizeof(tftp_bb_error_msg)
+							  / sizeof(char *))) {
+
+				msg = tftp_bb_error_msg[tmp];
+			}
+
+			if (msg) {
+				bb_error_msg("server says: %s", msg);
+			}
+
+			break;
+		}
+#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE
+		if (want_option_ack) {
+
+			want_option_ack = 0;
+
+			if (opcode == TFTP_OACK) {
+
+				/* server seems to support options */
+
+				char *res;
+
+				res = tftp_option_get(&buf[2], len - 2, OPTION_BLOCKSIZE);
+
+				if (res) {
+					int blksize = atoi(res);
+
+					if (tftp_blocksize_check(blksize, tftp_bufsize - 4)) {
+
+						if (cmd & tftp_cmd_put) {
+							opcode = TFTP_DATA;
+						} else {
+							opcode = TFTP_ACK;
+						}
+#ifdef CONFIG_DEBUG_TFTP
+						fprintf(stderr, "using %s %u\n", OPTION_BLOCKSIZE,
+								blksize);
+#endif
+						tftp_bufsize = blksize + 4;
+						block_nr = 0;
+						continue;
+					}
+				}
+				/* FIXME:
+				 * we should send ERROR 8 */
+				bb_error_msg("bad server option");
+				break;
+			}
+
+			bb_error_msg("warning: blksize not supported by server"
+						 " - reverting to 512");
+
+			tftp_bufsize = TFTP_BLOCKSIZE_DEFAULT + 4;
+		}
+#endif
+
+		if ((cmd & tftp_cmd_get) && (opcode == TFTP_DATA)) {
+
+			if (tmp == block_nr) {
+
+				len = bb_full_write(localfd, &buf[4], len - 4);
+
+				if (len < 0) {
+					bb_perror_msg(bb_msg_write_error);
+					break;
+				}
+
+				if (len != (tftp_bufsize - 4)) {
+					finished++;
+				}
+
+				opcode = TFTP_ACK;
+				continue;
+			}
+			/* in case the last ack disappeared into the ether */
+			if (tmp == (block_nr - 1)) {
+				--block_nr;
+				opcode = TFTP_ACK;
+				continue;
+			} else if (tmp + 1 == block_nr) {
+				/* Server lost our TFTP_ACK.  Resend it */
+				block_nr = tmp;
+				opcode = TFTP_ACK;
+				continue;
+			}
+		}
+
+		if ((cmd & tftp_cmd_put) && (opcode == TFTP_ACK)) {
+
+			if (tmp == (unsigned short) (block_nr - 1)) {
+				if (finished) {
+					break;
+				}
+
+				opcode = TFTP_DATA;
+				continue;
+			}
+		}
+	}
+
+#ifdef CONFIG_FEATURE_CLEAN_UP
+	close(socketfd);
+	free(buf);
+#endif
+
+	return finished ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+int tftp_main(int argc, char **argv)
+{
+	struct hostent *host = NULL;
+	const char *localfile = NULL;
+	const char *remotefile = NULL;
+	int port;
+	int cmd = 0;
+	int fd = -1;
+	int flags = 0;
+	int result;
+	int blocksize = TFTP_BLOCKSIZE_DEFAULT;
+
+	/* figure out what to pass to getopt */
+
+#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE
+	char *sblocksize = NULL;
+
+#define BS "b:"
+#define BS_ARG , &sblocksize
+#else
+#define BS
+#define BS_ARG
+#endif
+
+#ifdef CONFIG_FEATURE_TFTP_GET
+#define GET "g"
+#define GET_COMPL ":g"
+#else
+#define GET
+#define GET_COMPL
+#endif
+
+#ifdef CONFIG_FEATURE_TFTP_PUT
+#define PUT "p"
+#define PUT_COMPL ":p"
+#else
+#define PUT
+#define PUT_COMPL
+#endif
+
+#if defined(CONFIG_FEATURE_TFTP_GET) && defined(CONFIG_FEATURE_TFTP_PUT)
+	bb_opt_complementally = GET_COMPL PUT_COMPL ":?g--p:p--g";
+#elif defined(CONFIG_FEATURE_TFTP_GET) || defined(CONFIG_FEATURE_TFTP_PUT)
+	bb_opt_complementally = GET_COMPL PUT_COMPL;
+#endif
+
+
+	cmd = bb_getopt_ulflags(argc, argv, GET PUT "l:r:" BS,
+							&localfile, &remotefile BS_ARG);
+
+	cmd &= (tftp_cmd_get | tftp_cmd_put);
+#ifdef CONFIG_FEATURE_TFTP_GET
+	if (cmd == tftp_cmd_get)
+		flags = O_WRONLY | O_CREAT | O_TRUNC;
+#endif
+#ifdef CONFIG_FEATURE_TFTP_PUT
+	if (cmd == tftp_cmd_put)
+		flags = O_RDONLY;
+#endif
+
+#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE
+	if (sblocksize) {
+		blocksize = atoi(sblocksize);
+		if (!tftp_blocksize_check(blocksize, 0)) {
+			return EXIT_FAILURE;
+		}
+	}
+#endif
+
+	if (localfile == NULL)
+		localfile = remotefile;
+	if (remotefile == NULL)
+		remotefile = localfile;
+	if ((localfile == NULL && remotefile == NULL) || (argv[optind] == NULL))
+		bb_show_usage();
+
+	if (localfile == NULL || strcmp(localfile, "-") == 0) {
+		fd = (cmd == tftp_cmd_get) ? STDOUT_FILENO : STDIN_FILENO;
+	} else {
+		fd = open(localfile, flags, 0644); /* fail below */
+	}
+	if (fd < 0) {
+		bb_perror_msg_and_die("local file");
+	}
+
+	host = xgethostbyname(argv[optind]);
+	port = bb_lookup_port(argv[optind + 1], "udp", 69);
+
+#ifdef CONFIG_DEBUG_TFTP
+	fprintf(stderr, "using server \"%s\", remotefile \"%s\", "
+			"localfile \"%s\".\n",
+			inet_ntoa(*((struct in_addr *) host->h_addr)),
+			remotefile, localfile);
+#endif
+
+	result = tftp(cmd, host, remotefile, fd, port, blocksize);
+
+	if (!(fd == STDOUT_FILENO || fd == STDIN_FILENO)) {
+		if (ENABLE_FEATURE_CLEAN_UP)
+			close(fd);
+		if (cmd == tftp_cmd_get && result != EXIT_SUCCESS)
+			unlink(localfile);
+	}
+	return (result);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/traceroute.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/traceroute.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/traceroute.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1393 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Busybox port by Vladimir Oleynik (C) 2005 <dzo at simtreas.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+//#define version "1.4a12"
+
+
+/*
+ * traceroute host  - trace the route ip packets follow going to "host".
+ *
+ * Attempt to trace the route an ip packet would follow to some
+ * internet host.  We find out intermediate hops by launching probe
+ * packets with a small ttl (time to live) then listening for an
+ * icmp "time exceeded" reply from a gateway.  We start our probes
+ * with a ttl of one and increase by one until we get an icmp "port
+ * unreachable" (which means we got to "host") or hit a max (which
+ * defaults to 30 hops & can be changed with the -m flag).  Three
+ * probes (change with -q flag) are sent at each ttl setting and a
+ * line is printed showing the ttl, address of the gateway and
+ * round trip time of each probe.  If the probe answers come from
+ * different gateways, the address of each responding system will
+ * be printed.  If there is no response within a 5 sec. timeout
+ * interval (changed with the -w flag), a "*" is printed for that
+ * probe.
+ *
+ * Probe packets are UDP format.  We don't want the destination
+ * host to process them so the destination port is set to an
+ * unlikely value (if some clod on the destination is using that
+ * value, it can be changed with the -p flag).
+ *
+ * A sample use might be:
+ *
+ *     [yak 71]% traceroute nis.nsf.net.
+ *     traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
+ *      1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
+ *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
+ *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
+ *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
+ *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
+ *      6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
+ *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
+ *      8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
+ *      9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
+ *     10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
+ *     11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
+ *
+ * Note that lines 2 & 3 are the same.  This is due to a buggy
+ * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
+ * packets with a zero ttl.
+ *
+ * A more interesting example is:
+ *
+ *     [yak 72]% traceroute allspice.lcs.mit.edu.
+ *     traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
+ *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
+ *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
+ *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
+ *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
+ *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
+ *      6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
+ *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
+ *      8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
+ *      9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
+ *     10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
+ *     11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
+ *     12  * * *
+ *     13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
+ *     14  * * *
+ *     15  * * *
+ *     16  * * *
+ *     17  * * *
+ *     18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
+ *
+ * (I start to see why I'm having so much trouble with mail to
+ * MIT.)  Note that the gateways 12, 14, 15, 16 & 17 hops away
+ * either don't send ICMP "time exceeded" messages or send them
+ * with a ttl too small to reach us.  14 - 17 are running the
+ * MIT C Gateway code that doesn't send "time exceeded"s.  God
+ * only knows what's going on with 12.
+ *
+ * The silent gateway 12 in the above may be the result of a bug in
+ * the 4.[23]BSD network code (and its derivatives):  4.x (x <= 3)
+ * sends an unreachable message using whatever ttl remains in the
+ * original datagram.  Since, for gateways, the remaining ttl is
+ * zero, the icmp "time exceeded" is guaranteed to not make it back
+ * to us.  The behavior of this bug is slightly more interesting
+ * when it appears on the destination system:
+ *
+ *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
+ *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  39 ms
+ *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
+ *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
+ *      5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
+ *      6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
+ *      7  * * *
+ *      8  * * *
+ *      9  * * *
+ *     10  * * *
+ *     11  * * *
+ *     12  * * *
+ *     13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
+ *
+ * Notice that there are 12 "gateways" (13 is the final
+ * destination) and exactly the last half of them are "missing".
+ * What's really happening is that rip (a Sun-3 running Sun OS3.5)
+ * is using the ttl from our arriving datagram as the ttl in its
+ * icmp reply.  So, the reply will time out on the return path
+ * (with no notice sent to anyone since icmp's aren't sent for
+ * icmp's) until we probe with a ttl that's at least twice the path
+ * length.  I.e., rip is really only 7 hops away.  A reply that
+ * returns with a ttl of 1 is a clue this problem exists.
+ * Traceroute prints a "!" after the time if the ttl is <= 1.
+ * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
+ * non-standard (HPUX) software, expect to see this problem
+ * frequently and/or take care picking the target host of your
+ * probes.
+ *
+ * Other possible annotations after the time are !H, !N, !P (got a host,
+ * network or protocol unreachable, respectively), !S or !F (source
+ * route failed or fragmentation needed -- neither of these should
+ * ever occur and the associated gateway is busted if you see one).  If
+ * almost all the probes result in some kind of unreachable, traceroute
+ * will give up and exit.
+ *
+ * Notes
+ * -----
+ * This program must be run by root or be setuid.  (I suggest that
+ * you *don't* make it setuid -- casual use could result in a lot
+ * of unnecessary traffic on our poor, congested nets.)
+ *
+ * This program requires a kernel mod that does not appear in any
+ * system available from Berkeley:  A raw ip socket using proto
+ * IPPROTO_RAW must interpret the data sent as an ip datagram (as
+ * opposed to data to be wrapped in a ip datagram).  See the README
+ * file that came with the source to this program for a description
+ * of the mods I made to /sys/netinet/raw_ip.c.  Your mileage may
+ * vary.  But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
+ * MODIFIED TO RUN THIS PROGRAM.
+ *
+ * The udp port usage may appear bizarre (well, ok, it is bizarre).
+ * The problem is that an icmp message only contains 8 bytes of
+ * data from the original datagram.  8 bytes is the size of a udp
+ * header so, if we want to associate replies with the original
+ * datagram, the necessary information must be encoded into the
+ * udp header (the ip id could be used but there's no way to
+ * interlock with the kernel's assignment of ip id's and, anyway,
+ * it would have taken a lot more kernel hacking to allow this
+ * code to set the ip id).  So, to allow two or more users to
+ * use traceroute simultaneously, we use this task's pid as the
+ * source port (the high bit is set to move the port number out
+ * of the "likely" range).  To keep track of which probe is being
+ * replied to (so times and/or hop counts don't get confused by a
+ * reply that was delayed in transit), we increment the destination
+ * port number before each probe.
+ *
+ * Don't use this as a coding example.  I was trying to find a
+ * routing problem and this code sort-of popped out after 48 hours
+ * without sleep.  I was amazed it ever compiled, much less ran.
+ *
+ * I stole the idea for this program from Steve Deering.  Since
+ * the first release, I've learned that had I attended the right
+ * IETF working group meetings, I also could have stolen it from Guy
+ * Almes or Matt Mathis.  I don't know (or care) who came up with
+ * the idea first.  I envy the originators' perspicacity and I'm
+ * glad they didn't keep the idea a secret.
+ *
+ * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
+ * enhancements to the original distribution.
+ *
+ * I've hacked up a round-trip-route version of this that works by
+ * sending a loose-source-routed udp datagram through the destination
+ * back to yourself.  Unfortunately, SO many gateways botch source
+ * routing, the thing is almost worthless.  Maybe one day...
+ *
+ *  -- Van Jacobson (van at ee.lbl.gov)
+ *     Tue Dec 20 03:50:13 PST 1988
+ */
+
+#undef CONFIG_FEATURE_TRACEROUTE_VERBOSE
+//#define CONFIG_FEATURE_TRACEROUTE_VERBOSE
+#undef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG   /* not in documentation man */
+#undef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
+//#define CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
+#undef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
+//#define CONFIG_FEATURE_TRACEROUTE_USE_ICMP
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <endian.h>
+#include <getopt.h>
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include "inet_common.h"
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/udp.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+
+#include "busybox.h"
+
+
+/*
+ * Definitions for internet protocol version 4.
+ * Per RFC 791, September 1981.
+ */
+#define IPVERSION       4
+
+/*
+ * Overlay for ip header used by other protocols (tcp, udp).
+ */
+struct ipovly {
+	unsigned char  ih_x1[9];               /* (unused) */
+	unsigned char  ih_pr;                  /* protocol */
+	short   ih_len;                 /* protocol length */
+	struct  in_addr ih_src;         /* source internet address */
+	struct  in_addr ih_dst;         /* destination internet address */
+};
+
+/*
+ * UDP kernel structures and variables.
+ */
+struct  udpiphdr {
+	struct  ipovly ui_i;            /* overlaid ip structure */
+	struct  udphdr ui_u;            /* udp header */
+};
+#define ui_next         ui_i.ih_next
+#define ui_prev         ui_i.ih_prev
+#define ui_x1           ui_i.ih_x1
+#define ui_pr           ui_i.ih_pr
+#define ui_len          ui_i.ih_len
+#define ui_src          ui_i.ih_src
+#define ui_dst          ui_i.ih_dst
+#define ui_sport        ui_u.uh_sport
+#define ui_dport        ui_u.uh_dport
+#define ui_ulen         ui_u.uh_ulen
+#define ui_sum          ui_u.uh_sum
+
+
+/* Host name and address list */
+struct hostinfo {
+	char *name;
+	int n;
+	u_int32_t *addrs;
+};
+
+/* Data section of the probe packet */
+struct outdata {
+	unsigned char seq;             /* sequence number of this packet */
+	unsigned char ttl;             /* ttl packet left with */
+	struct timeval tv ATTRIBUTE_PACKED; /* time packet left */
+};
+
+struct IFADDRLIST {
+	u_int32_t addr;
+	char device[sizeof(struct ifreq)];
+};
+
+
+static const char route[] = "/proc/net/route";
+
+/* last inbound (icmp) packet */
+static unsigned char  packet[512] ATTRIBUTE_ALIGNED(32);
+
+static struct ip *outip;               /* last output (udp) packet */
+static struct udphdr *outudp;          /* last output (udp) packet */
+static struct outdata *outdata;        /* last output (udp) packet */
+
+#ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
+static struct icmp *outicmp;           /* last output (icmp) packet */
+#endif
+
+#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
+/* Maximum number of gateways (include room for one noop) */
+#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
+/* loose source route gateway list (including room for final destination) */
+static u_int32_t gwlist[NGATEWAYS + 1];
+#endif
+
+static int s;                          /* receive (icmp) socket file descriptor */
+static int sndsock;                    /* send (udp/icmp) socket file descriptor */
+
+static struct sockaddr_storage whereto;        /* Who to try to reach */
+static struct sockaddr_storage wherefrom;      /* Who we are */
+static int packlen;                    /* total length of packet */
+static int minpacket;                  /* min ip packet size */
+static int maxpacket = 32 * 1024;      /* max ip packet size */
+static int pmtu;                       /* Path MTU Discovery (RFC1191) */
+
+static char *hostname;
+
+static u_short ident;
+static u_short port = 32768 + 666;     /* start udp dest port # for probe packets */
+
+static int waittime = 5;               /* time to wait for response (in seconds) */
+static int nflag;                      /* print addresses numerically */
+static int doipcksum = 1;              /* calculate ip checksums by default */
+
+#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
+static int optlen;                     /* length of ip options */
+#else
+#define optlen 0
+#endif
+
+#ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
+static int useicmp;                    /* use icmp echo instead of udp packets */
+#endif
+#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
+static int verbose;
+#endif
+
+/*
+ * Return the interface list
+ */
+static int
+ifaddrlist(struct IFADDRLIST **ipaddrp)
+{
+	int fd, nipaddr;
+#ifdef HAVE_SOCKADDR_SA_LEN
+	int n;
+#endif
+	struct ifreq *ifrp, *ifend, *ifnext;
+	struct sockaddr_in *addr_sin;
+	struct IFADDRLIST *al;
+	struct ifconf ifc;
+	struct ifreq ibuf[(32 * 1024) / sizeof(struct ifreq)], ifr;
+	struct IFADDRLIST *st_ifaddrlist;
+
+	fd = bb_xsocket(AF_INET, SOCK_DGRAM, 0);
+
+	ifc.ifc_len = sizeof(ibuf);
+	ifc.ifc_buf = (caddr_t)ibuf;
+
+	if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
+	    ifc.ifc_len < sizeof(struct ifreq)) {
+		if (errno == EINVAL)
+			bb_error_msg_and_die(
+			    "SIOCGIFCONF: ifreq struct too small (%d bytes)",
+			    (int)sizeof(ibuf));
+		else
+			bb_perror_msg_and_die("SIOCGIFCONF");
+	}
+	ifrp = ibuf;
+	ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
+
+	nipaddr = 1 + (ifc.ifc_len / sizeof(struct ifreq));
+	st_ifaddrlist = xcalloc(nipaddr, sizeof(struct IFADDRLIST));
+	al = st_ifaddrlist;
+	nipaddr = 0;
+
+	for (; ifrp < ifend; ifrp = ifnext) {
+#ifdef HAVE_SOCKADDR_SA_LEN
+		n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
+		if (n < sizeof(*ifrp))
+			ifnext = ifrp + 1;
+		else
+			ifnext = (struct ifreq *)((char *)ifrp + n);
+		if (ifrp->ifr_addr.sa_family != AF_INET)
+			continue;
+#else
+		ifnext = ifrp + 1;
+#endif
+		/*
+		 * Need a template to preserve address info that is
+		 * used below to locate the next entry.  (Otherwise,
+		 * SIOCGIFFLAGS stomps over it because the requests
+		 * are returned in a union.)
+		 */
+		strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name));
+		if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
+			if (errno == ENXIO)
+				continue;
+			bb_perror_msg_and_die("SIOCGIFFLAGS: %.*s",
+			    (int)sizeof(ifr.ifr_name), ifr.ifr_name);
+		}
+
+		/* Must be up */
+		if ((ifr.ifr_flags & IFF_UP) == 0)
+			continue;
+
+		safe_strncpy(al->device, ifr.ifr_name, sizeof(ifr.ifr_name) + 1);
+#ifdef sun
+		/* Ignore sun virtual interfaces */
+		if (strchr(al->device, ':') != NULL)
+			continue;
+#endif
+		if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0)
+			bb_perror_msg_and_die("SIOCGIFADDR: %s", al->device);
+
+		addr_sin = (struct sockaddr_in *)&ifr.ifr_addr;
+		al->addr = addr_sin->sin_addr.s_addr;
+		++al;
+		++nipaddr;
+	}
+	if(nipaddr == 0)
+	    bb_error_msg_and_die ("Can't find any network interfaces");
+	(void)close(fd);
+
+	*ipaddrp = st_ifaddrlist;
+	return nipaddr;
+}
+
+
+static void
+setsin(struct sockaddr_in *addr_sin, u_int32_t addr)
+{
+	memset(addr_sin, 0, sizeof(*addr_sin));
+#ifdef HAVE_SOCKADDR_SA_LEN
+	addr_sin->sin_len = sizeof(*addr_sin);
+#endif
+	addr_sin->sin_family = AF_INET;
+	addr_sin->sin_addr.s_addr = addr;
+}
+
+
+/*
+ * Return the source address for the given destination address
+ */
+static void
+findsaddr(const struct sockaddr_in *to, struct sockaddr_in *from)
+{
+	int i, n;
+	FILE *f;
+	u_int32_t mask;
+	u_int32_t dest, tmask;
+	struct IFADDRLIST *al;
+	char buf[256], tdevice[256], device[256];
+
+	f = bb_xfopen(route, "r");
+
+	/* Find the appropriate interface */
+	n = 0;
+	mask = 0;
+	device[0] = '\0';
+	while (fgets(buf, sizeof(buf), f) != NULL) {
+		++n;
+		if (n == 1 && strncmp(buf, "Iface", 5) == 0)
+			continue;
+		if ((i = sscanf(buf, "%255s %x %*s %*s %*s %*s %*s %x",
+		    tdevice, &dest, &tmask)) != 3)
+			bb_error_msg_and_die ("junk in buffer");
+		if ((to->sin_addr.s_addr & tmask) == dest &&
+		    (tmask > mask || mask == 0)) {
+			mask = tmask;
+			strcpy(device, tdevice);
+		}
+	}
+	fclose(f);
+
+	if (device[0] == '\0')
+		bb_error_msg_and_die ("Can't find interface");
+
+	/* Get the interface address list */
+	n = ifaddrlist(&al);
+
+	/* Find our appropriate source address */
+	for (i = n; i > 0; --i, ++al)
+		if (strcmp(device, al->device) == 0)
+			break;
+	if (i <= 0)
+		bb_error_msg_and_die("Can't find interface %s", device);
+
+	setsin(from, al->addr);
+}
+
+/*
+"Usage: %s [-dFIlnrvx] [-g gateway] [-i iface] [-f first_ttl]\n"
+"\t[-m max_ttl] [ -p port] [-q nqueries] [-s src_addr] [-t tos]\n"
+"\t[-w waittime] [-z pausemsecs] host [packetlen]"
+
+*/
+
+/* String to value with optional min and max. Handles decimal and hex. */
+static int
+str2val(const char *str, const char *what, int mi, int ma)
+{
+	const char *cp;
+	int val;
+	char *ep;
+
+	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
+		cp = str + 2;
+		val = (int)strtol(cp, &ep, 16);
+	} else
+		val = (int)strtol(str, &ep, 10);
+	if (*ep != '\0') {
+		bb_error_msg_and_die("\"%s\" bad value for %s \n", str, what);
+	}
+	if (val < mi && mi >= 0) {
+		if (mi == 0)
+			bb_error_msg_and_die("%s must be >= %d\n", what, mi);
+		else
+			bb_error_msg_and_die("%s must be > %d\n", what, mi - 1);
+	}
+	if (val > ma && ma >= 0)
+		bb_error_msg_and_die("%s must be <= %d\n", what, ma);
+	return val;
+}
+
+
+/*
+ * Subtract 2 timeval structs:  out = out - in.
+ * Out is assumed to be >= in.
+ */
+static inline void
+tvsub(struct timeval *out, struct timeval *in)
+{
+
+	if ((out->tv_usec -= in->tv_usec) < 0)   {
+		--out->tv_sec;
+		out->tv_usec += 1000000;
+	}
+	out->tv_sec -= in->tv_sec;
+}
+
+static int
+wait_for_reply(int sock, struct sockaddr_in *fromp, const struct timeval *tp)
+{
+	fd_set fds;
+	struct timeval now, wait;
+	struct timezone tz;
+	int cc = 0;
+	socklen_t fromlen = sizeof(*fromp);
+
+	FD_ZERO(&fds);
+	FD_SET(sock, &fds);
+
+	wait.tv_sec = tp->tv_sec + waittime;
+	wait.tv_usec = tp->tv_usec;
+	(void)gettimeofday(&now, &tz);
+	tvsub(&wait, &now);
+
+	if (select(sock + 1, &fds, NULL, NULL, &wait) > 0)
+		cc = recvfrom(sock, (char *)packet, sizeof(packet), 0,
+			    (struct sockaddr *)fromp, &fromlen);
+
+	return cc;
+}
+
+/*
+ * Checksum routine for Internet Protocol family headers (C Version)
+ */
+static u_short
+in_cksum(u_short *addr, int len)
+{
+	int nleft = len;
+	u_short *w = addr;
+	u_short answer;
+	int sum = 0;
+
+	/*
+	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
+	 *  we add sequential 16 bit words to it, and at the end, fold
+	 *  back all the carry bits from the top 16 bits into the lower
+	 *  16 bits.
+	 */
+	while (nleft > 1)  {
+		sum += *w++;
+		nleft -= 2;
+	}
+
+	/* mop up an odd byte, if necessary */
+	if (nleft == 1)
+		sum += *(unsigned char *)w;
+
+	/*
+	 * add back carry outs from top 16 bits to low 16 bits
+	 */
+	sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
+	sum += (sum >> 16);                     /* add carry */
+	answer = ~sum;                          /* truncate to 16 bits */
+	return answer;
+}
+
+
+static void
+send_probe(int seq, int ttl, struct timeval *tp)
+{
+	int cc;
+	struct udpiphdr *ui, *oui;
+	struct ip tip;
+
+	outip->ip_ttl = ttl;
+	outip->ip_id = htons(ident + seq);
+
+	/*
+	 * In most cases, the kernel will recalculate the ip checksum.
+	 * But we must do it anyway so that the udp checksum comes out
+	 * right.
+	 */
+	if (doipcksum) {
+		outip->ip_sum =
+		    in_cksum((u_short *)outip, sizeof(*outip) + optlen);
+		if (outip->ip_sum == 0)
+			outip->ip_sum = 0xffff;
+	}
+
+	/* Payload */
+	outdata->seq = seq;
+	outdata->ttl = ttl;
+	memcpy(&outdata->tv, tp, sizeof(outdata->tv));
+
+#ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
+	if (useicmp)
+		outicmp->icmp_seq = htons(seq);
+	else
+#endif
+		outudp->dest = htons(port + seq);
+
+#ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
+	if (useicmp) {
+		/* Always calculate checksum for icmp packets */
+		outicmp->icmp_cksum = 0;
+		outicmp->icmp_cksum = in_cksum((u_short *)outicmp,
+		    packlen - (sizeof(*outip) + optlen));
+		if (outicmp->icmp_cksum == 0)
+			outicmp->icmp_cksum = 0xffff;
+	} else
+#endif
+	       if (doipcksum) {
+		/* Checksum (we must save and restore ip header) */
+		tip = *outip;
+		ui = (struct udpiphdr *)outip;
+		oui = (struct udpiphdr *)&tip;
+		/* Easier to zero and put back things that are ok */
+		memset((char *)ui, 0, sizeof(ui->ui_i));
+		ui->ui_src = oui->ui_src;
+		ui->ui_dst = oui->ui_dst;
+		ui->ui_pr = oui->ui_pr;
+		ui->ui_len = outudp->len;
+		outudp->check = 0;
+		outudp->check = in_cksum((u_short *)ui, packlen);
+		if (outudp->check == 0)
+			outudp->check = 0xffff;
+		*outip = tip;
+	}
+
+#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
+	/* XXX undocumented debugging hack */
+	if (verbose > 1) {
+		const u_short *sp;
+		int nshorts, i;
+
+		sp = (u_short *)outip;
+		nshorts = (u_int)packlen / sizeof(u_short);
+		i = 0;
+		printf("[ %d bytes", packlen);
+		while (--nshorts >= 0) {
+			if ((i++ % 8) == 0)
+				printf("\n\t");
+			printf(" %04x", ntohs(*sp));
+			sp++;
+		}
+		if (packlen & 1) {
+			if ((i % 8) == 0)
+				printf("\n\t");
+			printf(" %02x", *(unsigned char *)sp);
+		}
+		printf("]\n");
+	}
+#endif
+
+#if !defined(IP_HDRINCL) && defined(IP_TTL)
+	if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
+	    (char *)&ttl, sizeof(ttl)) < 0) {
+		bb_perror_msg_and_die("setsockopt ttl %d", ttl);
+	}
+#endif
+
+	cc = sendto(sndsock, (char *)outip,
+	    packlen, 0, (struct sockaddr *)&whereto, sizeof(whereto));
+	if (cc < 0 || cc != packlen)  {
+		if (cc < 0)
+			bb_perror_msg_and_die("sendto");
+		printf("%s: wrote %s %d chars, ret=%d\n",
+		    bb_applet_name, hostname, packlen, cc);
+		(void)fflush(stdout);
+	}
+}
+
+static inline double
+deltaT(struct timeval *t1p, struct timeval *t2p)
+{
+	double dt;
+
+	dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
+	     (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
+	return dt;
+}
+
+#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
+/*
+ * Convert an ICMP "type" field to a printable string.
+ */
+static inline const char *
+pr_type(unsigned char t)
+{
+	static const char * const ttab[] = {
+	"Echo Reply",   "ICMP 1",       "ICMP 2",       "Dest Unreachable",
+	"Source Quench", "Redirect",    "ICMP 6",       "ICMP 7",
+	"Echo",         "Router Advert", "Router Solicit", "Time Exceeded",
+	"Param Problem", "Timestamp",   "Timestamp Reply", "Info Request",
+	"Info Reply",   "Mask Request", "Mask Reply"
+	};
+
+	if (t > 18)
+		return "OUT-OF-RANGE";
+
+	return ttab[t];
+}
+#endif
+
+static int
+packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq)
+{
+	struct icmp *icp;
+	unsigned char type, code;
+	int hlen;
+	struct ip *ip;
+
+	ip = (struct ip *) buf;
+	hlen = ip->ip_hl << 2;
+	if (cc < hlen + ICMP_MINLEN) {
+#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
+		if (verbose)
+			printf("packet too short (%d bytes) from %s\n", cc,
+				inet_ntoa(from->sin_addr));
+#endif
+		return 0;
+	}
+	cc -= hlen;
+	icp = (struct icmp *)(buf + hlen);
+	type = icp->icmp_type;
+	code = icp->icmp_code;
+	/* Path MTU Discovery (RFC1191) */
+	if (code != ICMP_UNREACH_NEEDFRAG)
+		pmtu = 0;
+	else {
+		pmtu = ntohs(icp->icmp_nextmtu);
+	}
+	if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
+	    type == ICMP_UNREACH || type == ICMP_ECHOREPLY) {
+		struct ip *hip;
+		struct udphdr *up;
+
+		hip = &icp->icmp_ip;
+		hlen = hip->ip_hl << 2;
+#ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
+		if (useicmp) {
+			struct icmp *hicmp;
+
+			/* XXX */
+			if (type == ICMP_ECHOREPLY &&
+			    icp->icmp_id == htons(ident) &&
+			    icp->icmp_seq == htons(seq))
+				return -2;
+
+			hicmp = (struct icmp *)((unsigned char *)hip + hlen);
+			/* XXX 8 is a magic number */
+			if (hlen + 8 <= cc &&
+			    hip->ip_p == IPPROTO_ICMP &&
+			    hicmp->icmp_id == htons(ident) &&
+			    hicmp->icmp_seq == htons(seq))
+				return (type == ICMP_TIMXCEED ? -1 : code + 1);
+		} else
+#endif
+		      {
+			up = (struct udphdr *)((unsigned char *)hip + hlen);
+			/* XXX 8 is a magic number */
+			if (hlen + 12 <= cc &&
+			    hip->ip_p == IPPROTO_UDP &&
+			    up->source == htons(ident) &&
+			    up->dest == htons(port + seq))
+				return (type == ICMP_TIMXCEED ? -1 : code + 1);
+		}
+	}
+#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
+	if (verbose) {
+		int i;
+		u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
+
+		printf("\n%d bytes from %s to "
+		       "%s: icmp type %d (%s) code %d\n",
+		    cc, inet_ntoa(from->sin_addr),
+		    inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
+		for (i = 4; i < cc ; i += sizeof(*lp))
+			printf("%2d: x%8.8x\n", i, *lp++);
+	}
+#endif
+	return 0;
+}
+
+
+/*
+ * Construct an Internet address representation.
+ * If the nflag has been supplied, give
+ * numeric value, otherwise try for symbolic name.
+ */
+static inline void
+inetname(struct sockaddr_in *from)
+{
+	const char *n = NULL;
+	const char *ina;
+	char name[257];
+
+	if (!nflag && from->sin_addr.s_addr != INADDR_ANY) {
+		if(INET_rresolve(name, sizeof(name), from, 0x4000, 0xffffffff) >= 0)
+			n = name;
+	}
+	ina = inet_ntoa(from->sin_addr);
+	if (nflag)
+		printf(" %s", ina);
+	else
+		printf(" %s (%s)", (n ? n : ina), ina);
+}
+
+static inline void
+print(unsigned char *buf, int cc, struct sockaddr_in *from)
+{
+	struct ip *ip;
+	int hlen;
+
+	ip = (struct ip *) buf;
+	hlen = ip->ip_hl << 2;
+	cc -= hlen;
+
+	inetname(from);
+#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
+	if (verbose)
+		printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
+#endif
+}
+
+
+static struct hostinfo *
+gethostinfo(const char *host)
+{
+	int n;
+	struct hostent *hp;
+	struct hostinfo *hi;
+	char **p;
+	u_int32_t addr, *ap;
+
+	hi = xcalloc(1, sizeof(*hi));
+	addr = inet_addr(host);
+	if ((int32_t)addr != -1) {
+		hi->name = bb_xstrdup(host);
+		hi->n = 1;
+		hi->addrs = xcalloc(1, sizeof(hi->addrs[0]));
+		hi->addrs[0] = addr;
+		return hi;
+	}
+
+	hp = xgethostbyname(host);
+	if (hp->h_addrtype != AF_INET || hp->h_length != 4)
+		bb_perror_msg_and_die("bad host %s", host);
+	hi->name = bb_xstrdup(hp->h_name);
+	for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
+		continue;
+	hi->n = n;
+	hi->addrs = xcalloc(n, sizeof(hi->addrs[0]));
+	for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
+		memcpy(ap, *p, sizeof(*ap));
+	return hi;
+}
+
+static void
+freehostinfo(struct hostinfo *hi)
+{
+	free(hi->name);
+	hi->name = NULL;
+	free((char *)hi->addrs);
+	free((char *)hi);
+}
+
+#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
+static void
+getaddr(u_int32_t *ap, const char *host)
+{
+	struct hostinfo *hi;
+
+	hi = gethostinfo(host);
+	*ap = hi->addrs[0];
+	freehostinfo(hi);
+}
+#endif
+
+
+int
+traceroute_main(int argc, char *argv[])
+{
+	int code, n;
+	char *cp;
+	unsigned char *outp;
+	u_int32_t *ap;
+	struct sockaddr_in *from = (struct sockaddr_in *)&wherefrom;
+	struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
+	struct hostinfo *hi;
+	int on = 1;
+	struct protoent *pe;
+	int ttl, probe, i;
+	int seq = 0;
+	int tos = 0;
+	char *tos_str = NULL;
+	char *source = NULL;
+	unsigned long op;
+
+#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
+	int lsrr = 0;
+#endif
+	u_short off = 0;
+	struct IFADDRLIST *al;
+	char *device = NULL;
+	int max_ttl = 30;
+	char *max_ttl_str = NULL;
+	char *port_str = NULL;
+	int nprobes = 3;
+	char *nprobes_str = NULL;
+	char *waittime_str = NULL;
+	u_int pausemsecs = 0;
+	char *pausemsecs_str = NULL;
+	int first_ttl = 1;
+	char *first_ttl_str = NULL;
+#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
+	llist_t *sourse_route_list = NULL;
+#endif
+
+	opterr = 0;
+#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
+	bb_opt_complementally = "x-x:g::";
+#else
+	bb_opt_complementally = "x-x";
+#endif
+
+	op = bb_getopt_ulflags(argc, argv, "FIlnrdvxt:i:m:p:q:s:w:z:f:"
+#define USAGE_OP_DONT_FRAGMNT (1<<0)    /* F  */
+#define USAGE_OP_USE_ICMP     (1<<1)    /* I  */
+#define USAGE_OP_TTL_FLAG     (1<<2)    /* l  */
+#define USAGE_OP_ADDR_NUM     (1<<3)    /* n  */
+#define USAGE_OP_BYPASS_ROUTE (1<<4)    /* r  */
+#define USAGE_OP_DEBUG        (1<<5)    /* d */
+#define USAGE_OP_VERBOSE      (1<<6)    /* v */
+#define USAGE_OP_IP_CHKSUM    (1<<7)    /* x */
+
+#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
+					"g:"
+#endif
+	, &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str,
+	&source, &waittime_str, &pausemsecs_str, &first_ttl_str
+#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
+	, &sourse_route_list
+#endif
+	);
+
+	if(op & USAGE_OP_DONT_FRAGMNT)
+		off = IP_DF;
+#ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
+	useicmp = op & USAGE_OP_USE_ICMP;
+#endif
+	nflag = op & USAGE_OP_ADDR_NUM;
+#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
+	verbose = op &  USAGE_OP_VERBOSE;
+#endif
+	if(op & USAGE_OP_IP_CHKSUM) {
+		doipcksum = 0;
+		bb_error_msg("Warning: ip checksums disabled");
+	}
+	if (tos_str)
+		tos = str2val(tos_str, "tos", 0, 255);
+	if(max_ttl_str)
+		max_ttl = str2val(max_ttl_str, "max ttl", 1, 255);
+	if(port_str)
+		port = (u_short)str2val(port_str, "port", 1, (1 << 16) - 1);
+	if(nprobes_str)
+		nprobes = str2val(optarg, "nprobes", 1, -1);
+	if(source) {
+	    /*
+	     * set the ip source address of the outbound
+	     * probe (e.g., on a multi-homed host).
+	     */
+	     if (getuid()) bb_error_msg_and_die("-s %s: Permission denied", source);
+	}
+	if(waittime_str)
+		waittime = str2val(waittime_str, "wait time", 2, 24 * 60 * 60);
+	if(pausemsecs_str)
+		pausemsecs = str2val(pausemsecs_str, "pause msecs", 0, 60 * 60 * 1000);
+	if(first_ttl_str)
+		first_ttl = str2val(first_ttl_str, "first ttl", 1, 255);
+
+#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
+	if(sourse_route_list) {
+		llist_t *l_sr;
+
+		for(l_sr = sourse_route_list; l_sr; ) {
+			if (lsrr >= NGATEWAYS)
+				bb_error_msg_and_die("No more than %d gateways", NGATEWAYS);
+			getaddr(gwlist + lsrr, l_sr->data);
+			++lsrr;
+			l_sr = l_sr->link;
+			free(sourse_route_list);
+			sourse_route_list = l_sr;
+		}
+		optlen = (lsrr + 1) * sizeof(gwlist[0]);
+	}
+#endif
+
+	if (first_ttl > max_ttl) {
+		bb_error_msg_and_die(
+		    "first ttl (%d) may not be greater than max ttl (%d)",
+		    first_ttl, max_ttl);
+	}
+
+	minpacket = sizeof(*outip) + sizeof(*outdata) + optlen;
+
+#ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
+	if (useicmp)
+		minpacket += 8;                 /* XXX magic number */
+	else
+#endif
+		minpacket += sizeof(*outudp);
+	packlen = minpacket;                    /* minimum sized packet */
+
+	/* Process destination and optional packet size */
+	switch (argc - optind) {
+
+	case 2:
+		packlen = str2val(argv[optind + 1],
+		    "packet length", minpacket, maxpacket);
+		/* Fall through */
+
+	case 1:
+		hostname = argv[optind];
+		hi = gethostinfo(hostname);
+		setsin(to, hi->addrs[0]);
+		if (hi->n > 1)
+			bb_error_msg(
+		    "Warning: %s has multiple addresses; using %s",
+				hostname, inet_ntoa(to->sin_addr));
+		hostname = hi->name;
+		hi->name = NULL;
+		freehostinfo(hi);
+		break;
+
+	default:
+		bb_show_usage();
+	}
+
+	cp = "icmp";
+	if ((pe = getprotobyname(cp)) == NULL)
+		bb_perror_msg_and_die("unknown protocol %s", cp);
+
+	/* Insure the socket fds won't be 0, 1 or 2 */
+	do n = bb_xopen(bb_dev_null, O_RDONLY); while (n < 2);
+	if (n > 2)
+		close(n);
+
+	s = bb_xsocket(AF_INET, SOCK_RAW, pe->p_proto);
+
+#ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG
+	if (op & USAGE_OP_DEBUG)
+		(void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
+		    sizeof(on));
+#endif
+	if (op & USAGE_OP_BYPASS_ROUTE)
+		(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
+		    sizeof(on));
+
+	sndsock = bb_xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+
+#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
+#if defined(IP_OPTIONS)
+	if (lsrr > 0) {
+		unsigned char optlist[MAX_IPOPTLEN];
+
+		cp = "ip";
+		if ((pe = getprotobyname(cp)) == NULL)
+			bb_perror_msg_and_die("unknown protocol");
+
+		/* final hop */
+		gwlist[lsrr] = to->sin_addr.s_addr;
+		++lsrr;
+
+		/* force 4 byte alignment */
+		optlist[0] = IPOPT_NOP;
+		/* loose source route option */
+		optlist[1] = IPOPT_LSRR;
+		i = lsrr * sizeof(gwlist[0]);
+		optlist[2] = i + 3;
+		/* Pointer to LSRR addresses */
+		optlist[3] = IPOPT_MINOFF;
+		memcpy(optlist + 4, gwlist, i);
+
+		if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS,
+		    (char *)optlist, i + sizeof(gwlist[0]))) < 0) {
+			bb_perror_msg_and_die("IP_OPTIONS");
+		    }
+	}
+#endif /* IP_OPTIONS */
+#endif /* CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE */
+
+#ifdef SO_SNDBUF
+	if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
+	    sizeof(packlen)) < 0) {
+		bb_perror_msg_and_die("SO_SNDBUF");
+	}
+#endif
+#ifdef IP_HDRINCL
+	if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
+	    sizeof(on)) < 0 && errno != ENOPROTOOPT) {
+		bb_perror_msg_and_die("IP_HDRINCL");
+	}
+#else
+#ifdef IP_TOS
+	if (tos_str && setsockopt(sndsock, IPPROTO_IP, IP_TOS,
+	    (char *)&tos, sizeof(tos)) < 0) {
+		bb_perror_msg_and_die("setsockopt tos %d", tos);
+	}
+#endif
+#endif
+#ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG
+	if (op & USAGE_OP_DEBUG)
+		(void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
+		    sizeof(on));
+#endif
+	if (op & USAGE_OP_BYPASS_ROUTE)
+		(void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
+		    sizeof(on));
+
+	/* Revert to non-privileged user after opening sockets */
+	xsetgid(getgid());
+	xsetuid(getuid());
+
+	outip = (struct ip *)xcalloc(1, (unsigned)packlen);
+
+	outip->ip_v = IPVERSION;
+	if (tos_str)
+		outip->ip_tos = tos;
+	outip->ip_len = htons(packlen);
+	outip->ip_off = htons(off);
+	outp = (unsigned char *)(outip + 1);
+	outip->ip_dst = to->sin_addr;
+
+	outip->ip_hl = (outp - (unsigned char *)outip) >> 2;
+	ident = (getpid() & 0xffff) | 0x8000;
+#ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
+	if (useicmp) {
+		outip->ip_p = IPPROTO_ICMP;
+
+		outicmp = (struct icmp *)outp;
+		outicmp->icmp_type = ICMP_ECHO;
+		outicmp->icmp_id = htons(ident);
+
+		outdata = (struct outdata *)(outp + 8); /* XXX magic number */
+	} else
+#endif
+	       {
+		outip->ip_p = IPPROTO_UDP;
+
+		outudp = (struct udphdr *)outp;
+		outudp->source = htons(ident);
+		outudp->len =
+		    htons((u_short)(packlen - (sizeof(*outip) + optlen)));
+		outdata = (struct outdata *)(outudp + 1);
+	}
+
+	/* Get the interface address list */
+	n = ifaddrlist(&al);
+
+	/* Look for a specific device */
+	if (device != NULL) {
+		for (i = n; i > 0; --i, ++al)
+			if (strcmp(device, al->device) == 0)
+				break;
+		if (i <= 0) {
+			bb_error_msg_and_die("Can't find interface %s", device);
+		}
+	}
+
+	/* Determine our source address */
+	if (source == NULL) {
+		/*
+		 * If a device was specified, use the interface address.
+		 * Otherwise, try to determine our source address.
+		 */
+		if (device != NULL)
+			setsin(from, al->addr);
+		findsaddr(to, from);
+	} else {
+		hi = gethostinfo(source);
+		source = hi->name;
+		hi->name = NULL;
+		/*
+		 * If the device was specified make sure it
+		 * corresponds to the source address specified.
+		 * Otherwise, use the first address (and warn if
+		 * there are more than one).
+		 */
+		if (device != NULL) {
+			for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
+				if (*ap == al->addr)
+					break;
+			if (i <= 0) {
+				bb_error_msg_and_die(
+				    "%s is not on interface %s",
+				    source, device);
+			}
+			setsin(from, *ap);
+		} else {
+			setsin(from, hi->addrs[0]);
+			if (hi->n > 1)
+				bb_error_msg(
+			"Warning: %s has multiple addresses; using %s",
+				    source, inet_ntoa(from->sin_addr));
+		}
+		freehostinfo(hi);
+	}
+
+	outip->ip_src = from->sin_addr;
+#ifndef IP_HDRINCL
+	bb_xbind(sndsock, (struct sockaddr *)from, sizeof(*from));
+#endif
+
+	fprintf(stderr, "traceroute to %s (%s)", hostname, inet_ntoa(to->sin_addr));
+	if (source)
+		fprintf(stderr, " from %s", source);
+	fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
+	(void)fflush(stderr);
+
+	for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
+		u_int32_t lastaddr = 0;
+		int gotlastaddr = 0;
+		int got_there = 0;
+		int unreachable = 0;
+		int sentfirst = 0;
+
+		printf("%2d ", ttl);
+		for (probe = 0; probe < nprobes; ++probe) {
+			int cc;
+			struct timeval t1, t2;
+			struct timezone tz;
+			struct ip *ip;
+
+			if (sentfirst && pausemsecs > 0)
+				usleep(pausemsecs * 1000);
+			(void)gettimeofday(&t1, &tz);
+			send_probe(++seq, ttl, &t1);
+			++sentfirst;
+			while ((cc = wait_for_reply(s, from, &t1)) != 0) {
+				(void)gettimeofday(&t2, &tz);
+				i = packet_ok(packet, cc, from, seq);
+				/* Skip short packet */
+				if (i == 0)
+					continue;
+				if (!gotlastaddr ||
+				    from->sin_addr.s_addr != lastaddr) {
+					print(packet, cc, from);
+					lastaddr = from->sin_addr.s_addr;
+					++gotlastaddr;
+				}
+				printf("  %.3f ms", deltaT(&t1, &t2));
+				ip = (struct ip *)packet;
+				if (op & USAGE_OP_TTL_FLAG)
+					printf(" (%d)", ip->ip_ttl);
+				if (i == -2) {
+					if (ip->ip_ttl <= 1)
+						printf(" !");
+					++got_there;
+					break;
+				}
+				/* time exceeded in transit */
+				if (i == -1)
+					break;
+				code = i - 1;
+				switch (code) {
+
+				case ICMP_UNREACH_PORT:
+					if (ip->ip_ttl <= 1)
+						printf(" !");
+					++got_there;
+					break;
+
+				case ICMP_UNREACH_NET:
+					++unreachable;
+					printf(" !N");
+					break;
+
+				case ICMP_UNREACH_HOST:
+					++unreachable;
+					printf(" !H");
+					break;
+
+				case ICMP_UNREACH_PROTOCOL:
+					++got_there;
+					printf(" !P");
+					break;
+
+				case ICMP_UNREACH_NEEDFRAG:
+					++unreachable;
+					printf(" !F-%d", pmtu);
+					break;
+
+				case ICMP_UNREACH_SRCFAIL:
+					++unreachable;
+					printf(" !S");
+					break;
+
+				case ICMP_UNREACH_FILTER_PROHIB:
+				case ICMP_UNREACH_NET_PROHIB:   /* misuse */
+					++unreachable;
+					printf(" !A");
+					break;
+
+				case ICMP_UNREACH_HOST_PROHIB:
+					++unreachable;
+					printf(" !C");
+					break;
+
+				case ICMP_UNREACH_HOST_PRECEDENCE:
+					++unreachable;
+					printf(" !V");
+					break;
+
+				case ICMP_UNREACH_PRECEDENCE_CUTOFF:
+					++unreachable;
+					printf(" !C");
+					break;
+
+				case ICMP_UNREACH_NET_UNKNOWN:
+				case ICMP_UNREACH_HOST_UNKNOWN:
+					++unreachable;
+					printf(" !U");
+					break;
+
+				case ICMP_UNREACH_ISOLATED:
+					++unreachable;
+					printf(" !I");
+					break;
+
+				case ICMP_UNREACH_TOSNET:
+				case ICMP_UNREACH_TOSHOST:
+					++unreachable;
+					printf(" !T");
+					break;
+
+				default:
+					++unreachable;
+					printf(" !<%d>", code);
+					break;
+				}
+				break;
+			}
+			if (cc == 0)
+				printf(" *");
+			(void)fflush(stdout);
+		}
+		putchar('\n');
+		if (got_there ||
+		    (unreachable > 0 && unreachable >= nprobes - 1))
+			break;
+	}
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,62 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "udhcp Server/Client"
+
+config CONFIG_APP_UDHCPD
+	bool "udhcp Server (udhcpd)"
+	default n
+	help
+	  uDHCPd is a DHCP server geared primarily toward embedded systems,
+	  while striving to be fully functional and RFC compliant.
+
+	  See http://udhcp.busybox.net for further details.
+
+config CONFIG_APP_UDHCPC
+	bool "udhcp Client (udhcpc)"
+	default n
+	help
+	  uDHCPc is a DHCP client geared primarily toward embedded systems,
+	  while striving to be fully functional and RFC compliant.
+
+	  The udhcp client negotiates a lease with the DHCP server and
+	  notifies a set of scripts when a lease is obtained or lost.
+
+	  See http://udhcp.busybox.net for further details.
+
+config CONFIG_APP_DUMPLEASES
+	bool "Lease display utility (dumpleases)"
+	default n
+	depends on CONFIG_APP_UDHCPD
+	help
+	  dumpleases displays the leases written out by the udhcpd server.
+	  Lease times are stored in the file by time remaining in lease, or
+	  by the absolute time that it expires in seconds from epoch.
+
+	  See http://udhcp.busybox.net for further details.
+
+config CONFIG_FEATURE_UDHCP_SYSLOG
+	bool "  Log udhcp messages to syslog (instead of stdout)"
+	default n
+	depends on CONFIG_APP_UDHCPD || CONFIG_APP_UDHCPC
+	help
+	  If selected, udhcpd will log all its messages to syslog, otherwise,
+	  it will attempt to log them to stdout.
+
+	  See http://udhcp.busybox.net for further details.
+
+config CONFIG_FEATURE_UDHCP_DEBUG
+	bool "  Compile udhcp with noisy debugging messages"
+	default n
+	depends on CONFIG_APP_UDHCPD || CONFIG_APP_UDHCPC
+	help
+	  If selected, udhcpd will output extra debugging output.  If using
+	  this option, compile uDHCP with "-g", and do not fork the daemon to
+	  the background.
+
+	  See http://udhcp.busybox.net for further details.
+
+endmenu
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+
+#ifndef top_srcdir
+#top_srcdir=../..
+#endif
+#ifndef top_builddir
+#top_builddir=../..
+#endif
+srcdir=$(top_srcdir)/networking/udhcp
+UDHCP_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,53 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+#
+
+UDHCP_AR:=udhcp.a
+ifndef $(UDHCP_DIR)
+UDHCP_DIR:=$(top_builddir)/networking/udhcp/
+endif
+srcdir=$(top_srcdir)/networking/udhcp
+
+#ok, so I forgot how to do an or, but this is a quick and dirty hack
+ifeq ($(strip $(CONFIG_APP_UDHCPC)),y)
+CONFIG_UDHCP_SHARED=y
+else
+ifeq ($(strip $(CONFIG_APP_UDHCPD)),y)
+CONFIG_UDHCP_SHARED=y
+else
+CONFIG_UDHCP_SHARED=n
+endif
+endif
+
+UDHCP-y:=
+UDHCP-$(CONFIG_UDHCP_SHARED)    += common.c options.c packet.c pidfile.c \
+				   signalpipe.c socket.c
+UDHCP-$(CONFIG_APP_UDHCPC)	+= dhcpc.c clientpacket.c clientsocket.c \
+				   script.c
+UDHCP-$(CONFIG_APP_UDHCPD)	+= dhcpd.c arpping.c files.c leases.c \
+				   serverpacket.c static_leases.c
+UDHCP-$(CONFIG_APP_DUMPLEASES)	+= dumpleases.c
+UDHCP_OBJS:=$(patsubst %.c,$(UDHCP_DIR)%.o, $(UDHCP-y))
+
+ifneq ($(strip $(UDHCP-y)),)
+libraries-y+=$(UDHCP_DIR)$(UDHCP_AR)
+endif
+
+UDHCP-y:=$(patsubst %,$(srcdir)/%,$(UDHCP-y))
+UDHCP-a:=$(wildcard $(srcdir)/*.c)
+APPLET_SRC-y+=$(UDHCP-y)
+APPLET_SRC-a+=$(UDHCP-a)
+
+UDHCP_INCLUDES:=$(srcdir)
+
+APPLETS_DEFINE-y+=-DIN_BUSYBOX -I$(UDHCP_INCLUDES)
+APPLETS_DEFINE-a+=-DIN_BUSYBOX -I$(UDHCP_INCLUDES)
+
+$(UDHCP_DIR)$(UDHCP_AR): $(UDHCP_OBJS)
+	$(do_ar)
+
+$(UDHCP_OBJS): $(UDHCP_DIR)%.o : $(srcdir)/%.c
+	$(compile.c) -DIN_BUSYBOX

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/arpping.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/arpping.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/arpping.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,105 @@
+/*
+ * arpping.c
+ *
+ * Mostly stolen from: dhcpcd - DHCP client daemon
+ * by Yoichi Hariguchi <yoichi at fore.com>
+ */
+
+#include <time.h>
+#include <sys/socket.h>
+#include <netinet/if_ether.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "dhcpd.h"
+#include "arpping.h"
+#include "common.h"
+
+/* args:	yiaddr - what IP to ping
+ *		ip - our ip
+ *		mac - our arp address
+ *		interface - interface to use
+ * retn:	1 addr free
+ *		0 addr used
+ *		-1 error
+ */
+
+/* FIXME: match response against chaddr */
+int arpping(uint32_t yiaddr, uint32_t ip, uint8_t *mac, char *interface)
+{
+
+	int	timeout = 2;
+	int	optval = 1;
+	int	s;			/* socket */
+	int	rv = 1;			/* return value */
+	struct sockaddr addr;		/* for interface name */
+	struct arpMsg	arp;
+	fd_set		fdset;
+	struct timeval	tm;
+	time_t		prevTime;
+
+
+	if ((s = socket (PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) == -1) {
+#ifdef IN_BUSYBOX
+		LOG(LOG_ERR, bb_msg_can_not_create_raw_socket);
+#else
+		LOG(LOG_ERR, "Could not open raw socket");
+#endif
+		return -1;
+	}
+
+	if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) == -1) {
+		LOG(LOG_ERR, "Could not setsocketopt on raw socket");
+		close(s);
+		return -1;
+	}
+
+	/* send arp request */
+	memset(&arp, 0, sizeof(arp));
+	memcpy(arp.h_dest, MAC_BCAST_ADDR, 6);		/* MAC DA */
+	memcpy(arp.h_source, mac, 6);			/* MAC SA */
+	arp.h_proto = htons(ETH_P_ARP);			/* protocol type (Ethernet) */
+	arp.htype = htons(ARPHRD_ETHER);		/* hardware type */
+	arp.ptype = htons(ETH_P_IP);			/* protocol type (ARP message) */
+	arp.hlen = 6;					/* hardware address length */
+	arp.plen = 4;					/* protocol address length */
+	arp.operation = htons(ARPOP_REQUEST);		/* ARP op code */
+	memcpy(arp.sInaddr, &ip, sizeof(ip));		/* source IP address */
+	memcpy(arp.sHaddr, mac, 6);			/* source hardware address */
+	memcpy(arp.tInaddr, &yiaddr, sizeof(yiaddr));	/* target IP address */
+
+	memset(&addr, 0, sizeof(addr));
+	strcpy(addr.sa_data, interface);
+	if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0)
+		rv = 0;
+
+	/* wait arp reply, and check it */
+	tm.tv_usec = 0;
+	prevTime = uptime();
+	while (timeout > 0) {
+		FD_ZERO(&fdset);
+		FD_SET(s, &fdset);
+		tm.tv_sec = timeout;
+		if (select(s + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) < 0) {
+			DEBUG(LOG_ERR, "Error on ARPING request: %m");
+			if (errno != EINTR) rv = 0;
+		} else if (FD_ISSET(s, &fdset)) {
+			if (recv(s, &arp, sizeof(arp), 0) < 0 ) rv = 0;
+			if (arp.operation == htons(ARPOP_REPLY) &&
+			    memcmp(arp.tHaddr, mac, 6) == 0 &&
+			    *((uint32_t *) arp.sInaddr) == yiaddr) {
+				DEBUG(LOG_INFO, "Valid arp reply receved for this address");
+				rv = 0;
+				break;
+			}
+		}
+		timeout -= uptime() - prevTime;
+		prevTime = uptime();
+	}
+	close(s);
+	DEBUG(LOG_INFO, "%salid arp replies for this address", rv ? "No v" : "V");
+	return rv;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/arpping.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/arpping.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/arpping.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,35 @@
+/*
+ * arpping .h
+ */
+
+#ifndef ARPPING_H
+#define ARPPING_H
+
+#include <netinet/if_ether.h>
+#include <net/if_arp.h>
+#include <net/if.h>
+#include <netinet/in.h>
+
+struct arpMsg {
+	/* Ethernet header */
+	u_char   h_dest[6];			/* destination ether addr */
+	u_char   h_source[6];			/* source ether addr */
+	u_short  h_proto;			/* packet type ID field */
+
+	/* ARP packet */
+	uint16_t htype;				/* hardware type (must be ARPHRD_ETHER) */
+	uint16_t ptype;				/* protocol type (must be ETH_P_IP) */
+	uint8_t  hlen;				/* hardware address length (must be 6) */
+	uint8_t  plen;				/* protocol address length (must be 4) */
+	uint16_t operation;			/* ARP opcode */
+	uint8_t  sHaddr[6];			/* sender's hardware address */
+	uint8_t  sInaddr[4];			/* sender's IP address */
+	uint8_t  tHaddr[6];			/* target's hardware address */
+	uint8_t  tInaddr[4];			/* target's IP address */
+	uint8_t  pad[18];			/* pad for min. Ethernet payload (60 bytes) */
+} ATTRIBUTE_PACKED;
+
+/* function prototypes */
+int arpping(uint32_t yiaddr, uint32_t ip, uint8_t *arp, char *interface);
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/clientpacket.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/clientpacket.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/clientpacket.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,233 @@
+/* clientpacket.c
+ *
+ * Packet generation and dispatching functions for the DHCP client.
+ *
+ * Russ Dill <Russ.Dill at asu.edu> July 2001
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <string.h>
+#include <sys/socket.h>
+#include <features.h>
+#if (__GLIBC__ >= 2 && __GLIBC_MINOR >= 1) || defined _NEWLIB_VERSION
+#include <netpacket/packet.h>
+#include <net/ethernet.h>
+#else
+#include <asm/types.h>
+#include <linux/if_packet.h>
+#include <linux/if_ether.h>
+#endif
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+
+
+#include "dhcpd.h"
+#include "clientpacket.h"
+#include "options.h"
+#include "dhcpc.h"
+#include "common.h"
+
+
+/* Create a random xid */
+unsigned long random_xid(void)
+{
+	static int initialized;
+	if (!initialized) {
+		int fd;
+		unsigned long seed;
+
+		fd = open("/dev/urandom", 0);
+		if (fd < 0 || read(fd, &seed, sizeof(seed)) < 0) {
+			LOG(LOG_WARNING, "Could not load seed from /dev/urandom: %m");
+			seed = time(0);
+		}
+		if (fd >= 0) close(fd);
+		srand(seed);
+		initialized++;
+	}
+	return rand();
+}
+
+
+/* initialize a packet with the proper defaults */
+static void init_packet(struct dhcpMessage *packet, char type)
+{
+	udhcp_init_header(packet, type);
+	memcpy(packet->chaddr, client_config.arp, 6);
+	if (client_config.clientid)
+	    add_option_string(packet->options, client_config.clientid);
+	if (client_config.hostname) add_option_string(packet->options, client_config.hostname);
+	if (client_config.fqdn) add_option_string(packet->options, client_config.fqdn);
+	add_option_string(packet->options, client_config.vendorclass);
+}
+
+
+/* Add a parameter request list for stubborn DHCP servers. Pull the data
+ * from the struct in options.c. Don't do bounds checking here because it
+ * goes towards the head of the packet. */
+static void add_requests(struct dhcpMessage *packet)
+{
+	int end = end_option(packet->options);
+	int i, len = 0;
+
+	packet->options[end + OPT_CODE] = DHCP_PARAM_REQ;
+	for (i = 0; dhcp_options[i].code; i++)
+		if (dhcp_options[i].flags & OPTION_REQ)
+			packet->options[end + OPT_DATA + len++] = dhcp_options[i].code;
+	packet->options[end + OPT_LEN] = len;
+	packet->options[end + OPT_DATA + len] = DHCP_END;
+
+}
+
+
+/* Broadcast a DHCP discover packet to the network, with an optionally requested IP */
+int send_discover(unsigned long xid, unsigned long requested)
+{
+	struct dhcpMessage packet;
+
+	init_packet(&packet, DHCPDISCOVER);
+	packet.xid = xid;
+	if (requested)
+		add_simple_option(packet.options, DHCP_REQUESTED_IP, requested);
+
+	add_requests(&packet);
+	LOG(LOG_DEBUG, "Sending discover...");
+	return udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST,
+				SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex);
+}
+
+
+/* Broadcasts a DHCP request message */
+int send_selecting(unsigned long xid, unsigned long server, unsigned long requested)
+{
+	struct dhcpMessage packet;
+	struct in_addr addr;
+
+	init_packet(&packet, DHCPREQUEST);
+	packet.xid = xid;
+
+	add_simple_option(packet.options, DHCP_REQUESTED_IP, requested);
+	add_simple_option(packet.options, DHCP_SERVER_ID, server);
+
+	add_requests(&packet);
+	addr.s_addr = requested;
+	LOG(LOG_DEBUG, "Sending select for %s...", inet_ntoa(addr));
+	return udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST,
+				SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex);
+}
+
+
+/* Unicasts or broadcasts a DHCP renew message */
+int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr)
+{
+	struct dhcpMessage packet;
+	int ret = 0;
+
+	init_packet(&packet, DHCPREQUEST);
+	packet.xid = xid;
+	packet.ciaddr = ciaddr;
+
+	add_requests(&packet);
+	LOG(LOG_DEBUG, "Sending renew...");
+	if (server)
+		ret = udhcp_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT);
+	else ret = udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST,
+				SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex);
+	return ret;
+}
+
+
+/* Unicasts a DHCP release message */
+int send_release(unsigned long server, unsigned long ciaddr)
+{
+	struct dhcpMessage packet;
+
+	init_packet(&packet, DHCPRELEASE);
+	packet.xid = random_xid();
+	packet.ciaddr = ciaddr;
+
+	add_simple_option(packet.options, DHCP_REQUESTED_IP, ciaddr);
+	add_simple_option(packet.options, DHCP_SERVER_ID, server);
+
+	LOG(LOG_DEBUG, "Sending release...");
+	return udhcp_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT);
+}
+
+
+/* return -1 on errors that are fatal for the socket, -2 for those that aren't */
+int get_raw_packet(struct dhcpMessage *payload, int fd)
+{
+	int bytes;
+	struct udp_dhcp_packet packet;
+	uint32_t source, dest;
+	uint16_t check;
+
+	memset(&packet, 0, sizeof(struct udp_dhcp_packet));
+	bytes = read(fd, &packet, sizeof(struct udp_dhcp_packet));
+	if (bytes < 0) {
+		DEBUG(LOG_INFO, "couldn't read on raw listening socket -- ignoring");
+		usleep(500000); /* possible down interface, looping condition */
+		return -1;
+	}
+
+	if (bytes < (int) (sizeof(struct iphdr) + sizeof(struct udphdr))) {
+		DEBUG(LOG_INFO, "message too short, ignoring");
+		return -2;
+	}
+
+	if (bytes < ntohs(packet.ip.tot_len)) {
+		DEBUG(LOG_INFO, "Truncated packet");
+		return -2;
+	}
+
+	/* ignore any extra garbage bytes */
+	bytes = ntohs(packet.ip.tot_len);
+
+	/* Make sure its the right packet for us, and that it passes sanity checks */
+	if (packet.ip.protocol != IPPROTO_UDP || packet.ip.version != IPVERSION ||
+	    packet.ip.ihl != sizeof(packet.ip) >> 2 || packet.udp.dest != htons(CLIENT_PORT) ||
+	    bytes > (int) sizeof(struct udp_dhcp_packet) ||
+	    ntohs(packet.udp.len) != (uint16_t) (bytes - sizeof(packet.ip))) {
+		DEBUG(LOG_INFO, "unrelated/bogus packet");
+		return -2;
+	}
+
+	/* check IP checksum */
+	check = packet.ip.check;
+	packet.ip.check = 0;
+	if (check != udhcp_checksum(&(packet.ip), sizeof(packet.ip))) {
+		DEBUG(LOG_INFO, "bad IP header checksum, ignoring");
+		return -1;
+	}
+
+	/* verify the UDP checksum by replacing the header with a psuedo header */
+	source = packet.ip.saddr;
+	dest = packet.ip.daddr;
+	check = packet.udp.check;
+	packet.udp.check = 0;
+	memset(&packet.ip, 0, sizeof(packet.ip));
+
+	packet.ip.protocol = IPPROTO_UDP;
+	packet.ip.saddr = source;
+	packet.ip.daddr = dest;
+	packet.ip.tot_len = packet.udp.len; /* cheat on the psuedo-header */
+	if (check && check != udhcp_checksum(&packet, bytes)) {
+		DEBUG(LOG_ERR, "packet with bad UDP checksum received, ignoring");
+		return -2;
+	}
+
+	memcpy(payload, &(packet.data), bytes - (sizeof(packet.ip) + sizeof(packet.udp)));
+
+	if (ntohl(payload->cookie) != DHCP_MAGIC) {
+		LOG(LOG_ERR, "received bogus message (bad magic) -- ignoring");
+		return -2;
+	}
+	DEBUG(LOG_INFO, "oooooh!!! got some!");
+	return bytes - (sizeof(packet.ip) + sizeof(packet.udp));
+
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/clientpacket.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/clientpacket.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/clientpacket.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,14 @@
+#ifndef _CLIENTPACKET_H
+#define _CLIENTPACKET_H
+
+#include "packet.h"
+
+unsigned long random_xid(void);
+int send_discover(unsigned long xid, unsigned long requested);
+int send_selecting(unsigned long xid, unsigned long server, unsigned long requested);
+int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr);
+int send_renew(unsigned long xid, unsigned long server, unsigned long ciaddr);
+int send_release(unsigned long server, unsigned long ciaddr);
+int get_raw_packet(struct dhcpMessage *payload, int fd);
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/clientsocket.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/clientsocket.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/clientsocket.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,62 @@
+/*
+ * clientsocket.c -- DHCP client socket creation
+ *
+ * udhcp client
+ *
+ * Russ Dill <Russ.Dill at asu.edu> July 2001
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <features.h>
+#if (__GLIBC__ >= 2 && __GLIBC_MINOR >= 1) || defined _NEWLIB_VERSION
+#include <netpacket/packet.h>
+#include <net/ethernet.h>
+#else
+#include <asm/types.h>
+#include <linux/if_packet.h>
+#include <linux/if_ether.h>
+#endif
+
+#include "clientsocket.h"
+#include "common.h"
+
+
+int raw_socket(int ifindex)
+{
+	int fd;
+	struct sockaddr_ll sock;
+
+	DEBUG(LOG_INFO, "Opening raw socket on ifindex %d", ifindex);
+	if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) {
+		DEBUG(LOG_ERR, "socket call failed: %m");
+		return -1;
+	}
+
+	sock.sll_family = AF_PACKET;
+	sock.sll_protocol = htons(ETH_P_IP);
+	sock.sll_ifindex = ifindex;
+	if (bind(fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
+		DEBUG(LOG_ERR, "bind call failed: %m");
+		close(fd);
+		return -1;
+	}
+
+	return fd;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/clientsocket.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/clientsocket.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/clientsocket.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,7 @@
+/* clientsocket.h */
+#ifndef _CLIENTSOCKET_H
+#define _CLIENTSOCKET_H
+
+int raw_socket(int ifindex);
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/common.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/common.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/common.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,136 @@
+/* vi: set sw=4 ts=4: */
+/* common.c
+ *
+ * Functions for debugging and logging as well as some other
+ * simple helper functions.
+ *
+ * Russ Dill <Russ.Dill at asu.edu> 2001-2003
+ * Rewritten by Vladimir Oleynik <dzo at simtreas.ru> (C) 2003
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <paths.h>
+#include <sys/socket.h>
+#include <stdarg.h>
+
+#include "common.h"
+#include "pidfile.h"
+
+
+static int daemonized;
+
+long uptime(void)
+{
+	struct sysinfo info;
+	sysinfo(&info);
+	return info.uptime;
+}
+
+
+/*
+ * This function makes sure our first socket calls
+ * aren't going to fd 1 (printf badness...) and are
+ * not later closed by daemon()
+ */
+static inline void sanitize_fds(void)
+{
+	int zero;
+	if ((zero = open(bb_dev_null, O_RDWR, 0)) < 0)
+		return;
+	while (zero < 3)
+		zero = dup(zero);
+	close(zero);
+}
+
+
+void udhcp_background(const char *pidfile)
+{
+#ifdef __uClinux__
+	LOG(LOG_ERR, "Cannot background in uclinux (yet)");
+#else /* __uClinux__ */
+	int pid_fd;
+
+	/* hold lock during fork. */
+	pid_fd = pidfile_acquire(pidfile);
+	if (daemon(0, 0) == -1) { /* bb_xdaemon? */
+		perror("fork");
+		exit(1);
+	}
+	daemonized++;
+	pidfile_write_release(pid_fd);
+#endif /* __uClinux__ */
+}
+
+
+#ifdef CONFIG_FEATURE_UDHCP_SYSLOG
+
+void udhcp_logging(int level, const char *fmt, ...)
+{
+	va_list p;
+	va_list p2;
+
+	va_start(p, fmt);
+	__va_copy(p2, p);
+	if (!daemonized) {
+		vprintf(fmt, p);
+		putchar('\n');
+	}
+	vsyslog(level, fmt, p2);
+	va_end(p);
+}
+
+#else
+
+
+static char *syslog_level_msg[] = {
+	[LOG_EMERG]   = "EMERGENCY!",
+	[LOG_ALERT]   = "ALERT!",
+	[LOG_CRIT]    = "critical!",
+	[LOG_WARNING] = "warning",
+	[LOG_ERR]     = "error",
+	[LOG_INFO]    = "info",
+	[LOG_DEBUG]   = "debug"
+};
+
+
+void udhcp_logging(int level, const char *fmt, ...)
+{
+	va_list p;
+
+	va_start(p, fmt);
+	if (!daemonized) {
+		printf("%s, ", syslog_level_msg[level]);
+		vprintf(fmt, p);
+		putchar('\n');
+	}
+	va_end(p);
+}
+#endif
+
+
+void udhcp_start_log_and_pid(const char *client_server, const char *pidfile)
+{
+	int pid_fd;
+
+	/* Make sure our syslog fd isn't overwritten */
+	sanitize_fds();
+
+	/* do some other misc startup stuff while we are here to save bytes */
+	pid_fd = pidfile_acquire(pidfile);
+	pidfile_write_release(pid_fd);
+
+	/* equivelent of doing a fflush after every \n */
+	setlinebuf(stdout);
+
+	if (ENABLE_FEATURE_UDHCP_SYSLOG)
+		openlog(client_server, LOG_PID | LOG_CONS, LOG_LOCAL0);
+
+	udhcp_logging(LOG_INFO, "%s (v%s) started", client_server, BB_VER);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/common.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/common.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/common.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,36 @@
+/* common.h
+ *
+ * Russ Dill <Russ.Dill at asu.edu> September 2001
+ * Rewritten by Vladimir Oleynik <dzo at simtreas.ru> (C) 2003
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#ifndef _COMMON_H
+#define _COMMON_H
+
+#include "libbb_udhcp.h"
+
+
+enum syslog_levels {
+	LOG_EMERG = 0,
+	LOG_ALERT,
+	LOG_CRIT,
+	LOG_WARNING,
+	LOG_ERR,
+	LOG_INFO,
+	LOG_DEBUG
+};
+#include <syslog.h>
+
+long uptime(void);
+
+#define LOG(level, str, args...) udhcp_logging(level, str, ## args)
+
+#if ENABLE_FEATURE_UDHCP_DEBUG
+# define DEBUG(level, str, args...) LOG(level, str, ## args)
+#else
+# define DEBUG(level, str, args...) do {;} while(0)
+#endif
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dhcpc.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dhcpc.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dhcpc.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,533 @@
+/* dhcpc.c
+ *
+ * udhcp DHCP client
+ *
+ * Russ Dill <Russ.Dill at asu.edu> July 2001
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include <sys/file.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <signal.h>
+#include <time.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <errno.h>
+
+#include "common.h"
+#include "dhcpd.h"
+#include "dhcpc.h"
+#include "options.h"
+#include "clientpacket.h"
+#include "clientsocket.h"
+#include "socket.h"
+#include "signalpipe.h"
+
+static int state;
+static unsigned long requested_ip; /* = 0 */
+static unsigned long server_addr;
+static unsigned long timeout;
+static int packet_num; /* = 0 */
+static int fd = -1;
+
+#define LISTEN_NONE 0
+#define LISTEN_KERNEL 1
+#define LISTEN_RAW 2
+static int listen_mode;
+
+struct client_config_t client_config = {
+	/* Default options. */
+	.abort_if_no_lease = 0,
+	.foreground = 0,
+	.quit_after_lease = 0,
+	.background_if_no_lease = 0,
+	.interface = "eth0",
+	.pidfile = NULL,
+	.script = DEFAULT_SCRIPT,
+	.clientid = NULL,
+	.vendorclass = NULL,
+	.hostname = NULL,
+	.fqdn = NULL,
+	.ifindex = 0,
+	.retries = 3,
+	.timeout = 3,
+	.arp = "\0\0\0\0\0\0",		/* appease gcc-3.0 */
+};
+
+/* just a little helper */
+static void change_mode(int new_mode)
+{
+	DEBUG(LOG_INFO, "entering %s listen mode",
+		new_mode ? (new_mode == 1 ? "kernel" : "raw") : "none");
+	if (fd >= 0) close(fd);
+	fd = -1;
+	listen_mode = new_mode;
+}
+
+
+/* perform a renew */
+static void perform_renew(void)
+{
+	LOG(LOG_INFO, "Performing a DHCP renew");
+	switch (state) {
+	case BOUND:
+		change_mode(LISTEN_KERNEL);
+	case RENEWING:
+	case REBINDING:
+		state = RENEW_REQUESTED;
+		break;
+	case RENEW_REQUESTED: /* impatient are we? fine, square 1 */
+		udhcp_run_script(NULL, "deconfig");
+	case REQUESTING:
+	case RELEASED:
+		change_mode(LISTEN_RAW);
+		state = INIT_SELECTING;
+		break;
+	case INIT_SELECTING:
+		break;
+	}
+
+	/* start things over */
+	packet_num = 0;
+
+	/* Kill any timeouts because the user wants this to hurry along */
+	timeout = 0;
+}
+
+
+/* perform a release */
+static void perform_release(void)
+{
+	char buffer[16];
+	struct in_addr temp_addr;
+
+	/* send release packet */
+	if (state == BOUND || state == RENEWING || state == REBINDING) {
+		temp_addr.s_addr = server_addr;
+		sprintf(buffer, "%s", inet_ntoa(temp_addr));
+		temp_addr.s_addr = requested_ip;
+		LOG(LOG_INFO, "Unicasting a release of %s to %s",
+				inet_ntoa(temp_addr), buffer);
+		send_release(server_addr, requested_ip); /* unicast */
+		udhcp_run_script(NULL, "deconfig");
+	}
+	LOG(LOG_INFO, "Entering released state");
+
+	change_mode(LISTEN_NONE);
+	state = RELEASED;
+	timeout = 0x7fffffff;
+}
+
+
+static void client_background(void)
+{
+	udhcp_background(client_config.pidfile);
+	client_config.foreground = 1; /* Do not fork again. */
+	client_config.background_if_no_lease = 0;
+}
+
+
+int udhcpc_main(int argc, char *argv[])
+{
+	uint8_t *temp, *message;
+	unsigned long t1 = 0, t2 = 0, xid = 0;
+	unsigned long start = 0, lease;
+	fd_set rfds;
+	int retval;
+	struct timeval tv;
+	int c, len;
+	struct dhcpMessage packet;
+	struct in_addr temp_addr;
+	long now;
+	int max_fd;
+	int sig;
+	int no_clientid = 0;
+
+	static const struct option arg_options[] = {
+		{"clientid",	required_argument,	0, 'c'},
+		{"clientid-none", no_argument,		0, 'C'},
+		{"vendorclass",	required_argument,	0, 'V'},
+		{"foreground",	no_argument,		0, 'f'},
+		{"background",	no_argument,		0, 'b'},
+		{"hostname",	required_argument,	0, 'H'},
+		{"hostname",	required_argument,	0, 'h'},
+		{"fqdn",	required_argument,	0, 'F'},
+		{"interface",	required_argument,	0, 'i'},
+		{"now",		no_argument,		0, 'n'},
+		{"pidfile",	required_argument,	0, 'p'},
+		{"quit",	no_argument,		0, 'q'},
+		{"request",	required_argument,	0, 'r'},
+		{"script",	required_argument,	0, 's'},
+		{"timeout",	required_argument,	0, 'T'},
+		{"version",	no_argument,		0, 'v'},
+		{"retries",	required_argument,	0, 't'},
+		{0, 0, 0, 0}
+	};
+
+	/* get options */
+	while (1) {
+		int option_index = 0;
+		c = getopt_long(argc, argv, "c:CV:fbH:h:F:i:np:qr:s:T:t:v", arg_options, &option_index);
+		if (c == -1) break;
+
+		switch (c) {
+		case 'c':
+			if (no_clientid) bb_show_usage();
+			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
+			free(client_config.clientid);
+			client_config.clientid = xmalloc(len + 2);
+			client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
+			client_config.clientid[OPT_LEN] = len;
+			client_config.clientid[OPT_DATA] = '\0';
+			strncpy((char*)client_config.clientid + OPT_DATA, optarg, len);
+			break;
+		case 'C':
+			if (client_config.clientid) bb_show_usage();
+			no_clientid = 1;
+			break;
+		case 'V':
+			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
+			free(client_config.vendorclass);
+			client_config.vendorclass = xmalloc(len + 2);
+			client_config.vendorclass[OPT_CODE] = DHCP_VENDOR;
+			client_config.vendorclass[OPT_LEN] = len;
+			strncpy((char*)client_config.vendorclass + OPT_DATA, optarg, len);
+			break;
+		case 'f':
+			client_config.foreground = 1;
+			break;
+		case 'b':
+			client_config.background_if_no_lease = 1;
+			break;
+		case 'h':
+		case 'H':
+			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
+			free(client_config.hostname);
+			client_config.hostname = xmalloc(len + 2);
+			client_config.hostname[OPT_CODE] = DHCP_HOST_NAME;
+			client_config.hostname[OPT_LEN] = len;
+			strncpy((char*)client_config.hostname + 2, optarg, len);
+			break;
+		case 'F':
+			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
+			free(client_config.fqdn);
+			client_config.fqdn = xmalloc(len + 5);
+			client_config.fqdn[OPT_CODE] = DHCP_FQDN;
+			client_config.fqdn[OPT_LEN] = len + 3;
+			/* Flags: 0000NEOS
+			S: 1 => Client requests Server to update A RR in DNS as well as PTR
+			O: 1 => Server indicates to client that DNS has been updated regardless
+			E: 1 => Name data is DNS format, i.e. <4>host<6>domain<4>com<0> not "host.domain.com"
+			N: 1 => Client requests Server to not update DNS
+			*/
+			client_config.fqdn[OPT_LEN + 1] = 0x1;
+			client_config.fqdn[OPT_LEN + 2] = 0;
+			client_config.fqdn[OPT_LEN + 3] = 0;
+			strncpy((char*)client_config.fqdn + 5, optarg, len);
+			break;
+		case 'i':
+			client_config.interface =  optarg;
+			break;
+		case 'n':
+			client_config.abort_if_no_lease = 1;
+			break;
+		case 'p':
+			client_config.pidfile = optarg;
+			break;
+		case 'q':
+			client_config.quit_after_lease = 1;
+			break;
+		case 'r':
+			requested_ip = inet_addr(optarg);
+			break;
+		case 's':
+			client_config.script = optarg;
+			break;
+		case 'T':
+			client_config.timeout = atoi(optarg);
+			break;
+		case 't':
+			client_config.retries = atoi(optarg);
+			break;
+		case 'v':
+			printf("version %s\n\n", BB_VER);
+			return 0;
+			break;
+		default:
+			bb_show_usage();
+		}
+	}
+
+	/* Start the log, sanitize fd's, and write a pid file */
+	udhcp_start_log_and_pid("udhcpc", client_config.pidfile);
+
+	if (read_interface(client_config.interface, &client_config.ifindex,
+			   NULL, client_config.arp) < 0)
+		return 1;
+
+	/* if not set, and not suppressed, setup the default client ID */
+	if (!client_config.clientid && !no_clientid) {
+		client_config.clientid = xmalloc(6 + 3);
+		client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
+		client_config.clientid[OPT_LEN] = 7;
+		client_config.clientid[OPT_DATA] = 1;
+		memcpy(client_config.clientid + 3, client_config.arp, 6);
+	}
+
+	if (!client_config.vendorclass) {
+		client_config.vendorclass = xmalloc(sizeof("udhcp "BB_VER) + 2);
+		client_config.vendorclass[OPT_CODE] = DHCP_VENDOR;
+		client_config.vendorclass[OPT_LEN] = sizeof("udhcp "BB_VER) - 1;
+		client_config.vendorclass[OPT_DATA] = 1;
+		memcpy(&client_config.vendorclass[OPT_DATA],
+			"udhcp "BB_VER, sizeof("udhcp "BB_VER) - 1);
+	}
+
+
+	/* setup the signal pipe */
+	udhcp_sp_setup();
+
+	state = INIT_SELECTING;
+	udhcp_run_script(NULL, "deconfig");
+	change_mode(LISTEN_RAW);
+
+	for (;;) {
+
+		tv.tv_sec = timeout - uptime();
+		tv.tv_usec = 0;
+
+		if (listen_mode != LISTEN_NONE && fd < 0) {
+			if (listen_mode == LISTEN_KERNEL)
+				fd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface);
+			else
+				fd = raw_socket(client_config.ifindex);
+			if (fd < 0) {
+				LOG(LOG_ERR, "FATAL: couldn't listen on socket, %m");
+				return 0;
+			}
+		}
+		max_fd = udhcp_sp_fd_set(&rfds, fd);
+
+		if (tv.tv_sec > 0) {
+			DEBUG(LOG_INFO, "Waiting on select...");
+			retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
+		} else retval = 0; /* If we already timed out, fall through */
+
+		now = uptime();
+		if (retval == 0) {
+			/* timeout dropped to zero */
+			switch (state) {
+			case INIT_SELECTING:
+				if (packet_num < client_config.retries) {
+					if (packet_num == 0)
+						xid = random_xid();
+
+					/* send discover packet */
+					send_discover(xid, requested_ip); /* broadcast */
+
+					timeout = now + client_config.timeout;
+					packet_num++;
+				} else {
+					udhcp_run_script(NULL, "leasefail");
+					if (client_config.background_if_no_lease) {
+						LOG(LOG_INFO, "No lease, forking to background.");
+						client_background();
+					} else if (client_config.abort_if_no_lease) {
+						LOG(LOG_INFO, "No lease, failing.");
+						return 1;
+					}
+					/* wait to try again */
+					packet_num = 0;
+					timeout = now + 60;
+				}
+				break;
+			case RENEW_REQUESTED:
+			case REQUESTING:
+				if (packet_num < client_config.retries) {
+					/* send request packet */
+					if (state == RENEW_REQUESTED)
+						send_renew(xid, server_addr, requested_ip); /* unicast */
+					else send_selecting(xid, server_addr, requested_ip); /* broadcast */
+
+					timeout = now + ((packet_num == 2) ? 10 : 2);
+					packet_num++;
+				} else {
+					/* timed out, go back to init state */
+					if (state == RENEW_REQUESTED) udhcp_run_script(NULL, "deconfig");
+					state = INIT_SELECTING;
+					timeout = now;
+					packet_num = 0;
+					change_mode(LISTEN_RAW);
+				}
+				break;
+			case BOUND:
+				/* Lease is starting to run out, time to enter renewing state */
+				state = RENEWING;
+				change_mode(LISTEN_KERNEL);
+				DEBUG(LOG_INFO, "Entering renew state");
+				/* fall right through */
+			case RENEWING:
+				/* Either set a new T1, or enter REBINDING state */
+				if ((t2 - t1) <= (lease / 14400 + 1)) {
+					/* timed out, enter rebinding state */
+					state = REBINDING;
+					timeout = now + (t2 - t1);
+					DEBUG(LOG_INFO, "Entering rebinding state");
+				} else {
+					/* send a request packet */
+					send_renew(xid, server_addr, requested_ip); /* unicast */
+
+					t1 = (t2 - t1) / 2 + t1;
+					timeout = t1 + start;
+				}
+				break;
+			case REBINDING:
+				/* Either set a new T2, or enter INIT state */
+				if ((lease - t2) <= (lease / 14400 + 1)) {
+					/* timed out, enter init state */
+					state = INIT_SELECTING;
+					LOG(LOG_INFO, "Lease lost, entering init state");
+					udhcp_run_script(NULL, "deconfig");
+					timeout = now;
+					packet_num = 0;
+					change_mode(LISTEN_RAW);
+				} else {
+					/* send a request packet */
+					send_renew(xid, 0, requested_ip); /* broadcast */
+
+					t2 = (lease - t2) / 2 + t2;
+					timeout = t2 + start;
+				}
+				break;
+			case RELEASED:
+				/* yah, I know, *you* say it would never happen */
+				timeout = 0x7fffffff;
+				break;
+			}
+		} else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(fd, &rfds)) {
+			/* a packet is ready, read it */
+
+			if (listen_mode == LISTEN_KERNEL)
+				len = udhcp_get_packet(&packet, fd);
+			else len = get_raw_packet(&packet, fd);
+
+			if (len == -1 && errno != EINTR) {
+				DEBUG(LOG_INFO, "error on read, %m, reopening socket");
+				change_mode(listen_mode); /* just close and reopen */
+			}
+			if (len < 0) continue;
+
+			if (packet.xid != xid) {
+				DEBUG(LOG_INFO, "Ignoring XID %lx (our xid is %lx)",
+					(unsigned long) packet.xid, xid);
+				continue;
+			}
+
+			/* Ignore packets that aren't for us */
+			if (memcmp(packet.chaddr, client_config.arp, 6)) {
+				DEBUG(LOG_INFO, "packet does not have our chaddr -- ignoring");
+				continue;
+			}
+
+			if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) {
+				DEBUG(LOG_ERR, "couldnt get option from packet -- ignoring");
+				continue;
+			}
+
+			switch (state) {
+			case INIT_SELECTING:
+				/* Must be a DHCPOFFER to one of our xid's */
+				if (*message == DHCPOFFER) {
+					if ((temp = get_option(&packet, DHCP_SERVER_ID))) {
+						memcpy(&server_addr, temp, 4);
+						xid = packet.xid;
+						requested_ip = packet.yiaddr;
+
+						/* enter requesting state */
+						state = REQUESTING;
+						timeout = now;
+						packet_num = 0;
+					} else {
+						DEBUG(LOG_ERR, "No server ID in message");
+					}
+				}
+				break;
+			case RENEW_REQUESTED:
+			case REQUESTING:
+			case RENEWING:
+			case REBINDING:
+				if (*message == DHCPACK) {
+					if (!(temp = get_option(&packet, DHCP_LEASE_TIME))) {
+						LOG(LOG_ERR, "No lease time with ACK, using 1 hour lease");
+						lease = 60 * 60;
+					} else {
+						memcpy(&lease, temp, 4);
+						lease = ntohl(lease);
+					}
+
+					/* enter bound state */
+					t1 = lease / 2;
+
+					/* little fixed point for n * .875 */
+					t2 = (lease * 0x7) >> 3;
+					temp_addr.s_addr = packet.yiaddr;
+					LOG(LOG_INFO, "Lease of %s obtained, lease time %ld",
+						inet_ntoa(temp_addr), lease);
+					start = now;
+					timeout = t1 + start;
+					requested_ip = packet.yiaddr;
+					udhcp_run_script(&packet,
+						   ((state == RENEWING || state == REBINDING) ? "renew" : "bound"));
+
+					state = BOUND;
+					change_mode(LISTEN_NONE);
+					if (client_config.quit_after_lease)
+						return 0;
+					if (!client_config.foreground)
+						client_background();
+
+				} else if (*message == DHCPNAK) {
+					/* return to init state */
+					LOG(LOG_INFO, "Received DHCP NAK");
+					udhcp_run_script(&packet, "nak");
+					if (state != REQUESTING)
+						udhcp_run_script(NULL, "deconfig");
+					state = INIT_SELECTING;
+					timeout = now;
+					requested_ip = 0;
+					packet_num = 0;
+					change_mode(LISTEN_RAW);
+					sleep(3); /* avoid excessive network traffic */
+				}
+				break;
+			/* case BOUND, RELEASED: - ignore all packets */
+			}
+		} else if (retval > 0 && (sig = udhcp_sp_read(&rfds))) {
+			switch (sig) {
+			case SIGUSR1:
+				perform_renew();
+				break;
+			case SIGUSR2:
+				perform_release();
+				break;
+			case SIGTERM:
+				LOG(LOG_INFO, "Received SIGTERM");
+				return 0;
+			}
+		} else if (retval == -1 && errno == EINTR) {
+			/* a signal was caught */
+		} else {
+			/* An error occured */
+			DEBUG(LOG_ERR, "Error on select");
+		}
+
+	}
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dhcpc.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dhcpc.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dhcpc.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,39 @@
+/* dhcpc.h */
+#ifndef _DHCPC_H
+#define _DHCPC_H
+
+/* grab define DEFAULT_SCRIPT */
+#include "libbb_udhcp.h"
+
+#define INIT_SELECTING	0
+#define REQUESTING	1
+#define BOUND		2
+#define RENEWING	3
+#define REBINDING	4
+#define INIT_REBOOT	5
+#define RENEW_REQUESTED 6
+#define RELEASED	7
+
+
+struct client_config_t {
+	char foreground;		/* Do not fork */
+	char quit_after_lease;		/* Quit after obtaining lease */
+	char abort_if_no_lease;		/* Abort if no lease */
+	char background_if_no_lease;	/* Fork to background if no lease */
+	char *interface;		/* The name of the interface to use */
+	char *pidfile;			/* Optionally store the process ID */
+	char *script;			/* User script to run at dhcp events */
+	uint8_t *clientid;		/* Optional client id to use */
+	uint8_t *vendorclass;		/* Optional vendor class-id to use */
+	uint8_t *hostname;		/* Optional hostname to use */
+	uint8_t *fqdn;			/* Optional fully qualified domain name to use */
+	int ifindex;			/* Index number of the interface to use */
+	int retries;			/* Max number of request packets */        
+	int timeout;			/* Number of seconds to try to get a lease */
+	uint8_t arp[6];			/* Our arp address */
+};
+
+extern struct client_config_t client_config;
+
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dhcpd.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dhcpd.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dhcpd.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,247 @@
+/* dhcpd.c
+ *
+ * udhcp Server
+ * Copyright (C) 1999 Matthew Ramsay <matthewr at moreton.com.au>
+ *			Chris Trew <ctrew at moreton.com.au>
+ *
+ * Rewrite by Russ Dill <Russ.Dill at asu.edu> July 2001
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <time.h>
+
+#include "dhcpd.h"
+#include "arpping.h"
+#include "socket.h"
+#include "options.h"
+#include "files.h"
+#include "serverpacket.h"
+#include "common.h"
+#include "signalpipe.h"
+#include "static_leases.h"
+
+
+/* globals */
+struct dhcpOfferedAddr *leases;
+struct server_config_t server_config;
+
+
+int udhcpd_main(int argc, char *argv[])
+{
+	fd_set rfds;
+	struct timeval tv;
+	int server_socket = -1, bytes, retval, max_sock;
+	struct dhcpMessage packet;
+	uint8_t *state, *server_id, *requested;
+	uint32_t server_id_align, requested_align, static_lease_ip;
+	unsigned long timeout_end, num_ips;
+	struct option_set *option;
+	struct dhcpOfferedAddr *lease, static_lease;
+
+	read_config(argc < 2 ? DHCPD_CONF_FILE : argv[1]);
+
+	/* Start the log, sanitize fd's, and write a pid file */
+	udhcp_start_log_and_pid("udhcpd", server_config.pidfile);
+
+	if ((option = find_option(server_config.options, DHCP_LEASE_TIME))) {
+		memcpy(&server_config.lease, option->data + 2, 4);
+		server_config.lease = ntohl(server_config.lease);
+	}
+	else server_config.lease = LEASE_TIME;
+
+	/* Sanity check */
+	num_ips = ntohl(server_config.end) - ntohl(server_config.start) + 1;
+	if (server_config.max_leases > num_ips) {
+		LOG(LOG_ERR, "max_leases value (%lu) not sane, "
+			"setting to %lu instead",
+			server_config.max_leases, num_ips);
+		server_config.max_leases = num_ips;
+	}
+
+	leases = xzalloc(server_config.max_leases * sizeof(struct dhcpOfferedAddr));
+	read_leases(server_config.lease_file);
+
+	if (read_interface(server_config.interface, &server_config.ifindex,
+			   &server_config.server, server_config.arp) < 0)
+		return 1;
+
+	if (!ENABLE_FEATURE_UDHCP_DEBUG)
+		udhcp_background(server_config.pidfile); /* hold lock during fork. */
+
+	/* Setup the signal pipe */
+	udhcp_sp_setup();
+
+	timeout_end = time(0) + server_config.auto_time;
+	while(1) { /* loop until universe collapses */
+
+		if (server_socket < 0)
+			if ((server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface)) < 0) {
+				LOG(LOG_ERR, "FATAL: couldn't create server socket, %m");
+				return 2;
+			}
+
+		max_sock = udhcp_sp_fd_set(&rfds, server_socket);
+		if (server_config.auto_time) {
+			tv.tv_sec = timeout_end - time(0);
+			tv.tv_usec = 0;
+		}
+		if (!server_config.auto_time || tv.tv_sec > 0) {
+			retval = select(max_sock + 1, &rfds, NULL, NULL,
+					server_config.auto_time ? &tv : NULL);
+		} else retval = 0; /* If we already timed out, fall through */
+
+		if (retval == 0) {
+			write_leases();
+			timeout_end = time(0) + server_config.auto_time;
+			continue;
+		} else if (retval < 0 && errno != EINTR) {
+			DEBUG(LOG_INFO, "error on select");
+			continue;
+		}
+
+		switch (udhcp_sp_read(&rfds)) {
+		case SIGUSR1:
+			LOG(LOG_INFO, "Received a SIGUSR1");
+			write_leases();
+			/* why not just reset the timeout, eh */
+			timeout_end = time(0) + server_config.auto_time;
+			continue;
+		case SIGTERM:
+			LOG(LOG_INFO, "Received a SIGTERM");
+			return 0;
+		case 0: break;		/* no signal */
+		default: continue;	/* signal or error (probably EINTR) */
+		}
+
+		if ((bytes = udhcp_get_packet(&packet, server_socket)) < 0) { /* this waits for a packet - idle */
+			if (bytes == -1 && errno != EINTR) {
+				DEBUG(LOG_INFO, "error on read, %m, reopening socket");
+				close(server_socket);
+				server_socket = -1;
+			}
+			continue;
+		}
+
+		if ((state = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) {
+			DEBUG(LOG_ERR, "couldn't get option from packet, ignoring");
+			continue;
+		}
+
+		/* Look for a static lease */
+		static_lease_ip = getIpByMac(server_config.static_leases, &packet.chaddr);
+
+		if(static_lease_ip)
+		{
+			printf("Found static lease: %x\n", static_lease_ip);
+
+			memcpy(&static_lease.chaddr, &packet.chaddr, 16);
+			static_lease.yiaddr = static_lease_ip;
+			static_lease.expires = 0;
+
+			lease = &static_lease;
+
+		}
+		else
+		{
+		lease = find_lease_by_chaddr(packet.chaddr);
+		}
+
+		switch (state[0]) {
+		case DHCPDISCOVER:
+			DEBUG(LOG_INFO,"received DISCOVER");
+
+			if (sendOffer(&packet) < 0) {
+				LOG(LOG_ERR, "send OFFER failed");
+			}
+			break;
+		case DHCPREQUEST:
+			DEBUG(LOG_INFO, "received REQUEST");
+
+			requested = get_option(&packet, DHCP_REQUESTED_IP);
+			server_id = get_option(&packet, DHCP_SERVER_ID);
+
+			if (requested) memcpy(&requested_align, requested, 4);
+			if (server_id) memcpy(&server_id_align, server_id, 4);
+
+			if (lease) {
+				if (server_id) {
+					/* SELECTING State */
+					DEBUG(LOG_INFO, "server_id = %08x", ntohl(server_id_align));
+					if (server_id_align == server_config.server && requested &&
+					    requested_align == lease->yiaddr) {
+						sendACK(&packet, lease->yiaddr);
+					}
+				} else {
+					if (requested) {
+						/* INIT-REBOOT State */
+						if (lease->yiaddr == requested_align)
+							sendACK(&packet, lease->yiaddr);
+						else sendNAK(&packet);
+					} else {
+						/* RENEWING or REBINDING State */
+						if (lease->yiaddr == packet.ciaddr)
+							sendACK(&packet, lease->yiaddr);
+						else {
+							/* don't know what to do!!!! */
+							sendNAK(&packet);
+						}
+					}
+				}
+
+			/* what to do if we have no record of the client */
+			} else if (server_id) {
+				/* SELECTING State */
+
+			} else if (requested) {
+				/* INIT-REBOOT State */
+				if ((lease = find_lease_by_yiaddr(requested_align))) {
+					if (lease_expired(lease)) {
+						/* probably best if we drop this lease */
+						memset(lease->chaddr, 0, 16);
+					/* make some contention for this address */
+					} else sendNAK(&packet);
+				} else if (requested_align < server_config.start ||
+					   requested_align > server_config.end) {
+					sendNAK(&packet);
+				} /* else remain silent */
+
+			} else {
+				 /* RENEWING or REBINDING State */
+			}
+			break;
+		case DHCPDECLINE:
+			DEBUG(LOG_INFO,"received DECLINE");
+			if (lease) {
+				memset(lease->chaddr, 0, 16);
+				lease->expires = time(0) + server_config.decline_time;
+			}
+			break;
+		case DHCPRELEASE:
+			DEBUG(LOG_INFO,"received RELEASE");
+			if (lease) lease->expires = time(0);
+			break;
+		case DHCPINFORM:
+			DEBUG(LOG_INFO,"received INFORM");
+			send_inform(&packet);
+			break;
+		default:
+			LOG(LOG_WARNING, "unsupported DHCP message (%02x) -- ignoring", state[0]);
+		}
+	}
+
+	return 0;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dhcpd.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dhcpd.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dhcpd.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,140 @@
+/* dhcpd.h */
+#ifndef _DHCPD_H
+#define _DHCPD_H
+
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+
+#include "libbb_udhcp.h"
+#include "leases.h"
+
+/************************************/
+/* Defaults _you_ may want to tweak */
+/************************************/
+
+/* the period of time the client is allowed to use that address */
+#define LEASE_TIME              (60*60*24*10) /* 10 days of seconds */
+#define LEASES_FILE		"/var/lib/misc/udhcpd.leases"
+
+/* where to find the DHCP server configuration file */
+#define DHCPD_CONF_FILE         "/etc/udhcpd.conf"
+
+/*****************************************************************/
+/* Do not modify below here unless you know what you are doing!! */
+/*****************************************************************/
+
+/* DHCP protocol -- see RFC 2131 */
+#define SERVER_PORT		67
+#define CLIENT_PORT		68
+
+#define DHCP_MAGIC		0x63825363
+
+/* DHCP option codes (partial list) */
+#define DHCP_PADDING		0x00
+#define DHCP_SUBNET		0x01
+#define DHCP_TIME_OFFSET	0x02
+#define DHCP_ROUTER		0x03
+#define DHCP_TIME_SERVER	0x04
+#define DHCP_NAME_SERVER	0x05
+#define DHCP_DNS_SERVER		0x06
+#define DHCP_LOG_SERVER		0x07
+#define DHCP_COOKIE_SERVER	0x08
+#define DHCP_LPR_SERVER		0x09
+#define DHCP_HOST_NAME		0x0c
+#define DHCP_BOOT_SIZE		0x0d
+#define DHCP_DOMAIN_NAME	0x0f
+#define DHCP_SWAP_SERVER	0x10
+#define DHCP_ROOT_PATH		0x11
+#define DHCP_IP_TTL		0x17
+#define DHCP_MTU		0x1a
+#define DHCP_BROADCAST		0x1c
+#define DHCP_NTP_SERVER		0x2a
+#define DHCP_WINS_SERVER	0x2c
+#define DHCP_REQUESTED_IP	0x32
+#define DHCP_LEASE_TIME		0x33
+#define DHCP_OPTION_OVER	0x34
+#define DHCP_MESSAGE_TYPE	0x35
+#define DHCP_SERVER_ID		0x36
+#define DHCP_PARAM_REQ		0x37
+#define DHCP_MESSAGE		0x38
+#define DHCP_MAX_SIZE		0x39
+#define DHCP_T1			0x3a
+#define DHCP_T2			0x3b
+#define DHCP_VENDOR		0x3c
+#define DHCP_CLIENT_ID		0x3d
+#define DHCP_FQDN		0x51
+
+#define DHCP_END		0xFF
+
+
+#define BOOTREQUEST		1
+#define BOOTREPLY		2
+
+#define ETH_10MB		1
+#define ETH_10MB_LEN		6
+
+#define DHCPDISCOVER		1
+#define DHCPOFFER		2
+#define DHCPREQUEST		3
+#define DHCPDECLINE		4
+#define DHCPACK			5
+#define DHCPNAK			6
+#define DHCPRELEASE		7
+#define DHCPINFORM		8
+
+#define BROADCAST_FLAG		0x8000
+
+#define OPTION_FIELD		0
+#define FILE_FIELD		1
+#define SNAME_FIELD		2
+
+/* miscellaneous defines */
+#define MAC_BCAST_ADDR		(uint8_t *) "\xff\xff\xff\xff\xff\xff"
+#define OPT_CODE 0
+#define OPT_LEN 1
+#define OPT_DATA 2
+
+struct option_set {
+	uint8_t *data;
+	struct option_set *next;
+};
+
+struct static_lease {
+	uint8_t *mac;
+	uint32_t *ip;
+	struct static_lease *next;
+};
+
+struct server_config_t {
+	uint32_t server;		/* Our IP, in network order */
+	uint32_t start;			/* Start address of leases, network order */
+	uint32_t end;			/* End of leases, network order */
+	struct option_set *options;	/* List of DHCP options loaded from the config file */
+	char *interface;		/* The name of the interface to use */
+	int ifindex;			/* Index number of the interface to use */
+	uint8_t arp[6];			/* Our arp address */
+	unsigned long lease;		/* lease time in seconds (host order) */
+	unsigned long max_leases;	/* maximum number of leases (including reserved address) */
+	char remaining;			/* should the lease file be interpreted as lease time remaining, or
+					 * as the time the lease expires */
+	unsigned long auto_time;	/* how long should udhcpd wait before writing a config file.
+					 * if this is zero, it will only write one on SIGUSR1 */
+	unsigned long decline_time;	/* how long an address is reserved if a client returns a
+					 * decline message */
+	unsigned long conflict_time;	/* how long an arp conflict offender is leased for */
+	unsigned long offer_time;	/* how long an offered address is reserved */
+	unsigned long min_lease;	/* minimum lease a client can request*/
+	char *lease_file;
+	char *pidfile;
+	char *notify_file;		/* What to run whenever leases are written */
+	uint32_t siaddr;		/* next server bootp option */
+	char *sname;			/* bootp server name */
+	char *boot_file;		/* bootp boot file option */
+	struct static_lease *static_leases; /* List of ip/mac pairs to assign static leases */
+};
+
+extern struct server_config_t server_config;
+extern struct dhcpOfferedAddr *leases;
+
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dumpleases.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dumpleases.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/dumpleases.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,114 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/wait.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <time.h>
+
+#include "dhcpd.h"
+#include "leases.h"
+#include "libbb_udhcp.h"
+
+#define REMAINING 0
+#define ABSOLUTE 1
+
+
+#ifndef IN_BUSYBOX
+static void ATTRIBUTE_NORETURN show_usage(void)
+{
+	printf(
+"Usage: dumpleases -f <file> -[r|a]\n\n"
+"  -f, --file=FILENAME             Leases file to load\n"
+"  -r, --remaining                 Interepret lease times as time remaining\n"
+"  -a, --absolute                  Interepret lease times as expire time\n");
+	exit(0);
+}
+#else
+#define show_usage bb_show_usage
+#endif
+
+
+#ifdef IN_BUSYBOX
+int dumpleases_main(int argc, char *argv[])
+#else
+int main(int argc, char *argv[])
+#endif
+{
+	FILE *fp;
+	int i, c, mode = REMAINING;
+	long expires;
+	const char *file = LEASES_FILE;
+	struct dhcpOfferedAddr lease;
+	struct in_addr addr;
+
+	static const struct option options[] = {
+		{"absolute", 0, 0, 'a'},
+		{"remaining", 0, 0, 'r'},
+		{"file", 1, 0, 'f'},
+		{0, 0, 0, 0}
+	};
+
+	while (1) {
+		int option_index = 0;
+		c = getopt_long(argc, argv, "arf:", options, &option_index);
+		if (c == -1) break;
+
+		switch (c) {
+		case 'a': mode = ABSOLUTE; break;
+		case 'r': mode = REMAINING; break;
+		case 'f':
+			file = optarg;
+			break;
+		default:
+			show_usage();
+		}
+	}
+
+	fp = xfopen(file, "r");
+
+	printf("Mac Address       IP-Address      Expires %s\n", mode == REMAINING ? "in" : "at");
+	/*     "00:00:00:00:00:00 255.255.255.255 Wed Jun 30 21:49:08 1993" */
+	while (fread(&lease, sizeof(lease), 1, fp)) {
+
+		for (i = 0; i < 6; i++) {
+			printf("%02x", lease.chaddr[i]);
+			if (i != 5) printf(":");
+		}
+		addr.s_addr = lease.yiaddr;
+		printf(" %-15s", inet_ntoa(addr));
+		expires = ntohl(lease.expires);
+		printf(" ");
+		if (mode == REMAINING) {
+			if (!expires) printf("expired\n");
+			else {
+				if (expires > 60*60*24) {
+					printf("%ld days, ", expires / (60*60*24));
+					expires %= 60*60*24;
+				}
+				if (expires > 60*60) {
+					printf("%ld hours, ", expires / (60*60));
+					expires %= 60*60;
+				}
+				if (expires > 60) {
+					printf("%ld minutes, ", expires / 60);
+					expires %= 60;
+				}
+				printf("%ld seconds\n", expires);
+			}
+		} else printf("%s", ctime(&expires));
+	}
+	fclose(fp);
+
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/files.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/files.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/files.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,388 @@
+/*
+ * files.c -- DHCP server file manipulation *
+ * Rewrite by Russ Dill <Russ.Dill at asu.edu> July 2001
+ */
+
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+#include <netdb.h>
+
+#include <netinet/ether.h>
+#include "static_leases.h"
+
+#include "dhcpd.h"
+#include "options.h"
+#include "files.h"
+#include "common.h"
+
+/*
+ * Domain names may have 254 chars, and string options can be 254
+ * chars long. However, 80 bytes will be enough for most, and won't
+ * hog up memory. If you have a special application, change it
+ */
+#define READ_CONFIG_BUF_SIZE 80
+
+/* on these functions, make sure you datatype matches */
+static int read_ip(const char *line, void *arg)
+{
+	struct in_addr *addr = arg;
+	struct hostent *host;
+	int retval = 1;
+
+	if (!inet_aton(line, addr)) {
+		if ((host = gethostbyname(line)))
+			addr->s_addr = *((unsigned long *) host->h_addr_list[0]);
+		else retval = 0;
+	}
+	return retval;
+}
+
+static int read_mac(const char *line, void *arg)
+{
+	uint8_t *mac_bytes = arg;
+	struct ether_addr *temp_ether_addr;
+	int retval = 1;
+
+	temp_ether_addr = ether_aton(line);
+
+	if(temp_ether_addr == NULL)
+		retval = 0;
+	else
+		memcpy(mac_bytes, temp_ether_addr, 6);
+
+	return retval;
+}
+
+
+static int read_str(const char *line, void *arg)
+{
+	char **dest = arg;
+
+	free(*dest);
+	*dest = strdup(line);
+
+	return 1;
+}
+
+
+static int read_u32(const char *line, void *arg)
+{
+	uint32_t *dest = arg;
+	char *endptr;
+	*dest = strtoul(line, &endptr, 0);
+	return endptr[0] == '\0';
+}
+
+
+static int read_yn(const char *line, void *arg)
+{
+	char *dest = arg;
+	int retval = 1;
+
+	if (!strcasecmp("yes", line))
+		*dest = 1;
+	else if (!strcasecmp("no", line))
+		*dest = 0;
+	else retval = 0;
+
+	return retval;
+}
+
+
+/* find option 'code' in opt_list */
+struct option_set *find_option(struct option_set *opt_list, char code)
+{
+	while (opt_list && opt_list->data[OPT_CODE] < code)
+		opt_list = opt_list->next;
+
+	if (opt_list && opt_list->data[OPT_CODE] == code) return opt_list;
+	else return NULL;
+}
+
+
+/* add an option to the opt_list */
+static void attach_option(struct option_set **opt_list, struct dhcp_option *option, char *buffer, int length)
+{
+	struct option_set *existing, *new, **curr;
+
+	/* add it to an existing option */
+	if ((existing = find_option(*opt_list, option->code))) {
+		DEBUG(LOG_INFO, "Attaching option %s to existing member of list", option->name);
+		if (option->flags & OPTION_LIST) {
+			if (existing->data[OPT_LEN] + length <= 255) {
+				existing->data = realloc(existing->data,
+						existing->data[OPT_LEN] + length + 2);
+				memcpy(existing->data + existing->data[OPT_LEN] + 2, buffer, length);
+				existing->data[OPT_LEN] += length;
+			} /* else, ignore the data, we could put this in a second option in the future */
+		} /* else, ignore the new data */
+	} else {
+		DEBUG(LOG_INFO, "Attaching option %s to list", option->name);
+
+		/* make a new option */
+		new = xmalloc(sizeof(struct option_set));
+		new->data = xmalloc(length + 2);
+		new->data[OPT_CODE] = option->code;
+		new->data[OPT_LEN] = length;
+		memcpy(new->data + 2, buffer, length);
+
+		curr = opt_list;
+		while (*curr && (*curr)->data[OPT_CODE] < option->code)
+			curr = &(*curr)->next;
+
+		new->next = *curr;
+		*curr = new;
+	}
+}
+
+
+/* read a dhcp option and add it to opt_list */
+static int read_opt(const char *const_line, void *arg)
+{
+	struct option_set **opt_list = arg;
+	char *opt, *val, *endptr;
+	struct dhcp_option *option;
+	int retval = 0, length;
+	char buffer[8];
+	char *line;
+	uint16_t *result_u16 = (uint16_t *) buffer;
+	uint32_t *result_u32 = (uint32_t *) buffer;
+
+	/* Cheat, the only const line we'll actually get is "" */
+	line = (char *) const_line;
+	if (!(opt = strtok(line, " \t="))) return 0;
+
+	for (option = dhcp_options; option->code; option++)
+		if (!strcasecmp(option->name, opt))
+			break;
+
+	if (!option->code) return 0;
+
+	do {
+		if (!(val = strtok(NULL, ", \t"))) break;
+		length = option_lengths[option->flags & TYPE_MASK];
+		retval = 0;
+		opt = buffer; /* new meaning for variable opt */
+		switch (option->flags & TYPE_MASK) {
+		case OPTION_IP:
+			retval = read_ip(val, buffer);
+			break;
+		case OPTION_IP_PAIR:
+			retval = read_ip(val, buffer);
+			if (!(val = strtok(NULL, ", \t/-"))) retval = 0;
+			if (retval) retval = read_ip(val, buffer + 4);
+			break;
+		case OPTION_STRING:
+			length = strlen(val);
+			if (length > 0) {
+				if (length > 254) length = 254;
+				opt = val;
+				retval = 1;
+			}
+			break;
+		case OPTION_BOOLEAN:
+			retval = read_yn(val, buffer);
+			break;
+		case OPTION_U8:
+			buffer[0] = strtoul(val, &endptr, 0);
+			retval = (endptr[0] == '\0');
+			break;
+		case OPTION_U16:
+			*result_u16 = htons(strtoul(val, &endptr, 0));
+			retval = (endptr[0] == '\0');
+			break;
+		case OPTION_S16:
+			*result_u16 = htons(strtol(val, &endptr, 0));
+			retval = (endptr[0] == '\0');
+			break;
+		case OPTION_U32:
+			*result_u32 = htonl(strtoul(val, &endptr, 0));
+			retval = (endptr[0] == '\0');
+			break;
+		case OPTION_S32:
+			*result_u32 = htonl(strtol(val, &endptr, 0));
+			retval = (endptr[0] == '\0');
+			break;
+		default:
+			break;
+		}
+		if (retval)
+			attach_option(opt_list, option, opt, length);
+	} while (retval && option->flags & OPTION_LIST);
+	return retval;
+}
+
+static int read_staticlease(const char *const_line, void *arg)
+{
+
+	char *line;
+	char *mac_string;
+	char *ip_string;
+	uint8_t *mac_bytes;
+	uint32_t *ip;
+
+
+	/* Allocate memory for addresses */
+	mac_bytes = xmalloc(sizeof(unsigned char) * 8);
+	ip = xmalloc(sizeof(uint32_t));
+
+	/* Read mac */
+	line = (char *) const_line;
+	mac_string = strtok(line, " \t");
+	read_mac(mac_string, mac_bytes);
+
+	/* Read ip */
+	ip_string = strtok(NULL, " \t");
+	read_ip(ip_string, ip);
+
+	addStaticLease(arg, mac_bytes, ip);
+
+	if (ENABLE_FEATURE_UDHCP_DEBUG) printStaticLeases(arg);
+
+	return 1;
+
+}
+
+
+static const struct config_keyword keywords[] = {
+	/* keyword	handler   variable address		default */
+	{"start",	read_ip,  &(server_config.start),	"192.168.0.20"},
+	{"end",		read_ip,  &(server_config.end),		"192.168.0.254"},
+	{"interface",	read_str, &(server_config.interface),	"eth0"},
+	{"option",	read_opt, &(server_config.options),	""},
+	{"opt",		read_opt, &(server_config.options),	""},
+	{"max_leases",	read_u32, &(server_config.max_leases),	"254"},
+	{"remaining",	read_yn,  &(server_config.remaining),	"yes"},
+	{"auto_time",	read_u32, &(server_config.auto_time),	"7200"},
+	{"decline_time",read_u32, &(server_config.decline_time),"3600"},
+	{"conflict_time",read_u32,&(server_config.conflict_time),"3600"},
+	{"offer_time",	read_u32, &(server_config.offer_time),	"60"},
+	{"min_lease",	read_u32, &(server_config.min_lease),	"60"},
+	{"lease_file",	read_str, &(server_config.lease_file),	LEASES_FILE},
+	{"pidfile",	read_str, &(server_config.pidfile),	"/var/run/udhcpd.pid"},
+	{"notify_file", read_str, &(server_config.notify_file),	""},
+	{"siaddr",	read_ip,  &(server_config.siaddr),	"0.0.0.0"},
+	{"sname",	read_str, &(server_config.sname),	""},
+	{"boot_file",	read_str, &(server_config.boot_file),	""},
+	{"static_lease",read_staticlease, &(server_config.static_leases),	""},
+	/*ADDME: static lease */
+	{"",		NULL,	  NULL,				""}
+};
+
+
+int read_config(const char *file)
+{
+	FILE *in;
+	char buffer[READ_CONFIG_BUF_SIZE], *token, *line;
+	int i, lm = 0;
+
+	for (i = 0; keywords[i].keyword[0]; i++)
+		if (keywords[i].def[0])
+			keywords[i].handler(keywords[i].def, keywords[i].var);
+
+	if (!(in = fopen(file, "r"))) {
+		LOG(LOG_ERR, "unable to open config file: %s", file);
+		return 0;
+	}
+
+	while (fgets(buffer, READ_CONFIG_BUF_SIZE, in)) {
+		char debug_orig[READ_CONFIG_BUF_SIZE];
+
+		lm++;
+		if (strchr(buffer, '\n')) *(strchr(buffer, '\n')) = '\0';
+		if (ENABLE_FEATURE_UDHCP_DEBUG) strcpy(debug_orig, buffer);
+		if (strchr(buffer, '#')) *(strchr(buffer, '#')) = '\0';
+
+		if (!(token = strtok(buffer, " \t"))) continue;
+		if (!(line = strtok(NULL, ""))) continue;
+
+		/* eat leading whitespace */
+		line = line + strspn(line, " \t=");
+		/* eat trailing whitespace */
+		for (i = strlen(line); i > 0 && isspace(line[i - 1]); i--);
+		line[i] = '\0';
+
+		for (i = 0; keywords[i].keyword[0]; i++)
+			if (!strcasecmp(token, keywords[i].keyword))
+				if (!keywords[i].handler(line, keywords[i].var)) {
+					LOG(LOG_ERR, "Failure parsing line %d of %s", lm, file);
+					DEBUG(LOG_ERR, "unable to parse '%s'", debug_orig);
+					/* reset back to the default value */
+					keywords[i].handler(keywords[i].def, keywords[i].var);
+				}
+	}
+	fclose(in);
+	return 1;
+}
+
+
+void write_leases(void)
+{
+	FILE *fp;
+	unsigned int i;
+	char buf[255];
+	time_t curr = time(0);
+	unsigned long tmp_time;
+
+	if (!(fp = fopen(server_config.lease_file, "w"))) {
+		LOG(LOG_ERR, "Unable to open %s for writing", server_config.lease_file);
+		return;
+	}
+
+	for (i = 0; i < server_config.max_leases; i++) {
+		if (leases[i].yiaddr != 0) {
+
+			/* screw with the time in the struct, for easier writing */
+			tmp_time = leases[i].expires;
+
+			if (server_config.remaining) {
+				if (lease_expired(&(leases[i])))
+					leases[i].expires = 0;
+				else leases[i].expires -= curr;
+			} /* else stick with the time we got */
+			leases[i].expires = htonl(leases[i].expires);
+			fwrite(&leases[i], sizeof(struct dhcpOfferedAddr), 1, fp);
+
+			/* Then restore it when done. */
+			leases[i].expires = tmp_time;
+		}
+	}
+	fclose(fp);
+
+	if (server_config.notify_file) {
+		sprintf(buf, "%s %s", server_config.notify_file, server_config.lease_file);
+		system(buf);
+	}
+}
+
+
+void read_leases(const char *file)
+{
+	FILE *fp;
+	unsigned int i = 0;
+	struct dhcpOfferedAddr lease;
+
+	if (!(fp = fopen(file, "r"))) {
+		LOG(LOG_ERR, "Unable to open %s for reading", file);
+		return;
+	}
+
+	while (i < server_config.max_leases && (fread(&lease, sizeof lease, 1, fp) == 1)) {
+		/* ADDME: is it a static lease */
+		if (lease.yiaddr >= server_config.start && lease.yiaddr <= server_config.end) {
+			lease.expires = ntohl(lease.expires);
+			if (!server_config.remaining) lease.expires -= time(0);
+			if (!(add_lease(lease.chaddr, lease.yiaddr, lease.expires))) {
+				LOG(LOG_WARNING, "Too many leases while loading %s\n", file);
+				break;
+			}
+			i++;
+		}
+	}
+	DEBUG(LOG_INFO, "Read %d leases", i);
+	fclose(fp);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/files.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/files.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/files.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,19 @@
+/* files.h */
+#ifndef _FILES_H
+#define _FILES_H
+
+struct config_keyword {
+	const char *keyword;
+	int (* const handler)(const char *line, void *var);
+	void *var;
+	const char *def;
+};
+
+
+int read_config(const char *file);
+void write_leases(void);
+void read_leases(const char *file);
+
+struct option_set *find_option(struct option_set *opt_list, char code);
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/frontend.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/frontend.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/frontend.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,16 @@
+#include <string.h>
+
+extern int udhcpd_main(int argc, char *argv[]);
+extern int udhcpc_main(int argc, char *argv[]);
+
+int main(int argc, char *argv[])
+{
+	int ret = 0;
+	char *base = strrchr(argv[0], '/');
+
+	if (strstr(base ? (base + 1) : argv[0], "dhcpd"))
+		ret = udhcpd_main(argc, argv);
+	else ret = udhcpc_main(argc, argv);
+
+	return ret;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/leases.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/leases.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/leases.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,158 @@
+/*
+ * leases.c -- tools to manage DHCP leases
+ * Russ Dill <Russ.Dill at asu.edu> July 2001
+ */
+
+#include <time.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "dhcpd.h"
+#include "files.h"
+#include "options.h"
+#include "leases.h"
+#include "arpping.h"
+#include "common.h"
+
+#include "static_leases.h"
+
+
+uint8_t blank_chaddr[] = {[0 ... 15] = 0};
+
+/* clear every lease out that chaddr OR yiaddr matches and is nonzero */
+void clear_lease(uint8_t *chaddr, uint32_t yiaddr)
+{
+	unsigned int i, j;
+
+	for (j = 0; j < 16 && !chaddr[j]; j++);
+
+	for (i = 0; i < server_config.max_leases; i++)
+		if ((j != 16 && !memcmp(leases[i].chaddr, chaddr, 16)) ||
+		    (yiaddr && leases[i].yiaddr == yiaddr)) {
+			memset(&(leases[i]), 0, sizeof(struct dhcpOfferedAddr));
+		}
+}
+
+
+/* add a lease into the table, clearing out any old ones */
+struct dhcpOfferedAddr *add_lease(uint8_t *chaddr, uint32_t yiaddr, unsigned long lease)
+{
+	struct dhcpOfferedAddr *oldest;
+
+	/* clean out any old ones */
+	clear_lease(chaddr, yiaddr);
+
+	oldest = oldest_expired_lease();
+
+	if (oldest) {
+		memcpy(oldest->chaddr, chaddr, 16);
+		oldest->yiaddr = yiaddr;
+		oldest->expires = time(0) + lease;
+	}
+
+	return oldest;
+}
+
+
+/* true if a lease has expired */
+int lease_expired(struct dhcpOfferedAddr *lease)
+{
+	return (lease->expires < (unsigned long) time(0));
+}
+
+
+/* Find the oldest expired lease, NULL if there are no expired leases */
+struct dhcpOfferedAddr *oldest_expired_lease(void)
+{
+	struct dhcpOfferedAddr *oldest = NULL;
+	unsigned long oldest_lease = time(0);
+	unsigned int i;
+
+
+	for (i = 0; i < server_config.max_leases; i++)
+		if (oldest_lease > leases[i].expires) {
+			oldest_lease = leases[i].expires;
+			oldest = &(leases[i]);
+		}
+	return oldest;
+
+}
+
+
+/* Find the first lease that matches chaddr, NULL if no match */
+struct dhcpOfferedAddr *find_lease_by_chaddr(uint8_t *chaddr)
+{
+	unsigned int i;
+
+	for (i = 0; i < server_config.max_leases; i++)
+		if (!memcmp(leases[i].chaddr, chaddr, 16)) return &(leases[i]);
+
+	return NULL;
+}
+
+
+/* Find the first lease that matches yiaddr, NULL is no match */
+struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr)
+{
+	unsigned int i;
+
+	for (i = 0; i < server_config.max_leases; i++)
+		if (leases[i].yiaddr == yiaddr) return &(leases[i]);
+
+	return NULL;
+}
+
+
+/* check is an IP is taken, if it is, add it to the lease table */
+static int check_ip(uint32_t addr)
+{
+	struct in_addr temp;
+
+	if (arpping(addr, server_config.server, server_config.arp, server_config.interface) == 0) {
+		temp.s_addr = addr;
+		LOG(LOG_INFO, "%s belongs to someone, reserving it for %ld seconds",
+			inet_ntoa(temp), server_config.conflict_time);
+		add_lease(blank_chaddr, addr, server_config.conflict_time);
+		return 1;
+	} else return 0;
+}
+
+
+/* find an assignable address, it check_expired is true, we check all the expired leases as well.
+ * Maybe this should try expired leases by age... */
+uint32_t find_address(int check_expired)
+{
+	uint32_t addr, ret;
+	struct dhcpOfferedAddr *lease = NULL;
+
+	addr = ntohl(server_config.start); /* addr is in host order here */
+	for (;addr <= ntohl(server_config.end); addr++) {
+
+		/* ie, 192.168.55.0 */
+		if (!(addr & 0xFF)) continue;
+
+		/* ie, 192.168.55.255 */
+		if ((addr & 0xFF) == 0xFF) continue;
+
+		/* Only do if it isn't an assigned as a static lease */
+		if(!reservedIp(server_config.static_leases, htonl(addr)))
+		{
+
+		/* lease is not taken */
+		ret = htonl(addr);
+		if ((!(lease = find_lease_by_yiaddr(ret)) ||
+
+		     /* or it expired and we are checking for expired leases */
+		     (check_expired  && lease_expired(lease))) &&
+
+		     /* and it isn't on the network */
+		     !check_ip(ret)) {
+			return ret;
+			break;
+		}
+	}
+	}
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/leases.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/leases.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/leases.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+/* leases.h */
+#ifndef _LEASES_H
+#define _LEASES_H
+
+
+struct dhcpOfferedAddr {
+	uint8_t chaddr[16];
+	uint32_t yiaddr;	/* network order */
+	uint32_t expires;	/* host order */
+};
+
+extern uint8_t blank_chaddr[];
+
+void clear_lease(uint8_t *chaddr, uint32_t yiaddr);
+struct dhcpOfferedAddr *add_lease(uint8_t *chaddr, uint32_t yiaddr, unsigned long lease);
+int lease_expired(struct dhcpOfferedAddr *lease);
+struct dhcpOfferedAddr *oldest_expired_lease(void);
+struct dhcpOfferedAddr *find_lease_by_chaddr(uint8_t *chaddr);
+struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr);
+uint32_t find_address(int check_expired);
+
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/libbb_udhcp.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/libbb_udhcp.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/libbb_udhcp.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,49 @@
+/* libbb_udhcp.h - busybox compatibility wrapper */
+
+/* bit of a hack, do this no matter what the order of the includes.
+ * (for busybox) */
+
+#ifndef _LIBBB_UDHCP_H
+#define _LIBBB_UDHCP_H
+
+#include "packet.h"
+#include "busybox.h"
+
+#ifdef CONFIG_INSTALL_NO_USR
+# define DEFAULT_SCRIPT  "/share/udhcpc/default.script"
+#else
+# define DEFAULT_SCRIPT  "/usr/share/udhcpc/default.script"
+#endif
+
+
+
+#define COMBINED_BINARY
+
+#define xfopen bb_xfopen
+
+void udhcp_background(const char *pidfile);
+void udhcp_start_log_and_pid(const char *client_server, const char *pidfile);
+void udhcp_logging(int level, const char *fmt, ...);
+
+void udhcp_run_script(struct dhcpMessage *packet, const char *name);
+
+// Still need to clean these up...
+
+/* from pidfile.h */
+#define pidfile_acquire		udhcp_pidfile_acquire
+#define pidfile_write_release	udhcp_pidfile_write_release
+/* from options.h */
+#define get_option		udhcp_get_option
+#define end_option		udhcp_end_option
+#define add_option_string	udhcp_add_option_string
+#define add_simple_option	udhcp_add_simple_option
+#define option_lengths		udhcp_option_lengths
+/* from socket.h */
+#define listen_socket		udhcp_listen_socket
+#define read_interface		udhcp_read_interface
+/* from dhcpc.h */
+#define client_config		udhcp_client_config
+/* from dhcpd.h */
+#define server_config		udhcp_server_config
+
+#endif /* _LIBBB_UDHCP_H */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/options.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/options.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/options.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,171 @@
+/*
+ * options.c -- DHCP server option packet tools
+ * Rewrite by Russ Dill <Russ.Dill at asu.edu> July 2001
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+#include "dhcpd.h"
+#include "options.h"
+#include "files.h"
+
+
+/* supported options are easily added here */
+struct dhcp_option dhcp_options[] = {
+	/* name[10]	flags					code */
+	{"subnet",	OPTION_IP | OPTION_REQ,			0x01},
+	{"timezone",	OPTION_S32,				0x02},
+	{"router",	OPTION_IP | OPTION_LIST | OPTION_REQ,	0x03},
+	{"timesvr",	OPTION_IP | OPTION_LIST,		0x04},
+	{"namesvr",	OPTION_IP | OPTION_LIST,		0x05},
+	{"dns",		OPTION_IP | OPTION_LIST | OPTION_REQ,	0x06},
+	{"logsvr",	OPTION_IP | OPTION_LIST,		0x07},
+	{"cookiesvr",	OPTION_IP | OPTION_LIST,		0x08},
+	{"lprsvr",	OPTION_IP | OPTION_LIST,		0x09},
+	{"hostname",	OPTION_STRING | OPTION_REQ,		0x0c},
+	{"bootsize",	OPTION_U16,				0x0d},
+	{"domain",	OPTION_STRING | OPTION_REQ,		0x0f},
+	{"swapsvr",	OPTION_IP,				0x10},
+	{"rootpath",	OPTION_STRING,				0x11},
+	{"ipttl",	OPTION_U8,				0x17},
+	{"mtu",		OPTION_U16,				0x1a},
+	{"broadcast",	OPTION_IP | OPTION_REQ,			0x1c},
+	{"nisdomain",	OPTION_STRING | OPTION_REQ,		0x28},
+	{"nissrv",	OPTION_IP | OPTION_LIST | OPTION_REQ,	0x29},
+	{"ntpsrv",	OPTION_IP | OPTION_LIST | OPTION_REQ,	0x2a},
+	{"wins",	OPTION_IP | OPTION_LIST,		0x2c},
+	{"requestip",	OPTION_IP,				0x32},
+	{"lease",	OPTION_U32,				0x33},
+	{"dhcptype",	OPTION_U8,				0x35},
+	{"serverid",	OPTION_IP,				0x36},
+	{"message",	OPTION_STRING,				0x38},
+	{"tftp",	OPTION_STRING,				0x42},
+	{"bootfile",	OPTION_STRING,				0x43},
+	{"",		0x00,				0x00}
+};
+
+/* Lengths of the different option types */
+int option_lengths[] = {
+	[OPTION_IP] =		4,
+	[OPTION_IP_PAIR] =	8,
+	[OPTION_BOOLEAN] =	1,
+	[OPTION_STRING] =	1,
+	[OPTION_U8] =		1,
+	[OPTION_U16] =		2,
+	[OPTION_S16] =		2,
+	[OPTION_U32] =		4,
+	[OPTION_S32] =		4
+};
+
+
+/* get an option with bounds checking (warning, not aligned). */
+uint8_t *get_option(struct dhcpMessage *packet, int code)
+{
+	int i, length;
+	uint8_t *optionptr;
+	int over = 0, done = 0, curr = OPTION_FIELD;
+
+	optionptr = packet->options;
+	i = 0;
+	length = 308;
+	while (!done) {
+		if (i >= length) {
+			LOG(LOG_WARNING, "bogus packet, option fields too long.");
+			return NULL;
+		}
+		if (optionptr[i + OPT_CODE] == code) {
+			if (i + 1 + optionptr[i + OPT_LEN] >= length) {
+				LOG(LOG_WARNING, "bogus packet, option fields too long.");
+				return NULL;
+			}
+			return optionptr + i + 2;
+		}
+		switch (optionptr[i + OPT_CODE]) {
+		case DHCP_PADDING:
+			i++;
+			break;
+		case DHCP_OPTION_OVER:
+			if (i + 1 + optionptr[i + OPT_LEN] >= length) {
+				LOG(LOG_WARNING, "bogus packet, option fields too long.");
+				return NULL;
+			}
+			over = optionptr[i + 3];
+			i += optionptr[OPT_LEN] + 2;
+			break;
+		case DHCP_END:
+			if (curr == OPTION_FIELD && over & FILE_FIELD) {
+				optionptr = packet->file;
+				i = 0;
+				length = 128;
+				curr = FILE_FIELD;
+			} else if (curr == FILE_FIELD && over & SNAME_FIELD) {
+				optionptr = packet->sname;
+				i = 0;
+				length = 64;
+				curr = SNAME_FIELD;
+			} else done = 1;
+			break;
+		default:
+			i += optionptr[OPT_LEN + i] + 2;
+		}
+	}
+	return NULL;
+}
+
+
+/* return the position of the 'end' option (no bounds checking) */
+int end_option(uint8_t *optionptr)
+{
+	int i = 0;
+
+	while (optionptr[i] != DHCP_END) {
+		if (optionptr[i] == DHCP_PADDING) i++;
+		else i += optionptr[i + OPT_LEN] + 2;
+	}
+	return i;
+}
+
+
+/* add an option string to the options (an option string contains an option code,
+ * length, then data) */
+int add_option_string(uint8_t *optionptr, uint8_t *string)
+{
+	int end = end_option(optionptr);
+
+	/* end position + string length + option code/length + end option */
+	if (end + string[OPT_LEN] + 2 + 1 >= 308) {
+		LOG(LOG_ERR, "Option 0x%02x did not fit into the packet!", string[OPT_CODE]);
+		return 0;
+	}
+	DEBUG(LOG_INFO, "adding option 0x%02x", string[OPT_CODE]);
+	memcpy(optionptr + end, string, string[OPT_LEN] + 2);
+	optionptr[end + string[OPT_LEN] + 2] = DHCP_END;
+	return string[OPT_LEN] + 2;
+}
+
+
+/* add a one to four byte option to a packet */
+int add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data)
+{
+	struct dhcp_option *dh;
+
+	for (dh=dhcp_options; dh->code; dh++) {
+		if (dh->code == code) {
+			uint8_t option[6], len;
+
+			option[OPT_CODE] = code;
+			len = option_lengths[dh->flags & TYPE_MASK];
+			option[OPT_LEN] = len;
+			if (BB_BIG_ENDIAN) data <<= 8 * (4 - len);
+			/* This memcpy is for broken processors which can't
+			 * handle a simple unaligned 32-bit assignment */
+			memcpy(&option[OPT_DATA], &data, 4);
+			return add_option_string(optionptr, option);
+		}
+	}
+
+	DEBUG(LOG_ERR, "Could not add option 0x%02x", code);
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/options.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/options.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/options.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,38 @@
+/* options.h */
+#ifndef _OPTIONS_H
+#define _OPTIONS_H
+
+#include "packet.h"
+
+#define TYPE_MASK	0x0F
+
+enum {
+	OPTION_IP=1,
+	OPTION_IP_PAIR,
+	OPTION_STRING,
+	OPTION_BOOLEAN,
+	OPTION_U8,
+	OPTION_U16,
+	OPTION_S16,
+	OPTION_U32,
+	OPTION_S32
+};
+
+#define OPTION_REQ	0x10 /* have the client request this option */
+#define OPTION_LIST	0x20 /* There can be a list of 1 or more of these */
+
+struct dhcp_option {
+	char name[10];
+	char flags;
+	uint8_t code;
+};
+
+extern struct dhcp_option dhcp_options[];
+extern int option_lengths[];
+
+uint8_t *get_option(struct dhcpMessage *packet, int code);
+int end_option(uint8_t *optionptr);
+int add_option_string(uint8_t *optionptr, uint8_t *string);
+int add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data);
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/packet.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/packet.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/packet.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,207 @@
+#include <unistd.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <features.h>
+#if (__GLIBC__ >= 2 && __GLIBC_MINOR >= 1) || defined _NEWLIB_VERSION
+#include <netpacket/packet.h>
+#include <net/ethernet.h>
+#else
+#include <asm/types.h>
+#include <linux/if_packet.h>
+#include <linux/if_ether.h>
+#endif
+#include <errno.h>
+
+#include "common.h"
+#include "packet.h"
+#include "dhcpd.h"
+#include "options.h"
+
+
+void udhcp_init_header(struct dhcpMessage *packet, char type)
+{
+	memset(packet, 0, sizeof(struct dhcpMessage));
+	switch (type) {
+	case DHCPDISCOVER:
+	case DHCPREQUEST:
+	case DHCPRELEASE:
+	case DHCPINFORM:
+		packet->op = BOOTREQUEST;
+		break;
+	case DHCPOFFER:
+	case DHCPACK:
+	case DHCPNAK:
+		packet->op = BOOTREPLY;
+	}
+	packet->htype = ETH_10MB;
+	packet->hlen = ETH_10MB_LEN;
+	packet->cookie = htonl(DHCP_MAGIC);
+	packet->options[0] = DHCP_END;
+	add_simple_option(packet->options, DHCP_MESSAGE_TYPE, type);
+}
+
+
+/* read a packet from socket fd, return -1 on read error, -2 on packet error */
+int udhcp_get_packet(struct dhcpMessage *packet, int fd)
+{
+	static const char broken_vendors[][8] = {
+		"MSFT 98",
+		""
+	};
+	int bytes;
+	int i;
+	char unsigned *vendor;
+
+	memset(packet, 0, sizeof(struct dhcpMessage));
+	bytes = read(fd, packet, sizeof(struct dhcpMessage));
+	if (bytes < 0) {
+		DEBUG(LOG_INFO, "couldn't read on listening socket, ignoring");
+		return -1;
+	}
+
+	if (ntohl(packet->cookie) != DHCP_MAGIC) {
+		LOG(LOG_ERR, "received bogus message, ignoring");
+		return -2;
+	}
+	DEBUG(LOG_INFO, "Received a packet");
+
+	if (packet->op == BOOTREQUEST && (vendor = get_option(packet, DHCP_VENDOR))) {
+		for (i = 0; broken_vendors[i][0]; i++) {
+			if (vendor[OPT_LEN - 2] == (uint8_t) strlen(broken_vendors[i]) &&
+			    !strncmp((char*)vendor, broken_vendors[i], vendor[OPT_LEN - 2])) {
+				DEBUG(LOG_INFO, "broken client (%s), forcing broadcast",
+					broken_vendors[i]);
+				packet->flags |= htons(BROADCAST_FLAG);
+			}
+		}
+	}
+
+	return bytes;
+}
+
+
+uint16_t udhcp_checksum(void *addr, int count)
+{
+	/* Compute Internet Checksum for "count" bytes
+	 *         beginning at location "addr".
+	 */
+	register int32_t sum = 0;
+	uint16_t *source = (uint16_t *) addr;
+
+	while (count > 1)  {
+		/*  This is the inner loop */
+		sum += *source++;
+		count -= 2;
+	}
+
+	/*  Add left-over byte, if any */
+	if (count > 0) {
+		/* Make sure that the left-over byte is added correctly both
+		 * with little and big endian hosts */
+		uint16_t tmp = 0;
+		*(uint8_t *) (&tmp) = * (uint8_t *) source;
+		sum += tmp;
+	}
+	/*  Fold 32-bit sum to 16 bits */
+	while (sum >> 16)
+		sum = (sum & 0xffff) + (sum >> 16);
+
+	return ~sum;
+}
+
+
+/* Construct a ip/udp header for a packet, and specify the source and dest hardware address */
+int udhcp_raw_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port,
+		   uint32_t dest_ip, int dest_port, uint8_t *dest_arp, int ifindex)
+{
+	int fd;
+	int result;
+	struct sockaddr_ll dest;
+	struct udp_dhcp_packet packet;
+
+	if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) {
+		DEBUG(LOG_ERR, "socket call failed: %m");
+		return -1;
+	}
+
+	memset(&dest, 0, sizeof(dest));
+	memset(&packet, 0, sizeof(packet));
+
+	dest.sll_family = AF_PACKET;
+	dest.sll_protocol = htons(ETH_P_IP);
+	dest.sll_ifindex = ifindex;
+	dest.sll_halen = 6;
+	memcpy(dest.sll_addr, dest_arp, 6);
+	if (bind(fd, (struct sockaddr *)&dest, sizeof(struct sockaddr_ll)) < 0) {
+		DEBUG(LOG_ERR, "bind call failed: %m");
+		close(fd);
+		return -1;
+	}
+
+	packet.ip.protocol = IPPROTO_UDP;
+	packet.ip.saddr = source_ip;
+	packet.ip.daddr = dest_ip;
+	packet.udp.source = htons(source_port);
+	packet.udp.dest = htons(dest_port);
+	packet.udp.len = htons(sizeof(packet.udp) + sizeof(struct dhcpMessage)); /* cheat on the psuedo-header */
+	packet.ip.tot_len = packet.udp.len;
+	memcpy(&(packet.data), payload, sizeof(struct dhcpMessage));
+	packet.udp.check = udhcp_checksum(&packet, sizeof(struct udp_dhcp_packet));
+
+	packet.ip.tot_len = htons(sizeof(struct udp_dhcp_packet));
+	packet.ip.ihl = sizeof(packet.ip) >> 2;
+	packet.ip.version = IPVERSION;
+	packet.ip.ttl = IPDEFTTL;
+	packet.ip.check = udhcp_checksum(&(packet.ip), sizeof(packet.ip));
+
+	result = sendto(fd, &packet, sizeof(struct udp_dhcp_packet), 0, (struct sockaddr *) &dest, sizeof(dest));
+	if (result <= 0) {
+		DEBUG(LOG_ERR, "write on socket failed: %m");
+	}
+	close(fd);
+	return result;
+}
+
+
+/* Let the kernel do all the work for packet generation */
+int udhcp_kernel_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port,
+		   uint32_t dest_ip, int dest_port)
+{
+	int n = 1;
+	int fd, result;
+	struct sockaddr_in client;
+
+	if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+		return -1;
+
+	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == -1) {
+		close(fd);
+		return -1;
+	}
+
+	memset(&client, 0, sizeof(client));
+	client.sin_family = AF_INET;
+	client.sin_port = htons(source_port);
+	client.sin_addr.s_addr = source_ip;
+
+	if (bind(fd, (struct sockaddr *)&client, sizeof(struct sockaddr)) == -1) {
+		close(fd);
+		return -1;
+	}
+
+	memset(&client, 0, sizeof(client));
+	client.sin_family = AF_INET;
+	client.sin_port = htons(dest_port);
+	client.sin_addr.s_addr = dest_ip;
+
+	if (connect(fd, (struct sockaddr *)&client, sizeof(struct sockaddr)) == -1) {
+		close(fd);
+		return -1;
+	}
+
+	result = write(fd, payload, sizeof(struct dhcpMessage));
+	close(fd);
+	return result;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/packet.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/packet.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/packet.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,41 @@
+#ifndef _PACKET_H
+#define _PACKET_H
+
+#include <netinet/udp.h>
+#include <netinet/ip.h>
+
+struct dhcpMessage {
+	uint8_t op;
+	uint8_t htype;
+	uint8_t hlen;
+	uint8_t hops;
+	uint32_t xid;
+	uint16_t secs;
+	uint16_t flags;
+	uint32_t ciaddr;
+	uint32_t yiaddr;
+	uint32_t siaddr;
+	uint32_t giaddr;
+	uint8_t chaddr[16];
+	uint8_t sname[64];
+	uint8_t file[128];
+	uint32_t cookie;
+	uint8_t options[308]; /* 312 - cookie */
+};
+
+struct udp_dhcp_packet {
+	struct iphdr ip;
+	struct udphdr udp;
+	struct dhcpMessage data;
+};
+
+void udhcp_init_header(struct dhcpMessage *packet, char type);
+int udhcp_get_packet(struct dhcpMessage *packet, int fd);
+uint16_t udhcp_checksum(void *addr, int count);
+int udhcp_raw_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port,
+		   uint32_t dest_ip, int dest_port, uint8_t *dest_arp, int ifindex);
+int udhcp_kernel_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port,
+		   uint32_t dest_ip, int dest_port);
+
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/pidfile.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/pidfile.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/pidfile.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,75 @@
+/* pidfile.c
+ *
+ * Functions to assist in the writing and removing of pidfiles.
+ *
+ * Russ Dill <Russ.Dill at asu.edu> September 2001
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"
+#include "pidfile.h"
+
+static char *saved_pidfile;
+
+static void pidfile_delete(void)
+{
+	if (saved_pidfile) unlink(saved_pidfile);
+}
+
+
+int pidfile_acquire(const char *pidfile)
+{
+	int pid_fd;
+	if (!pidfile) return -1;
+
+	pid_fd = open(pidfile, O_CREAT | O_WRONLY, 0644);
+	if (pid_fd < 0) {
+		LOG(LOG_ERR, "Unable to open pidfile %s: %m\n", pidfile);
+	} else {
+		lockf(pid_fd, F_LOCK, 0);
+		if (!saved_pidfile)
+			atexit(pidfile_delete);
+		saved_pidfile = (char *) pidfile;
+	}
+
+	return pid_fd;
+}
+
+
+void pidfile_write_release(int pid_fd)
+{
+	FILE *out;
+
+	if (pid_fd < 0) return;
+
+	if ((out = fdopen(pid_fd, "w")) != NULL) {
+		fprintf(out, "%d\n", getpid());
+		fclose(out);
+	}
+	lockf(pid_fd, F_UNLCK, 0);
+	close(pid_fd);
+}
+
+
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/pidfile.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/pidfile.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/pidfile.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,25 @@
+/* pidfile.h
+ *
+ * Functions to assist in the writing and removing of pidfiles.
+ *
+ * Russ Dill <Russ.Dill at asu.edu> September 2001
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+int pidfile_acquire(const char *pidfile);
+void pidfile_write_release(int pid_fd);
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/script.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/script.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/script.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,221 @@
+/* script.c
+ *
+ * Functions to call the DHCP client notification scripts
+ *
+ * Russ Dill <Russ.Dill at asu.edu> July 2001
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "common.h"
+#include "options.h"
+#include "dhcpd.h"
+#include "dhcpc.h"
+
+/* get a rough idea of how long an option will be (rounding up...) */
+static const int max_option_length[] = {
+	[OPTION_IP] =		sizeof("255.255.255.255 "),
+	[OPTION_IP_PAIR] =	sizeof("255.255.255.255 ") * 2,
+	[OPTION_STRING] =	1,
+	[OPTION_BOOLEAN] =	sizeof("yes "),
+	[OPTION_U8] =		sizeof("255 "),
+	[OPTION_U16] =		sizeof("65535 "),
+	[OPTION_S16] =		sizeof("-32768 "),
+	[OPTION_U32] =		sizeof("4294967295 "),
+	[OPTION_S32] =		sizeof("-2147483684 "),
+};
+
+
+static inline int upper_length(int length, int opt_index)
+{
+	return max_option_length[opt_index] *
+		(length / option_lengths[opt_index]);
+}
+
+
+static int sprintip(char *dest, char *pre, uint8_t *ip)
+{
+	return sprintf(dest, "%s%d.%d.%d.%d", pre, ip[0], ip[1], ip[2], ip[3]);
+}
+
+
+/* really simple implementation, just count the bits */
+static int mton(struct in_addr *mask)
+{
+	int i;
+	unsigned long bits = ntohl(mask->s_addr);
+	/* too bad one can't check the carry bit, etc in c bit
+	 * shifting */
+	for (i = 0; i < 32 && !((bits >> i) & 1); i++);
+	return 32 - i;
+}
+
+
+/* Fill dest with the text of option 'option'. */
+static void fill_options(char *dest, uint8_t *option, struct dhcp_option *type_p)
+{
+	int type, optlen;
+	uint16_t val_u16;
+	int16_t val_s16;
+	uint32_t val_u32;
+	int32_t val_s32;
+	int len = option[OPT_LEN - 2];
+
+	dest += sprintf(dest, "%s=", type_p->name);
+
+	type = type_p->flags & TYPE_MASK;
+	optlen = option_lengths[type];
+	for(;;) {
+		switch (type) {
+		case OPTION_IP_PAIR:
+			dest += sprintip(dest, "", option);
+			*(dest++) = '/';
+			option += 4;
+			optlen = 4;
+		case OPTION_IP:	/* Works regardless of host byte order. */
+			dest += sprintip(dest, "", option);
+			break;
+		case OPTION_BOOLEAN:
+			dest += sprintf(dest, *option ? "yes" : "no");
+			break;
+		case OPTION_U8:
+			dest += sprintf(dest, "%u", *option);
+			break;
+		case OPTION_U16:
+			memcpy(&val_u16, option, 2);
+			dest += sprintf(dest, "%u", ntohs(val_u16));
+			break;
+		case OPTION_S16:
+			memcpy(&val_s16, option, 2);
+			dest += sprintf(dest, "%d", ntohs(val_s16));
+			break;
+		case OPTION_U32:
+			memcpy(&val_u32, option, 4);
+			dest += sprintf(dest, "%lu", (unsigned long) ntohl(val_u32));
+			break;
+		case OPTION_S32:
+			memcpy(&val_s32, option, 4);
+			dest += sprintf(dest, "%ld", (long) ntohl(val_s32));
+			break;
+		case OPTION_STRING:
+			memcpy(dest, option, len);
+			dest[len] = '\0';
+			return;	 /* Short circuit this case */
+		}
+		option += optlen;
+		len -= optlen;
+		if (len <= 0) break;
+		dest += sprintf(dest, " ");
+	}
+}
+
+
+/* put all the parameters into an environment */
+static char **fill_envp(struct dhcpMessage *packet)
+{
+	int num_options = 0;
+	int i, j;
+	char **envp;
+	uint8_t *temp;
+	struct in_addr subnet;
+	char over = 0;
+
+	if (packet == NULL)
+		num_options = 0;
+	else {
+		for (i = 0; dhcp_options[i].code; i++)
+			if (get_option(packet, dhcp_options[i].code)) {
+				num_options++;
+				if (dhcp_options[i].code == DHCP_SUBNET)
+					num_options++; /* for mton */
+			}
+		if (packet->siaddr) num_options++;
+		if ((temp = get_option(packet, DHCP_OPTION_OVER)))
+			over = *temp;
+		if (!(over & FILE_FIELD) && packet->file[0]) num_options++;
+		if (!(over & SNAME_FIELD) && packet->sname[0]) num_options++;
+	}
+
+	envp = xzalloc(sizeof(char *) * (num_options + 5));
+	j = 0;
+	envp[j++] = bb_xasprintf("interface=%s", client_config.interface);
+	envp[j++] = bb_xasprintf("PATH=%s",
+		getenv("PATH") ? : "/bin:/usr/bin:/sbin:/usr/sbin");
+	envp[j++] = bb_xasprintf("HOME=%s", getenv("HOME") ? : "/");
+
+	if (packet == NULL) return envp;
+
+	envp[j] = xmalloc(sizeof("ip=255.255.255.255"));
+	sprintip(envp[j++], "ip=", (uint8_t *) &packet->yiaddr);
+
+
+	for (i = 0; dhcp_options[i].code; i++) {
+		if (!(temp = get_option(packet, dhcp_options[i].code)))
+			continue;
+		envp[j] = xmalloc(upper_length(temp[OPT_LEN - 2],
+			dhcp_options[i].flags & TYPE_MASK) + strlen(dhcp_options[i].name) + 2);
+		fill_options(envp[j++], temp, &dhcp_options[i]);
+
+		/* Fill in a subnet bits option for things like /24 */
+		if (dhcp_options[i].code == DHCP_SUBNET) {
+			memcpy(&subnet, temp, 4);
+			envp[j++] = bb_xasprintf("mask=%d", mton(&subnet));
+		}
+	}
+	if (packet->siaddr) {
+		envp[j] = xmalloc(sizeof("siaddr=255.255.255.255"));
+		sprintip(envp[j++], "siaddr=", (uint8_t *) &packet->siaddr);
+	}
+	if (!(over & FILE_FIELD) && packet->file[0]) {
+		/* watch out for invalid packets */
+		packet->file[sizeof(packet->file) - 1] = '\0';
+		envp[j++] = bb_xasprintf("boot_file=%s", packet->file);
+	}
+	if (!(over & SNAME_FIELD) && packet->sname[0]) {
+		/* watch out for invalid packets */
+		packet->sname[sizeof(packet->sname) - 1] = '\0';
+		envp[j++] = bb_xasprintf("sname=%s", packet->sname);
+	}
+	return envp;
+}
+
+
+/* Call a script with a par file and env vars */
+void udhcp_run_script(struct dhcpMessage *packet, const char *name)
+{
+	int pid;
+	char **envp, **curr;
+
+	if (client_config.script == NULL)
+		return;
+
+	DEBUG(LOG_INFO, "vforking and execle'ing %s", client_config.script);
+
+	envp = fill_envp(packet);
+	/* call script */
+	pid = vfork();
+	if (pid) {
+		waitpid(pid, NULL, 0);
+		for (curr = envp; *curr; curr++) free(*curr);
+		free(envp);
+		return;
+	} else if (pid == 0) {
+		/* close fd's? */
+
+		/* exec script */
+		execle(client_config.script, client_config.script,
+		       name, NULL, envp);
+		LOG(LOG_ERR, "script %s failed: %m", client_config.script);
+		exit(1);
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/serverpacket.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/serverpacket.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/serverpacket.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,275 @@
+/* serverpacket.c
+ *
+ * Construct and send DHCP server packets
+ *
+ * Russ Dill <Russ.Dill at asu.edu> July 2001
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <time.h>
+
+#include "common.h"
+#include "serverpacket.h"
+#include "dhcpd.h"
+#include "options.h"
+#include "static_leases.h"
+
+/* send a packet to giaddr using the kernel ip stack */
+static int send_packet_to_relay(struct dhcpMessage *payload)
+{
+	DEBUG(LOG_INFO, "Forwarding packet to relay");
+
+	return udhcp_kernel_packet(payload, server_config.server, SERVER_PORT,
+			payload->giaddr, SERVER_PORT);
+}
+
+
+/* send a packet to a specific arp address and ip address by creating our own ip packet */
+static int send_packet_to_client(struct dhcpMessage *payload, int force_broadcast)
+{
+	uint8_t *chaddr;
+	uint32_t ciaddr;
+
+	if (force_broadcast) {
+		DEBUG(LOG_INFO, "broadcasting packet to client (NAK)");
+		ciaddr = INADDR_BROADCAST;
+		chaddr = MAC_BCAST_ADDR;
+	} else if (payload->ciaddr) {
+		DEBUG(LOG_INFO, "unicasting packet to client ciaddr");
+		ciaddr = payload->ciaddr;
+		chaddr = payload->chaddr;
+	} else if (ntohs(payload->flags) & BROADCAST_FLAG) {
+		DEBUG(LOG_INFO, "broadcasting packet to client (requested)");
+		ciaddr = INADDR_BROADCAST;
+		chaddr = MAC_BCAST_ADDR;
+	} else {
+		DEBUG(LOG_INFO, "unicasting packet to client yiaddr");
+		ciaddr = payload->yiaddr;
+		chaddr = payload->chaddr;
+	}
+	return udhcp_raw_packet(payload, server_config.server, SERVER_PORT,
+			ciaddr, CLIENT_PORT, chaddr, server_config.ifindex);
+}
+
+
+/* send a dhcp packet, if force broadcast is set, the packet will be broadcast to the client */
+static int send_packet(struct dhcpMessage *payload, int force_broadcast)
+{
+	int ret;
+
+	if (payload->giaddr)
+		ret = send_packet_to_relay(payload);
+	else ret = send_packet_to_client(payload, force_broadcast);
+	return ret;
+}
+
+
+static void init_packet(struct dhcpMessage *packet, struct dhcpMessage *oldpacket, char type)
+{
+	udhcp_init_header(packet, type);
+	packet->xid = oldpacket->xid;
+	memcpy(packet->chaddr, oldpacket->chaddr, 16);
+	packet->flags = oldpacket->flags;
+	packet->giaddr = oldpacket->giaddr;
+	packet->ciaddr = oldpacket->ciaddr;
+	add_simple_option(packet->options, DHCP_SERVER_ID, server_config.server);
+}
+
+
+/* add in the bootp options */
+static void add_bootp_options(struct dhcpMessage *packet)
+{
+	packet->siaddr = server_config.siaddr;
+	if (server_config.sname)
+		strncpy((char*)packet->sname, server_config.sname, sizeof(packet->sname) - 1);
+	if (server_config.boot_file)
+		strncpy((char*)packet->file, server_config.boot_file, sizeof(packet->file) - 1);
+}
+
+
+/* send a DHCP OFFER to a DHCP DISCOVER */
+int sendOffer(struct dhcpMessage *oldpacket)
+{
+	struct dhcpMessage packet;
+	struct dhcpOfferedAddr *lease = NULL;
+	uint32_t req_align, lease_time_align = server_config.lease;
+	uint8_t *req, *lease_time;
+	struct option_set *curr;
+	struct in_addr addr;
+
+	uint32_t static_lease_ip;
+
+	init_packet(&packet, oldpacket, DHCPOFFER);
+
+	static_lease_ip = getIpByMac(server_config.static_leases, oldpacket->chaddr);
+
+	/* ADDME: if static, short circuit */
+	if(!static_lease_ip)
+	{
+	/* the client is in our lease/offered table */
+	if ((lease = find_lease_by_chaddr(oldpacket->chaddr))) {
+		if (!lease_expired(lease))
+			lease_time_align = lease->expires - time(0);
+		packet.yiaddr = lease->yiaddr;
+
+	/* Or the client has a requested ip */
+	} else if ((req = get_option(oldpacket, DHCP_REQUESTED_IP)) &&
+
+		   /* Don't look here (ugly hackish thing to do) */
+		   memcpy(&req_align, req, 4) &&
+
+		   /* and the ip is in the lease range */
+		   ntohl(req_align) >= ntohl(server_config.start) &&
+		   ntohl(req_align) <= ntohl(server_config.end) &&
+
+			!static_lease_ip &&  /* Check that its not a static lease */
+			/* and is not already taken/offered */
+		   ((!(lease = find_lease_by_yiaddr(req_align)) ||
+
+		   /* or its taken, but expired */ /* ADDME: or maybe in here */
+		   lease_expired(lease)))) {
+				packet.yiaddr = req_align; /* FIXME: oh my, is there a host using this IP? */
+
+			/* otherwise, find a free IP */
+	} else {
+			/* Is it a static lease? (No, because find_address skips static lease) */
+		packet.yiaddr = find_address(0);
+
+		/* try for an expired lease */
+		if (!packet.yiaddr) packet.yiaddr = find_address(1);
+	}
+
+	if(!packet.yiaddr) {
+		LOG(LOG_WARNING, "no IP addresses to give -- OFFER abandoned");
+		return -1;
+	}
+
+	if (!add_lease(packet.chaddr, packet.yiaddr, server_config.offer_time)) {
+		LOG(LOG_WARNING, "lease pool is full -- OFFER abandoned");
+		return -1;
+	}
+
+	if ((lease_time = get_option(oldpacket, DHCP_LEASE_TIME))) {
+		memcpy(&lease_time_align, lease_time, 4);
+		lease_time_align = ntohl(lease_time_align);
+		if (lease_time_align > server_config.lease)
+			lease_time_align = server_config.lease;
+	}
+
+	/* Make sure we aren't just using the lease time from the previous offer */
+	if (lease_time_align < server_config.min_lease)
+		lease_time_align = server_config.lease;
+	}
+	/* ADDME: end of short circuit */
+	else
+	{
+		/* It is a static lease... use it */
+		packet.yiaddr = static_lease_ip;
+	}
+
+	add_simple_option(packet.options, DHCP_LEASE_TIME, htonl(lease_time_align));
+
+	curr = server_config.options;
+	while (curr) {
+		if (curr->data[OPT_CODE] != DHCP_LEASE_TIME)
+			add_option_string(packet.options, curr->data);
+		curr = curr->next;
+	}
+
+	add_bootp_options(&packet);
+
+	addr.s_addr = packet.yiaddr;
+	LOG(LOG_INFO, "sending OFFER of %s", inet_ntoa(addr));
+	return send_packet(&packet, 0);
+}
+
+
+int sendNAK(struct dhcpMessage *oldpacket)
+{
+	struct dhcpMessage packet;
+
+	init_packet(&packet, oldpacket, DHCPNAK);
+
+	DEBUG(LOG_INFO, "sending NAK");
+	return send_packet(&packet, 1);
+}
+
+
+int sendACK(struct dhcpMessage *oldpacket, uint32_t yiaddr)
+{
+	struct dhcpMessage packet;
+	struct option_set *curr;
+	uint8_t *lease_time;
+	uint32_t lease_time_align = server_config.lease;
+	struct in_addr addr;
+
+	init_packet(&packet, oldpacket, DHCPACK);
+	packet.yiaddr = yiaddr;
+
+	if ((lease_time = get_option(oldpacket, DHCP_LEASE_TIME))) {
+		memcpy(&lease_time_align, lease_time, 4);
+		lease_time_align = ntohl(lease_time_align);
+		if (lease_time_align > server_config.lease)
+			lease_time_align = server_config.lease;
+		else if (lease_time_align < server_config.min_lease)
+			lease_time_align = server_config.lease;
+	}
+
+	add_simple_option(packet.options, DHCP_LEASE_TIME, htonl(lease_time_align));
+
+	curr = server_config.options;
+	while (curr) {
+		if (curr->data[OPT_CODE] != DHCP_LEASE_TIME)
+			add_option_string(packet.options, curr->data);
+		curr = curr->next;
+	}
+
+	add_bootp_options(&packet);
+
+	addr.s_addr = packet.yiaddr;
+	LOG(LOG_INFO, "sending ACK to %s", inet_ntoa(addr));
+
+	if (send_packet(&packet, 0) < 0)
+		return -1;
+
+	add_lease(packet.chaddr, packet.yiaddr, lease_time_align);
+
+	return 0;
+}
+
+
+int send_inform(struct dhcpMessage *oldpacket)
+{
+	struct dhcpMessage packet;
+	struct option_set *curr;
+
+	init_packet(&packet, oldpacket, DHCPACK);
+
+	curr = server_config.options;
+	while (curr) {
+		if (curr->data[OPT_CODE] != DHCP_LEASE_TIME)
+			add_option_string(packet.options, curr->data);
+		curr = curr->next;
+	}
+
+	add_bootp_options(&packet);
+
+	return send_packet(&packet, 0);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/serverpacket.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/serverpacket.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/serverpacket.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,12 @@
+#ifndef _SERVERPACKET_H
+#define _SERVERPACKET_H
+
+#include "packet.h"
+
+int sendOffer(struct dhcpMessage *oldpacket);
+int sendNAK(struct dhcpMessage *oldpacket);
+int sendACK(struct dhcpMessage *oldpacket, uint32_t yiaddr);
+int send_inform(struct dhcpMessage *oldpacket);
+
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/signalpipe.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/signalpipe.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/signalpipe.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,84 @@
+/* signalpipe.c
+ *
+ * Signal pipe infrastructure. A reliable way of delivering signals.
+ *
+ * Russ Dill <Russ.Dill at asu.edu> December 2003
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+
+
+#include "signalpipe.h"
+#include "common.h"
+
+static int signal_pipe[2];
+
+static void signal_handler(int sig)
+{
+	if (send(signal_pipe[1], &sig, sizeof(sig), MSG_DONTWAIT) < 0)
+		DEBUG(LOG_ERR, "Could not send signal: %m");
+}
+
+
+/* Call this before doing anything else. Sets up the socket pair
+ * and installs the signal handler */
+void udhcp_sp_setup(void)
+{
+	socketpair(AF_UNIX, SOCK_STREAM, 0, signal_pipe);
+	fcntl(signal_pipe[0], F_SETFD, FD_CLOEXEC);
+	fcntl(signal_pipe[1], F_SETFD, FD_CLOEXEC);
+	signal(SIGUSR1, signal_handler);
+	signal(SIGUSR2, signal_handler);
+	signal(SIGTERM, signal_handler);
+}
+
+
+/* Quick little function to setup the rfds. Will return the
+ * max_fd for use with select. Limited in that you can only pass
+ * one extra fd */
+int udhcp_sp_fd_set(fd_set *rfds, int extra_fd)
+{
+	FD_ZERO(rfds);
+	FD_SET(signal_pipe[0], rfds);
+	if (extra_fd >= 0) {
+		fcntl(extra_fd, F_SETFD, FD_CLOEXEC);
+		FD_SET(extra_fd, rfds);
+	}
+	return signal_pipe[0] > extra_fd ? signal_pipe[0] : extra_fd;
+}
+
+
+/* Read a signal from the signal pipe. Returns 0 if there is
+ * no signal, -1 on error (and sets errno appropriately), and
+ * your signal on success */
+int udhcp_sp_read(fd_set *rfds)
+{
+	int sig;
+
+	if (!FD_ISSET(signal_pipe[0], rfds))
+		return 0;
+
+	if (read(signal_pipe[0], &sig, sizeof(sig)) < 0)
+		return -1;
+
+	return sig;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/signalpipe.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/signalpipe.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/signalpipe.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,22 @@
+/* signalpipe.h
+ *
+ * Russ Dill <Russ.Dill at asu.edu> December 2003
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+void udhcp_sp_setup(void);
+int udhcp_sp_fd_set(fd_set *rfds, int extra_fd);
+int udhcp_sp_read(fd_set *rfds);

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/socket.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/socket.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/socket.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,135 @@
+/*
+ * socket.c -- DHCP server client/server socket creation
+ *
+ * udhcp client/server
+ * Copyright (C) 1999 Matthew Ramsay <matthewr at moreton.com.au>
+ *			Chris Trew <ctrew at moreton.com.au>
+ *
+ * Rewrite by Russ Dill <Russ.Dill at asu.edu> July 2001
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <errno.h>
+#include <features.h>
+#if (__GLIBC__ >= 2 && __GLIBC_MINOR >= 1) || defined _NEWLIB_VERSION
+#include <netpacket/packet.h>
+#include <net/ethernet.h>
+#else
+#include <asm/types.h>
+#include <linux/if_packet.h>
+#include <linux/if_ether.h>
+#endif
+
+#include "common.h"
+#include "socket.h"
+
+int read_interface(char *interface, int *ifindex, uint32_t *addr, uint8_t *arp)
+{
+	int fd;
+	struct ifreq ifr;
+	struct sockaddr_in *our_ip;
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+	if((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) >= 0) {
+		ifr.ifr_addr.sa_family = AF_INET;
+		strcpy(ifr.ifr_name, interface);
+
+		if (addr) {
+			if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
+				our_ip = (struct sockaddr_in *) &ifr.ifr_addr;
+				*addr = our_ip->sin_addr.s_addr;
+				DEBUG(LOG_INFO, "%s (our ip) = %s", ifr.ifr_name, inet_ntoa(our_ip->sin_addr));
+			} else {
+				LOG(LOG_ERR, "SIOCGIFADDR failed, is the interface up and configured?: %m");
+				close(fd);
+				return -1;
+			}
+		}
+
+		if (ioctl(fd, SIOCGIFINDEX, &ifr) == 0) {
+			DEBUG(LOG_INFO, "adapter index %d", ifr.ifr_ifindex);
+			*ifindex = ifr.ifr_ifindex;
+		} else {
+			LOG(LOG_ERR, "SIOCGIFINDEX failed!: %m");
+			close(fd);
+			return -1;
+		}
+		if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) {
+			memcpy(arp, ifr.ifr_hwaddr.sa_data, 6);
+			DEBUG(LOG_INFO, "adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x",
+				arp[0], arp[1], arp[2], arp[3], arp[4], arp[5]);
+		} else {
+			LOG(LOG_ERR, "SIOCGIFHWADDR failed!: %m");
+			close(fd);
+			return -1;
+		}
+	} else {
+		LOG(LOG_ERR, "socket failed!: %m");
+		return -1;
+	}
+	close(fd);
+	return 0;
+}
+
+
+int listen_socket(uint32_t ip, int port, char *inf)
+{
+	struct ifreq interface;
+	int fd;
+	struct sockaddr_in addr;
+	int n = 1;
+
+	DEBUG(LOG_INFO, "Opening listen socket on 0x%08x:%d %s", ip, port, inf);
+	if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+		DEBUG(LOG_ERR, "socket call failed: %m");
+		return -1;
+	}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+	addr.sin_port = htons(port);
+	addr.sin_addr.s_addr = ip;
+
+	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == -1) {
+		close(fd);
+		return -1;
+	}
+	if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char *) &n, sizeof(n)) == -1) {
+		close(fd);
+		return -1;
+	}
+
+	strncpy(interface.ifr_name, inf, IFNAMSIZ);
+	if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,(char *)&interface, sizeof(interface)) < 0) {
+		close(fd);
+		return -1;
+	}
+
+	if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
+		close(fd);
+		return -1;
+	}
+
+	return fd;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/socket.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/socket.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/socket.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,8 @@
+/* socket.h */
+#ifndef _SOCKET_H
+#define _SOCKET_H
+
+int read_interface(char *interface, int *ifindex, uint32_t *addr, uint8_t *arp);
+int listen_socket(uint32_t ip, int port, char *inf);
+
+#endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/static_leases.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/static_leases.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/static_leases.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,119 @@
+/*
+ * static_leases.c -- Couple of functions to assist with storing and
+ * retrieving data for static leases
+ *
+ * Wade Berrier <wberrier at myrealbox.com> September 2004
+ *
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "static_leases.h"
+#include "dhcpd.h"
+
+/* Takes the address of the pointer to the static_leases linked list,
+ *   Address to a 6 byte mac address
+ *   Address to a 4 byte ip address */
+int addStaticLease(struct static_lease **lease_struct, uint8_t *mac, uint32_t *ip)
+{
+
+	struct static_lease *cur;
+	struct static_lease *new_static_lease;
+
+	/* Build new node */
+	new_static_lease = xmalloc(sizeof(struct static_lease));
+	new_static_lease->mac = mac;
+	new_static_lease->ip = ip;
+	new_static_lease->next = NULL;
+
+	/* If it's the first node to be added... */
+	if(*lease_struct == NULL)
+	{
+		*lease_struct = new_static_lease;
+	}
+	else
+	{
+		cur = *lease_struct;
+		while(cur->next != NULL)
+		{
+			cur = cur->next;
+		}
+
+		cur->next = new_static_lease;
+	}
+
+	return 1;
+
+}
+
+/* Check to see if a mac has an associated static lease */
+uint32_t getIpByMac(struct static_lease *lease_struct, void *arg)
+{
+	uint32_t return_ip;
+	struct static_lease *cur = lease_struct;
+	uint8_t *mac = arg;
+
+	return_ip = 0;
+
+	while(cur != NULL)
+	{
+		/* If the client has the correct mac  */
+		if(memcmp(cur->mac, mac, 6) == 0)
+		{
+			return_ip = *(cur->ip);
+		}
+
+		cur = cur->next;
+	}
+
+	return return_ip;
+
+}
+
+/* Check to see if an ip is reserved as a static ip */
+uint32_t reservedIp(struct static_lease *lease_struct, uint32_t ip)
+{
+	struct static_lease *cur = lease_struct;
+
+	uint32_t return_val = 0;
+
+	while(cur != NULL)
+	{
+		/* If the client has the correct ip  */
+		if(*cur->ip == ip)
+			return_val = 1;
+
+		cur = cur->next;
+	}
+
+	return return_val;
+
+}
+
+#ifdef CONFIG_FEATURE_UDHCP_DEBUG
+/* Print out static leases just to check what's going on */
+/* Takes the address of the pointer to the static_leases linked list */
+void printStaticLeases(struct static_lease **arg)
+{
+	/* Get a pointer to the linked list */
+	struct static_lease *cur = *arg;
+
+	while(cur != NULL)
+	{
+		/* printf("PrintStaticLeases: Lease mac Address: %x\n", cur->mac); */
+		printf("PrintStaticLeases: Lease mac Value: %x\n", *(cur->mac));
+		/* printf("PrintStaticLeases: Lease ip Address: %x\n", cur->ip); */
+		printf("PrintStaticLeases: Lease ip Value: %x\n", *(cur->ip));
+
+		cur = cur->next;
+	}
+
+
+}
+#endif
+
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/static_leases.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/static_leases.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/udhcp/static_leases.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+/* static_leases.h */
+#ifndef _STATIC_LEASES_H
+#define _STATIC_LEASES_H
+
+#include "dhcpd.h"
+
+/* Config file will pass static lease info to this function which will add it
+ * to a data structure that can be searched later */
+int addStaticLease(struct static_lease **lease_struct, uint8_t *mac, uint32_t *ip);
+
+/* Check to see if a mac has an associated static lease */
+uint32_t getIpByMac(struct static_lease *lease_struct, void *arg);
+
+/* Check to see if an ip is reserved as a static ip */
+uint32_t reservedIp(struct static_lease *lease_struct, uint32_t ip);
+
+/* Print out static leases just to check what's going on (debug code) */
+void printStaticLeases(struct static_lease **lease_struct);
+
+#endif
+
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/vconfig.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/vconfig.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/vconfig.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,169 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * vconfig implementation for busybox
+ *
+ * Copyright (C) 2001  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 N/A */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <string.h>
+#include <limits.h>
+#include "busybox.h"
+
+/* Stuff from linux/if_vlan.h, kernel version 2.4.23 */
+enum vlan_ioctl_cmds {
+	ADD_VLAN_CMD,
+	DEL_VLAN_CMD,
+	SET_VLAN_INGRESS_PRIORITY_CMD,
+	SET_VLAN_EGRESS_PRIORITY_CMD,
+	GET_VLAN_INGRESS_PRIORITY_CMD,
+	GET_VLAN_EGRESS_PRIORITY_CMD,
+	SET_VLAN_NAME_TYPE_CMD,
+	SET_VLAN_FLAG_CMD
+};
+enum vlan_name_types {
+	VLAN_NAME_TYPE_PLUS_VID, /* Name will look like:  vlan0005 */
+	VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like:  eth1.0005 */
+	VLAN_NAME_TYPE_PLUS_VID_NO_PAD, /* Name will look like:  vlan5 */
+	VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, /* Name will look like:  eth0.5 */
+	VLAN_NAME_TYPE_HIGHEST
+};
+
+struct vlan_ioctl_args {
+	int cmd; /* Should be one of the vlan_ioctl_cmds enum above. */
+	char device1[24];
+
+	union {
+		char device2[24];
+		int VID;
+		unsigned int skb_priority;
+		unsigned int name_type;
+		unsigned int bind_type;
+		unsigned int flag; /* Matches vlan_dev_info flags */
+	} u;
+
+	short vlan_qos;
+};
+
+#define VLAN_GROUP_ARRAY_LEN 4096
+#define SIOCSIFVLAN	0x8983		/* Set 802.1Q VLAN options */
+
+/* On entry, table points to the length of the current string plus
+ * nul terminator plus data length for the subsequent entry.  The
+ * return value is the last data entry for the matching string. */
+static const char *xfind_str(const char *table, const char *str)
+{
+	while (strcasecmp(str, table+1) != 0) {
+		if (!*(table += table[0])) {
+			bb_show_usage();
+		}
+	}
+	return table - 1;
+}
+
+static const char cmds[] = {
+	4, ADD_VLAN_CMD, 7,
+	'a', 'd', 'd', 0,
+	3, DEL_VLAN_CMD, 7,
+	'r', 'e', 'm', 0,
+	3, SET_VLAN_NAME_TYPE_CMD, 17,
+	's', 'e', 't', '_',
+	'n', 'a', 'm', 'e', '_',
+	't', 'y', 'p', 'e', 0,
+	4, SET_VLAN_FLAG_CMD, 12,
+	's', 'e', 't', '_',
+	'f', 'l', 'a', 'g', 0,
+	5, SET_VLAN_EGRESS_PRIORITY_CMD, 18,
+	's', 'e', 't', '_',
+	'e', 'g', 'r', 'e', 's', 's', '_',
+	'm', 'a', 'p', 0,
+	5, SET_VLAN_INGRESS_PRIORITY_CMD, 16,
+	's', 'e', 't', '_',
+	'i', 'n', 'g', 'r', 'e', 's', 's', '_',
+	'm', 'a', 'p', 0,
+};
+
+static const char name_types[] = {
+	VLAN_NAME_TYPE_PLUS_VID, 16,
+	'V', 'L', 'A', 'N',
+	'_', 'P', 'L', 'U', 'S', '_', 'V', 'I', 'D',
+	0,
+	VLAN_NAME_TYPE_PLUS_VID_NO_PAD, 22,
+	'V', 'L', 'A', 'N',
+	'_', 'P', 'L', 'U', 'S', '_', 'V', 'I', 'D',
+	'_', 'N', 'O', '_', 'P', 'A', 'D', 0,
+	VLAN_NAME_TYPE_RAW_PLUS_VID, 15,
+	'D', 'E', 'V',
+	'_', 'P', 'L', 'U', 'S', '_', 'V', 'I', 'D',
+	0,
+	VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, 20,
+	'D', 'E', 'V',
+	'_', 'P', 'L', 'U', 'S', '_', 'V', 'I', 'D',
+	'_', 'N', 'O', '_', 'P', 'A', 'D', 0,
+};
+
+static const char conf_file_name[] = "/proc/net/vlan/config";
+
+int vconfig_main(int argc, char **argv)
+{
+	struct vlan_ioctl_args ifr;
+	const char *p;
+	int fd;
+
+	if (argc < 3) {
+		bb_show_usage();
+	}
+
+	/* Don't bother closing the filedes.  It will be closed on cleanup. */
+	/* Will die if 802.1q is not present */
+	bb_xopen3(conf_file_name, O_RDONLY, 0);
+
+	memset(&ifr, 0, sizeof(struct vlan_ioctl_args));
+
+	++argv;
+	p = xfind_str(cmds+2, *argv);
+	ifr.cmd = *p;
+	if (argc != p[-1]) {
+		bb_show_usage();
+	}
+
+	if (ifr.cmd == SET_VLAN_NAME_TYPE_CMD) { /* set_name_type */
+		ifr.u.name_type = *xfind_str(name_types+1, argv[1]);
+	} else {
+		if (strlen(argv[1]) >= IF_NAMESIZE) {
+			bb_error_msg_and_die("if_name >= %d chars\n", IF_NAMESIZE);
+		}
+		strcpy(ifr.device1, argv[1]);
+		p = argv[2];
+
+		/* I suppose one could try to combine some of the function calls below,
+		 * since ifr.u.flag, ifr.u.VID, and ifr.u.skb_priority are all same-sized
+		 * (unsigned) int members of a unions.  But because of the range checking,
+		 * doing so wouldn't save that much space and would also make maintainence
+		 * more of a pain. */
+		if (ifr.cmd == SET_VLAN_FLAG_CMD) { /* set_flag */
+			ifr.u.flag = bb_xgetularg10_bnd(p, 0, 1);
+		} else if (ifr.cmd == ADD_VLAN_CMD) { /* add */
+			ifr.u.VID = bb_xgetularg10_bnd(p, 0, VLAN_GROUP_ARRAY_LEN-1);
+		} else if (ifr.cmd != DEL_VLAN_CMD) { /* set_{egress|ingress}_map */
+			ifr.u.skb_priority = bb_xgetularg10_bnd(p, 0, ULONG_MAX);
+			ifr.vlan_qos = bb_xgetularg10_bnd(argv[3], 0, 7);
+		}
+	}
+
+	fd = bb_xsocket(AF_INET, SOCK_STREAM, 0);
+	if (ioctl(fd, SIOCSIFVLAN, &ifr) < 0) {
+		bb_perror_msg_and_die("ioctl error for %s", *argv);
+	}
+
+	return 0;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/wget.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/wget.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/wget.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,829 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * wget - retrieve a file using HTTP or FTP
+ *
+ * Chip Rosenthal Covad Communications <chip at laserlink.net>
+ *
+ */
+
+#include "busybox.h"
+#include <errno.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <getopt.h>
+
+
+struct host_info {
+	char *host;
+	int port;
+	char *path;
+	int is_ftp;
+	char *user;
+};
+
+static void parse_url(char *url, struct host_info *h);
+static FILE *open_socket(struct sockaddr_in *s_in);
+static char *gethdr(char *buf, size_t bufsiz, FILE *fp, int *istrunc);
+static int ftpcmd(char *s1, char *s2, FILE *fp, char *buf);
+
+/* Globals (can be accessed from signal handlers */
+static off_t filesize;		/* content-length of the file */
+static int chunked;		/* chunked transfer encoding */
+#ifdef CONFIG_FEATURE_WGET_STATUSBAR
+static void progressmeter(int flag);
+static char *curfile;		/* Name of current file being transferred. */
+static struct timeval start;	/* Time a transfer started. */
+static off_t transferred;	/* Number of bytes transferred so far. */
+/* For progressmeter() -- number of seconds before xfer considered "stalled" */
+enum {
+	STALLTIME = 5
+};
+#else
+static inline void progressmeter(int flag) {}
+#endif
+
+static void close_and_delete_outfile(FILE* output, char *fname_out, int do_continue)
+{
+	if (output != stdout && do_continue==0) {
+		fclose(output);
+		unlink(fname_out);
+	}
+}
+
+/* Read NMEMB elements of SIZE bytes into PTR from STREAM.  Returns the
+ * number of elements read, and a short count if an eof or non-interrupt
+ * error is encountered.  */
+static size_t safe_fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+	size_t ret = 0;
+
+	do {
+		clearerr(stream);
+		ret += fread((char *)ptr + (ret * size), size, nmemb - ret, stream);
+	} while (ret < nmemb && ferror(stream) && errno == EINTR);
+
+	return ret;
+}
+
+/* Write NMEMB elements of SIZE bytes from PTR to STREAM.  Returns the
+ * number of elements written, and a short count if an eof or non-interrupt
+ * error is encountered.  */
+static size_t safe_fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+	size_t ret = 0;
+
+	do {
+		clearerr(stream);
+		ret += fwrite((char *)ptr + (ret * size), size, nmemb - ret, stream);
+	} while (ret < nmemb && ferror(stream) && errno == EINTR);
+
+	return ret;
+}
+
+/* Read a line or SIZE - 1 bytes into S, whichever is less, from STREAM.
+ * Returns S, or NULL if an eof or non-interrupt error is encountered.  */
+static char *safe_fgets(char *s, int size, FILE *stream)
+{
+	char *ret;
+
+	do {
+		clearerr(stream);
+		ret = fgets(s, size, stream);
+	} while (ret == NULL && ferror(stream) && errno == EINTR);
+
+	return ret;
+}
+
+#define close_delete_and_die(s...) { \
+	close_and_delete_outfile(output, fname_out, do_continue); \
+	bb_error_msg_and_die(s); }
+
+
+#ifdef CONFIG_FEATURE_WGET_AUTHENTICATION
+/*
+ *  Base64-encode character string
+ *  oops... isn't something similar in uuencode.c?
+ *  XXX: It would be better to use already existing code
+ */
+static char *base64enc(unsigned char *p, char *buf, int len) {
+
+	char al[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+		    "0123456789+/";
+	char *s = buf;
+
+	while(*p) {
+		if (s >= buf+len-4)
+			bb_error_msg_and_die("buffer overflow");
+		*(s++) = al[(*p >> 2) & 0x3F];
+		*(s++) = al[((*p << 4) & 0x30) | ((*(p+1) >> 4) & 0x0F)];
+		*s = *(s+1) = '=';
+		*(s+2) = 0;
+		if (! *(++p)) break;
+		*(s++) = al[((*p << 2) & 0x3C) | ((*(p+1) >> 6) & 0x03)];
+		if (! *(++p)) break;
+		*(s++) = al[*(p++) & 0x3F];
+	}
+
+	return buf;
+}
+#endif
+
+#define WGET_OPT_CONTINUE	1
+#define WGET_OPT_QUIET	2
+#define WGET_OPT_PASSIVE	4
+#define WGET_OPT_OUTNAME	8
+#define WGET_OPT_HEADER	16
+#define WGET_OPT_PREFIX	32
+#define WGET_OPT_PROXY	64
+
+#if ENABLE_WGET_LONG_OPTIONS
+static const struct option wget_long_options[] = {
+	{ "continue",        0, NULL, 'c' },
+	{ "quiet",           0, NULL, 'q' },
+	{ "passive-ftp",     0, NULL, 139 },
+	{ "output-document", 1, NULL, 'O' },
+	{ "header",          1, NULL, 131 },
+	{ "directory-prefix",1, NULL, 'P' },
+	{ "proxy",           1, NULL, 'Y' },
+	{ 0,                 0, 0, 0 }
+};
+#endif
+
+int wget_main(int argc, char **argv)
+{
+	int n, try=5, status;
+	unsigned long opt;
+	int port;
+	char *proxy = 0;
+	char *dir_prefix=NULL;
+	char *s, buf[512];
+	struct stat sbuf;
+	char extra_headers[1024];
+	char *extra_headers_ptr = extra_headers;
+	int extra_headers_left = sizeof(extra_headers);
+	struct host_info server, target;
+	struct sockaddr_in s_in;
+	llist_t *headers_llist = NULL;
+
+	FILE *sfp = NULL;		/* socket to web/ftp server	    */
+	FILE *dfp = NULL;		/* socket to ftp server (data)	    */
+	char *fname_out = NULL;		/* where to direct output (-O)	    */
+	int do_continue = 0;		/* continue a prev transfer (-c)    */
+	long beg_range = 0L;		/*   range at which continue begins */
+	int got_clen = 0;		/* got content-length: from server  */
+	FILE *output;			/* socket to web server		    */
+	int quiet_flag = FALSE;		/* Be verry, verry quiet...	    */
+	int use_proxy = 1;		/* Use proxies if env vars are set  */
+	char *proxy_flag = "on";	/* Use proxies if env vars are set  */
+
+	/*
+	 * Crack command line.
+	 */
+	bb_opt_complementally = "-1:\203::";
+#if ENABLE_WGET_LONG_OPTIONS
+	bb_applet_long_options = wget_long_options;
+#endif
+	opt = bb_getopt_ulflags(argc, argv, "cq\213O:\203:P:Y:",
+					&fname_out, &headers_llist,
+					&dir_prefix, &proxy_flag);
+	if (opt & WGET_OPT_CONTINUE) {
+		++do_continue;
+	}
+	if (opt & WGET_OPT_QUIET) {
+		quiet_flag = TRUE;
+	}
+	if (strcmp(proxy_flag, "off") == 0) {
+		/* Use the proxy if necessary. */
+		use_proxy = 0;
+	}
+	if (opt & WGET_OPT_HEADER) {
+		while (headers_llist) {
+			int arglen = strlen(headers_llist->data);
+			if (extra_headers_left - arglen - 2 <= 0)
+				bb_error_msg_and_die("extra_headers buffer too small(need %i)", extra_headers_left - arglen);
+			strcpy(extra_headers_ptr, headers_llist->data);
+			extra_headers_ptr += arglen;
+			extra_headers_left -= ( arglen + 2 );
+			*extra_headers_ptr++ = '\r';
+			*extra_headers_ptr++ = '\n';
+			*(extra_headers_ptr + 1) = 0;
+			headers_llist = headers_llist->link;
+		}
+	}
+
+	parse_url(argv[optind], &target);
+	server.host = target.host;
+	server.port = target.port;
+
+	/*
+	 * Use the proxy if necessary.
+	 */
+	if (use_proxy) {
+		proxy = getenv(target.is_ftp ? "ftp_proxy" : "http_proxy");
+		if (proxy && *proxy) {
+			parse_url(bb_xstrdup(proxy), &server);
+		} else {
+			use_proxy = 0;
+		}
+	}
+
+	/* Guess an output filename */
+	if (!fname_out) {
+		// Dirty hack. Needed because bb_get_last_path_component
+		// will destroy trailing / by storing '\0' in last byte!
+		if(*target.path && target.path[strlen(target.path)-1]!='/') {
+			fname_out =
+#ifdef CONFIG_FEATURE_WGET_STATUSBAR
+				curfile =
+#endif
+				bb_get_last_path_component(target.path);
+		}
+		if (fname_out==NULL || strlen(fname_out)<1) {
+			fname_out =
+#ifdef CONFIG_FEATURE_WGET_STATUSBAR
+				curfile =
+#endif
+				"index.html";
+		}
+		if (dir_prefix != NULL)
+			fname_out = concat_path_file(dir_prefix, fname_out);
+#ifdef CONFIG_FEATURE_WGET_STATUSBAR
+	} else {
+		curfile = bb_get_last_path_component(fname_out);
+#endif
+	}
+	if (do_continue && !fname_out)
+		bb_error_msg_and_die("cannot specify continue (-c) without a filename (-O)");
+
+
+	/*
+	 * Open the output file stream.
+	 */
+	if (strcmp(fname_out, "-") == 0) {
+		output = stdout;
+		quiet_flag = TRUE;
+	} else {
+		output = bb_xfopen(fname_out, (do_continue ? "a" : "w"));
+	}
+
+	/*
+	 * Determine where to start transfer.
+	 */
+	if (do_continue) {
+		if (fstat(fileno(output), &sbuf) < 0)
+			bb_perror_msg_and_die("fstat()");
+		if (sbuf.st_size > 0)
+			beg_range = sbuf.st_size;
+		else
+			do_continue = 0;
+	}
+
+	/* We want to do exactly _one_ DNS lookup, since some
+	 * sites (i.e. ftp.us.debian.org) use round-robin DNS
+	 * and we want to connect to only one IP... */
+	bb_lookup_host(&s_in, server.host);
+	s_in.sin_port = server.port;
+	if (quiet_flag==FALSE) {
+		fprintf(stdout, "Connecting to %s[%s]:%d\n",
+				server.host, inet_ntoa(s_in.sin_addr), ntohs(server.port));
+	}
+
+	if (use_proxy || !target.is_ftp) {
+		/*
+		 *  HTTP session
+		 */
+		do {
+			got_clen = chunked = 0;
+
+			if (! --try)
+				close_delete_and_die("too many redirections");
+
+			/*
+			 * Open socket to http server
+			 */
+			if (sfp) fclose(sfp);
+			sfp = open_socket(&s_in);
+
+			/*
+			 * Send HTTP request.
+			 */
+			if (use_proxy) {
+				const char *format = "GET %stp://%s:%d/%s HTTP/1.1\r\n";
+#ifdef CONFIG_FEATURE_WGET_IP6_LITERAL
+				if (strchr(target.host, ':'))
+					format = "GET %stp://[%s]:%d/%s HTTP/1.1\r\n";
+#endif
+				fprintf(sfp, format,
+					target.is_ftp ? "f" : "ht", target.host,
+					ntohs(target.port), target.path);
+			} else {
+				fprintf(sfp, "GET /%s HTTP/1.1\r\n", target.path);
+			}
+
+			fprintf(sfp, "Host: %s\r\nUser-Agent: Wget\r\n", target.host);
+
+#ifdef CONFIG_FEATURE_WGET_AUTHENTICATION
+			if (target.user) {
+				fprintf(sfp, "Authorization: Basic %s\r\n",
+					base64enc((unsigned char*)target.user, buf, sizeof(buf)));
+			}
+			if (use_proxy && server.user) {
+				fprintf(sfp, "Proxy-Authorization: Basic %s\r\n",
+					base64enc((unsigned char*)server.user, buf, sizeof(buf)));
+			}
+#endif
+
+			if (do_continue)
+				fprintf(sfp, "Range: bytes=%ld-\r\n", beg_range);
+			if(extra_headers_left < sizeof(extra_headers))
+				fputs(extra_headers,sfp);
+			fprintf(sfp,"Connection: close\r\n\r\n");
+
+			/*
+			* Retrieve HTTP response line and check for "200" status code.
+			*/
+read_response:
+			if (fgets(buf, sizeof(buf), sfp) == NULL)
+				close_delete_and_die("no response from server");
+
+			for (s = buf ; *s != '\0' && !isspace(*s) ; ++s)
+				;
+			for ( ; isspace(*s) ; ++s)
+				;
+			switch (status = atoi(s)) {
+				case 0:
+				case 100:
+					while (gethdr(buf, sizeof(buf), sfp, &n) != NULL);
+					goto read_response;
+				case 200:
+					if (do_continue && output != stdout)
+						output = freopen(fname_out, "w", output);
+					do_continue = 0;
+					break;
+				case 300:	/* redirection */
+				case 301:
+				case 302:
+				case 303:
+					break;
+				case 206:
+					if (do_continue)
+						break;
+					/*FALLTHRU*/
+				default:
+					chomp(buf);
+					close_delete_and_die("server returned error %d: %s", atoi(s), buf);
+			}
+
+			/*
+			 * Retrieve HTTP headers.
+			 */
+			while ((s = gethdr(buf, sizeof(buf), sfp, &n)) != NULL) {
+				if (strcasecmp(buf, "content-length") == 0) {
+					unsigned long value;
+					if (safe_strtoul(s, &value)) {
+						close_delete_and_die("content-length %s is garbage", s);
+					}
+					filesize = value;
+					got_clen = 1;
+					continue;
+				}
+				if (strcasecmp(buf, "transfer-encoding") == 0) {
+					if (strcasecmp(s, "chunked") == 0) {
+						chunked = got_clen = 1;
+					} else {
+						close_delete_and_die("server wants to do %s transfer encoding", s);
+					}
+				}
+				if (strcasecmp(buf, "location") == 0) {
+					if (s[0] == '/')
+						target.path = bb_xstrdup(s+1);
+					else {
+						parse_url(bb_xstrdup(s), &target);
+						if (use_proxy == 0) {
+							server.host = target.host;
+							server.port = target.port;
+						}
+						bb_lookup_host(&s_in, server.host);
+						s_in.sin_port = server.port;
+						break;
+					}
+				}
+			}
+		} while(status >= 300);
+
+		dfp = sfp;
+	}
+	else
+	{
+		/*
+		 *  FTP session
+		 */
+		if (! target.user)
+			target.user = bb_xstrdup("anonymous:busybox@");
+
+		sfp = open_socket(&s_in);
+		if (ftpcmd(NULL, NULL, sfp, buf) != 220)
+			close_delete_and_die("%s", buf+4);
+
+		/*
+		 * Splitting username:password pair,
+		 * trying to log in
+		 */
+		s = strchr(target.user, ':');
+		if (s)
+			*(s++) = '\0';
+		switch(ftpcmd("USER ", target.user, sfp, buf)) {
+			case 230:
+				break;
+			case 331:
+				if (ftpcmd("PASS ", s, sfp, buf) == 230)
+					break;
+				/* FALLTHRU (failed login) */
+			default:
+				close_delete_and_die("ftp login: %s", buf+4);
+		}
+
+		ftpcmd("TYPE I", NULL, sfp, buf);
+
+		/*
+		 * Querying file size
+		 */
+		if (ftpcmd("SIZE ", target.path, sfp, buf) == 213) {
+			unsigned long value;
+			if (safe_strtoul(buf+4, &value)) {
+				close_delete_and_die("SIZE value is garbage");
+			}
+			filesize = value;
+			got_clen = 1;
+		}
+
+		/*
+		 * Entering passive mode
+		 */
+		if (ftpcmd("PASV", NULL, sfp, buf) !=  227)
+			close_delete_and_die("PASV: %s", buf+4);
+		s = strrchr(buf, ',');
+		*s = 0;
+		port = atoi(s+1);
+		s = strrchr(buf, ',');
+		port += atoi(s+1) * 256;
+		s_in.sin_port = htons(port);
+		dfp = open_socket(&s_in);
+
+		if (do_continue) {
+			sprintf(buf, "REST %ld", beg_range);
+			if (ftpcmd(buf, NULL, sfp, buf) != 350) {
+				if (output != stdout)
+					output = freopen(fname_out, "w", output);
+				do_continue = 0;
+			} else
+				filesize -= beg_range;
+		}
+
+		if (ftpcmd("RETR ", target.path, sfp, buf) > 150)
+			close_delete_and_die("RETR: %s", buf+4);
+	}
+
+
+	/*
+	 * Retrieve file
+	 */
+	if (chunked) {
+		fgets(buf, sizeof(buf), dfp);
+		filesize = strtol(buf, (char **) NULL, 16);
+	}
+
+	if (quiet_flag==FALSE)
+		progressmeter(-1);
+
+	do {
+		while ((filesize > 0 || !got_clen) && (n = safe_fread(buf, 1, ((chunked || got_clen) && (filesize < sizeof(buf)) ? filesize : sizeof(buf)), dfp)) > 0) {
+			if (safe_fwrite(buf, 1, n, output) != n) {
+				bb_perror_msg_and_die(bb_msg_write_error);
+			}
+#ifdef CONFIG_FEATURE_WGET_STATUSBAR
+			transferred += n;
+#endif
+			if (got_clen) {
+				filesize -= n;
+			}
+		}
+
+		if (chunked) {
+			safe_fgets(buf, sizeof(buf), dfp); /* This is a newline */
+			safe_fgets(buf, sizeof(buf), dfp);
+			filesize = strtol(buf, (char **) NULL, 16);
+			if (filesize==0) {
+				chunked = 0; /* all done! */
+			}
+		}
+
+		if (n == 0 && ferror(dfp)) {
+			bb_perror_msg_and_die(bb_msg_read_error);
+		}
+	} while (chunked);
+
+	if (quiet_flag==FALSE)
+		progressmeter(1);
+
+	if ((use_proxy == 0) && target.is_ftp) {
+		fclose(dfp);
+		if (ftpcmd(NULL, NULL, sfp, buf) != 226)
+			bb_error_msg_and_die("ftp error: %s", buf+4);
+		ftpcmd("QUIT", NULL, sfp, buf);
+	}
+	exit(EXIT_SUCCESS);
+}
+
+
+void parse_url(char *url, struct host_info *h)
+{
+	char *cp, *sp, *up, *pp;
+
+	if (strncmp(url, "http://", 7) == 0) {
+		h->port = bb_lookup_port("http", "tcp", 80);
+		h->host = url + 7;
+		h->is_ftp = 0;
+	} else if (strncmp(url, "ftp://", 6) == 0) {
+		h->port = bb_lookup_port("ftp", "tfp", 21);
+		h->host = url + 6;
+		h->is_ftp = 1;
+	} else
+		bb_error_msg_and_die("not an http or ftp url: %s", url);
+
+	sp = strchr(h->host, '/');
+	if (sp) {
+		*sp++ = '\0';
+		h->path = sp;
+	} else
+		h->path = bb_xstrdup("");
+
+	up = strrchr(h->host, '@');
+	if (up != NULL) {
+		h->user = h->host;
+		*up++ = '\0';
+		h->host = up;
+	} else
+		h->user = NULL;
+
+	pp = h->host;
+
+#ifdef CONFIG_FEATURE_WGET_IP6_LITERAL
+	if (h->host[0] == '[') {
+		char *ep;
+
+		ep = h->host + 1;
+		while (*ep == ':' || isxdigit (*ep))
+			ep++;
+		if (*ep == ']') {
+			h->host++;
+			*ep = '\0';
+			pp = ep + 1;
+		}
+	}
+#endif
+
+	cp = strchr(pp, ':');
+	if (cp != NULL) {
+		*cp++ = '\0';
+		h->port = htons(atoi(cp));
+	}
+}
+
+
+FILE *open_socket(struct sockaddr_in *s_in)
+{
+	FILE *fp;
+
+	fp = fdopen(xconnect(s_in), "r+");
+	if (fp == NULL)
+		bb_perror_msg_and_die("fdopen()");
+
+	return fp;
+}
+
+
+char *gethdr(char *buf, size_t bufsiz, FILE *fp, int *istrunc)
+{
+	char *s, *hdrval;
+	int c;
+
+	*istrunc = 0;
+
+	/* retrieve header line */
+	if (fgets(buf, bufsiz, fp) == NULL)
+		return NULL;
+
+	/* see if we are at the end of the headers */
+	for (s = buf ; *s == '\r' ; ++s)
+		;
+	if (s[0] == '\n')
+		return NULL;
+
+	/* convert the header name to lower case */
+	for (s = buf ; isalnum(*s) || *s == '-' ; ++s)
+		*s = tolower(*s);
+
+	/* verify we are at the end of the header name */
+	if (*s != ':')
+		bb_error_msg_and_die("bad header line: %s", buf);
+
+	/* locate the start of the header value */
+	for (*s++ = '\0' ; *s == ' ' || *s == '\t' ; ++s)
+		;
+	hdrval = s;
+
+	/* locate the end of header */
+	while (*s != '\0' && *s != '\r' && *s != '\n')
+		++s;
+
+	/* end of header found */
+	if (*s != '\0') {
+		*s = '\0';
+		return hdrval;
+	}
+
+	/* Rats!  The buffer isn't big enough to hold the entire header value. */
+	while (c = getc(fp), c != EOF && c != '\n')
+		;
+	*istrunc = 1;
+	return hdrval;
+}
+
+static int ftpcmd(char *s1, char *s2, FILE *fp, char *buf)
+{
+	if (s1) {
+		if (!s2) s2="";
+		fprintf(fp, "%s%s\r\n", s1, s2);
+		fflush(fp);
+	}
+
+	do {
+		char *buf_ptr;
+
+		if (fgets(buf, 510, fp) == NULL) {
+			bb_perror_msg_and_die("fgets()");
+		}
+		buf_ptr = strstr(buf, "\r\n");
+		if (buf_ptr) {
+			*buf_ptr = '\0';
+		}
+	} while (! isdigit(buf[0]) || buf[3] != ' ');
+
+	return atoi(buf);
+}
+
+#ifdef CONFIG_FEATURE_WGET_STATUSBAR
+/* Stuff below is from BSD rcp util.c, as added to openshh.
+ * Original copyright notice is retained at the end of this file.
+ *
+ */
+
+
+static int
+getttywidth(void)
+{
+	int width=0;
+	get_terminal_width_height(0, &width, NULL);
+	return (width);
+}
+
+static void
+updateprogressmeter(int ignore)
+{
+	int save_errno = errno;
+
+	progressmeter(0);
+	errno = save_errno;
+}
+
+static void
+alarmtimer(int wait)
+{
+	struct itimerval itv;
+
+	itv.it_value.tv_sec = wait;
+	itv.it_value.tv_usec = 0;
+	itv.it_interval = itv.it_value;
+	setitimer(ITIMER_REAL, &itv, NULL);
+}
+
+
+static void
+progressmeter(int flag)
+{
+	static struct timeval lastupdate;
+	static off_t lastsize, totalsize;
+
+	struct timeval now, td, wait;
+	off_t abbrevsize;
+	int elapsed, ratio, barlength, i;
+	char buf[256];
+
+	if (flag == -1) {
+		(void) gettimeofday(&start, (struct timezone *) 0);
+		lastupdate = start;
+		lastsize = 0;
+		totalsize = filesize; /* as filesize changes.. */
+	}
+
+	(void) gettimeofday(&now, (struct timezone *) 0);
+	ratio = 100;
+	if (totalsize != 0 && !chunked) {
+		ratio = (int) (100 * transferred / totalsize);
+		ratio = MIN(ratio, 100);
+	}
+
+	fprintf(stderr, "\r%-20.20s%4d%% ", curfile, ratio);
+
+	barlength = getttywidth() - 51;
+	if (barlength > 0 && barlength < sizeof(buf)) {
+		i = barlength * ratio / 100;
+		memset(buf, '*', i);
+		memset(buf + i, ' ', barlength - i);
+		buf[barlength] = '\0';
+		fprintf(stderr, "|%s|", buf);
+	}
+	i = 0;
+	abbrevsize = transferred;
+	while (abbrevsize >= 100000) {
+		i++;
+		abbrevsize >>= 10;
+	}
+	/* See http://en.wikipedia.org/wiki/Tera */
+	fprintf(stderr, "%6d %c%c ", (int)abbrevsize, " KMGTPEZY"[i], i?'B':' ');
+
+	timersub(&now, &lastupdate, &wait);
+	if (transferred > lastsize) {
+		lastupdate = now;
+		lastsize = transferred;
+		if (wait.tv_sec >= STALLTIME)
+			timeradd(&start, &wait, &start);
+		wait.tv_sec = 0;
+	}
+	timersub(&now, &start, &td);
+	elapsed = td.tv_sec;
+
+	if (wait.tv_sec >= STALLTIME) {
+		fprintf(stderr, " - stalled -");
+	} else if (transferred <= 0 || elapsed <= 0 || transferred > totalsize || chunked) {
+		fprintf(stderr, "--:--:-- ETA");
+	} else {
+		/* totalsize / (transferred/elapsed) - elapsed: */
+		int eta = (int) (totalsize*elapsed/transferred - elapsed);
+		i = eta % 3600;
+		fprintf(stderr, "%02d:%02d:%02d ETA", eta / 3600, i / 60, i % 60);
+	}
+
+	if (flag == -1) {
+		struct sigaction sa;
+		sa.sa_handler = updateprogressmeter;
+		sigemptyset(&sa.sa_mask);
+		sa.sa_flags = SA_RESTART;
+		sigaction(SIGALRM, &sa, NULL);
+		alarmtimer(1);
+	} else if (flag == 1) {
+		alarmtimer(0);
+		transferred = 0;
+		putc('\n', stderr);
+	}
+}
+#endif
+
+/* Original copyright notice which applies to the CONFIG_FEATURE_WGET_STATUSBAR stuff,
+ * much of which was blatantly stolen from openssh.  */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
+ *		ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
+ *
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	$Id: wget.c,v 1.75 2004/10/08 08:27:40 andersen Exp $
+ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/zcip.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/zcip.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/networking/zcip.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,480 @@
+/*
+ * RFC3927 ZeroConf IPv4 Link-Local addressing
+ * (see <http://www.zeroconf.org/>)
+ *
+ * Copyright (C) 2003 by Arthur van Hoff (avh at strangeberry.com)
+ * Copyright (C) 2004 by David Brownell
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+/*
+ * ZCIP just manages the 169.254.*.* addresses.  That network is not
+ * routed at the IP level, though various proxies or bridges can
+ * certainly be used.  Its naming is built over multicast DNS.
+ */
+
+// #define      DEBUG
+
+// TODO:
+// - more real-world usage/testing, especially daemon mode
+// - kernel packet filters to reduce scheduling noise
+// - avoid silent script failures, especially under load...
+// - link status monitoring (restart on link-up; stop on link-down)
+
+#include "busybox.h"
+#include <errno.h>
+#include <string.h>
+#include <syslog.h>
+#include <poll.h>
+#include <time.h>
+
+#include <sys/wait.h>
+
+#include <netinet/ether.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+
+#include <linux/if_packet.h>
+#include <linux/sockios.h>
+
+
+struct arp_packet {
+	struct ether_header hdr;
+	// FIXME this part is netinet/if_ether.h "struct ether_arp"
+	struct arphdr arp;
+	struct ether_addr source_addr;
+	struct in_addr source_ip;
+	struct ether_addr target_addr;
+	struct in_addr target_ip;
+} ATTRIBUTE_PACKED;
+
+enum {
+/* 169.254.0.0 */
+	LINKLOCAL_ADDR = 0xa9fe0000,
+
+/* protocol timeout parameters, specified in seconds */
+	PROBE_WAIT = 1,
+	PROBE_MIN = 1,
+	PROBE_MAX = 2,
+	PROBE_NUM = 3,
+	MAX_CONFLICTS = 10,
+	RATE_LIMIT_INTERVAL = 60,
+	ANNOUNCE_WAIT = 2,
+	ANNOUNCE_NUM = 2,
+	ANNOUNCE_INTERVAL = 2,
+	DEFEND_INTERVAL = 10
+};
+
+static const struct in_addr null_ip = { 0 };
+static const struct ether_addr null_addr = { {0, 0, 0, 0, 0, 0} };
+
+static int verbose = 0;
+
+#define DBG(fmt,args...) \
+	do { } while (0)
+#define VDBG	DBG
+
+/**
+ * Pick a random link local IP address on 169.254/16, except that
+ * the first and last 256 addresses are reserved.
+ */
+static void pick(struct in_addr *ip)
+{
+	unsigned	tmp;
+
+	/* use cheaper math than lrand48() mod N */
+	do {
+		tmp = (lrand48() >> 16) & IN_CLASSB_HOST;
+	} while (tmp > (IN_CLASSB_HOST - 0x0200));
+	ip->s_addr = htonl((LINKLOCAL_ADDR + 0x0100) + tmp);
+}
+
+/**
+ * Broadcast an ARP packet.
+ */
+static int arp(int fd, struct sockaddr *saddr, int op,
+	const struct ether_addr *source_addr, struct in_addr source_ip,
+	const struct ether_addr *target_addr, struct in_addr target_ip)
+{
+	struct arp_packet p;
+
+	// ether header
+	p.hdr.ether_type = htons(ETHERTYPE_ARP);
+	memcpy(p.hdr.ether_shost, source_addr, ETH_ALEN);
+	memset(p.hdr.ether_dhost, 0xff, ETH_ALEN);
+
+	// arp request
+	p.arp.ar_hrd = htons(ARPHRD_ETHER);
+	p.arp.ar_pro = htons(ETHERTYPE_IP);
+	p.arp.ar_hln = ETH_ALEN;
+	p.arp.ar_pln = 4;
+	p.arp.ar_op = htons(op);
+	memcpy(&p.source_addr, source_addr, ETH_ALEN);
+	memcpy(&p.source_ip, &source_ip, sizeof (p.source_ip));
+	memcpy(&p.target_addr, target_addr, ETH_ALEN);
+	memcpy(&p.target_ip, &target_ip, sizeof (p.target_ip));
+
+	// send it
+	if (sendto(fd, &p, sizeof (p), 0, saddr, sizeof (*saddr)) < 0) {
+		perror("sendto");
+		return -errno;
+	}
+	return 0;
+}
+
+/**
+ * Run a script.
+ */
+static int run(char *script, char *arg, char *intf, struct in_addr *ip)
+{
+	int pid, status;
+	char *why;
+
+	if (script != NULL) {
+		VDBG("%s run %s %s\n", intf, script, arg);
+		if (ip != NULL) {
+			char *addr = inet_ntoa(*ip);
+			setenv("ip", addr, 1);
+			syslog(LOG_INFO, "%s %s %s", arg, intf, addr);
+		}
+
+		pid = vfork();
+		if (pid < 0) {			// error
+			why = "vfork";
+			goto bad;
+		} else if (pid == 0) {		// child
+			execl(script, script, arg, NULL);
+			perror("execl");
+			_exit(EXIT_FAILURE);
+		}
+
+		if (waitpid(pid, &status, 0) <= 0) {
+			why = "waitpid";
+			goto bad;
+		}
+		if (WEXITSTATUS(status) != 0) {
+			bb_error_msg("script %s failed, exit=%d\n",
+					script, WEXITSTATUS(status));
+			return -errno;
+		}
+	}
+	return 0;
+bad:
+	status = -errno;
+	syslog(LOG_ERR, "%s %s, %s error: %s",
+		arg, intf, why, strerror(errno));
+	return status;
+}
+
+
+/**
+ * Return milliseconds of random delay, up to "secs" seconds.
+ */
+static inline unsigned ms_rdelay(unsigned secs)
+{
+	return lrand48() % (secs * 1000);
+}
+
+/**
+ * main program
+ */
+
+int zcip_main(int argc, char *argv[])
+{
+	char *intf = NULL;
+	char *script = NULL;
+	int quit = 0;
+	int foreground = 0;
+
+	char *why;
+	struct sockaddr saddr;
+	struct ether_addr addr;
+	struct in_addr ip = { 0 };
+	int fd;
+	int ready = 0;
+	suseconds_t timeout = 0;	// milliseconds
+	time_t defend = 0;
+	unsigned conflicts = 0;
+	unsigned nprobes = 0;
+	unsigned nclaims = 0;
+	int t;
+
+	// parse commandline: prog [options] ifname script
+	while ((t = getopt(argc, argv, "fqr:v")) != EOF) {
+		switch (t) {
+		case 'f':
+			foreground = 1;
+			continue;
+		case 'q':
+			quit = 1;
+			continue;
+		case 'r':
+			if (inet_aton(optarg, &ip) == 0
+					|| (ntohl(ip.s_addr) & IN_CLASSB_NET)
+						!= LINKLOCAL_ADDR) {
+				bb_error_msg_and_die("invalid link address");
+			}
+			continue;
+		case 'v':
+			verbose++;
+			foreground = 1;
+			continue;
+		default:
+			bb_error_msg_and_die("bad option");
+		}
+	}
+	if (optind < argc - 1) {
+		intf = argv[optind++];
+		setenv("interface", intf, 1);
+		script = argv[optind++];
+	}
+	if (optind != argc || !intf)
+		bb_show_usage();
+	openlog(bb_applet_name, 0, LOG_DAEMON);
+
+	// initialize the interface (modprobe, ifup, etc)
+	if (run(script, "init", intf, NULL) < 0)
+		return EXIT_FAILURE;
+
+	// initialize saddr
+	memset(&saddr, 0, sizeof (saddr));
+	safe_strncpy(saddr.sa_data, intf, sizeof (saddr.sa_data));
+
+	// open an ARP socket
+	if ((fd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) < 0) {
+		why = "open";
+fail:
+		foreground = 1;
+		goto bad;
+	}
+	// bind to the interface's ARP socket
+	if (bind(fd, &saddr, sizeof (saddr)) < 0) {
+		why = "bind";
+		goto fail;
+	} else {
+		struct ifreq ifr;
+		unsigned short seed[3];
+
+		// get the interface's ethernet address
+		memset(&ifr, 0, sizeof (ifr));
+		strncpy(ifr.ifr_name, intf, sizeof (ifr.ifr_name));
+		if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
+			why = "get ethernet address";
+			goto fail;
+		}
+		memcpy(&addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+
+		// start with some stable ip address, either a function of
+		// the hardware address or else the last address we used.
+		// NOTE: the sequence of addresses we try changes only
+		// depending on when we detect conflicts.
+		memcpy(seed, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+		seed48(seed);
+		if (ip.s_addr == 0)
+			pick(&ip);
+	}
+
+	// FIXME cases to handle:
+	//  - zcip already running!
+	//  - link already has local address... just defend/update
+
+	// daemonize now; don't delay system startup
+	if (!foreground) {
+		if (daemon(0, verbose) < 0) {
+			why = "daemon";
+			goto bad;
+		}
+		syslog(LOG_INFO, "start, interface %s", intf);
+	}
+
+	// run the dynamic address negotiation protocol,
+	// restarting after address conflicts:
+	//  - start with some address we want to try
+	//  - short random delay
+	//  - arp probes to see if another host else uses it
+	//  - arp announcements that we're claiming it
+	//  - use it
+	//  - defend it, within limits
+	while (1) {
+		struct pollfd fds[1];
+		struct timeval tv1;
+		struct arp_packet p;
+
+		fds[0].fd = fd;
+		fds[0].events = POLLIN;
+		fds[0].revents = 0;
+
+		// poll, being ready to adjust current timeout
+		if (!timeout) {
+			timeout = ms_rdelay(PROBE_WAIT);
+			// FIXME setsockopt(fd, SO_ATTACH_FILTER, ...) to
+			// make the kernel filter out all packets except
+			// ones we'd care about.
+		}
+		gettimeofday(&tv1, NULL);
+		tv1.tv_usec += (timeout % 1000) * 1000;
+		while (tv1.tv_usec > 1000000) {
+			tv1.tv_usec -= 1000000;
+			tv1.tv_sec++;
+		}
+		tv1.tv_sec += timeout / 1000;
+	
+		VDBG("...wait %ld %s nprobes=%d, nclaims=%d\n",
+				timeout, intf, nprobes, nclaims);
+		switch (poll(fds, 1, timeout)) {
+
+		// timeouts trigger protocol transitions
+		case 0:
+			// probes
+			if (nprobes < PROBE_NUM) {
+				nprobes++;
+				VDBG("probe/%d %s@%s\n",
+						nprobes, intf, inet_ntoa(ip));
+				(void)arp(fd, &saddr, ARPOP_REQUEST,
+						&addr, null_ip,
+						&null_addr, ip);
+				if (nprobes < PROBE_NUM) {
+					timeout = PROBE_MIN * 1000;
+					timeout += ms_rdelay(PROBE_MAX
+							- PROBE_MIN);
+				} else
+					timeout = ANNOUNCE_WAIT * 1000;
+			}
+			// then announcements
+			else if (nclaims < ANNOUNCE_NUM) {
+				nclaims++;
+				VDBG("announce/%d %s@%s\n",
+						nclaims, intf, inet_ntoa(ip));
+				(void)arp(fd, &saddr, ARPOP_REQUEST,
+						&addr, ip,
+						&addr, ip);
+				if (nclaims < ANNOUNCE_NUM) {
+					timeout = ANNOUNCE_INTERVAL * 1000;
+				} else {
+					// link is ok to use earlier
+					run(script, "config", intf, &ip);
+					ready = 1;
+					conflicts = 0;
+					timeout = -1;
+
+					// NOTE:  all other exit paths
+					// should deconfig ...
+					if (quit)
+						return EXIT_SUCCESS;
+					// FIXME update filters
+				}
+			}
+			break;
+
+		// packets arriving
+		case 1:
+			// maybe adjust timeout
+			if (timeout > 0) {
+				struct timeval tv2;
+
+				gettimeofday(&tv2, NULL);
+				if (timercmp(&tv1, &tv2, <)) {
+					timeout = 0;
+				} else {
+					timersub(&tv1, &tv2, &tv1);
+					timeout = 1000 * tv1.tv_sec
+							+ tv1.tv_usec / 1000;
+				}
+			}
+			if ((fds[0].revents & POLLIN) == 0) {
+				if (fds[0].revents & POLLERR) {
+					// FIXME: links routinely go down;
+					// this shouldn't necessarily exit.
+					bb_error_msg("%s: poll error\n", intf);
+					if (ready) {
+						run(script, "deconfig",
+								intf, &ip);
+					}
+					return EXIT_FAILURE;
+				}
+				continue;
+			}
+			// read ARP packet
+			if (recv(fd, &p, sizeof (p), 0) < 0) {
+				why = "recv";
+				goto bad;
+			}
+			if (p.hdr.ether_type != htons(ETHERTYPE_ARP))
+				continue;
+
+			VDBG("%s recv arp type=%d, op=%d,\n",
+					intf, ntohs(p.hdr.ether_type),
+					ntohs(p.arp.ar_op));
+			VDBG("\tsource=%s %s\n",
+					ether_ntoa(&p.source_addr),
+					inet_ntoa(p.source_ip));
+			VDBG("\ttarget=%s %s\n",
+					ether_ntoa(&p.target_addr),
+					inet_ntoa(p.target_ip));
+			if (p.arp.ar_op != htons(ARPOP_REQUEST)
+					&& p.arp.ar_op != htons(ARPOP_REPLY))
+				continue;
+
+			// some cases are always conflicts
+			if ((p.source_ip.s_addr == ip.s_addr)
+					&& (memcmp(&addr, &p.source_addr,
+							ETH_ALEN) != 0)) {
+collision:
+				VDBG("%s ARP conflict from %s\n", intf,
+						ether_ntoa(&p.source_addr));
+				if (ready) {
+					time_t now = time(0);
+
+					if ((defend + DEFEND_INTERVAL)
+							< now) {
+						defend = now;
+						(void)arp(fd, &saddr,
+								ARPOP_REQUEST,
+								&addr, ip,
+								&addr, ip);
+						VDBG("%s defend\n", intf);
+						timeout = -1;
+						continue;
+					}
+					defend = now;
+					ready = 0;
+					run(script, "deconfig", intf, &ip);
+					// FIXME rm filters: setsockopt(fd,
+					// SO_DETACH_FILTER, ...)
+				}
+				conflicts++;
+				if (conflicts >= MAX_CONFLICTS) {
+					VDBG("%s ratelimit\n", intf);
+					sleep(RATE_LIMIT_INTERVAL);
+				}
+				// restart the whole protocol
+				pick(&ip);
+				timeout = 0;
+				nprobes = 0;
+				nclaims = 0;
+			}
+			// two hosts probing one address is a collision too
+			else if (p.target_ip.s_addr == ip.s_addr
+					&& nclaims == 0
+					&& p.arp.ar_op == htons(ARPOP_REQUEST)
+					&& memcmp(&addr, &p.target_addr,
+							ETH_ALEN) != 0) {
+				goto collision;
+			}
+			break;
+
+		default:
+			why = "poll";
+			goto bad;
+		}
+	}
+bad:
+	if (foreground)
+		perror(why);
+	else
+		syslog(LOG_ERR, "%s %s, %s error: %s",
+			bb_applet_name, intf, why, strerror(errno));
+	return EXIT_FAILURE;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,116 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Process Utilities"
+
+config CONFIG_FREE
+	bool "free"
+	default n
+	help
+	  free displays the total amount of free and used physical and swap
+	  memory in the system, as well as the buffers used by the kernel.
+	  The shared memory column should be ignored; it is obsolete.
+
+config CONFIG_FUSER
+	bool "fuser"
+	default n
+	help
+	  fuser lists all PIDs (Process IDs) that currently have a given
+	  file open.  fuser can also list all PIDs that have a given network
+	  (TCP or UDP) port open.
+
+config CONFIG_KILL
+	bool "kill"
+	default n
+	help
+	  The command kill sends the specified signal to the specified
+	  process or process group.  If no signal is specified, the TERM
+	  signal is sent.
+
+config CONFIG_KILLALL
+	bool "killall"
+	default n
+	depends on CONFIG_KILL
+	help
+	  killall sends a signal to all processes running any of the
+	  specified commands.  If no signal name is specified, SIGTERM is
+	  sent.
+
+config CONFIG_PIDOF
+	bool "pidof"
+	default n
+	help
+	  Pidof finds the process id's (pids) of the named programs. It prints
+	  those id's on the standard output.
+
+config CONFIG_FEATURE_PIDOF_SINGLE
+	bool "Enable argument for single shot (-s)"
+	default n
+	depends on CONFIG_PIDOF
+	help
+	  Support argument '-s' for returning only the first pid found.
+
+config CONFIG_FEATURE_PIDOF_OMIT
+	bool "Enable argument for omitting pids (-o)"
+	default n
+	depends on CONFIG_PIDOF
+	help
+	  Support argument '-o' for omitting the given pids in output.
+	  The special pid %PPID can be used to name the parent process
+	  of the pidof, in other words the calling shell or shell script.
+
+config CONFIG_PS
+	bool "ps"
+	default n
+	help
+	  ps gives a snapshot of the current processes.
+
+config CONFIG_FEATURE_PS_WIDE
+	bool "Enable argument for wide output (-w)"
+	default n
+	depends on CONFIG_PS
+	help
+	  Support argument 'w' for wide output.
+	  If given once, 132 chars are printed and given more than
+	  one, the length is unlimited.
+
+config CONFIG_RENICE
+	bool "renice"
+	default n
+	help
+	  Renice alters the scheduling priority of one or more running
+	  processes.
+
+config CONFIG_BB_SYSCTL
+	bool "sysctl"
+	default n
+	help
+	  Configure kernel parameters at runtime.
+
+config CONFIG_TOP
+	bool "top"
+	default n
+	help
+	  The top program provides a dynamic real-time view of a running
+	  system.
+
+config CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+	bool "Support showing CPU usage percentage (add 2k bytes)"
+	default y
+	depends on CONFIG_TOP
+	help
+	  Make top display CPU usage.
+
+config CONFIG_UPTIME
+	bool "uptime"
+	default n
+	help
+	  uptime gives a one line display of the current time, how long
+	  the system has been running, how many users are currently logged
+	  on, and the system load averages for the past 1, 5, and 15 minutes.
+
+
+endmenu
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/procps
+PROCPS_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,37 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+PROCPS_AR:=procps.a
+ifndef $(PROCPS_DIR)
+PROCPS_DIR:=$(top_builddir)/procps/
+endif
+srcdir=$(top_srcdir)/procps
+
+PROCPS-y:=
+PROCPS-$(CONFIG_FREE)		+= free.o
+PROCPS-$(CONFIG_KILL)		+= kill.o
+PROCPS-$(CONFIG_PIDOF)		+= pidof.o
+PROCPS-$(CONFIG_PS)		+= ps.o
+PROCPS-$(CONFIG_RENICE)		+= renice.o
+PROCPS-$(CONFIG_BB_SYSCTL)	+= sysctl.o
+PROCPS-$(CONFIG_TOP)		+= top.o
+PROCPS-$(CONFIG_UPTIME)		+= uptime.o
+PROCPS-$(CONFIG_FUSER)		+= fuser.o
+
+ifneq ($(strip $(PROCPS-y)),)
+libraries-y+=$(PROCPS_DIR)$(PROCPS_AR)
+endif
+
+PROCPS_SRC-y:=$(patsubst %.o,$(srcdir)/%.c,$(PROCPS-y))
+PROCPS_SRC-a:=$(wildcard $(srcdir)/*.c)
+APPLET_SRC-y+=$(PROCPS_SRC-y)
+APPLET_SRC-a+=$(PROCPS_SRC-a)
+
+$(PROCPS_DIR)$(PROCPS_AR): $(patsubst %,$(PROCPS_DIR)%, $(PROCPS-y))
+	$(do_ar)
+
+$(PROCPS_DIR)%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/free.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/free.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/free.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,71 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini free implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+/* getopt not needed */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int free_main(int argc, char **argv)
+{
+	struct sysinfo info;
+	sysinfo(&info);
+
+	/* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */
+	if (info.mem_unit==0) {
+		info.mem_unit=1;
+	}
+	if ( info.mem_unit == 1 ) {
+		info.mem_unit=1024;
+
+		/* TODO:  Make all this stuff not overflow when mem >= 4 Gib */
+		info.totalram/=info.mem_unit;
+		info.freeram/=info.mem_unit;
+#ifndef __uClinux__
+		info.totalswap/=info.mem_unit;
+		info.freeswap/=info.mem_unit;
+#endif
+		info.sharedram/=info.mem_unit;
+		info.bufferram/=info.mem_unit;
+	} else {
+		info.mem_unit/=1024;
+		/* TODO:  Make all this stuff not overflow when mem >= 4 Gib */
+		info.totalram*=info.mem_unit;
+		info.freeram*=info.mem_unit;
+#ifndef __uClinux__
+		info.totalswap*=info.mem_unit;
+		info.freeswap*=info.mem_unit;
+#endif
+		info.sharedram*=info.mem_unit;
+		info.bufferram*=info.mem_unit;
+	}
+
+	if (argc > 1 && **(argv + 1) == '-')
+		bb_show_usage();
+
+	printf("%6s%13s%13s%13s%13s%13s\n", "", "total", "used", "free",
+			"shared", "buffers");
+
+	printf("%6s%13ld%13ld%13ld%13ld%13ld\n", "Mem:", info.totalram,
+			info.totalram-info.freeram, info.freeram,
+			info.sharedram, info.bufferram);
+
+#ifndef __uClinux__
+	printf("%6s%13ld%13ld%13ld\n", "Swap:", info.totalswap,
+			info.totalswap-info.freeswap, info.freeswap);
+
+	printf("%6s%13ld%13ld%13ld\n", "Total:", info.totalram+info.totalswap,
+			(info.totalram-info.freeram)+(info.totalswap-info.freeswap),
+			info.freeram+info.freeswap);
+#endif
+	return EXIT_SUCCESS;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/fuser.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/fuser.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/fuser.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,380 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * tiny fuser implementation
+ *
+ * Copyright 2004 Tony J. White
+ *
+ * May be distributed under the conditions of the
+ * GNU Library General Public License
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <dirent.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/sysmacros.h>
+
+#define FUSER_PROC_DIR "/proc"
+#define FUSER_MAX_LINE 255
+
+#define FUSER_OPT_MOUNT  1
+#define FUSER_OPT_KILL   2
+#define FUSER_OPT_SILENT 4
+#define FUSER_OPT_IP6    8
+#define FUSER_OPT_IP4    16
+
+typedef struct inode_list {
+	ino_t inode;
+	dev_t dev;
+	struct inode_list *next;
+} inode_list;
+
+typedef struct pid_list {
+	pid_t pid;
+	struct pid_list *next;
+} pid_list;
+
+static int fuser_option(char *option)
+{
+	int opt = 0;
+
+	if(!(strlen(option))) return 0;
+	if(option[0] != '-') return 0;
+	++option;
+	while(*option != '\0') {
+		if(*option == 'm') opt |= FUSER_OPT_MOUNT;
+		else if(*option == 'k') opt |= FUSER_OPT_KILL;
+		else if(*option == 's') opt |= FUSER_OPT_SILENT;
+		else if(*option == '6') opt |= FUSER_OPT_IP6;
+		else if(*option == '4') opt |= FUSER_OPT_IP4;
+		else {
+			bb_error_msg_and_die(
+				"Unsupported option '%c'", *option);
+		}
+		++option;
+	}
+	return opt;
+}
+
+static int fuser_file_to_dev_inode(const char *filename,
+	 dev_t *dev, ino_t *inode)
+{
+	struct stat f_stat;
+	if((stat(filename, &f_stat)) < 0) return 0;
+	*inode = f_stat.st_ino;
+	*dev = f_stat.st_dev;
+	return 1;
+}
+
+static int fuser_find_socket_dev(dev_t *dev)
+{
+	int fd = socket(PF_INET, SOCK_DGRAM,0);
+	struct stat buf;
+
+	if (fd >= 0 && (fstat(fd, &buf)) == 0) {
+		*dev =  buf.st_dev;
+		close(fd);
+		return 1;
+	}
+	return 0;
+}
+
+static int fuser_parse_net_arg(const char *filename,
+	const char **proto, int *port)
+{
+	char path[sizeof(FUSER_PROC_DIR)+12], tproto[5];
+
+	if((sscanf(filename, "%d/%4s", port, tproto)) != 2) return 0;
+	sprintf(path, "%s/net/%s", FUSER_PROC_DIR, tproto);
+	if((access(path, R_OK)) != 0) return 0;
+	*proto = bb_xstrdup(tproto);
+	return 1;
+}
+
+static int fuser_add_pid(pid_list *plist, pid_t pid)
+{
+	pid_list *curr = NULL, *last = NULL;
+
+	if(plist->pid == 0) plist->pid = pid;
+	curr = plist;
+	while(curr != NULL) {
+		if(curr->pid == pid) return 1;
+		last = curr;
+		curr = curr->next;
+	}
+	curr = xmalloc(sizeof(pid_list));
+	last->next = curr;
+	curr->pid = pid;
+	curr->next = NULL;
+	return 1;
+}
+
+static int fuser_add_inode(inode_list *ilist, dev_t dev, ino_t inode)
+{
+	inode_list *curr = NULL, *last = NULL;
+
+	if(!ilist->inode && !ilist->dev) {
+		ilist->dev = dev;
+		ilist->inode = inode;
+	}
+	curr = ilist;
+	while(curr != NULL) {
+		if(curr->inode == inode && curr->dev == dev) return 1;
+		last = curr;
+		curr = curr->next;
+	}
+	curr = xmalloc(sizeof(inode_list));
+	last->next = curr;
+	curr->dev = dev;
+	curr->inode = inode;
+	curr->next = NULL;
+	return 1;
+}
+
+static int fuser_scan_proc_net(int opts, const char *proto,
+	int port, inode_list *ilist)
+{
+	char path[sizeof(FUSER_PROC_DIR)+12], line[FUSER_MAX_LINE+1];
+	char addr[128];
+	ino_t tmp_inode;
+	dev_t tmp_dev;
+	long long  uint64_inode;
+	int tmp_port;
+	FILE *f;
+
+	if(!fuser_find_socket_dev(&tmp_dev)) tmp_dev = 0;
+	sprintf(path, "%s/net/%s", FUSER_PROC_DIR, proto);
+
+	if (!(f = fopen(path, "r"))) return 0;
+	while(fgets(line, FUSER_MAX_LINE, f)) {
+		if(sscanf(line,
+			"%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x "
+			"%*x:%*x %*x %*d %*d %llu",
+			addr, &tmp_port, &uint64_inode) == 3) {
+			if((strlen(addr) == 8) &&
+				(opts & FUSER_OPT_IP6)) continue;
+			else if((strlen(addr) > 8) &&
+				(opts & FUSER_OPT_IP4)) continue;
+			if(tmp_port == port) {
+				tmp_inode = uint64_inode;
+				fuser_add_inode(ilist, tmp_dev, tmp_inode);
+			}
+		}
+
+	}
+	fclose(f);
+	return 1;
+}
+
+static int fuser_search_dev_inode(int opts, inode_list *ilist,
+	dev_t dev, ino_t inode)
+{
+	inode_list *curr;
+	curr = ilist;
+
+	while(curr) {
+		if((opts & FUSER_OPT_MOUNT) &&  curr->dev == dev)
+			return 1;
+		if(curr->inode == inode && curr->dev == dev)
+			return 1;
+		curr = curr->next;
+	}
+	return 0;
+}
+
+static int fuser_scan_pid_maps(int opts, const char *fname, pid_t pid,
+	inode_list *ilist, pid_list *plist)
+{
+	FILE *file;
+	char line[FUSER_MAX_LINE + 1];
+	int major, minor;
+	ino_t inode;
+	long long uint64_inode;
+	dev_t dev;
+
+	if (!(file = fopen(fname, "r"))) return 0;
+	while (fgets(line, FUSER_MAX_LINE, file)) {
+		if(sscanf(line, "%*s %*s %*s %x:%x %llu",
+			&major, &minor, &uint64_inode) != 3) continue;
+		inode = uint64_inode;
+		if(major == 0 && minor == 0 && inode == 0) continue;
+		dev = makedev(major, minor);
+		if(fuser_search_dev_inode(opts, ilist, dev, inode)) {
+			fuser_add_pid(plist, pid);
+		}
+
+	}
+	fclose(file);
+	return 1;
+}
+
+static int fuser_scan_link(int opts, const char *lname, pid_t pid,
+	inode_list *ilist, pid_list *plist)
+{
+	ino_t inode;
+	dev_t dev;
+
+	if(!fuser_file_to_dev_inode(lname, &dev, &inode)) return 0;
+	if(fuser_search_dev_inode(opts, ilist, dev, inode))
+		fuser_add_pid(plist, pid);
+	return 1;
+}
+
+static int fuser_scan_dir_links(int opts, const char *dname, pid_t pid,
+	inode_list *ilist, pid_list *plist)
+{
+	DIR *d;
+	struct dirent *de;
+	char *lname;
+
+	if((d = opendir(dname))) {
+		while((de = readdir(d)) != NULL) {
+			lname = concat_subpath_file(dname, de->d_name);
+			if(lname == NULL)
+				continue;
+			fuser_scan_link(opts, lname, pid, ilist, plist);
+			free(lname);
+		}
+		closedir(d);
+	}
+	else return 0;
+	return 1;
+
+}
+
+static int fuser_scan_proc_pids(int opts, inode_list *ilist, pid_list *plist)
+{
+	DIR *d;
+	struct dirent *de;
+	pid_t pid;
+	char *dname;
+
+	if(!(d = opendir(FUSER_PROC_DIR))) return 0;
+	while((de = readdir(d)) != NULL) {
+		pid = (pid_t)atoi(de->d_name);
+		if(!pid) continue;
+		dname = concat_subpath_file(FUSER_PROC_DIR, de->d_name);
+		if(chdir(dname) < 0) {
+			free(dname);
+			continue;
+		}
+		free(dname);
+		fuser_scan_link(opts, "cwd", pid, ilist, plist);
+		fuser_scan_link(opts, "exe", pid, ilist, plist);
+		fuser_scan_link(opts, "root", pid, ilist, plist);
+		fuser_scan_dir_links(opts, "fd", pid, ilist, plist);
+		fuser_scan_dir_links(opts, "lib", pid, ilist, plist);
+		fuser_scan_dir_links(opts, "mmap", pid, ilist, plist);
+		fuser_scan_pid_maps(opts, "maps", pid, ilist, plist);
+		chdir("..");
+	}
+	closedir(d);
+	return 1;
+}
+
+static int fuser_print_pid_list(pid_list *plist)
+{
+	pid_list *curr = plist;
+
+	if(plist == NULL) return 0;
+	while(curr != NULL) {
+		if(curr->pid > 0) printf("%d ", curr->pid);
+		curr = curr->next;
+	}
+	printf("\n");
+	return 1;
+}
+
+static int fuser_kill_pid_list(pid_list *plist, int sig)
+{
+	pid_list *curr = plist;
+	pid_t mypid = getpid();
+	int success = 1;
+
+	if(plist == NULL) return 0;
+	while(curr != NULL) {
+		if(curr->pid > 0 && curr->pid != mypid) {
+			if (kill(curr->pid, sig) != 0) {
+				bb_perror_msg(
+					"Could not kill pid '%d'", curr->pid);
+				success = 0;
+			}
+		}
+		curr = curr->next;
+	}
+	return success;
+}
+
+int fuser_main(int argc, char **argv)
+{
+	int port, i, optn;
+	int* fni; /* file name indexes of argv */
+	int fnic = 0;  /* file name index count */
+	const char *proto;
+	static int opt = 0; /* FUSER_OPT_ */
+	dev_t dev;
+	ino_t inode;
+	pid_list *pids;
+	inode_list *inodes;
+	int killsig = SIGTERM;
+	int success = 1;
+
+	if (argc < 2)
+		bb_show_usage();
+
+	fni = xmalloc(sizeof(int));
+	for(i=1;i<argc;i++) {
+		optn = fuser_option(argv[i]);
+		if(optn) opt |= optn;
+		else if(argv[i][0] == '-') {
+			if(!(u_signal_names(argv[i]+1, &killsig, 0)))
+				killsig = SIGTERM;
+		}
+		else {
+			fni = xrealloc(fni, sizeof(int) * (fnic+2));
+			fni[fnic++] = i;
+		}
+	}
+	if(!fnic) return 1;
+
+	pids = xmalloc(sizeof(pid_list));
+	inodes = xmalloc(sizeof(inode_list));
+	for(i=0;i<fnic;i++) {
+		if(fuser_parse_net_arg(argv[fni[i]], &proto, &port)) {
+			fuser_scan_proc_net(opt, proto, port, inodes);
+		}
+		else {
+			if(!fuser_file_to_dev_inode(
+				argv[fni[i]], &dev, &inode)) {
+				free(pids);
+				free(inodes);
+				bb_perror_msg_and_die(
+					"Could not open '%s'", argv[fni[i]]);
+			}
+			fuser_add_inode(inodes, dev, inode);
+		}
+	}
+	success = fuser_scan_proc_pids(opt, inodes, pids);
+	/* if the first pid in the list is 0, none have been found */
+	if(pids->pid == 0) success = 0;
+	if(success) {
+		if(opt & FUSER_OPT_KILL) {
+			success = fuser_kill_pid_list(pids, killsig);
+		}
+		else if(!(opt & FUSER_OPT_SILENT)) {
+			success = fuser_print_pid_list(pids);
+		}
+	}
+	free(pids);
+	free(inodes);
+	/* return 0 on (success == 1) 1 otherwise */
+	return (success != 1);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/kill.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/kill.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/kill.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,146 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini kill/killall implementation for busybox
+ *
+ * Copyright (C) 1995, 1996 by Bruce Perens <bruce at pixar.com>.
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+
+#define KILL 0
+#define KILLALL 1
+
+int kill_main(int argc, char **argv)
+{
+	int whichApp, signo = SIGTERM;
+	const char *name;
+	int errors = 0;
+
+#ifdef CONFIG_KILLALL
+	int quiet=0;
+	/* Figure out what we are trying to do here */
+	whichApp = (strcmp(bb_applet_name, "killall") == 0)? KILLALL : KILL;
+#else
+	whichApp = KILL;
+#endif
+
+	/* Parse any options */
+	if (argc < 2)
+		bb_show_usage();
+
+	if(argv[1][0] != '-'){
+		argv++;
+		argc--;
+		goto do_it_now;
+	}
+
+	/* The -l option, which prints out signal names. */
+	if(argv[1][1]=='l' && argv[1][2]=='\0'){
+		if(argc==2) {
+			/* Print the whole signal list */
+			int col = 0;
+			for(signo=1; signo < NSIG; signo++) {
+				name = u_signal_names(0, &signo, 1);
+				if(name==NULL)  /* unnamed */
+					continue;
+				col += printf("%2d) %-16s", signo, name);
+				if (col > 60) {
+					printf("\n");
+					col = 0;
+				}
+			}
+			printf("\n");
+
+		} else {
+			for(argv++; *argv; argv++) {
+				name = u_signal_names(*argv, &signo, -1);
+				if(name!=NULL)
+					printf("%s\n", name);
+			}
+		}
+		/* If they specified -l, were all done */
+		return EXIT_SUCCESS;
+	}
+
+#ifdef CONFIG_KILLALL
+	/* The -q quiet option */
+	if(whichApp != KILL && argv[1][1]=='q' && argv[1][2]=='\0'){
+		quiet++;
+		argv++;
+		argc--;
+		if(argc<2 || argv[1][0] != '-'){
+			goto do_it_now;
+		}
+	}
+#endif
+
+	if(!u_signal_names(argv[1]+1, &signo, 0))
+		bb_error_msg_and_die( "bad signal name '%s'", argv[1]+1);
+	argv+=2;
+	argc-=2;
+
+do_it_now:
+
+	/* Pid or name required */
+	if (argc <= 0)
+		bb_show_usage();
+
+	if (whichApp == KILL) {
+		/* Looks like they want to do a kill. Do that */
+		while (--argc >= 0) {
+			int pid;
+
+			if (!isdigit(**argv) && **argv != '-')
+				bb_error_msg_and_die( "Bad PID '%s'", *argv);
+			pid = strtol(*argv, NULL, 0);
+			if (kill(pid, signo) != 0) {
+				bb_perror_msg( "Could not kill pid '%d'", pid);
+				errors++;
+			}
+			argv++;
+		}
+
+	}
+#ifdef CONFIG_KILLALL
+	else {
+		pid_t myPid=getpid();
+		/* Looks like they want to do a killall.  Do that */
+		while (--argc >= 0) {
+			long* pidList;
+
+			pidList = find_pid_by_name(*argv);
+			if (!pidList || *pidList<=0) {
+				errors++;
+				if (quiet==0)
+					bb_error_msg( "%s: no process killed", *argv);
+			} else {
+				long *pl;
+
+				for(pl = pidList; *pl !=0 ; pl++) {
+					if (*pl==myPid)
+						continue;
+					if (kill(*pl, signo) != 0) {
+						errors++;
+						if (quiet==0)
+							bb_perror_msg( "Could not kill pid '%ld'", *pl);
+					}
+				}
+			}
+			free(pidList);
+			argv++;
+		}
+	}
+#endif
+	return errors;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/pidof.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/pidof.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/pidof.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,117 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * pidof implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under the GPL v2, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#if ENABLE_FEATURE_PIDOF_SINGLE
+#define _SINGLE_COMPL(a) a
+#define SINGLE (1<<0)
+#else
+#define _SINGLE_COMPL(a)
+#define SINGLE (0)
+#endif
+
+#if ENABLE_FEATURE_PIDOF_OMIT
+#define _OMIT_COMPL(a) a
+#define _OMIT(a) ,a
+#if ENABLE_FEATURE_PIDOF_SINGLE
+#define OMIT (1<<1)
+#else
+#define OMIT (1<<0)
+#endif
+#else
+#define _OMIT_COMPL(a) ""
+#define _OMIT(a)
+#define OMIT (0)
+#define omitted (0)
+#endif
+
+int pidof_main(int argc, char **argv)
+{
+	unsigned n = 0;
+	unsigned fail = 1;
+	unsigned long int opt;
+#if ENABLE_FEATURE_PIDOF_OMIT
+	llist_t *omits = NULL; /* list of pids to omit */
+	bb_opt_complementally = _OMIT_COMPL("o::");
+#endif
+
+	/* do unconditional option parsing */
+	opt = bb_getopt_ulflags(argc, argv,
+					_SINGLE_COMPL("s") _OMIT_COMPL("o:")
+					_OMIT(&omits));
+
+#if ENABLE_FEATURE_PIDOF_OMIT
+	/* fill omit list.  */
+	{
+		char getppid_str[32];
+		llist_t * omits_p = omits;
+		while (omits_p) {
+			/* are we asked to exclude the parent's process ID?  */
+			if (!strncmp(omits_p->data, "%PPID", 5)) {
+				llist_pop(&omits_p);
+				snprintf(getppid_str, sizeof(getppid_str), "%d", getppid());
+				llist_add_to(&omits_p, getppid_str);
+			}
+			omits_p = omits_p->link;
+		}
+	}
+#endif
+	/* Looks like everything is set to go.  */
+	while(optind < argc) {
+		long *pidList;
+		long *pl;
+
+		/* reverse the pidlist like GNU pidof does.  */
+		pidList = pidlist_reverse(find_pid_by_name(argv[optind]));
+		for(pl = pidList; *pl > 0; pl++) {
+#if ENABLE_FEATURE_PIDOF_OMIT
+			unsigned omitted = 0;
+			if (opt & OMIT) {
+				llist_t *omits_p = omits;
+				while (omits_p)
+					if (strtol(omits_p->data, NULL, 10) == *pl) {
+						omitted = 1; break;
+					} else
+						omits_p = omits_p->link;
+			}
+#endif
+			if (!omitted) {
+				if (n) {
+					putchar(' ');
+				} else {
+					n = 1;
+				}
+				printf("%ld", *pl);
+			}
+			fail = (!ENABLE_FEATURE_PIDOF_OMIT && omitted);
+
+			if (ENABLE_FEATURE_PIDOF_SINGLE && (opt & SINGLE))
+				break;
+		}
+		free(pidList);
+		optind++;
+	}
+	putchar('\n');
+
+#if ENABLE_FEATURE_PIDOF_OMIT
+	if (ENABLE_FEATURE_CLEAN_UP)
+		llist_free(omits, NULL);
+#endif
+	return fail ? EXIT_FAILURE : EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/ps.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/ps.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/ps.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,130 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini ps implementation(s) for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under the GPL v2, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <string.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#if ENABLE_SELINUX
+#include <selinux/selinux.h>  /* for is_selinux_enabled()  */
+#endif
+
+int ps_main(int argc, char **argv)
+{
+	procps_status_t * p;
+	int i, len;
+
+#if ENABLE_SELINUX
+	int use_selinux = 0;
+	security_context_t sid=NULL;
+#endif
+
+#if ENABLE_FEATURE_PS_WIDE
+	int terminal_width;
+	int w_count = 0;
+
+	bb_opt_complementally="-:ww";
+#else
+# define terminal_width 79
+#endif
+
+#if ENABLE_FEATURE_PS_WIDE || ENABLE_SELINUX
+	/* handle arguments */
+#if ENABLE_FEATURE_PS_WIDE && ENABLE_SELINUX
+	i = bb_getopt_ulflags(argc, argv, "wc", &w_count);
+#elif ENABLE_FEATURE_PS_WIDE && !ENABLE_SELINUX
+	bb_getopt_ulflags(argc, argv, "w", &w_count);
+#else /* !ENABLE_FEATURE_PS_WIDE && ENABLE_SELINUX */
+	i = bb_getopt_ulflags(argc, argv, "c");
+#endif
+#if ENABLE_FEATURE_PS_WIDE
+	/* if w is given once, GNU ps sets the width to 132,
+	 * if w is given more than once, it is "unlimited"
+	 */
+	if(w_count) {
+		terminal_width = (w_count==1) ? 132 : INT_MAX;
+	} else {
+		get_terminal_width_height(1, &terminal_width, NULL);
+		/* Go one less... */
+		terminal_width--;
+	}
+#endif
+#if ENABLE_SELINUX
+	if ((i & (1+ENABLE_FEATURE_PS_WIDE)) && is_selinux_enabled())
+		use_selinux = 1;
+#endif
+#endif  /* ENABLE_FEATURE_PS_WIDE || ENABLE_SELINUX */
+
+#if ENABLE_SELINUX
+	if (use_selinux)
+	  printf("  PID Context                          Stat Command\n");
+	else
+#endif
+	  printf("  PID  Uid     VmSize Stat Command\n");
+
+	while ((p = procps_scan(1)) != 0)  {
+		char *namecmd = p->cmd;
+#if ENABLE_SELINUX
+		if (use_selinux)
+		  {
+			char sbuf[128];
+			len = sizeof(sbuf);
+
+			if (is_selinux_enabled()) {
+			  if (getpidcon(p->pid,&sid)<0)
+			    sid=NULL;
+			}
+
+			if (sid) {
+			  /*  I assume sid initilized with NULL  */
+			  len = strlen(sid)+1;
+			  safe_strncpy(sbuf, sid, len);
+			  freecon(sid);
+			  sid=NULL;
+			}else {
+			  safe_strncpy(sbuf, "unknown",7);
+			}
+			len = printf("%5d %-32s %s ", p->pid, sbuf, p->state);
+		}
+		else
+#endif
+		  if(p->rss == 0)
+		    len = printf("%5d %-8s        %s ", p->pid, p->user, p->state);
+		  else
+		    len = printf("%5d %-8s %6ld %s ", p->pid, p->user, p->rss, p->state);
+
+		i = terminal_width-len;
+
+		if(namecmd && namecmd[0]) {
+			if(i < 0)
+				i = 0;
+			if(strlen(namecmd) > (size_t)i)
+				namecmd[i] = 0;
+			printf("%s\n", namecmd);
+		} else {
+			namecmd = p->short_cmd;
+			if(i < 2)
+				i = 2;
+			if(strlen(namecmd) > ((size_t)i-2))
+				namecmd[i-2] = 0;
+			printf("[%s]\n", namecmd);
+		}
+		/* no check needed, but to make valgrind happy..  */
+		if (ENABLE_FEATURE_CLEAN_UP && p->cmd)
+			free(p->cmd);
+	}
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/renice.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/renice.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/renice.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,138 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * renice implementation for busybox
+ *
+ * Copyright (C) 2005  Manuel Novoa III  <mjn3 at codepoet.org>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+/* Notes:
+ *   Setting an absolute priority was obsoleted in SUSv2 and removed
+ *   in SUSv3.  However, the common linux version of renice does
+ *   absolute and not relative.  So we'll continue supporting absolute,
+ *   although the stdout logging has been removed since both SUSv2 and
+ *   SUSv3 specify that stdout isn't used.
+ *
+ *   This version is lenient in that it doesn't require any IDs.  The
+ *   options -p, -g, and -u are treated as mode switches for the
+ *   following IDs (if any).  Multiple switches are allowed.
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/resource.h>
+
+#if (PRIO_PROCESS < CHAR_MIN) || (PRIO_PROCESS > CHAR_MAX)
+#error Assumption violated : PRIO_PROCESS value
+#endif
+#if (PRIO_PGRP < CHAR_MIN) || (PRIO_PGRP > CHAR_MAX)
+#error Assumption violated : PRIO_PGRP value
+#endif
+#if (PRIO_USER < CHAR_MIN) || (PRIO_USER > CHAR_MAX)
+#error Assumption violated : PRIO_USER value
+#endif
+
+static inline int int_add_no_wrap(int a, int b)
+{
+	int s = a + b;
+
+	if (b < 0) {
+		if (s > a) s = INT_MIN;
+	} else {
+		if (s < a) s = INT_MAX;
+	}
+
+	return s;
+}
+
+int renice_main(int argc, char **argv)
+{
+	static const char Xetpriority_msg[] = "%d : %cetpriority";
+
+	int retval = EXIT_SUCCESS;
+	int which = PRIO_PROCESS;	/* Default 'which' value. */
+	int use_relative = 0;
+	int adjustment, new_priority;
+	id_t who;
+
+	++argv;
+
+	/* Check if we are using a relative adjustment. */
+	if (argv[0] && (argv[0][0] == '-') && (argv[0][1] == 'n') && !argv[0][2]) {
+		use_relative = 1;
+		++argv;
+	}
+
+	if (!*argv) {				/* No args?  Then show usage. */
+		bb_show_usage();
+	}
+
+	/* Get the priority adjustment (absolute or relative). */
+	adjustment = bb_xgetlarg(*argv, 10, INT_MIN, INT_MAX);
+
+	while (*++argv) {
+		/* Check for a mode switch. */
+		if ((argv[0][0] == '-') && argv[0][1] && !argv[0][2]) {
+			static const char opts[]
+				= { 'p', 'g', 'u', 0, PRIO_PROCESS, PRIO_PGRP, PRIO_USER };
+			const char *p;
+			if ((p = strchr(opts, argv[0][1]))) {
+				which = p[4];
+				continue;
+			}
+		}
+
+		/* Process an ID arg. */
+		if (which == PRIO_USER) {
+			struct passwd *p;
+			if (!(p = getpwnam(*argv))) {
+				bb_error_msg("unknown user: %s", *argv);
+				goto HAD_ERROR;
+			}
+			who = p->pw_uid;
+		} else {
+			char *e;
+			errno = 0;
+			who = strtoul(*argv, &e, 10);
+			if (*e || (*argv == e) || errno) {
+				bb_error_msg("bad value: %s", *argv);
+				goto HAD_ERROR;
+			}
+		}
+
+		/* Get priority to use, and set it. */
+		if (use_relative) {
+			int old_priority;
+
+			errno = 0;	 /* Needed for getpriority error detection. */
+			old_priority = getpriority(which, who);
+			if (errno) {
+				bb_perror_msg(Xetpriority_msg, who, 'g');
+				goto HAD_ERROR;
+			}
+
+			new_priority = int_add_no_wrap(old_priority, adjustment);
+		} else {
+			new_priority = adjustment;
+		}
+
+		if (setpriority(which, who, new_priority) == 0) {
+			continue;
+		}
+
+		bb_perror_msg(Xetpriority_msg, who, 's');
+	HAD_ERROR:
+		retval = EXIT_FAILURE;
+	}
+
+	/* No need to check for errors outputing to stderr since, if it
+	 * was used, the HAD_ERROR label was reached and retval was set. */
+
+	return retval;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/sysctl.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/sysctl.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/sysctl.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,336 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Sysctl 1.01 - A utility to read and manipulate the sysctl parameters
+ *
+ * Copyright 1999 George Staikos
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * Changelog:
+ *	v1.01:
+ *		- added -p <preload> to preload values from a file
+ *	v1.01.1
+ *		- busybox applet aware by <solar at gentoo.org>
+ *
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+/*
+ *    Function Prototypes
+ */
+static int sysctl_read_setting(const char *setting, int output);
+static int sysctl_write_setting(const char *setting, int output);
+static int sysctl_preload_file(const char *filename, int output);
+static int sysctl_display_all(const char *path, int output, int show_table);
+
+/*
+ *    Globals...
+ */
+static const char PROC_PATH[] = "/proc/sys/";
+static const char DEFAULT_PRELOAD[] = "/etc/sysctl.conf";
+
+/* error messages */
+static const char ERR_UNKNOWN_PARAMETER[] = "error: Unknown parameter '%s'\n";
+static const char ERR_MALFORMED_SETTING[] = "error: Malformed setting '%s'\n";
+static const char ERR_NO_EQUALS[] =
+	"error: '%s' must be of the form name=value\n";
+static const char ERR_INVALID_KEY[] = "error: '%s' is an unknown key\n";
+static const char ERR_UNKNOWN_WRITING[] =
+	"error: unknown error %d setting key '%s'\n";
+static const char ERR_UNKNOWN_READING[] =
+	"error: unknown error %d reading key '%s'\n";
+static const char ERR_PERMISSION_DENIED[] =
+	"error: permission denied on key '%s'\n";
+static const char ERR_PRELOAD_FILE[] =
+	"error: unable to open preload file '%s'\n";
+static const char WARN_BAD_LINE[] =
+	"warning: %s(%d): invalid syntax, continuing...\n";
+
+
+static void dwrite_str(int fd, const char *buf)
+{
+	write(fd, buf, strlen(buf));
+}
+
+/*
+ *    sysctl_main()...
+ */
+int sysctl_main(int argc, char **argv)
+{
+	int retval = 0;
+	int output = 1;
+	int write_mode = 0;
+	int switches_allowed = 1;
+
+	if (argc < 2)
+		bb_show_usage();
+
+	argv++;
+
+	for (; argv && *argv && **argv; argv++) {
+		if (switches_allowed && **argv == '-') {	/* we have a switch */
+			switch ((*argv)[1]) {
+			case 'n':
+				output = 0;
+				break;
+			case 'w':
+				write_mode = 1;
+				switches_allowed = 0;
+				break;
+			case 'p':
+				argv++;
+				return
+					sysctl_preload_file(((argv && *argv
+										  && **argv) ? *argv :
+										 DEFAULT_PRELOAD), output);
+			case 'a':
+			case 'A':
+				switches_allowed = 0;
+				return sysctl_display_all(PROC_PATH, output,
+										  ((*argv)[1] == 'a') ? 0 : 1);
+			case 'h':
+			case '?':
+				bb_show_usage();
+			default:
+				bb_error_msg(ERR_UNKNOWN_PARAMETER, *argv);
+				bb_show_usage();
+			}
+		} else {
+			switches_allowed = 0;
+			if (write_mode)
+				retval = sysctl_write_setting(*argv, output);
+			else
+				sysctl_read_setting(*argv, output);
+		}
+	}
+	return retval;
+}						/* end sysctl_main() */
+
+
+
+/*
+ *     sysctl_preload_file
+ *	preload the sysctl's from a conf file
+ *           - we parse the file and then reform it (strip out whitespace)
+ */
+#define PRELOAD_BUF 256
+
+int sysctl_preload_file(const char *filename, int output)
+{
+	int lineno = 0;
+	char oneline[PRELOAD_BUF];
+	char buffer[PRELOAD_BUF];
+	char *name, *value, *ptr;
+	FILE *fp = NULL;
+
+	if (!filename || ((fp = fopen(filename, "r")) == NULL)) {
+		bb_error_msg_and_die(ERR_PRELOAD_FILE, filename);
+	}
+
+	while (fgets(oneline, sizeof(oneline) - 1, fp)) {
+		oneline[sizeof(oneline) - 1] = 0;
+		lineno++;
+		trim(oneline);
+		ptr = (char *) oneline;
+
+		if (*ptr == '#' || *ptr == ';')
+			continue;
+
+		if (strlen(ptr) < 2)
+			continue;
+
+		name = strtok(ptr, "=");
+		if (!name || !*name) {
+			bb_error_msg(WARN_BAD_LINE, filename, lineno);
+			continue;
+		}
+
+		trim(name);
+
+		value = strtok(NULL, "\n\r");
+		if (!value || !*value) {
+			bb_error_msg(WARN_BAD_LINE, filename, lineno);
+			continue;
+		}
+
+		while ((*value == ' ' || *value == '\t') && *value != 0)
+			value++;
+		strcpy(buffer, name);
+		strcat(buffer, "=");
+		strcat(buffer, value);
+		sysctl_write_setting(buffer, output);
+	}
+	fclose(fp);
+	return 0;
+}						/* end sysctl_preload_file() */
+
+
+/*
+ *     Write a single sysctl setting
+ */
+int sysctl_write_setting(const char *setting, int output)
+{
+	int retval = 0;
+	const char *name = setting;
+	const char *value;
+	const char *equals;
+	char *tmpname, *outname, *cptr;
+	int fd = -1;
+
+	if (!name)			/* probably dont' want to display this  err */
+		return 0;
+
+	if (!(equals = strchr(setting, '='))) {
+		bb_error_msg(ERR_NO_EQUALS, setting);
+		return -1;
+	}
+
+	value = equals + sizeof(char);	/* point to the value in name=value */
+
+	if (!*name || !*value || name == equals) {
+		bb_error_msg(ERR_MALFORMED_SETTING, setting);
+		return -2;
+	}
+
+	tmpname = bb_xasprintf("%s%.*s", PROC_PATH, (int)(equals - name), name);
+	outname = bb_xstrdup(tmpname + strlen(PROC_PATH));
+
+	while ((cptr = strchr(tmpname, '.')) != NULL)
+		*cptr = '/';
+
+	while ((cptr = strchr(outname, '/')) != NULL)
+		*cptr = '.';
+
+	if ((fd = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) {
+		switch (errno) {
+		case ENOENT:
+			bb_error_msg(ERR_INVALID_KEY, outname);
+			break;
+		case EACCES:
+			bb_perror_msg(ERR_PERMISSION_DENIED, outname);
+			break;
+		default:
+			bb_error_msg(ERR_UNKNOWN_WRITING, errno, outname);
+			break;
+		}
+		retval = -1;
+	} else {
+		dwrite_str(fd, value);
+		close(fd);
+		if (output) {
+			dwrite_str(STDOUT_FILENO, outname);
+			dwrite_str(STDOUT_FILENO, " = ");
+		}
+		dwrite_str(STDOUT_FILENO, value);
+		dwrite_str(STDOUT_FILENO, "\n");
+	}
+
+	/* cleanup */
+	free(tmpname);
+	free(outname);
+	return retval;
+}						/* end sysctl_write_setting() */
+
+
+/*
+ *     Read a sysctl setting
+ *
+ */
+int sysctl_read_setting(const char *setting, int output)
+{
+	int retval = 0;
+	char *tmpname, *outname, *cptr;
+	char inbuf[1025];
+	const char *name = setting;
+	FILE *fp;
+
+	if (!setting || !*setting)
+		bb_error_msg(ERR_INVALID_KEY, setting);
+
+	tmpname = concat_path_file(PROC_PATH, name);
+	outname = bb_xstrdup(tmpname + strlen(PROC_PATH));
+
+	while ((cptr = strchr(tmpname, '.')) != NULL)
+		*cptr = '/';
+	while ((cptr = strchr(outname, '/')) != NULL)
+		*cptr = '.';
+
+	if ((fp = fopen(tmpname, "r")) == NULL) {
+		switch (errno) {
+		case ENOENT:
+			bb_error_msg(ERR_INVALID_KEY, outname);
+			break;
+		case EACCES:
+			bb_error_msg(ERR_PERMISSION_DENIED, outname);
+			break;
+		default:
+			bb_error_msg(ERR_UNKNOWN_READING, errno, outname);
+			break;
+		}
+		retval = -1;
+	} else {
+		while (fgets(inbuf, sizeof(inbuf) - 1, fp)) {
+			if (output) {
+				dwrite_str(STDOUT_FILENO, outname);
+				dwrite_str(STDOUT_FILENO, " = ");
+			}
+			dwrite_str(STDOUT_FILENO, inbuf);
+		}
+		fclose(fp);
+	}
+
+	free(tmpname);
+	free(outname);
+	return retval;
+}						/* end sysctl_read_setting() */
+
+
+
+/*
+ *     Display all the sysctl settings
+ *
+ */
+int sysctl_display_all(const char *path, int output, int show_table)
+{
+	int retval = 0;
+	int retval2;
+	DIR *dp;
+	struct dirent *de;
+	char *tmpdir;
+	struct stat ts;
+
+	if (!(dp = bb_opendir(path))) {
+		retval = -1;
+	} else {
+		while ((de = readdir(dp)) != NULL) {
+			tmpdir = concat_subpath_file(path, de->d_name);
+			if(tmpdir == NULL)
+				continue;
+			if ((retval2 = stat(tmpdir, &ts)) != 0)
+				bb_perror_msg(tmpdir);
+			else {
+				if (S_ISDIR(ts.st_mode)) {
+					sysctl_display_all(tmpdir, output, show_table);
+				} else
+					retval |=
+						sysctl_read_setting(tmpdir + strlen(PROC_PATH),
+											output);
+
+			}
+			free(tmpdir);
+		}				/* end while */
+		closedir(dp);
+	}
+
+	return retval;
+}						/* end sysctl_display_all() */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/top.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/top.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/top.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,532 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * A tiny 'top' utility.
+ *
+ * This is written specifically for the linux /proc/<PID>/stat(m)
+ * files format.
+
+ * This reads the PIDs of all processes and their status and shows
+ * the status of processes (first ones that fit to screen) at given
+ * intervals.
+ *
+ * NOTES:
+ * - At startup this changes to /proc, all the reads are then
+ *   relative to that.
+ *
+ * (C) Eero Tamminen <oak at welho dot com>
+ *
+ * Rewritten by Vladimir Oleynik (C) 2002 <dzo at simtreas.ru>
+ */
+
+/* Original code Copyrights */
+/*
+ * Copyright (c) 1992 Branko Lankester
+ * Copyright (c) 1992 Roger Binns
+ * Copyright (C) 1994-1996 Charles L. Blake.
+ * Copyright (C) 1992-1998 Michael K. Johnson
+ * May be distributed under the conditions of the
+ * GNU Library General Public License
+ */
+
+#include "busybox.h"
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+//#define CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE  /* + 2k */
+
+#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+#include <time.h>
+#include <fcntl.h>
+#include <netinet/in.h>  /* htons */
+#endif
+
+
+typedef int (*cmp_t)(procps_status_t *P, procps_status_t *Q);
+
+static procps_status_t *top;   /* Hehe */
+static int ntop;
+
+#ifdef CONFIG_FEATURE_USE_TERMIOS
+static int pid_sort(procps_status_t *P, procps_status_t *Q)
+{
+	return (Q->pid - P->pid);
+}
+#endif
+
+static int mem_sort(procps_status_t *P, procps_status_t *Q)
+{
+	return (int)(Q->rss - P->rss);
+}
+
+#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+
+#define sort_depth 3
+static cmp_t sort_function[sort_depth];
+
+static int pcpu_sort(procps_status_t *P, procps_status_t *Q)
+{
+	return (Q->pcpu - P->pcpu);
+}
+
+static int time_sort(procps_status_t *P, procps_status_t *Q)
+{
+	return (int)((Q->stime + Q->utime) - (P->stime + P->utime));
+}
+
+static int mult_lvl_cmp(void* a, void* b) {
+	int i, cmp_val;
+
+	for (i = 0; i < sort_depth; i++) {
+		cmp_val = (*sort_function[i])(a, b);
+		if (cmp_val != 0)
+			return cmp_val;
+	}
+	return 0;
+}
+
+/* This structure stores some critical information from one frame to
+   the next. mostly used for sorting. Added cumulative and resident fields. */
+struct save_hist {
+	int ticks;
+	int pid;
+};
+
+/*
+ * Calculates percent cpu usage for each task.
+ */
+
+static struct save_hist *prev_hist;
+static int prev_hist_count;
+/* static int hist_iterations; */
+
+
+static unsigned total_pcpu;
+/* static unsigned long total_rss; */
+
+struct jiffy_counts {
+	unsigned long long usr,nic,sys,idle,iowait,irq,softirq,steal;
+	unsigned long long total;
+	unsigned long long busy;
+};
+static struct jiffy_counts jif, prev_jif;
+
+static void get_jiffy_counts(void)
+{
+	FILE* fp = bb_xfopen("stat", "r");
+	prev_jif = jif;
+	if (fscanf(fp, "cpu  %lld %lld %lld %lld %lld %lld %lld %lld",
+			&jif.usr,&jif.nic,&jif.sys,&jif.idle,
+			&jif.iowait,&jif.irq,&jif.softirq,&jif.steal) < 4) {
+		bb_error_msg_and_die("failed to read 'stat'");
+	}
+	fclose(fp);
+	jif.total = jif.usr + jif.nic + jif.sys + jif.idle
+			+ jif.iowait + jif.irq + jif.softirq + jif.steal;
+	/* procps 2.x does not count iowait as busy time */
+	jif.busy = jif.total - jif.idle - jif.iowait;
+}
+
+static void do_stats(void)
+{
+	procps_status_t *cur;
+	int pid, total_time, i, last_i, n;
+	struct save_hist *new_hist;
+
+	get_jiffy_counts();
+	total_pcpu = 0;
+	/* total_rss = 0; */
+	new_hist = xmalloc(sizeof(struct save_hist)*ntop);
+	/*
+	 * Make a pass through the data to get stats.
+	 */
+	/* hist_iterations = 0; */
+	i = 0;
+	for (n = 0; n < ntop; n++) {
+		cur = top + n;
+
+		/*
+		 * Calculate time in cur process.  Time is sum of user time
+		 * and system time
+		 */
+		pid = cur->pid;
+		total_time = cur->stime + cur->utime;
+		new_hist[n].ticks = total_time;
+		new_hist[n].pid = pid;
+
+		/* find matching entry from previous pass */
+		cur->pcpu = 0;
+		/* do not start at index 0, continue at last used one
+		 * (brought hist_iterations from ~14000 down to 172) */
+		last_i = i;
+		if (prev_hist_count) do {
+			if (prev_hist[i].pid == pid) {
+				cur->pcpu = total_time - prev_hist[i].ticks;
+				break;
+			}
+			i = (i+1) % prev_hist_count;
+			/* hist_iterations++; */
+		} while (i != last_i);
+		total_pcpu += cur->pcpu;
+		/* total_rss += cur->rss; */
+	}
+
+	/*
+	 * Save cur frame's information.
+	 */
+	free(prev_hist);
+	prev_hist = new_hist;
+	prev_hist_count = ntop;
+}
+#else
+static cmp_t sort_function;
+#endif /* CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE */
+
+/* display generic info (meminfo / loadavg) */
+static unsigned long display_generic(int scr_width)
+{
+	FILE *fp;
+	char buf[80];
+	char scrbuf[80];
+	char *end;
+	unsigned long total, used, mfree, shared, buffers, cached;
+	unsigned int needs_conversion = 1;
+
+	/* read memory info */
+	fp = bb_xfopen("meminfo", "r");
+
+	/*
+	 * Old kernels (such as 2.4.x) had a nice summary of memory info that
+	 * we could parse, however this is gone entirely in 2.6. Try parsing
+	 * the old way first, and if that fails, parse each field manually.
+	 *
+	 * First, we read in the first line. Old kernels will have bogus
+	 * strings we don't care about, whereas new kernels will start right
+	 * out with MemTotal:
+	 *                              -- PFM.
+	 */
+	if (fscanf(fp, "MemTotal: %lu %s\n", &total, buf) != 2) {
+		fgets(buf, sizeof(buf), fp);    /* skip first line */
+
+		fscanf(fp, "Mem: %lu %lu %lu %lu %lu %lu",
+		   &total, &used, &mfree, &shared, &buffers, &cached);
+	} else {
+		/*
+		 * Revert to manual parsing, which incidentally already has the
+		 * sizes in kilobytes. This should be safe for both 2.4 and
+		 * 2.6.
+		 */
+		needs_conversion = 0;
+
+		fscanf(fp, "MemFree: %lu %s\n", &mfree, buf);
+
+		/*
+		 * MemShared: is no longer present in 2.6. Report this as 0,
+		 * to maintain consistent behavior with normal procps.
+		 */
+		if (fscanf(fp, "MemShared: %lu %s\n", &shared, buf) != 2)
+			shared = 0;
+
+		fscanf(fp, "Buffers: %lu %s\n", &buffers, buf);
+		fscanf(fp, "Cached: %lu %s\n", &cached, buf);
+
+		used = total - mfree;
+	}
+	fclose(fp);
+
+	/* read load average as a string */
+	fp = bb_xfopen("loadavg", "r");
+	buf[0] = '\0';
+	fgets(buf, sizeof(buf), fp);
+	end = strchr(buf, ' ');
+	if (end) end = strchr(end+1, ' ');
+	if (end) end = strchr(end+1, ' ');
+	if (end) *end = '\0';
+	fclose(fp);
+
+	if (needs_conversion) {
+		/* convert to kilobytes */
+		used /= 1024;
+		mfree /= 1024;
+		shared /= 1024;
+		buffers /= 1024;
+		cached /= 1024;
+		total /= 1024;
+	}
+
+	/* output memory info and load average */
+	/* clear screen & go to top */
+	if (scr_width > sizeof(scrbuf))
+		scr_width = sizeof(scrbuf);
+	snprintf(scrbuf, scr_width,
+		"Mem: %ldK used, %ldK free, %ldK shrd, %ldK buff, %ldK cached",
+		used, mfree, shared, buffers, cached);
+	printf("\e[H\e[J%s\n", scrbuf);
+	snprintf(scrbuf, scr_width,
+		"Load average: %s  (Status: S=sleeping R=running, W=waiting)", buf);
+	printf("%s\n", scrbuf);
+
+	return total;
+}
+
+
+/* display process statuses */
+static void display_status(int count, int scr_width)
+{
+	enum {
+		bits_per_int = sizeof(int)*8
+	};
+
+	procps_status_t *s = top;
+	char rss_str_buf[8];
+	unsigned long total_memory = display_generic(scr_width); /* or use total_rss? */
+	unsigned pmem_shift, pmem_scale;
+
+#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+	unsigned pcpu_shift, pcpu_scale;
+
+	/* what info of the processes is shown */
+	printf("\e[7m%.*s\e[0m", scr_width,
+		"  PID USER     STATUS   RSS  PPID %CPU %MEM COMMAND");
+#define MIN_WIDTH \
+	sizeof( "  PID USER     STATUS   RSS  PPID %CPU %MEM C")
+#else
+	printf("\e[7m%.*s\e[0m", scr_width,
+		"  PID USER     STATUS   RSS  PPID %MEM COMMAND");
+#define MIN_WIDTH \
+	sizeof( "  PID USER     STATUS   RSS  PPID %MEM C")
+#endif
+
+	/*
+	 * MEM% = s->rss/MemTotal
+	 */
+	pmem_shift = bits_per_int-11;
+	pmem_scale = 1000*(1U<<(bits_per_int-11)) / total_memory;
+	/* s->rss is in kb. we want (s->rss * pmem_scale) to never overflow */
+	while (pmem_scale >= 512) {
+		pmem_scale /= 4;
+		pmem_shift -= 2;
+	}
+#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+	/*
+	 * CPU% = s->pcpu/sum(s->pcpu) * busy_cpu_ticks/total_cpu_ticks
+	 * (pcpu is delta of sys+user time between samples)
+	 */
+	/* (jif.xxx - prev_jif.xxx) and s->pcpu are
+	 * in 0..~64000 range (HZ*update_interval).
+	 * we assume that unsigned is at least 32-bit.
+	 */
+	pcpu_shift = 6;
+	pcpu_scale = (1000*64*(uint16_t)(jif.busy-prev_jif.busy) ? : 1);
+	while (pcpu_scale < (1U<<(bits_per_int-2))) {
+		pcpu_scale *= 4;
+		pcpu_shift += 2;
+	}
+	pcpu_scale /= ( (uint16_t)(jif.total-prev_jif.total)*total_pcpu ? : 1);
+	/* we want (s->pcpu * pcpu_scale) to never overflow */
+	while (pcpu_scale >= 1024) {
+		pcpu_scale /= 4;
+		pcpu_shift -= 2;
+	}
+	/* printf(" pmem_scale=%u pcpu_scale=%u ", pmem_scale, pcpu_scale); */
+#endif
+
+	while (count--) {
+		div_t pmem = div( (s->rss*pmem_scale) >> pmem_shift, 10);
+		int col = scr_width+1;
+		USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(div_t pcpu;)
+
+		if (s->rss >= 100*1024)
+			sprintf(rss_str_buf, "%6ldM", s->rss/1024);
+		else
+			sprintf(rss_str_buf, "%7ld", s->rss);
+		USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu = div((s->pcpu*pcpu_scale) >> pcpu_shift, 10);)
+		col -= printf("\n%5d %-8s %s  %s%6d%3u.%c" \
+				USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE("%3u.%c") " ",
+				s->pid, s->user, s->state, rss_str_buf, s->ppid,
+				USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu.quot, '0'+pcpu.rem,)
+				pmem.quot, '0'+pmem.rem);
+		if (col>0)
+			printf("%.*s", col, s->short_cmd);
+		/* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu,
+			jif.busy - prev_jif.busy, jif.total - prev_jif.total); */
+		s++;
+	}
+	/* printf(" %d", hist_iterations); */
+	putchar('\r');
+	fflush(stdout);
+}
+
+static void clearmems(void)
+{
+	free(top);
+	top = 0;
+	ntop = 0;
+}
+
+#ifdef CONFIG_FEATURE_USE_TERMIOS
+#include <termios.h>
+#include <signal.h>
+
+
+static struct termios initial_settings;
+
+static void reset_term(void)
+{
+	tcsetattr(0, TCSANOW, (void *) &initial_settings);
+#ifdef CONFIG_FEATURE_CLEAN_UP
+	clearmems();
+#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+	free(prev_hist);
+#endif
+#endif /* CONFIG_FEATURE_CLEAN_UP */
+}
+
+static void sig_catcher(int sig ATTRIBUTE_UNUSED)
+{
+	reset_term();
+	exit(1);
+}
+#endif /* CONFIG_FEATURE_USE_TERMIOS */
+
+
+int top_main(int argc, char **argv)
+{
+	int opt, interval, lines, col;
+	char *sinterval;
+#ifdef CONFIG_FEATURE_USE_TERMIOS
+	struct termios new_settings;
+	struct timeval tv;
+	fd_set readfds;
+	unsigned char c;
+#endif /* CONFIG_FEATURE_USE_TERMIOS */
+
+	/* do normal option parsing */
+	opt = bb_getopt_ulflags(argc, argv, "d:", &sinterval);
+	if ((opt & 1)) {
+		interval = atoi(sinterval);
+	} else {
+		/* Default update rate is 5 seconds */
+		interval = 5;
+	}
+
+	/* change to /proc */
+	bb_xchdir("/proc");
+#ifdef CONFIG_FEATURE_USE_TERMIOS
+	tcgetattr(0, (void *) &initial_settings);
+	memcpy(&new_settings, &initial_settings, sizeof(struct termios));
+	new_settings.c_lflag &= ~(ISIG | ICANON); /* unbuffered input */
+	/* Turn off echoing */
+	new_settings.c_lflag &= ~(ECHO | ECHONL);
+
+	signal(SIGTERM, sig_catcher);
+	signal(SIGINT, sig_catcher);
+	tcsetattr(0, TCSANOW, (void *) &new_settings);
+	atexit(reset_term);
+#endif /* CONFIG_FEATURE_USE_TERMIOS */
+
+#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+	sort_function[0] = pcpu_sort;
+	sort_function[1] = mem_sort;
+	sort_function[2] = time_sort;
+#else
+	sort_function = mem_sort;
+#endif /* CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE */
+
+	while (1) {
+		procps_status_t *p;
+
+		/* Default to 25 lines - 5 lines for status */
+		lines = 24 - 3;
+		col = 79;
+#ifdef CONFIG_FEATURE_USE_TERMIOS
+		get_terminal_width_height(0, &col, &lines);
+		if (lines < 5 || col < MIN_WIDTH) {
+			sleep(interval);
+			continue;
+		}
+		lines -= 3;
+#endif /* CONFIG_FEATURE_USE_TERMIOS */
+
+		/* read process IDs & status for all the processes */
+		while ((p = procps_scan(0)) != 0) {
+			int n = ntop;
+
+			top = xrealloc(top, (++ntop)*sizeof(procps_status_t));
+			memcpy(top + n, p, sizeof(procps_status_t));
+		}
+		if (ntop == 0) {
+			bb_error_msg_and_die("Can't find process info in /proc");
+		}
+#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+		if (!prev_hist_count) {
+			do_stats();
+			sleep(1);
+			clearmems();
+			continue;
+		}
+		do_stats();
+		qsort(top, ntop, sizeof(procps_status_t), (void*)mult_lvl_cmp);
+#else
+		qsort(top, ntop, sizeof(procps_status_t), (void*)sort_function);
+#endif /* CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE */
+		opt = lines;
+		if (opt > ntop) {
+			opt = ntop;
+		}
+		/* show status for each of the processes */
+		display_status(opt, col);
+#ifdef CONFIG_FEATURE_USE_TERMIOS
+		tv.tv_sec = interval;
+		tv.tv_usec = 0;
+		FD_ZERO(&readfds);
+		FD_SET(0, &readfds);
+		select(1, &readfds, NULL, NULL, &tv);
+		if (FD_ISSET(0, &readfds)) {
+			if (read(0, &c, 1) <= 0) {   /* signal */
+				return EXIT_FAILURE;
+			}
+			if (c == 'q' || c == initial_settings.c_cc[VINTR])
+				break;
+			if (c == 'M') {
+#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+				sort_function[0] = mem_sort;
+				sort_function[1] = pcpu_sort;
+				sort_function[2] = time_sort;
+#else
+				sort_function = mem_sort;
+#endif
+			}
+#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+			if (c == 'P') {
+				sort_function[0] = pcpu_sort;
+				sort_function[1] = mem_sort;
+				sort_function[2] = time_sort;
+			}
+			if (c == 'T') {
+				sort_function[0] = time_sort;
+				sort_function[1] = mem_sort;
+				sort_function[2] = pcpu_sort;
+			}
+#endif
+			if (c == 'N') {
+#ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+				sort_function[0] = pid_sort;
+#else
+				sort_function = pid_sort;
+#endif
+			}
+		}
+#else
+		sleep(interval);
+#endif /* CONFIG_FEATURE_USE_TERMIOS */
+		clearmems();
+	}
+	if (ENABLE_FEATURE_CLEAN_UP)
+		clearmems();
+	putchar('\n');
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/uptime.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/uptime.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/procps/uptime.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,63 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini uptime implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+/* This version of uptime doesn't display the number of users on the system,
+ * since busybox init doesn't mess with utmp.  For folks using utmp that are
+ * just dying to have # of users reported, feel free to write it as some type
+ * of CONFIG_FEATURE_UTMP_SUPPORT #define
+ */
+
+/* getopt not needed */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <time.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#ifndef FSHIFT
+# define FSHIFT 16              /* nr of bits of precision */
+#endif
+#define FIXED_1         (1<<FSHIFT)     /* 1.0 as fixed-point */
+#define LOAD_INT(x) ((x) >> FSHIFT)
+#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+
+
+int uptime_main(int argc, char **argv)
+{
+	int updays, uphours, upminutes;
+	struct sysinfo info;
+	struct tm *current_time;
+	time_t current_secs;
+
+	time(&current_secs);
+	current_time = localtime(&current_secs);
+
+	sysinfo(&info);
+
+	printf(" %02d:%02d:%02d up ",
+			current_time->tm_hour, current_time->tm_min, current_time->tm_sec);
+	updays = (int) info.uptime / (60*60*24);
+	if (updays)
+		printf("%d day%s, ", updays, (updays != 1) ? "s" : "");
+	upminutes = (int) info.uptime / 60;
+	uphours = (upminutes / 60) % 24;
+	upminutes %= 60;
+	if(uphours)
+		printf("%2d:%02d, ", uphours, upminutes);
+	else
+		printf("%d min, ", upminutes);
+
+	printf("load average: %ld.%02ld, %ld.%02ld, %ld.%02ld\n",
+			LOAD_INT(info.loads[0]), LOAD_FRAC(info.loads[0]),
+			LOAD_INT(info.loads[1]), LOAD_FRAC(info.loads[1]),
+			LOAD_INT(info.loads[2]), LOAD_FRAC(info.loads[2]));
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/bb_mkdep
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/bb_mkdep
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/bb_mkdep.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/bb_mkdep.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/bb_mkdep.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1787 @@
+/*
+ * Another fast dependencies generator for Makefiles, Version 4.2
+ *
+ * Copyright (C) 2005,2006 by Vladimir Oleynik <dzo at simtreas.ru>
+ *
+ * mmaping file may be originally by Linus Torvalds.
+ *
+ * infix parser/evaluator for #if expression
+ *      Copyright (c) 2001 Aaron Lehmann <aaronl at vitelus.com>
+ *      Copyright (c) 2001 Manuel Novoa III <mjn3 at codepoet.org>
+ *      Copyright (c) 2003 Vladimir Oleynik <dzo at simtreas.ru>
+ *
+ * bb_simplify_path()
+ *      Copyright (C) 2005 Manuel Novoa III <mjn3 at codepoet.org>
+ *
+ * xmalloc() bb_xstrdup() bb_error_d():
+ *      Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * llist routine
+ *      Copyright (C) 2003 Glenn McGrath
+ *      Copyright (C) Vladimir Oleynik <dzo at simtreas.ru>
+ *
+ * (c) 2005,2006 Bernhard Fischer:
+ *  - commentary typos,
+ *  - move "memory exhausted" into msg_enomem,
+ *  - more verbose --help output.
+ *
+ * This program does:
+ * 1) find #define KEY VALUE or #undef KEY from include/bb_config.h
+ * 2) recursive find and scan *.[ch] files, but skips scan of include/config/
+ * 3) find #include "*.h" and KEYs using, if not as #define and #undef
+ * 4) generate dependencies to stdout
+ *    pwd/file.o: include/config/key*.h found_include_*.h
+ *    path/inc.h: include/config/key*.h found_included_include_*.h
+ * 5) save include/config/key*.h if changed after previous usage
+ * This program does not generate dependencies for #include <...>
+ * Config file can have #if #elif #else #ifdef #ifndef #endif lines
+ */
+
+#define LOCAL_INCLUDE_PATH          "include"
+#define INCLUDE_CONFIG_PATH         LOCAL_INCLUDE_PATH"/config"
+#define INCLUDE_CONFIG_KEYS_PATH    LOCAL_INCLUDE_PATH"/bb_config.h"
+
+#define bb_mkdep_full_options \
+"\nOptions:" \
+"\n\t-I local_include_path  include paths, default: \"" LOCAL_INCLUDE_PATH "\"" \
+"\n\t-d                     don't generate depend" \
+"\n\t-w                     show warning if include files not found" \
+"\n\t-k include/config      default: \"" INCLUDE_CONFIG_PATH "\"" \
+"\n\t-c include/config.h    configs, default: \"" INCLUDE_CONFIG_KEYS_PATH "\"" \
+"\n\tdirs_to_scan           default \".\""
+
+#define bb_mkdep_terse_options "Usage: [-I local_include_paths] [-dw] " \
+		   "[-k path_for_stored_keys] [dirs]"
+
+
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <getopt.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#ifdef __GNUC__
+#define ATTRIBUTE __attribute__
+#else
+#define ATTRIBUTE(a) /* nothing */
+#endif
+
+#if !(defined __USE_ISOC99 || (defined __GLIBC_HAVE_LONG_LONG && defined __USE_MISC))
+#define strtoll strtol
+#endif
+
+/* partial and simplified libbb routine */
+static void bb_error_d(const char *s, ...) ATTRIBUTE ((noreturn, format (printf, 1, 2)));
+static char * bb_asprint(const char *format, ...) ATTRIBUTE ((format (printf, 1, 2)));
+static char *bb_simplify_path(const char *path);
+
+/* stolen from libbb as is */
+typedef struct llist_s {
+	char *data;
+	struct llist_s *link;
+} llist_t;
+
+static const char msg_enomem[] = "memory exhausted";
+
+/* inline realization for fast works */
+static inline void *xmalloc(size_t size)
+{
+	void *p = malloc(size);
+
+	if(p == NULL)
+		bb_error_d(msg_enomem);
+	return p;
+}
+
+static inline char *bb_xstrdup(const char *s)
+{
+	char *r = strdup(s);
+
+	if(r == NULL)
+	    bb_error_d(msg_enomem);
+	return r;
+}
+
+
+static int dontgenerate_dep;    /* flag -d usaged */
+static int noiwarning;          /* flag -w usaged */
+static llist_t *configs;    /* list of -c usaged and them stat() after parsed */
+static llist_t *Iop;        /* list of -I include usaged */
+
+static char *pwd;           /* current work directory */
+static size_t replace;      /* replace current work directory with build dir */
+
+static const char *kp;      /* KEY path, argument of -k used */
+static size_t kp_len;
+static struct stat st_kp;   /* stat(kp) */
+
+typedef struct BB_KEYS {
+	char *keyname;
+	size_t key_sz;
+	const char *value;
+	const char *checked;
+	char *stored_path;
+	const char *src_have_this_key;
+	struct BB_KEYS *next;
+} bb_key_t;
+
+static bb_key_t *key_top;   /* list of found KEYs */
+static bb_key_t *Ifound;    /* list of parsed includes */
+
+
+static void parse_conf_opt(const char *opt, const char *val, size_t key_sz);
+static void parse_inc(const char *include, const char *fname);
+
+static inline bb_key_t *check_key(bb_key_t *k, const char *nk, size_t key_sz)
+{
+    bb_key_t *cur;
+
+    for(cur = k; cur; cur = cur->next) {
+	if(key_sz == cur->key_sz && memcmp(cur->keyname, nk, key_sz) == 0) {
+	    cur->checked = cur->stored_path;
+	    return cur;
+	}
+    }
+    return NULL;
+}
+
+static inline const char *lookup_key(const char *nk, size_t key_sz)
+{
+    bb_key_t *cur;
+
+    for(cur = key_top; cur; cur = cur->next) {
+	if(key_sz == cur->key_sz && memcmp(cur->keyname, nk, key_sz) == 0) {
+	    return cur->value;
+	}
+    }
+    return NULL;
+}
+
+/* for lexical analyser */
+static int pagesizem1;      /* padding mask = getpagesize() - 1 */
+
+/* for speed tricks */
+static char first_chars[1+UCHAR_MAX];               /* + L_EOF */
+static char isalnums[1+UCHAR_MAX];                  /* + L_EOF */
+
+/* trick for fast find "define", "include", "undef",
+"if((n)def)" "else", "endif"  */
+static const char * const preproc[] = {
+/* 0   1       2      3       4     5       6        7         8      9 */
+"", "efine", "lif", "lse", "ndif", "f", "fdef", "fndef", "nclude", "ndef" };
+static const unsigned char first_chars_deiu[UCHAR_MAX] = {
+	[(int)'d'] = (unsigned char)(1|0x10),     /* define */
+	[(int)'e'] = (unsigned char)(2|0x40),     /* elif, else, endif  */
+	[(int)'i'] = (unsigned char)(5|0x80),     /* if ifdef ifndef include */
+	[(int)'u'] = (unsigned char)(9|0x90),     /* undef */
+};
+
+#define CONFIG_MODE  0
+#define IF0_MODE     1  /* #if 0  */
+#define IF1_MODE     2  /* #if 1 */
+#define ELSE0_MODE   4  /* #else found after #if 0 */
+#define ELSE1_MODE   8  /* #else found after #if 1 */
+#define ELIF1_MODE   16 /* #elif found after #if 1 */
+#define FALSE_MODES  (IF0_MODE|ELSE1_MODE|ELIF1_MODE)
+
+#define yy_error_d(s) bb_error_d("%s:%d hmm, %s", fname, line, s)
+
+/* state */
+#define S      0        /* start state */
+#define STR    '"'      /* string */
+#define CHR    '\''     /* char */
+#define REM    '/'      /* block comment */
+#define BS     '\\'     /* back slash */
+#define POUND  '#'      /* # */
+#define D      '1'      /* #define preprocessor's directive */
+#define EI     '2'      /* #elif preprocessor's directive */
+#define E      '3'      /* #else preprocessor's directive */
+#define EF     '4'      /* #endif preprocessor's directive */
+#define F      '5'      /* #if preprocessor's directive */
+#define IFD    '6'      /* #ifdef preprocessor's directive */
+#define IFND   '7'      /* #ifndef preprocessor's directive */
+#define I      '8'      /* #include preprocessor's directive */
+#define U      '9'      /* #undef preprocessor's directive */
+#define DK     'K'      /* #define KEY... (config mode) */
+#define ANY    '*'      /* any unparsed chars */
+
+/* [A-Z_a-z] */
+#define ID(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_')
+/* [A-Z_a-z0-9] */
+#define ISALNUM(c)  (ID(c) || (c >= '0' && c <= '9'))
+
+#define L_EOF  (1+UCHAR_MAX)
+
+#define getc0()     do { c = (optr >= oend) ? L_EOF : *optr++; } while(0)
+
+#define getc1()     do { getc0(); if(c == BS) { getc0(); \
+				    if(c == '\n') { line++; continue; } \
+				    else { optr--; c = BS; } \
+				  } break; } while(1)
+
+static char id_s[4096];
+#define put_id(ic)  do {    if(id_len == sizeof(id_s)) goto too_long; \
+				id[id_len++] = ic; } while(0)
+
+static char ifcpp_stack[1024];
+static int  ptr_ifcpp_stack;
+#define push_mode() do { \
+			if(ptr_ifcpp_stack == (int)sizeof(ifcpp_stack)) \
+				yy_error_d("#if* stack overflow"); \
+			ifcpp_stack[ptr_ifcpp_stack++] = (char)mode; \
+			} while(0)
+
+#define pop_mode()  do { \
+			if(ptr_ifcpp_stack == 0) \
+				yy_error_d("unexpected #endif"); \
+			mode = ifcpp_stack[--ptr_ifcpp_stack]; \
+			} while(0)
+
+/* #if expression */
+typedef long long arith_t;
+
+static arith_t arith (const char *expr, int *perrcode);
+
+/* The code uses a simple two-stack algorithm. See
+ * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
+ * for a detailed explanation of the infix-to-postfix algorithm on which
+ * this is based (this code differs in that it applies operators immediately
+ * to the stack instead of adding them to a queue to end up with an
+ * expression). */
+
+#define arith_isspace(arithval) \
+	(arithval == ' ' || arithval == '\v' || arithval == '\t' || arithval == '\f')
+
+
+typedef unsigned char operator;
+
+/* An operator's token id is a bit of a bitfield. The lower 5 bits are the
+ * precedence, and 3 high bits are an ID unique across operators of that
+ * precedence. The ID portion is so that multiple operators can have the
+ * same precedence, ensuring that the leftmost one is evaluated first.
+ * Consider * and /. */
+
+#define tok_decl(prec,id) (((id)<<5)|(prec))
+#define PREC(op) ((op) & 0x1F)
+
+#define TOK_LPAREN tok_decl(0,0)
+
+#define TOK_COMMA tok_decl(1,0)
+
+/* conditional is right associativity too */
+#define TOK_CONDITIONAL tok_decl(2,0)
+#define TOK_CONDITIONAL_SEP tok_decl(2,1)
+
+#define TOK_OR tok_decl(3,0)
+
+#define TOK_AND tok_decl(4,0)
+
+#define TOK_BOR tok_decl(5,0)
+
+#define TOK_BXOR tok_decl(6,0)
+
+#define TOK_BAND tok_decl(7,0)
+
+#define TOK_EQ tok_decl(8,0)
+#define TOK_NE tok_decl(8,1)
+
+#define TOK_LT tok_decl(9,0)
+#define TOK_GT tok_decl(9,1)
+#define TOK_GE tok_decl(9,2)
+#define TOK_LE tok_decl(9,3)
+
+#define TOK_LSHIFT tok_decl(10,0)
+#define TOK_RSHIFT tok_decl(10,1)
+
+#define TOK_ADD tok_decl(11,0)
+#define TOK_SUB tok_decl(11,1)
+
+#define TOK_MUL tok_decl(12,0)
+#define TOK_DIV tok_decl(12,1)
+#define TOK_REM tok_decl(12,2)
+
+/* For now unary operators. */
+#define UNARYPREC 13
+#define TOK_BNOT tok_decl(UNARYPREC,0)
+#define TOK_NOT tok_decl(UNARYPREC,1)
+
+#define TOK_UMINUS tok_decl(UNARYPREC+1,0)
+#define TOK_UPLUS tok_decl(UNARYPREC+1,1)
+
+#define SPEC_PREC (UNARYPREC+2)
+
+#define TOK_NUM tok_decl(SPEC_PREC, 0)
+#define TOK_RPAREN tok_decl(SPEC_PREC, 1)
+
+#define NUMPTR (*numstackptr)
+
+typedef struct ARITCH_VAR_NUM {
+	arith_t val;
+	arith_t contidional_second_val;
+	char contidional_second_val_initialized;
+} v_n_t;
+
+
+typedef struct CHK_VAR_RECURSIVE_LOOPED {
+	const char *var;
+	size_t var_sz;
+	struct CHK_VAR_RECURSIVE_LOOPED *next;
+} chk_var_recursive_looped_t;
+
+static chk_var_recursive_looped_t *prev_chk_var_recursive;
+
+
+static int arith_lookup_val(const char *var, size_t key_sz, arith_t *pval)
+{
+    const char * p = lookup_key(var, key_sz);
+
+    if(p) {
+	int errcode;
+
+	/* recursive try as expression */
+	chk_var_recursive_looped_t *cur;
+	chk_var_recursive_looped_t cur_save;
+
+	for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
+	    if(cur->var_sz == key_sz && memcmp(cur->var, var, key_sz) == 0) {
+		/* expression recursion loop detected */
+		return -5;
+	    }
+	}
+	/* save current lookuped var name */
+	cur = prev_chk_var_recursive;
+	cur_save.var = var;
+	cur_save.var_sz = key_sz;
+	cur_save.next = cur;
+	prev_chk_var_recursive = &cur_save;
+
+	*pval = arith (p, &errcode);
+	/* restore previous ptr after recursiving */
+	prev_chk_var_recursive = cur;
+	return errcode;
+    } else {
+	/* disallow undefined var */
+	fprintf(stderr, "%.*s ", (int)key_sz, var);
+	return -4;
+    }
+}
+
+/* "applying" a token means performing it on the top elements on the integer
+ * stack. For a unary operator it will only change the top element, but a
+ * binary operator will pop two arguments and push a result */
+static inline int
+arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
+{
+	v_n_t *numptr_m1;
+	arith_t numptr_val, rez;
+
+	if (NUMPTR == numstack) goto err; /* There is no operator that can work
+										 without arguments */
+	numptr_m1 = NUMPTR - 1;
+
+	rez = numptr_m1->val;
+	if (op == TOK_UMINUS)
+		rez *= -1;
+	else if (op == TOK_NOT)
+		rez = !rez;
+	else if (op == TOK_BNOT)
+		rez = ~rez;
+	else if (op != TOK_UPLUS) {
+		/* Binary operators */
+
+	    /* check and binary operators need two arguments */
+	    if (numptr_m1 == numstack) goto err;
+
+	    /* ... and they pop one */
+	    --NUMPTR;
+	    numptr_val = rez;
+	    if (op == TOK_CONDITIONAL) {
+		if(! numptr_m1->contidional_second_val_initialized) {
+		    /* protect $((expr1 ? expr2)) without ": expr" */
+		    goto err;
+		}
+		rez = numptr_m1->contidional_second_val;
+	    } else if(numptr_m1->contidional_second_val_initialized) {
+		    /* protect $((expr1 : expr2)) without "expr ? " */
+		    goto err;
+	    }
+	    numptr_m1 = NUMPTR - 1;
+	    if (op == TOK_CONDITIONAL) {
+		    numptr_m1->contidional_second_val = rez;
+	    }
+	    rez = numptr_m1->val;
+	    if (op == TOK_BOR)
+			rez |= numptr_val;
+	    else if (op == TOK_OR)
+			rez = numptr_val || rez;
+	    else if (op == TOK_BAND)
+			rez &= numptr_val;
+	    else if (op == TOK_BXOR)
+			rez ^= numptr_val;
+	    else if (op == TOK_AND)
+			rez = rez && numptr_val;
+	    else if (op == TOK_EQ)
+			rez = (rez == numptr_val);
+	    else if (op == TOK_NE)
+			rez = (rez != numptr_val);
+	    else if (op == TOK_GE)
+			rez = (rez >= numptr_val);
+	    else if (op == TOK_RSHIFT)
+			rez >>= numptr_val;
+	    else if (op == TOK_LSHIFT)
+			rez <<= numptr_val;
+	    else if (op == TOK_GT)
+			rez = (rez > numptr_val);
+	    else if (op == TOK_LT)
+			rez = (rez < numptr_val);
+	    else if (op == TOK_LE)
+			rez = (rez <= numptr_val);
+	    else if (op == TOK_MUL)
+			rez *= numptr_val;
+	    else if (op == TOK_ADD)
+			rez += numptr_val;
+	    else if (op == TOK_SUB)
+			rez -= numptr_val;
+	    else if (op == TOK_COMMA)
+			rez = numptr_val;
+	    else if (op == TOK_CONDITIONAL_SEP) {
+			if (numptr_m1 == numstack) {
+			    /* protect $((expr : expr)) without "expr ? " */
+			    goto err;
+			}
+			numptr_m1->contidional_second_val_initialized = op;
+			numptr_m1->contidional_second_val = numptr_val;
+	    }
+	    else if (op == TOK_CONDITIONAL) {
+			rez = rez ?
+			      numptr_val : numptr_m1->contidional_second_val;
+	    }
+	    else if(numptr_val==0)          /* zero divisor check */
+			return -2;
+	    else if (op == TOK_DIV)
+			rez /= numptr_val;
+	    else if (op == TOK_REM)
+			rez %= numptr_val;
+	}
+	numptr_m1->val = rez;
+	return 0;
+err: return(-1);
+}
+
+/* longest must first */
+static const char op_tokens[] = {
+	'<','<',    0, TOK_LSHIFT,
+	'>','>',    0, TOK_RSHIFT,
+	'|','|',    0, TOK_OR,
+	'&','&',    0, TOK_AND,
+	'!','=',    0, TOK_NE,
+	'<','=',    0, TOK_LE,
+	'>','=',    0, TOK_GE,
+	'=','=',    0, TOK_EQ,
+	'!',        0, TOK_NOT,
+	'<',        0, TOK_LT,
+	'>',        0, TOK_GT,
+	'|',        0, TOK_BOR,
+	'&',        0, TOK_BAND,
+	'*',        0, TOK_MUL,
+	'/',        0, TOK_DIV,
+	'%',        0, TOK_REM,
+	'+',        0, TOK_ADD,
+	'-',        0, TOK_SUB,
+	'^',        0, TOK_BXOR,
+	'~',        0, TOK_BNOT,
+	',',        0, TOK_COMMA,
+	'?',        0, TOK_CONDITIONAL,
+	':',        0, TOK_CONDITIONAL_SEP,
+	')',        0, TOK_RPAREN,
+	'(',        0, TOK_LPAREN,
+	0
+};
+/* ptr to ")" */
+#define endexpression &op_tokens[sizeof(op_tokens)-7]
+
+/*
+ * Return of a legal variable name (a letter or underscore followed by zero or
+ * more letters, underscores, and digits).
+ */
+
+static inline char *
+endofname(const char *name)
+{
+	char *p;
+
+	p = (char *) name;
+	if (! ID(*p))
+		return p;
+	while (*++p) {
+		if (! ISALNUM(*p))
+			break;
+	}
+	return p;
+}
+
+
+static arith_t arith (const char *expr, int *perrcode)
+{
+    char arithval;          /* Current character under analysis */
+    operator lasttok, op;
+    operator prec;
+
+    const char *p = endexpression;
+    int errcode;
+
+    size_t datasizes = strlen(expr) + 2;
+
+    /* Stack of integers */
+    /* The proof that there can be no more than strlen(startbuf)/2+1 integers
+     * in any given correct or incorrect expression is left as an exercise to
+     * the reader. */
+    v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
+	    *numstackptr = numstack;
+    /* Stack of operator tokens */
+    operator *stack = alloca((datasizes) * sizeof(operator)),
+	    *stackptr = stack;
+
+    *stackptr++ = lasttok = TOK_LPAREN;     /* start off with a left paren */
+    *perrcode = errcode = 0;
+
+    while(1) {
+	if ((arithval = *expr) == 0) {
+		if (p == endexpression) {
+			/* Null expression. */
+err:
+			return (*perrcode = -1);
+		}
+
+		/* This is only reached after all tokens have been extracted from the
+		 * input stream. If there are still tokens on the operator stack, they
+		 * are to be applied in order. At the end, there should be a final
+		 * result on the integer stack */
+
+		if (expr != endexpression + 1) {
+			/* If we haven't done so already, */
+			/* append a closing right paren */
+			expr = endexpression;
+			/* and let the loop process it. */
+			continue;
+		}
+		/* At this point, we're done with the expression. */
+		if (numstackptr != numstack+1) {
+			/* ... but if there isn't, it's bad */
+			goto err;
+		}
+	ret:
+		*perrcode = errcode;
+		return numstack->val;
+	} else {
+		/* Continue processing the expression. */
+		if (arith_isspace(arithval)) {
+			/* Skip whitespace */
+			goto prologue;
+		}
+		if((p = endofname(expr)) != expr) {
+			size_t var_name_size = (p-expr);
+
+			if(var_name_size == 7 &&
+				strncmp(expr, "defined", var_name_size) == 0) {
+			    int brace_form = 0;
+			    const char *v;
+
+			    while(arith_isspace(*p)) p++;
+			    if(*p == '(') {
+				p++;
+				while(arith_isspace(*p)) p++;
+				brace_form = 1;
+			    }
+			    expr = p;
+			    if((p = endofname(expr)) == expr)
+				goto err;
+			    var_name_size = (p-expr);
+			    while(arith_isspace(*p)) p++;
+			    if(brace_form && *p++ != ')')
+				goto err;
+			    v = lookup_key(expr, var_name_size);
+			    numstackptr->val = (v != NULL) ? 1 : 0;
+			} else {
+			    errcode = arith_lookup_val(expr, var_name_size,
+					&(numstackptr->val));
+			    if(errcode) goto ret;
+			}
+			expr = p;
+		num:
+			numstackptr->contidional_second_val_initialized = 0;
+			numstackptr++;
+			lasttok = TOK_NUM;
+			continue;
+		} else if (arithval >= '0' && arithval <= '9') {
+			numstackptr->val = strtoll(expr, (char **) &expr, 0);
+			while(*expr == 'l' || *expr == 'L' || *expr == 'u' ||
+								*expr == 'U')
+			    expr++;
+			goto num;
+		}
+		for(p = op_tokens; ; p++) {
+			const char *o;
+
+			if(*p == 0) {
+				/* strange operator not found */
+				goto err;
+			}
+			for(o = expr; *p && *o == *p; p++)
+				o++;
+			if(! *p) {
+				/* found */
+				expr = o - 1;
+				break;
+			}
+			/* skip tail uncompared token */
+			while(*p)
+				p++;
+			/* skip zero delim */
+			p++;
+		}
+		op = p[1];
+
+		/* Plus and minus are binary (not unary) _only_ if the last
+		 * token was as number, or a right paren (which pretends to be
+		 * a number, since it evaluates to one). Think about it.
+		 * It makes sense. */
+		if (lasttok != TOK_NUM) {
+			if(op == TOK_ADD)
+			    op = TOK_UPLUS;
+			else if(op == TOK_SUB)
+			    op = TOK_UMINUS;
+		}
+		/* We don't want a unary operator to cause recursive descent on the
+		 * stack, because there can be many in a row and it could cause an
+		 * operator to be evaluated before its argument is pushed onto the
+		 * integer stack. */
+		/* But for binary operators, "apply" everything on the operator
+		 * stack until we find an operator with a lesser priority than the
+		 * one we have just extracted. */
+		/* Left paren is given the lowest priority so it will never be
+		 * "applied" in this way.
+		 * if associativity is right and priority eq, applied also skip
+		 */
+		prec = PREC(op);
+		if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
+			/* not left paren or unary */
+			if (lasttok != TOK_NUM) {
+				/* binary op must be preceded by a num */
+				goto err;
+			}
+			while (stackptr != stack) {
+			    if (op == TOK_RPAREN) {
+				/* The algorithm employed here is simple: while we don't
+				 * hit an open paren nor the bottom of the stack, pop
+				 * tokens and apply them */
+				if (stackptr[-1] == TOK_LPAREN) {
+				    --stackptr;
+				    /* Any operator directly after a */
+				    lasttok = TOK_NUM;
+				    /* close paren should consider itself binary */
+				    goto prologue;
+				}
+			    } else {
+				operator prev_prec = PREC(stackptr[-1]);
+
+				if (prev_prec < prec)
+					break;
+				/* check right assoc */
+				if(prev_prec == prec && prec == PREC(TOK_CONDITIONAL))
+					break;
+			    }
+			    errcode = arith_apply(*--stackptr, numstack, &numstackptr);
+			    if(errcode) goto ret;
+			}
+			if (op == TOK_RPAREN) {
+				goto err;
+			}
+		}
+
+		/* Push this operator to the stack and remember it. */
+		*stackptr++ = lasttok = op;
+
+	  prologue:
+		++expr;
+	}
+    }
+}
+
+/* stupid C lexical analyser for configs.h */
+static void c_lex_config(const char *fname, long fsize)
+{
+  int c;
+  int state;
+  int line;
+  char *id = id_s;
+  size_t id_len = 0;                /* stupid initialization */
+  unsigned char *optr, *oend;
+  int mode = CONFIG_MODE;
+
+  int fd;
+  char *map;
+  int mapsize;
+
+  if(fsize == 0) {
+    fprintf(stderr, "Warning: %s is empty\n", fname);
+    return;
+  }
+  fd = open(fname, O_RDONLY);
+  if(fd < 0) {
+	perror(fname);
+	return;
+  }
+  mapsize = (fsize+pagesizem1) & ~pagesizem1;
+  map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
+  if ((long) map == -1)
+	bb_error_d("%s: mmap: %m", fname);
+
+  optr = (unsigned char *)map;
+  oend = optr + fsize;
+
+  line = 1;
+  state = S;
+
+  for(;;) {
+    getc1();
+    for(;;) {
+	/* [ \t]+ eat first space */
+	while(c == ' ' || c == '\t')
+	    getc1();
+
+	if(state == S) {
+		while(first_chars[c] == ANY) {
+		    /* <S>unparsed */
+		    if(c == '\n')
+			line++;
+		    getc1();
+		}
+		if(c == L_EOF) {
+			/* <S><<EOF>> */
+			munmap(map, mapsize);
+			close(fd);
+			if(mode != CONFIG_MODE)
+				yy_error_d("expected #endif");
+			return;
+		}
+		if(c == REM) {
+			/* <S>/ */
+			getc0();
+			if(c == REM) {
+				/* <S>"//"[^\n]* */
+				do getc0(); while(c != '\n' && c != L_EOF);
+			} else if(c == '*') {
+				/* <S>[/][*] goto parse block comments */
+				break;
+			}
+		} else if(c == POUND) {
+			/* <S># */
+			state = c;
+			getc1();
+		} else if(c == STR || c == CHR) {
+			/* <S>\"|\' */
+			int qc = c;
+
+			for(;;) {
+			    /* <STR,CHR>. */
+			    getc1();
+			    if(c == qc) {
+				/* <STR>\" or <CHR>\' */
+				break;
+			    }
+			    if(c == BS) {
+				/* <STR,CHR>\\ but is not <STR,CHR>\\\n */
+				getc0();
+			    }
+			    if(c == '\n' || c == L_EOF)
+				yy_error_d("unterminated");
+			}
+			getc1();
+		} else {
+			/* <S>[A-Z_a-z0-9] */
+
+			/* trick for fast drop id
+			   if key with this first char undefined */
+			if(first_chars[c] == 0 || (mode & FALSE_MODES) != 0) {
+			    /* skip <S>[A-Z_a-z0-9]+ */
+			    do getc1(); while(isalnums[c]);
+			} else {
+			    id_len = 0;
+			    do {
+				/* <S>[A-Z_a-z0-9]+ */
+				put_id(c);
+				getc1();
+			    } while(isalnums[c]);
+			    check_key(key_top, id, id_len);
+			}
+		}
+		continue;
+	}
+	/* begin preprocessor states */
+	if(c == L_EOF)
+	    yy_error_d("unexpected EOF");
+	if(c == REM) {
+		/* <#.*>/ */
+		getc0();
+		if(c == REM)
+			yy_error_d("detected // in preprocessor line");
+		if(c == '*') {
+			/* <#.*>[/][*] goto parse block comments */
+			break;
+		}
+		/* hmm, #.*[/] */
+		yy_error_d("strange preprocessor line");
+	}
+	if(state == POUND) {
+	    /* tricks */
+	    int diu = (int)first_chars_deiu[c];   /* preproc ptr */
+
+	    state = S;
+	    if(diu != S) {
+		int p_num_str, p_num_max;
+
+		getc1();
+		id_len = 0;
+		while(isalnums[c]) {
+		    put_id(c);
+		    getc1();
+		}
+		put_id(0);
+		p_num_str = diu & 0xf;
+		p_num_max = diu >> 4;
+		for(diu = p_num_str; diu <= p_num_max; diu++)
+		    if(!strcmp(id, preproc[diu])) {
+			state = (diu + '0');
+			/* common */
+			id_len = 0;
+			break;
+		}
+	    } else {
+		while(isalnums[c]) getc1();
+	    }
+	} else if(state == EF) {
+		/* #endif */
+		pop_mode();
+		state = S;
+	} else if(state == I) {
+		if(c == STR && (mode & FALSE_MODES) == 0) {
+			/* <I>\" */
+			for(;;) {
+			    getc1();
+			    if(c == STR)
+				break;
+			    if(c == L_EOF)
+				yy_error_d("unexpected EOF");
+			    put_id(c);
+			}
+			put_id(0);
+			/* store "include.h" */
+			parse_inc(id, fname);
+			getc1();
+		}
+		/* else another (may be wrong) #include ... */
+		state = S;
+	} else if(state == F) {
+	    arith_t t;
+	    int errcode;
+
+	    while(c != '\n' && c != L_EOF) {
+		put_id(c);
+		getc1();
+	    }
+	    put_id(0);
+	    t = arith(id, &errcode);
+	    if (errcode < 0) {
+		if (errcode == -2)
+		    yy_error_d("divide by zero");
+		else if (errcode == -4)
+		    yy_error_d("undefined");
+		else if (errcode == -5)
+		    yy_error_d("expression recursion loop detected");
+		else
+		    yy_error_d("syntax error");
+	    }
+	    push_mode();
+	    mode = t != 0 ? IF1_MODE : IF0_MODE;
+	    state = S;
+	} else if(state == IFD || state == IFND) {
+	    /* save KEY from #if(n)def KEY ... */
+	    const char *v;
+
+	    push_mode();
+	    while(isalnums[c]) {
+		put_id(c);
+		getc1();
+	    }
+	    if(!id_len)
+		yy_error_d("expected identifier");
+	    v = lookup_key(id, id_len);
+	    mode = IF1_MODE;
+	    if(state == IFD && v == NULL)
+		mode = IF0_MODE;
+	    else if(state == IFND && v != NULL)
+		    mode = IF0_MODE;
+	    state = S;
+	} else if(state == EI) {
+	    /* #elif */
+	    if(mode == CONFIG_MODE || mode == ELSE0_MODE || mode == ELSE1_MODE)
+		yy_error_d("unexpected #elif");
+	    if(mode == IF0_MODE) {
+		pop_mode();
+		state = F;
+	    } else {
+		mode = ELIF1_MODE;
+		state = S;
+	    }
+	} else if(state == E) {
+	    if(mode == CONFIG_MODE || mode == ELSE0_MODE || mode == ELSE1_MODE)
+		yy_error_d("unexpected #else");
+	    if(mode == IF0_MODE)
+		mode = ELSE0_MODE;
+	    else if(mode == IF1_MODE)
+		mode = ELSE1_MODE;
+	    state = S;
+	} else if(state == D || state == U) {
+	    /* save KEY from #"define"|"undef" ... */
+	    while(isalnums[c]) {
+		put_id(c);
+		getc1();
+	    }
+	    if(!id_len)
+		yy_error_d("expected identifier");
+	    if(state == U) {
+		if((mode & FALSE_MODES) == 0)
+		    parse_conf_opt(id, NULL, id_len);
+		state = S;
+	    } else {
+		/* D -> DK */
+		state = DK;
+	    }
+	} else {
+	    /* state==<DK> #define KEY[ ] */
+	    size_t opt_len = id_len;
+	    char *val = id + opt_len;
+	    char *sp;
+
+	    for(;;) {
+		if(c == L_EOF || c == '\n')
+		    break;
+		put_id(c);
+		getc1();
+	    }
+	    sp = id + id_len;
+	    put_id(0);
+	    /* trim tail spaces */
+	    while(--sp >= val && (*sp == ' ' || *sp == '\t'
+				|| *sp == '\f' || *sp == '\v'))
+		*sp = '\0';
+	    if((mode & FALSE_MODES) == 0)
+		parse_conf_opt(id, val, opt_len);
+	    state = S;
+	}
+    }
+
+    /* <REM> */
+    getc0();
+    for(;;) {
+	  /* <REM>[^*]+ */
+	  while(c != '*') {
+		if(c == '\n') {
+		    /* <REM>\n */
+		    if(state != S)
+			yy_error_d("unexpected newline");
+		    line++;
+		} else if(c == L_EOF)
+		    yy_error_d("unexpected EOF");
+		getc0();
+	  }
+	  /* <REM>[*] */
+	  getc0();
+	  if(c == REM) {
+		/* <REM>[*][/] */
+		break;
+	  }
+    }
+  }
+too_long:
+  yy_error_d("phrase too long");
+}
+
+/* trick for fast find "define", "include", "undef" */
+static const char first_chars_diu[UCHAR_MAX] = {
+	[(int)'d'] = (char)5,           /* strlen("define")  - 1; */
+	[(int)'i'] = (char)6,           /* strlen("include") - 1; */
+	[(int)'u'] = (char)4,           /* strlen("undef")   - 1; */
+};
+
+#undef D
+#undef I
+#undef U
+#define D      '5'      /* #define preprocessor's directive */
+#define I      '6'      /* #include preprocessor's directive */
+#define U      '4'      /* #undef preprocessor's directive */
+
+/* stupid C lexical analyser for sources */
+static void c_lex_src(const char *fname, long fsize)
+{
+  int c;
+  int state;
+  int line;
+  char *id = id_s;
+  size_t id_len = 0;                /* stupid initialization */
+  unsigned char *optr, *oend;
+
+  int fd;
+  char *map;
+  int mapsize;
+
+  if(fsize == 0) {
+    fprintf(stderr, "Warning: %s is empty\n", fname);
+    return;
+  }
+  fd = open(fname, O_RDONLY);
+  if(fd < 0) {
+	perror(fname);
+	return;
+  }
+  mapsize = (fsize+pagesizem1) & ~pagesizem1;
+  map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
+  if ((long) map == -1)
+	bb_error_d("%s: mmap: %m", fname);
+
+  optr = (unsigned char *)map;
+  oend = optr + fsize;
+
+  line = 1;
+  state = S;
+
+  for(;;) {
+    getc1();
+    for(;;) {
+	/* [ \t]+ eat first space */
+	while(c == ' ' || c == '\t')
+	    getc1();
+
+	if(state == S) {
+		while(first_chars[c] == ANY) {
+		    /* <S>unparsed */
+		    if(c == '\n')
+			line++;
+		    getc1();
+		}
+		if(c == L_EOF) {
+			/* <S><<EOF>> */
+			munmap(map, mapsize);
+			close(fd);
+			return;
+		}
+		if(c == REM) {
+			/* <S>/ */
+			getc0();
+			if(c == REM) {
+				/* <S>"//"[^\n]* */
+				do getc0(); while(c != '\n' && c != L_EOF);
+			} else if(c == '*') {
+				/* <S>[/][*] goto parse block comments */
+				break;
+			}
+		} else if(c == POUND) {
+			/* <S># */
+			state = c;
+			getc1();
+		} else if(c == STR || c == CHR) {
+			/* <S>\"|\' */
+			int qc = c;
+
+			for(;;) {
+			    /* <STR,CHR>. */
+			    getc1();
+			    if(c == qc) {
+				/* <STR>\" or <CHR>\' */
+				break;
+			    }
+			    if(c == BS) {
+				/* <STR,CHR>\\ but is not <STR,CHR>\\\n */
+				getc0();
+			    }
+			    if(c == '\n' || c == L_EOF)
+				yy_error_d("unterminated");
+			}
+			getc1();
+		} else {
+			/* <S>[A-Z_a-z0-9] */
+
+			/* trick for fast drop id
+			   if key with this first char undefined */
+			if(first_chars[c] == 0) {
+			    /* skip <S>[A-Z_a-z0-9]+ */
+			    do getc1(); while(isalnums[c]);
+			} else {
+			    id_len = 0;
+			    do {
+				/* <S>[A-Z_a-z0-9]+ */
+				put_id(c);
+				getc1();
+			    } while(isalnums[c]);
+			    check_key(key_top, id, id_len);
+			}
+		}
+		continue;
+	}
+	/* begin preprocessor states */
+	if(c == L_EOF)
+	    yy_error_d("unexpected EOF");
+	if(c == REM) {
+		/* <#.*>/ */
+		getc0();
+		if(c == REM)
+			yy_error_d("detected // in preprocessor line");
+		if(c == '*') {
+			/* <#.*>[/][*] goto parse block comments */
+			break;
+		}
+		/* hmm, #.*[/] */
+		yy_error_d("strange preprocessor line");
+	}
+	if(state == POUND) {
+	    /* tricks */
+	    static const char * const p_preproc[] = {
+		    /* 0 1   2  3     4        5        6 */
+		    "", "", "", "", "ndef", "efine", "nclude"
+	    };
+	    size_t diu = first_chars_diu[c];   /* strlen and p_preproc ptr */
+
+	    state = S;
+	    if(diu != S) {
+		getc1();
+		id_len = 0;
+		while(isalnums[c]) {
+		    put_id(c);
+		    getc1();
+		}
+		/* str begins with c, read == strlen key and compared */
+		if(diu == id_len && !memcmp(id, p_preproc[diu], diu)) {
+		    state = diu + '0';
+		    id_len = 0; /* common for save */
+		}
+	    } else {
+		while(isalnums[c]) getc1();
+	    }
+	} else if(state == I) {
+		if(c == STR) {
+			/* <I>\" */
+			for(;;) {
+			    getc1();
+			    if(c == STR)
+				break;
+			    if(c == L_EOF)
+				yy_error_d("unexpected EOF");
+			    put_id(c);
+			}
+			put_id(0);
+			/* store "include.h" */
+			parse_inc(id, fname);
+			getc1();
+		}
+		/* else another (may be wrong) #include ... */
+		state = S;
+	} else /* if(state == D || state == U) */ {
+		/* ignore depend with #define or #undef KEY */
+		while(isalnums[c]) getc1();
+		state = S;
+	}
+    }
+
+    /* <REM> */
+    getc0();
+    for(;;) {
+	  /* <REM>[^*]+ */
+	  while(c != '*') {
+		if(c == '\n') {
+		    /* <REM>\n */
+		    if(state != S)
+			yy_error_d("unexpected newline");
+		    line++;
+		} else if(c == L_EOF)
+		    yy_error_d("unexpected EOF");
+		getc0();
+	  }
+	  /* <REM>[*] */
+	  getc0();
+	  if(c == REM) {
+		/* <REM>[*][/] */
+		break;
+	  }
+    }
+  }
+too_long:
+  yy_error_d("phrase too long");
+}
+
+
+/* bb_simplify_path special variant for absolute pathname */
+static size_t bb_qa_simplify_path(char *path)
+{
+	char *s, *p;
+
+	p = s = path;
+
+	do {
+	    if (*p == '/') {
+		if (*s == '/') {    /* skip duplicate (or initial) slash */
+		    continue;
+		} else if (*s == '.') {
+		    if (s[1] == '/' || s[1] == 0) { /* remove extra '.' */
+			continue;
+		    } else if ((s[1] == '.') && (s[2] == '/' || s[2] == 0)) {
+			++s;
+			if (p > path) {
+			    while (*--p != '/');    /* omit previous dir */
+			}
+			continue;
+		    }
+		}
+	    }
+	    *++p = *s;
+	} while (*++s);
+
+	if ((p == path) || (*p != '/')) {  /* not a trailing slash */
+	    ++p;                            /* so keep last character */
+	}
+	*p = 0;
+
+	return (p - path);
+}
+
+static void parse_inc(const char *include, const char *fname)
+{
+    bb_key_t *cur;
+    const char *p_i;
+    llist_t *lo;
+    char *ap;
+    size_t key_sz;
+    struct stat st;
+
+    if(*include == '/') {
+	lo = NULL;
+	ap = bb_xstrdup(include);
+    } else {
+	int w;
+	const char *p;
+
+	lo = Iop;
+	p = strrchr(fname, '/');    /* fname has absolute pathname */
+	w = (p-fname);
+	/* find from current directory of source file */
+	ap = bb_asprint("%.*s/%s", w, fname, include);
+    }
+
+    for(;;) {
+	key_sz = bb_qa_simplify_path(ap);
+	cur = check_key(Ifound, ap, key_sz);
+	if(cur) {
+	    cur->checked = cur->value;
+	    free(ap);
+	    return;
+	}
+	if(stat(ap, &st) == 0) {
+	    /* found */
+	    llist_t *cfl;
+
+	    for(cfl = configs; cfl; cfl = cfl->link) {
+		struct stat *config = (struct stat *)cfl->data;
+
+		if (st.st_dev == config->st_dev && st.st_ino == config->st_ino) {
+			/* skip depend with bb_configs.h */
+			return;
+		}
+	    }
+	    p_i = ap;
+	    break;
+	} else if(lo == NULL) {
+	    p_i = NULL;
+	    break;
+	}
+
+	/* find from "-I include" specified directories */
+	free(ap);
+	/* lo->data has absolute pathname */
+	ap = bb_asprint("%s/%s", lo->data, include);
+	lo = lo->link;
+    }
+
+    cur = xmalloc(sizeof(bb_key_t));
+    cur->keyname = ap;
+    cur->key_sz = key_sz;
+    cur->stored_path = ap;
+    cur->value = cur->checked = p_i;
+    if(p_i == NULL && noiwarning)
+	fprintf(stderr, "%s: Warning: #include \"%s\" not found\n", fname, include);
+    cur->next = Ifound;
+    Ifound = cur;
+}
+
+static size_t max_rec_sz;
+
+static void parse_conf_opt(const char *opt, const char *val, size_t key_sz)
+{
+	bb_key_t *cur;
+	char *k;
+	char *p;
+	size_t val_sz = 0;
+
+	cur = check_key(key_top, opt, key_sz);
+	if(cur != NULL) {
+	    /* already present */
+	    cur->checked = NULL;        /* store only */
+	    if(cur->value == NULL && val == NULL)
+		return;
+	    if(cur->value != NULL && val != NULL && !strcmp(cur->value, val))
+		return;
+	    k = cur->keyname;
+	    fprintf(stderr, "Warning: redefined %s\n", k);
+	} else {
+	    size_t recordsz;
+
+	    if(val && *val)
+		val_sz = strlen(val) + 1;
+	    recordsz = key_sz + val_sz + 1;
+	    if(max_rec_sz < recordsz)
+		max_rec_sz = recordsz;
+	    cur = xmalloc(sizeof(bb_key_t) + recordsz);
+	    k = cur->keyname = memcpy(cur + 1, opt, key_sz);
+	    cur->keyname[key_sz] = '\0';
+	    cur->key_sz = key_sz;
+	    cur->checked = NULL;
+	    cur->src_have_this_key = NULL;
+	    cur->next = key_top;
+	    key_top = cur;
+	}
+	/* save VAL */
+	if(val) {
+	    if(*val == '\0') {
+		cur->value = "";
+	    } else {
+		cur->value = p = cur->keyname + key_sz + 1;
+		memcpy(p, val, val_sz);
+	    }
+	} else {
+	    cur->value = NULL;
+	}
+	/* trick, save first char KEY for do fast identify id */
+	first_chars[(int)*k] = *k;
+
+	cur->stored_path = k = bb_asprint("%s/%s.h", kp, k);
+	/* key conversion [A-Z_] -> [a-z/] */
+	for(p = k + kp_len + 1; *p; p++) {
+	    if(*p >= 'A' && *p <= 'Z')
+		    *p = *p - 'A' + 'a';
+	    else if(*p == '_' && p[1] > '9')    /* do not change A_1 to A/1 */
+		    *p = '/';
+	}
+}
+
+static void store_keys(void)
+{
+    bb_key_t *cur;
+    char *k;
+    struct stat st;
+    int cmp_ok;
+    ssize_t rw_ret;
+    size_t recordsz = max_rec_sz * 2 + 10 * 2 + 16;
+    /* buffer for double "#define KEY VAL\n" */
+    char *record_buf = xmalloc(recordsz);
+
+    for(cur = key_top; cur; cur = cur->next) {
+	if(cur->src_have_this_key) {
+	    /* do generate record */
+	    k = cur->keyname;
+	    if(cur->value == NULL) {
+		recordsz = sprintf(record_buf, "#undef %s\n", k);
+	    } else {
+		const char *val = cur->value;
+		if(*val == '\0') {
+		    recordsz = sprintf(record_buf, "#define %s\n", k);
+		} else {
+		    if(val[0] != '(')
+			recordsz = sprintf(record_buf, "#define %s %s\n", k, val);
+		    else
+			recordsz = sprintf(record_buf, "#define %s%s\n", k, val);
+		}
+	    }
+	    /* size_t -> ssize_t :( */
+	    rw_ret = (ssize_t)recordsz;
+	    /* check kp/key.h, compare after previous use */
+	    cmp_ok = 0;
+	    k = cur->stored_path;
+	    if(stat(k, &st)) {
+		char *p;
+		for(p = k + kp_len + 1; *p; p++) {
+		    /* Auto-create directories. */
+		    if (*p == '/') {
+			*p = '\0';
+			if (access(k, F_OK) != 0 && mkdir(k, 0755) != 0)
+			    bb_error_d("mkdir(%s): %m", k);
+			*p = '/';
+		    }
+		}
+	    } else {
+		    /* found */
+		    if(st.st_size == (off_t)recordsz) {
+			char *r_cmp;
+			int fd;
+			size_t padded = recordsz;
+
+			/* 16-byte padding for read(2) and memcmp(3) */
+			padded = (padded+15) & ~15;
+			r_cmp = record_buf + padded;
+			fd = open(k, O_RDONLY);
+			if(fd < 0 || read(fd, r_cmp, recordsz) < rw_ret)
+			    bb_error_d("%s: %m", k);
+			close(fd);
+			cmp_ok = memcmp(record_buf, r_cmp, recordsz) == 0;
+		    }
+	    }
+	    if(!cmp_ok) {
+		int fd = open(k, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+		if(fd < 0 || write(fd, record_buf, recordsz) < rw_ret)
+		    bb_error_d("%s: %m", k);
+		close(fd);
+	    }
+	}
+    }
+}
+
+static int show_dep(int first, bb_key_t *k, const char *name, const char *f)
+{
+    bb_key_t *cur;
+
+    for(cur = k; cur; cur = cur->next) {
+	if(cur->checked) {
+	    if(first >= 0) {
+		if(first) {
+		    if(f == NULL)
+			printf("\n%s:", name);
+		    else
+			printf("\n%s/%s:", pwd, name);
+		    first = 0;
+		} else {
+		    printf(" \\\n  ");
+		}
+		printf(" %s", cur->checked);
+	    }
+	    cur->src_have_this_key = cur->checked;
+	    cur->checked = NULL;
+	}
+    }
+    return first;
+}
+
+static char *
+parse_chd(const char *fe, const char *p, size_t dirlen)
+{
+    struct stat st;
+    char *fp;
+    size_t df_sz;
+    static char dir_and_entry[4096];
+    size_t fe_sz = strlen(fe) + 1;
+
+    df_sz = dirlen + fe_sz + 1;         /* dir/file\0 */
+    if(df_sz > sizeof(dir_and_entry))
+	bb_error_d("%s: file name too long", fe);
+    fp = dir_and_entry;
+    /* sprintf(fp, "%s/%s", p, fe); */
+    memcpy(fp, p, dirlen);
+    fp[dirlen] = '/';
+    memcpy(fp + dirlen + 1, fe, fe_sz);
+
+    if(stat(fp, &st)) {
+	fprintf(stderr, "Warning: stat(%s): %m\n", fp);
+	return NULL;
+    }
+    if(S_ISREG(st.st_mode)) {
+	llist_t *cfl;
+	char *e = fp + df_sz - 3;
+
+	if(*e++ != '.' || (*e != 'c' && *e != 'h')) {
+	    /* direntry is regular file, but is not *.[ch] */
+	    return NULL;
+	}
+	for(cfl = configs; cfl; cfl = cfl->link) {
+	    struct stat *config = (struct stat *)cfl->data;
+
+	    if (st.st_dev == config->st_dev && st.st_ino == config->st_ino) {
+		/* skip already parsed bb_configs.h */
+		return NULL;
+	    }
+	}
+	/* direntry is *.[ch] regular file and is not configs */
+	c_lex_src(fp, st.st_size);
+	if(!dontgenerate_dep) {
+	    int first;
+	    if(*e == 'c') {
+		/* *.c -> *.o */
+		*e = 'o';
+		/* /src_dir/path/file.o to path/file.o */
+		fp += replace;
+		if(*fp == '/')
+		    fp++;
+	    } else {
+		e = NULL;
+	    }
+	    first = show_dep(1, Ifound, fp, e);
+	    first = show_dep(first, key_top, fp, e);
+	    if(first == 0)
+		putchar('\n');
+	} else {
+	    show_dep(-1, key_top, NULL, NULL);
+	}
+	return NULL;
+    } else if(S_ISDIR(st.st_mode)) {
+	if (st.st_dev == st_kp.st_dev && st.st_ino == st_kp.st_ino)
+	    return NULL;    /* drop scan kp/ directory */
+	/* direntry is directory. buff is returned */
+	return bb_xstrdup(fp);
+    }
+    /* hmm, direntry is device! */
+    return NULL;
+}
+
+/* from libbb but inlined for speed considerations */
+static inline llist_t *llist_add_to(llist_t *old_head, char *new_item)
+{
+	llist_t *new_head;
+
+	new_head = xmalloc(sizeof(llist_t));
+	new_head->data = new_item;
+	new_head->link = old_head;
+
+	return(new_head);
+}
+
+static void scan_dir_find_ch_files(const char *p)
+{
+    llist_t *dirs;
+    llist_t *d_add;
+    llist_t *d;
+    struct dirent *de;
+    DIR *dir;
+    size_t dirlen;
+
+    dirs = llist_add_to(NULL, bb_simplify_path(p));
+    replace = strlen(dirs->data);
+    /* emulate recursion */
+    while(dirs) {
+	d_add = NULL;
+	while(dirs) {
+	    dir = opendir(dirs->data);
+	    if (dir == NULL)
+		fprintf(stderr, "Warning: opendir(%s): %m\n", dirs->data);
+	    dirlen = strlen(dirs->data);
+	    while ((de = readdir(dir)) != NULL) {
+		char *found_dir;
+
+		if (de->d_name[0] == '.')
+			continue;
+		found_dir = parse_chd(de->d_name, dirs->data, dirlen);
+		if(found_dir)
+		    d_add = llist_add_to(d_add, found_dir);
+	    }
+	    closedir(dir);
+	    free(dirs->data);
+	    d = dirs;
+	    dirs = dirs->link;
+	    free(d);
+	}
+	dirs = d_add;
+    }
+}
+
+static void show_usage(void) ATTRIBUTE ((noreturn));
+static void show_usage(void)
+{
+	bb_error_d("%s\n%s\n", bb_mkdep_terse_options, bb_mkdep_full_options);
+}
+
+int main(int argc, char **argv)
+{
+	char *s;
+	int i;
+	llist_t *fl;
+
+	{
+	    /* for bb_simplify_path, this program has no chdir() */
+	    /* libbb-like my xgetcwd() */
+	    unsigned path_max = 512;
+
+	    s = xmalloc (path_max);
+	    while (getcwd (s, path_max) == NULL) {
+		if(errno != ERANGE)
+		    bb_error_d("getcwd: %m");
+		free(s);
+		s = xmalloc(path_max *= 2);
+	    }
+	    pwd = s;
+	}
+
+	while ((i = getopt(argc, argv, "I:c:dk:w")) > 0) {
+		switch(i) {
+		    case 'I':
+			    s = bb_simplify_path(optarg);
+			    Iop = llist_add_to(Iop, s);
+			    break;
+		    case 'c':
+			    s = bb_simplify_path(optarg);
+			    configs = llist_add_to(configs, s);
+			    break;
+		    case 'd':
+			    dontgenerate_dep = 1;
+			    break;
+		    case 'k':
+			    if(kp)
+				bb_error_d("Hmm, why multiple -k?");
+			    kp = bb_simplify_path(optarg);
+			    break;
+		    case 'w':
+			    noiwarning = 1;
+			    break;
+		    default:
+			    show_usage();
+		}
+	}
+	/* default kp */
+	if(kp == NULL)
+	    kp = bb_simplify_path(INCLUDE_CONFIG_PATH);
+	/* globals initialize */
+	kp_len = strlen(kp);
+	if(stat(kp, &st_kp))
+	    bb_error_d("stat(%s): %m", kp);
+	if(!S_ISDIR(st_kp.st_mode))
+	    bb_error_d("%s is not directory", kp);
+	/* defaults */
+	if(Iop == NULL)
+	    Iop = llist_add_to(Iop, bb_simplify_path(LOCAL_INCLUDE_PATH));
+	if(configs == NULL) {
+	    s = bb_simplify_path(INCLUDE_CONFIG_KEYS_PATH);
+	    configs = llist_add_to(configs, s);
+	}
+	/* for c_lex */
+	pagesizem1 = getpagesize() - 1;
+	for(i = 0; i < UCHAR_MAX; i++) {
+	    if(ISALNUM(i))
+		isalnums[i] = i;
+	    /* set unparsed chars to speed up the parser */
+	    else if(i != CHR && i != STR && i != POUND && i != REM)
+		first_chars[i] = ANY;
+	}
+	first_chars[i] = '-';   /* L_EOF */
+
+	/* parse configs */
+	for(fl = configs; fl; fl = fl->link) {
+	    struct stat st;
+
+	    if(stat(fl->data, &st))
+		bb_error_d("stat(%s): %m", fl->data);
+	    c_lex_config(fl->data, st.st_size);
+	    free(fl->data);
+	    /* trick for fast comparing found files with configs */
+	    fl->data = xmalloc(sizeof(struct stat));
+	    memcpy(fl->data, &st, sizeof(struct stat));
+	}
+
+	/* main loop */
+	argv += optind;
+	if(*argv) {
+	    while(*argv)
+		scan_dir_find_ch_files(*argv++);
+	} else {
+		scan_dir_find_ch_files(".");
+	}
+	store_keys();
+	return 0;
+}
+
+/* partial and simplified libbb routine */
+static void bb_error_d(const char *s, ...)
+{
+	va_list p;
+
+	va_start(p, s);
+	vfprintf(stderr, s, p);
+	va_end(p);
+	putc('\n', stderr);
+	exit(1);
+}
+
+static char *bb_asprint(const char *format, ...)
+{
+	va_list p;
+	int r;
+	char *out;
+
+#ifdef __USE_GNU
+	va_start(p, format);
+	r = vasprintf(&out, format, p);
+	va_end(p);
+#else
+	out = xmalloc(BUFSIZ);
+	va_start(p, format);
+	r = vsprintf(out, format, p);
+	va_end(p);
+#endif
+
+	if (r < 0)
+		bb_error_d("bb_asprint: %m");
+	return out;
+}
+
+/* partial libbb routine as is */
+
+static char *bb_simplify_path(const char *path)
+{
+	char *s, *start, *p;
+
+	if (path[0] == '/')
+		start = bb_xstrdup(path);
+	else {
+		/* is not libbb, but this program has no chdir() */
+		start = bb_asprint("%s/%s", pwd, path);
+	}
+	p = s = start;
+
+	do {
+	    if (*p == '/') {
+		if (*s == '/') {    /* skip duplicate (or initial) slash */
+		    continue;
+		} else if (*s == '.') {
+		    if (s[1] == '/' || s[1] == 0) { /* remove extra '.' */
+			continue;
+		    } else if ((s[1] == '.') && (s[2] == '/' || s[2] == 0)) {
+			++s;
+			if (p > start) {
+			    while (*--p != '/');    /* omit previous dir */
+			}
+			continue;
+		    }
+		}
+	    }
+	    *++p = *s;
+	} while (*++s);
+
+	if ((p == start) || (*p != '/')) {  /* not a trailing slash */
+	    ++p;                            /* so keep last character */
+	}
+	*p = 0;
+
+	return start;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/bloat-o-meter
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/bloat-o-meter	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/bloat-o-meter	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+#
+# Copyright 2004 Matt Mackall <mpm at selenic.com>
+#
+# inspired by perl Bloat-O-Meter (c) 1997 by Andi Kleen
+#
+# This software may be used and distributed according to the terms
+# of the GNU General Public License, incorporated herein by reference.
+
+import sys, os, re
+
+if len(sys.argv) != 3:
+    sys.stderr.write("usage: %s file1 file2\n" % sys.argv[0])
+    sys.exit(-1)
+
+def getsizes(file):
+    sym = {}
+    for l in os.popen("nm --size-sort " + file).readlines():
+        size, type, name = l[:-1].split()
+        if type in "tTdDbB":
+            if "." in name: name = "static." + name.split(".")[0]
+            sym[name] = sym.get(name, 0) + int(size, 16)
+    for l in os.popen("readelf -S " + file).readlines():
+        x = l.split()
+        if len(x)<6 or x[1] != ".rodata": continue
+        sym[".rodata"] = int(x[5], 16)
+    return sym
+
+old = getsizes(sys.argv[1])
+new = getsizes(sys.argv[2])
+grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0
+delta, common = [], {}
+
+for a in old:
+    if a in new:
+        common[a] = 1
+
+for name in old:
+    if name not in common:
+        remove += 1
+        down += old[name]
+        delta.append((-old[name], name))
+
+for name in new:
+    if name not in common:
+        add += 1
+        up += new[name]
+        delta.append((new[name], name))
+
+for name in common:
+        d = new.get(name, 0) - old.get(name, 0)
+        if d>0: grow, up = grow+1, up+d
+        if d<0: shrink, down = shrink+1, down-d
+        delta.append((d, name))
+
+delta.sort()
+delta.reverse()
+
+print "%-48s %7s %7s %+7s" % ("function", "old", "new", "delta")
+for d, n in delta:
+    if d: print "%-48s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d)
+print "-"*78
+total="(add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s)%%sTotal: %s bytes"\
+    % (add, remove, grow, shrink, up, -down, up-down)
+print total % (" "*(80-len(total)))


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/bloat-o-meter
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/checkhelp.awk
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/checkhelp.awk	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/checkhelp.awk	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,40 @@
+#!/usr/bin/awk -f
+# AWK script to check for missing help entries for config options
+#
+# Copyright (C) 2006 Bernhard Fischer
+# 
+# This file is distributed under the terms and conditions of the
+# MIT/X public licenses. See http://opensource.org/licenses/mit-license.html
+# and notice http://www.gnu.org/licenses/license-list.html#X11License
+
+
+/^choice/ { is_choice = 1; }
+/^endchoice/ { is_choice = 0; }
+/^config/ {
+	pos++;
+	conf[pos] = $2;
+	file[pos] = FILENAME;
+	if (is_choice) {
+		help[pos] = 1; # do not warn about 'choice' config entries.
+	} else {
+		help[pos] = 0;
+	}
+}
+/^[[:space:]]*help[[:space:]]*$/ {
+	help[pos] = 1;
+}
+/^[[:space:]]*bool[[:space:]]*$/ {
+	help[pos] = 1; # ignore options which are not selectable
+}
+BEGIN {
+	pos = -1;
+	is_choice = 0;
+}
+END {
+	for (i = 0; i < pos; i++) {
+#	printf("%s: help for #%i '%s' == %i\n", file[i], i, conf[i], help[i]);
+		if (help[i] == 0) {
+			printf("%s: No helptext for '%s'\n", file[i], conf[i]);
+		}
+	}
+}


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/checkhelp.awk
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/Kconfig-language.txt
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/Kconfig-language.txt	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/Kconfig-language.txt	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,255 @@
+Introduction
+------------
+
+The configuration database is collection of configuration options
+organized in a tree structure:
+
+	+- Code maturity level options
+	|  +- Prompt for development and/or incomplete code/drivers
+	+- General setup
+	|  +- Networking support
+	|  +- System V IPC
+	|  +- BSD Process Accounting
+	|  +- Sysctl support
+	+- Loadable module support
+	|  +- Enable loadable module support
+	|     +- Set version information on all module symbols
+	|     +- Kernel module loader
+	+- ...
+
+Every entry has its own dependencies. These dependencies are used
+to determine the visible of an entry. Any child entry is only
+visible if its parent entry is also visible.
+
+Menu entries
+------------
+
+Most entries define a config option, all other entries help to organize
+them. A single configuration option is defined like this:
+
+config MODVERSIONS
+	bool "Set version information on all module symbols"
+	depends MODULES
+	help
+	  Usually, modules have to be recompiled whenever you switch to a new
+	  kernel.  ...
+
+Every line starts with a key word and can be followed by multiple
+arguments.  "config" starts a new config entry. The following lines
+define attributes for this config option. Attributes can be the type of
+the config option, input prompt, dependencies, help text and default
+values. A config option can be defined multiple times with the same
+name, but every definition can have only a single input prompt and the
+type must not conflict.
+
+Menu attributes
+---------------
+
+A menu entry can have a number of attributes. Not all of them are
+applicable everywhere (see syntax).
+
+- type definition: "bool"/"tristate"/"string"/"hex"/"integer"
+  Every config option must have a type. There are only two basic types:
+  tristate and string, the other types base on these two. The type
+  definition optionally accepts an input prompt, so these two examples
+  are equivalent:
+
+	bool "Networking support"
+  and
+	bool
+	prompt "Networking support"
+
+- input prompt: "prompt" <prompt> ["if" <expr>]
+  Every menu entry can have at most one prompt, which is used to display
+  to the user. Optionally dependencies only for this prompt can be added
+  with "if".
+
+- default value: "default" <symbol> ["if" <expr>]
+  A config option can have any number of default values. If multiple
+  default values are visible, only the first defined one is active.
+  Default values are not limited to the menu entry, where they are
+  defined, this means the default can be defined somewhere else or be
+  overridden by an earlier definition.
+  The default value is only assigned to the config symbol if no other
+  value was set by the user (via the input prompt above). If an input
+  prompt is visible the default value is presented to the user and can
+  be overridden by him.
+  Optionally dependencies only for this default value can be added with
+  "if".
+
+- dependencies: "depends on"/"requires" <expr>
+  This defines a dependency for this menu entry. If multiple
+  dependencies are defined they are connected with '&&'. Dependencies
+  are applied to all other options within this menu entry (which also
+  accept "if" expression), so these two examples are equivalent:
+
+	bool "foo" if BAR
+	default y if BAR
+  and
+	depends on BAR
+	bool "foo"
+	default y
+
+- help text: "help"
+  This defines a help text. The end of the help text is determined by
+  the level indentation, this means it ends at the first line which has
+  a smaller indentation than the first line of the help text.
+
+
+Menu dependencies
+-----------------
+
+Dependencies define the visibility of a menu entry and can also reduce
+the input range of tristate symbols. The tristate logic used in the
+expressions uses one more state than normal boolean logic to express the
+module state. Dependency expressions have the following syntax:
+
+<expr> ::= <symbol>                             (1)
+           <symbol> '=' <symbol>                (2)
+           <symbol> '!=' <symbol>               (3)
+           '(' <expr> ')'                       (4)
+           '!' <expr>                           (5)
+           <expr> '||' <expr>                   (6)
+           <expr> '&&' <expr>                   (7)
+
+Expressions are listed in decreasing order of precedence.
+
+(1) Convert the symbol into an expression. Boolean and tristate symbols
+    are simply converted into the respective expression values. All
+    other symbol types result in 'n'.
+(2) If the values of both symbols are equal, it returns 'y',
+    otherwise 'n'.
+(3) If the values of both symbols are equal, it returns 'n',
+    otherwise 'y'.
+(4) Returns the value of the expression. Used to override precedence.
+(5) Returns the result of (2-/expr/).
+(6) Returns the result of min(/expr/, /expr/).
+(7) Returns the result of max(/expr/, /expr/).
+
+An expression can have a value of 'n', 'm' or 'y' (or 0, 1, 2
+respectively for calculations). A menu entry becomes visible when it's
+expression evaluates to 'm' or 'y'.
+
+There are two type of symbols: constant and nonconstant symbols.
+Nonconstant symbols are the most common ones and are defined with the
+'config' statement. Nonconstant symbols consist entirely of alphanumeric
+characters or underscores.
+Constant symbols are only part of expressions. Constant symbols are
+always surrounded by single or double quotes. Within the quote any
+other character is allowed and the quotes can be escaped using '\'.
+
+Menu structure
+--------------
+
+The position of a menu entry in the tree is determined in two ways. First
+it can be specified explicitely:
+
+menu "Network device support"
+	depends NET
+
+config NETDEVICES
+	...
+
+endmenu
+
+All entries within the "menu" ... "endmenu" block become a submenu of
+"Network device support". All subentries inherit the dependencies from
+the menu entry, e.g. this means the dependency "NET" is added to the
+dependency list of the config option NETDEVICES.
+
+The other way to generate the menu structure is done by analyzing the
+dependencies. If a menu entry somehow depends on the previous entry, it
+can be made a submenu of it. First the the previous (parent) symbol must
+be part of the dependency list and then one of these two condititions
+must be true:
+- the child entry must become invisible, if the parent is set to 'n'
+- the child entry must only be visible, if the parent is visible
+
+config MODULES
+	bool "Enable loadable module support"
+
+config MODVERSIONS
+	bool "Set version information on all module symbols"
+	depends MODULES
+
+comment "module support disabled"
+	depends !MODULES
+
+MODVERSIONS directly depends on MODULES, this means it's only visible if
+MODULES is different from 'n'. The comment on the other hand is always
+visible when MODULES it's visible (the (empty) dependency of MODULES is
+also part of the comment dependencies).
+
+
+Kconfig syntax
+--------------
+
+The configuration file describes a series of menu entries, where every
+line starts with a keyword (except help texts). The following keywords
+end a menu entry:
+- config
+- choice/endchoice
+- comment
+- menu/endmenu
+- if/endif
+- source
+The first four also start the definition of a menu entry.
+
+config:
+
+	"config" <symbol>
+	<config options>
+
+This defines a config symbol <symbol> and accepts any of above
+attributes as options.
+
+choices:
+
+	"choice"
+	<choice options>
+	<choice block>
+	"endchoice"
+
+This defines a choice group and accepts any of above attributes as
+options. A choice can only be of type bool or tristate, while a boolean
+choice only allows a single config entry to be selected, a tristate
+choice also allows any number of config entries to be set to 'm'. This
+can be used if multiple drivers for a single hardware exists and only a
+single driver can be compiled/loaded into the kernel, but all drivers
+can be compiled as modules.
+A choice accepts another option "optional", which allows to set the
+choice to 'n' and no entry needs to be selected.
+
+comment:
+
+	"comment" <prompt>
+	<comment options>
+
+This defines a comment which is displayed to the user during the
+configuration process and is also echoed to the output files. The only
+possible options are dependencies.
+
+menu:
+
+	"menu" <prompt>
+	<menu options>
+	<menu block>
+	"endmenu"
+
+This defines a menu block, see "Menu structure" above for more
+information. The only possible options are dependencies.
+
+if:
+
+	"if" <expr>
+	<if block>
+	"endif"
+
+This defines an if block. The dependency expression <expr> is appended
+to all enclosed menu entries.
+
+source:
+
+	"source" <prompt>
+
+This reads the specified configuration file. This file is always parsed.

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,122 @@
+# Makefile for BusyBox
+#
+# Copyright (C) 2002 Erik Andersen <andersen at codepoet.org>
+
+top_srcdir=../..
+top_builddir=../..
+srcdir=$(top_srcdir)/scripts/config
+include $(top_srcdir)/Rules.mak
+
+all: ncurses conf mconf
+
+ifeq ($(shell uname),SunOS)
+LIBS = -lcurses
+else
+LIBS = -lncurses
+endif
+ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h))
+	HOSTNCURSES += -I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"
+else
+ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h))
+	HOSTNCURSES += -I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"
+else
+ifeq (/usr/local/include/ncurses/ncurses.h, $(wildcard /usr/local/include/ncurses/ncurses.h))
+	HOSTCFLAGS += -I/usr/local/include/ncurses -DCURSES_LOC="<ncurses.h>"
+else
+ifeq (/usr/local/include/ncurses/curses.h, $(wildcard /usr/local/include/ncurses/curses.h))
+	HOSTCFLAGS += -I/usr/local/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"
+else
+ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h))
+	HOSTNCURSES += -DCURSES_LOC="<ncurses.h>"
+else
+	HOSTNCURSES += -DCURSES_LOC="<curses.h>"
+endif
+endif
+endif
+endif
+endif
+
+CONF_SRC     = conf.c
+MCONF_SRC    = mconf.c
+LXD_SRC      = lxdialog/checklist.c lxdialog/menubox.c lxdialog/textbox.c \
+               lxdialog/yesno.c lxdialog/inputbox.c lxdialog/util.c \
+               lxdialog/msgbox.c
+
+SHARED_SRC   = zconf.tab.c
+SHARED_DEPS := $(srcdir)/lkc.h $(srcdir)/lkc_proto.h \
+               lkc_defs.h $(srcdir)/expr.h zconf.tab.h
+CONF_OBJS    = $(patsubst %.c,%.o, $(CONF_SRC))
+MCONF_OBJS   = $(patsubst %.c,%.o, $(MCONF_SRC) $(LXD_SRC))
+SHARED_OBJS  = $(patsubst %.c,%.o, $(SHARED_SRC))
+
+conf: $(CONF_OBJS) $(SHARED_OBJS)
+	$(SECHO) "  "HOSTCC $@ ; true
+	$(Q)$(HOSTCC) $(NATIVE_LDFLAGS) $^ -o $@
+
+mconf: $(MCONF_OBJS) $(SHARED_OBJS)
+	$(SECHO) "  "HOSTCC $@ ; true
+	$(Q)$(HOSTCC) $(NATIVE_LDFLAGS) $^ -o $@ $(LIBS)
+
+$(CONF_OBJS): %.o : $(srcdir)/%.c $(SHARED_DEPS)
+	$(compile.h) -I.
+
+$(MCONF_OBJS): %.o : $(srcdir)/%.c $(SHARED_DEPS)
+	@[ -d $(@D) ] || mkdir $(@D)
+	$(compile.h) $(HOSTNCURSES) -I.
+
+lkc_defs.h: $(srcdir)/lkc_proto.h
+	@$(SED) < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/'
+
+###
+# The following requires flex/bison
+# By default we use the _shipped versions, uncomment the
+# following line if you are modifying the flex/bison src.
+#LKC_GENPARSER := 1
+
+ifdef LKC_GENPARSER
+
+%.tab.c %.tab.h: $(srcdir)/%.y
+	bison -t -d -v -b $* -p $(notdir $*) $<
+
+lex.%.c: $(srcdir)/%.l
+	flex -P$(notdir $*) -o$@ $<
+else
+
+lex.zconf.o: lex.zconf.c $(SHARED_DEPS)
+	$(compile.h) -I$(srcdir)
+
+lex.zconf.c: $(srcdir)/lex.zconf.c_shipped
+	$(Q)cp $< $@
+
+zconf.tab.c: $(srcdir)/zconf.tab.c_shipped
+	$(Q)cp $< $@
+
+zconf.tab.h: $(srcdir)/zconf.tab.h_shipped
+	$(Q)cp $< $@
+endif
+
+zconf.tab.o: zconf.tab.c lex.zconf.c $(srcdir)/confdata.c $(srcdir)/expr.c \
+             $(srcdir)/symbol.c $(srcdir)/menu.c $(SHARED_DEPS)
+	$(compile.h) -I$(srcdir) -I.
+
+.PHONY: ncurses
+
+ncurses:
+	@echo "main() {}" > lxtemp.c
+	@if $(HOSTCC) lxtemp.c $(LIBS) ; then \
+		rm -f lxtemp.c a.out; \
+	else \
+		rm -f lxtemp.c; \
+		echo -e "\007" ;\
+		echo ">> Unable to find the Ncurses libraries." ;\
+		echo ">>" ;\
+		echo ">> You must have Ncurses installed in order" ;\
+		echo ">> to use 'make menuconfig'" ;\
+		echo ;\
+		exit 1 ;\
+	fi
+
+clean:
+	rm -f *.o *~ core $(TARGETS) $(MCONF_OBJS) $(CONF_OBJS) \
+		conf mconf zconf.tab.c zconf.tab.h lex.zconf.c lkc_defs.h
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/conf.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/conf.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/conf.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,583 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/stat.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+static void conf(struct menu *menu);
+static void check_conf(struct menu *menu);
+
+enum {
+	ask_all,
+	ask_new,
+	ask_silent,
+	set_default,
+	set_yes,
+	set_mod,
+	set_no,
+	set_random
+} input_mode = ask_all;
+char *defconfig_file;
+
+static int indent = 1;
+static int valid_stdin = 1;
+static int conf_cnt;
+static char line[128];
+static struct menu *rootEntry;
+
+static char nohelp_text[] = "Sorry, no help available for this option yet.\n";
+
+static void strip(char *str)
+{
+	char *p = str;
+	int l;
+
+	while ((isspace(*p)))
+		p++;
+	l = strlen(p);
+	if (p != str)
+		memmove(str, p, l + 1);
+	if (!l)
+		return;
+	p = str + l - 1;
+	while ((isspace(*p)))
+		*p-- = 0;
+}
+
+static void check_stdin(void)
+{
+	if (!valid_stdin && input_mode == ask_silent) {
+		printf("aborted!\n\n");
+		printf("Console input/output is redirected. ");
+		printf("Run 'make oldconfig' to update configuration.\n\n");
+		exit(1);
+	}
+}
+
+static void conf_askvalue(struct symbol *sym, const char *def)
+{
+	enum symbol_type type = sym_get_type(sym);
+	tristate val;
+
+	if (!sym_has_value(sym))
+		printf("(NEW) ");
+
+	line[0] = '\n';
+	line[1] = 0;
+
+	if (!sym_is_changable(sym)) {
+		printf("%s\n", def);
+		line[0] = '\n';
+		line[1] = 0;
+		return;
+	}
+
+	switch (input_mode) {
+	case ask_new:
+	case ask_silent:
+		if (sym_has_value(sym)) {
+			printf("%s\n", def);
+			return;
+		}
+		check_stdin();
+	case ask_all:
+		fflush(stdout);
+		fgets(line, 128, stdin);
+		return;
+	case set_default:
+		printf("%s\n", def);
+		return;
+	default:
+		break;
+	}
+
+	switch (type) {
+	case S_INT:
+	case S_HEX:
+	case S_STRING:
+		printf("%s\n", def);
+		return;
+	default:
+		;
+	}
+	switch (input_mode) {
+	case set_yes:
+		if (sym_tristate_within_range(sym, yes)) {
+			line[0] = 'y';
+			line[1] = '\n';
+			line[2] = 0;
+			break;
+		}
+	case set_mod:
+		if (type == S_TRISTATE) {
+			if (sym_tristate_within_range(sym, mod)) {
+				line[0] = 'm';
+				line[1] = '\n';
+				line[2] = 0;
+				break;
+			}
+		} else {
+			if (sym_tristate_within_range(sym, yes)) {
+				line[0] = 'y';
+				line[1] = '\n';
+				line[2] = 0;
+				break;
+			}
+		}
+	case set_no:
+		if (sym_tristate_within_range(sym, no)) {
+			line[0] = 'n';
+			line[1] = '\n';
+			line[2] = 0;
+			break;
+		}
+	case set_random:
+		do {
+			val = (tristate)(random() % 3);
+		} while (!sym_tristate_within_range(sym, val));
+		switch (val) {
+		case no: line[0] = 'n'; break;
+		case mod: line[0] = 'm'; break;
+		case yes: line[0] = 'y'; break;
+		}
+		line[1] = '\n';
+		line[2] = 0;
+		break;
+	default:
+		break;
+	}
+	printf("%s", line);
+}
+
+int conf_string(struct menu *menu)
+{
+	struct symbol *sym = menu->sym;
+	const char *def, *help;
+
+	while (1) {
+		printf("%*s%s ", indent - 1, "", menu->prompt->text);
+		printf("(%s) ", sym->name);
+		def = sym_get_string_value(sym);
+		if (sym_get_string_value(sym))
+			printf("[%s] ", def);
+		conf_askvalue(sym, def);
+		switch (line[0]) {
+		case '\n':
+			break;
+		case '?':
+			/* print help */
+			if (line[1] == '\n') {
+				help = nohelp_text;
+				if (menu->sym->help)
+					help = menu->sym->help;
+				printf("\n%s\n", menu->sym->help);
+				def = NULL;
+				break;
+			}
+		default:
+			line[strlen(line)-1] = 0;
+			def = line;
+		}
+		if (def && sym_set_string_value(sym, def))
+			return 0;
+	}
+}
+
+static int conf_sym(struct menu *menu)
+{
+	struct symbol *sym = menu->sym;
+	int type;
+	tristate oldval, newval;
+	const char *help;
+
+	while (1) {
+		printf("%*s%s ", indent - 1, "", menu->prompt->text);
+		if (sym->name)
+			printf("(%s) ", sym->name);
+		type = sym_get_type(sym);
+		putchar('[');
+		oldval = sym_get_tristate_value(sym);
+		switch (oldval) {
+		case no:
+			putchar('N');
+			break;
+		case mod:
+			putchar('M');
+			break;
+		case yes:
+			putchar('Y');
+			break;
+		}
+		if (oldval != no && sym_tristate_within_range(sym, no))
+			printf("/n");
+		if (oldval != mod && sym_tristate_within_range(sym, mod))
+			printf("/m");
+		if (oldval != yes && sym_tristate_within_range(sym, yes))
+			printf("/y");
+		if (sym->help)
+			printf("/?");
+		printf("] ");
+		conf_askvalue(sym, sym_get_string_value(sym));
+		strip(line);
+
+		switch (line[0]) {
+		case 'n':
+		case 'N':
+			newval = no;
+			if (!line[1] || !strcmp(&line[1], "o"))
+				break;
+			continue;
+		case 'm':
+		case 'M':
+			newval = mod;
+			if (!line[1])
+				break;
+			continue;
+		case 'y':
+		case 'Y':
+			newval = yes;
+			if (!line[1] || !strcmp(&line[1], "es"))
+				break;
+			continue;
+		case 0:
+			newval = oldval;
+			break;
+		case '?':
+			goto help;
+		default:
+			continue;
+		}
+		if (sym_set_tristate_value(sym, newval))
+			return 0;
+help:
+		help = nohelp_text;
+		if (sym->help)
+			help = sym->help;
+		printf("\n%s\n", help);
+	}
+}
+
+static int conf_choice(struct menu *menu)
+{
+	struct symbol *sym, *def_sym;
+	struct menu *child;
+	int type;
+	bool is_new;
+
+	sym = menu->sym;
+	type = sym_get_type(sym);
+	is_new = !sym_has_value(sym);
+	if (sym_is_changable(sym)) {
+		conf_sym(menu);
+		sym_calc_value(sym);
+		switch (sym_get_tristate_value(sym)) {
+		case no:
+			return 1;
+		case mod:
+			return 0;
+		case yes:
+			break;
+		}
+	} else {
+		switch (sym_get_tristate_value(sym)) {
+		case no:
+			return 1;
+		case mod:
+			printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
+			return 0;
+		case yes:
+			break;
+		}
+	}
+
+	while (1) {
+		int cnt, def;
+
+		printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
+		def_sym = sym_get_choice_value(sym);
+		cnt = def = 0;
+		line[0] = '0';
+		line[1] = 0;
+		for (child = menu->list; child; child = child->next) {
+			if (!menu_is_visible(child))
+				continue;
+			if (!child->sym) {
+				printf("%*c %s\n", indent, '*', menu_get_prompt(child));
+				continue;
+			}
+			cnt++;
+			if (child->sym == def_sym) {
+				def = cnt;
+				printf("%*c", indent, '>');
+			} else
+				printf("%*c", indent, ' ');
+			printf(" %d. %s", cnt, menu_get_prompt(child));
+			if (child->sym->name)
+				printf(" (%s)", child->sym->name);
+			if (!sym_has_value(child->sym))
+				printf(" (NEW)");
+			printf("\n");
+		}
+		printf("%*schoice", indent - 1, "");
+		if (cnt == 1) {
+			printf("[1]: 1\n");
+			goto conf_childs;
+		}
+		printf("[1-%d", cnt);
+		if (sym->help)
+			printf("?");
+		printf("]: ");
+		switch (input_mode) {
+		case ask_new:
+		case ask_silent:
+			if (!is_new) {
+				cnt = def;
+				printf("%d\n", cnt);
+				break;
+			}
+			check_stdin();
+		case ask_all:
+			fflush(stdout);
+			fgets(line, 128, stdin);
+			strip(line);
+			if (line[0] == '?') {
+				printf("\n%s\n", menu->sym->help ?
+					menu->sym->help : nohelp_text);
+				continue;
+			}
+			if (!line[0])
+				cnt = def;
+			else if (isdigit(line[0]))
+				cnt = atoi(line);
+			else
+				continue;
+			break;
+		case set_random:
+			def = (random() % cnt) + 1;
+		case set_default:
+		case set_yes:
+		case set_mod:
+		case set_no:
+			cnt = def;
+			printf("%d\n", cnt);
+			break;
+		}
+
+	conf_childs:
+		for (child = menu->list; child; child = child->next) {
+			if (!child->sym || !menu_is_visible(child))
+				continue;
+			if (!--cnt)
+				break;
+		}
+		if (!child)
+			continue;
+		if (line[strlen(line) - 1] == '?') {
+			printf("\n%s\n", child->sym->help ?
+				child->sym->help : nohelp_text);
+			continue;
+		}
+		sym_set_choice_value(sym, child->sym);
+		if (child->list) {
+			indent += 2;
+			conf(child->list);
+			indent -= 2;
+		}
+		return 1;
+	}
+}
+
+static void conf(struct menu *menu)
+{
+	struct symbol *sym;
+	struct property *prop;
+	struct menu *child;
+
+	if (!menu_is_visible(menu))
+		return;
+
+	sym = menu->sym;
+	prop = menu->prompt;
+	if (prop) {
+		const char *prompt;
+
+		switch (prop->type) {
+		case P_MENU:
+			if (input_mode == ask_silent && rootEntry != menu) {
+				check_conf(menu);
+				return;
+			}
+		case P_COMMENT:
+			prompt = menu_get_prompt(menu);
+			if (prompt)
+				printf("%*c\n%*c %s\n%*c\n",
+					indent, '*',
+					indent, '*', prompt,
+					indent, '*');
+		default:
+			;
+		}
+	}
+
+	if (!sym)
+		goto conf_childs;
+
+	if (sym_is_choice(sym)) {
+		conf_choice(menu);
+		if (sym->curr.tri != mod)
+			return;
+		goto conf_childs;
+	}
+
+	switch (sym->type) {
+	case S_INT:
+	case S_HEX:
+	case S_STRING:
+		conf_string(menu);
+		break;
+	default:
+		conf_sym(menu);
+		break;
+	}
+
+conf_childs:
+	if (sym)
+		indent += 2;
+	for (child = menu->list; child; child = child->next)
+		conf(child);
+	if (sym)
+		indent -= 2;
+}
+
+static void check_conf(struct menu *menu)
+{
+	struct symbol *sym;
+	struct menu *child;
+
+	if (!menu_is_visible(menu))
+		return;
+
+	sym = menu->sym;
+	if (sym) {
+		if (sym_is_changable(sym) && !sym_has_value(sym)) {
+			if (!conf_cnt++)
+				printf("*\n* Restart config...\n*\n");
+			rootEntry = menu_get_parent_menu(menu);
+			conf(rootEntry);
+		}
+		if (sym_is_choice(sym) && sym_get_tristate_value(sym) != mod)
+			return;
+	}
+
+	for (child = menu->list; child; child = child->next)
+		check_conf(child);
+}
+
+int main(int ac, char **av)
+{
+	int i = 1;
+	const char *name;
+	struct stat tmpstat;
+
+	if (ac > i && av[i][0] == '-') {
+		switch (av[i++][1]) {
+		case 'o':
+			input_mode = ask_new;
+			break;
+		case 's':
+			input_mode = ask_silent;
+			valid_stdin = isatty(0) && isatty(1) && isatty(2);
+			break;
+		case 'd':
+			input_mode = set_default;
+			break;
+		case 'D':
+			input_mode = set_default;
+			defconfig_file = av[i++];
+			if (!defconfig_file) {
+				printf("%s: No default config file specified\n",
+					av[0]);
+				exit(1);
+			}
+			break;
+		case 'n':
+			input_mode = set_no;
+			break;
+		case 'm':
+			input_mode = set_mod;
+			break;
+		case 'y':
+			input_mode = set_yes;
+			break;
+		case 'r':
+			input_mode = set_random;
+			srandom(time(NULL));
+			break;
+		case 'h':
+		case '?':
+			printf("%s [-o|-s] config\n", av[0]);
+			exit(0);
+		}
+	}
+	name = av[i];
+	if (!name) {
+		printf("%s: configuration file missing\n", av[0]);
+	}
+	conf_parse(name);
+	//zconfdump(stdout);
+	switch (input_mode) {
+	case set_default:
+		if (!defconfig_file)
+			defconfig_file = conf_get_default_confname();
+		if (conf_read(defconfig_file)) {
+			printf("***\n"
+				"*** Can't find default configuration \"%s\"!\n"
+				"***\n", defconfig_file);
+			exit(1);
+		}
+		break;
+	case ask_silent:
+		if (stat(".config", &tmpstat)) {
+			printf("***\n"
+				"*** You have not yet configured BusyBox!\n"
+				"***\n"
+				"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
+				"*** \"make menuconfig\" or \"make config\").\n"
+				"***\n");
+			exit(1);
+		}
+	case ask_all:
+	case ask_new:
+		conf_read(NULL);
+		break;
+	default:
+		break;
+	}
+
+	if (input_mode != ask_silent) {
+		rootEntry = &rootmenu;
+		conf(&rootmenu);
+		if (input_mode == ask_all) {
+			input_mode = ask_silent;
+			valid_stdin = 1;
+		}
+	}
+	do {
+		conf_cnt = 0;
+		check_conf(&rootmenu);
+	} while (conf_cnt);
+	if (conf_write(NULL)) {
+		fprintf(stderr, "\n*** Error during writing of the BusyBox configuration.\n\n");
+		return 1;
+	}
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/confdata.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/confdata.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/confdata.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <sys/stat.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+const char conf_def_filename[] = ".config";
+
+const char conf_defname[] = "defconfig";
+
+const char *conf_confnames[] = {
+	".config",
+	conf_defname,
+	NULL,
+};
+
+static char *conf_expand_value(const char *in)
+{
+	struct symbol *sym;
+	const char *src;
+	static char res_value[SYMBOL_MAXLENGTH];
+	char *dst, name[SYMBOL_MAXLENGTH];
+
+	res_value[0] = 0;
+	dst = name;
+	while ((src = strchr(in, '$'))) {
+		strncat(res_value, in, src - in);
+		src++;
+		dst = name;
+		while (isalnum(*src) || *src == '_')
+			*dst++ = *src++;
+		*dst = 0;
+		sym = sym_lookup(name, 0);
+		sym_calc_value(sym);
+		strcat(res_value, sym_get_string_value(sym));
+		in = src;
+	}
+	strcat(res_value, in);
+
+	return res_value;
+}
+
+char *conf_get_default_confname(void)
+{
+	struct stat buf;
+	static char fullname[PATH_MAX+1];
+	char *env, *name;
+
+	name = conf_expand_value(conf_defname);
+	env = getenv(SRCTREE);
+	if (env) {
+		sprintf(fullname, "%s/%s", env, name);
+		if (!stat(fullname, &buf))
+			return fullname;
+	}
+	return name;
+}
+
+int conf_read(const char *name)
+{
+	FILE *in = NULL;
+	char line[1024];
+	char *p, *p2;
+	int lineno = 0;
+	struct symbol *sym;
+	struct property *prop;
+	struct expr *e;
+	int i;
+
+	if (name) {
+		in = zconf_fopen(name);
+	} else {
+		const char **names = conf_confnames;
+		while ((name = *names++)) {
+			name = conf_expand_value(name);
+			in = zconf_fopen(name);
+			if (in) {
+				printf("#\n"
+				       "# using defaults found in %s\n"
+				       "#\n", name);
+				break;
+			}
+		}
+	}
+
+	if (!in)
+		return 1;
+
+	for_all_symbols(i, sym) {
+		sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
+		sym->flags &= ~SYMBOL_VALID;
+		switch (sym->type) {
+		case S_INT:
+		case S_HEX:
+		case S_STRING:
+			free(sym->user.val);
+		default:
+			sym->user.val = NULL;
+			sym->user.tri = no;
+		}
+	}
+
+	while (fgets(line, sizeof(line), in)) {
+		lineno++;
+		sym = NULL;
+		switch (line[0]) {
+		case '#':
+			if (line[1]!=' ')
+				continue;
+			p = strchr(line + 2, ' ');
+			if (!p)
+				continue;
+			*p++ = 0;
+			if (strncmp(p, "is not set", 10))
+				continue;
+			sym = sym_find(line + 2);
+			if (!sym) {
+				fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 2);
+				break;
+			}
+			switch (sym->type) {
+			case S_BOOLEAN:
+			case S_TRISTATE:
+				sym->user.tri = no;
+				sym->flags &= ~SYMBOL_NEW;
+				break;
+			default:
+				;
+			}
+			break;
+
+		case 'A' ... 'Z':
+			p = strchr(line, '=');
+			if (!p)
+				continue;
+			*p++ = 0;
+			p2 = strchr(p, '\n');
+			if (p2)
+				*p2 = 0;
+			sym = sym_find(line);
+			if (!sym) {
+				fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line);
+				break;
+			}
+			switch (sym->type) {
+			case S_TRISTATE:
+				if (p[0] == 'm') {
+					sym->user.tri = mod;
+					sym->flags &= ~SYMBOL_NEW;
+					break;
+				}
+			case S_BOOLEAN:
+				if (p[0] == 'y') {
+					sym->user.tri = yes;
+					sym->flags &= ~SYMBOL_NEW;
+					break;
+				}
+				if (p[0] == 'n') {
+					sym->user.tri = no;
+					sym->flags &= ~SYMBOL_NEW;
+					break;
+				}
+				break;
+			case S_STRING:
+				if (*p++ != '"')
+					break;
+				for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
+					if (*p2 == '"') {
+						*p2 = 0;
+						break;
+					}
+					memmove(p2, p2 + 1, strlen(p2));
+				}
+				if (!p2) {
+					fprintf(stderr, "%s:%d: invalid string found\n", name, lineno);
+					exit(1);
+				}
+			case S_INT:
+			case S_HEX:
+				if (sym_string_valid(sym, p)) {
+					sym->user.val = strdup(p);
+					sym->flags &= ~SYMBOL_NEW;
+				} else {
+					fprintf(stderr, "%s:%d: symbol value '%s' invalid for %s\n", name, lineno, p, sym->name);
+					exit(1);
+				}
+				break;
+			default:
+				;
+			}
+			break;
+		case '\n':
+			break;
+		default:
+			continue;
+		}
+		if (sym && sym_is_choice_value(sym)) {
+			struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
+			switch (sym->user.tri) {
+			case no:
+				break;
+			case mod:
+				if (cs->user.tri == yes)
+					/* warn? */;
+				break;
+			case yes:
+				if (cs->user.tri != no)
+					/* warn? */;
+				cs->user.val = sym;
+				break;
+			}
+			cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
+			cs->flags &= ~SYMBOL_NEW;
+		}
+	}
+	fclose(in);
+
+	if (modules_sym)
+		sym_calc_value(modules_sym);
+	for_all_symbols(i, sym) {
+		sym_calc_value(sym);
+		if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
+			if (sym->visible == no)
+				sym->flags |= SYMBOL_NEW;
+			switch (sym->type) {
+			case S_STRING:
+			case S_INT:
+			case S_HEX:
+				if (!sym_string_within_range(sym, sym->user.val))
+					sym->flags |= SYMBOL_NEW;
+			default:
+				break;
+			}
+		}
+		if (!sym_is_choice(sym))
+			continue;
+		prop = sym_get_choice_prop(sym);
+		for (e = prop->expr; e; e = e->left.expr)
+			if (e->right.sym->visible != no)
+				sym->flags |= e->right.sym->flags & SYMBOL_NEW;
+	}
+
+	sym_change_count = 1;
+
+	return 0;
+}
+
+struct menu *next_menu(struct menu *menu)
+{
+	if (menu->list) return menu->list;
+	do {
+		if (menu->next) {
+			menu = menu->next;
+			break;
+		}
+	} while ((menu = menu->parent));
+
+	return menu;
+}
+
+#define SYMBOL_FORCEWRITE (1<<31)
+
+int conf_write(const char *name)
+{
+	FILE *out, *out_h;
+	struct symbol *sym;
+	struct menu *menu;
+	const char *basename;
+	char dirname[128], tmpname[128], newname[128];
+	int type, l;
+	const char *str;
+
+	/* busybox`s code */
+	const char *opt_name;
+	int use_flg;
+
+	dirname[0] = 0;
+	if (name && name[0]) {
+		struct stat st;
+		char *slash;
+
+		if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
+			strcpy(dirname, name);
+			strcat(dirname, "/");
+			basename = conf_def_filename;
+		} else if ((slash = strrchr(name, '/'))) {
+			int size = slash - name + 1;
+			memcpy(dirname, name, size);
+			dirname[size] = 0;
+			if (slash[1])
+				basename = slash + 1;
+			else
+				basename = conf_def_filename;
+		} else
+			basename = name;
+	} else
+		basename = conf_def_filename;
+
+	sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid());
+	out = fopen(newname, "w");
+	if (!out)
+		return 1;
+	out_h = NULL;
+	if (!name) {
+		out_h = fopen(".tmpconfig.h", "w");
+		if (!out_h)
+			return 1;
+	}
+	fprintf(out, "#\n"
+		     "# Automatically generated make config: don't edit\n"
+		     "#\n");
+
+	/* busybox`s code */
+	if (out_h) {
+		fprintf(out_h, "#ifndef BB_CONFIG_H\n#define BB_CONFIG_H\n");
+		fprintf(out_h, "/*\n"
+			     " * Automatically generated header file: don't edit\n"
+			     " */\n\n"
+			     "/* Version Number */\n"
+			     "#define BB_VER \"%s\"\n"
+			     "#define BB_BT \"%s\"\n",
+			     getenv("VERSION"),
+			     getenv("BUILDTIME"));
+		if (getenv("EXTRA_VERSION"))
+			fprintf(out_h, "#define BB_EXTRA_VERSION \"%s\"\n",
+				     getenv("EXTRA_VERSION"));
+		fprintf(out_h, "\n");
+	}
+	/* end busybox`s code */
+
+	if (!sym_change_count)
+		sym_clear_all_valid();
+
+	/* Force write of all non-duplicate symbols. */
+
+	/* Write out everything by default. */
+	for(menu = rootmenu.list; menu; menu = next_menu(menu))
+		if (menu->sym) menu->sym->flags |= SYMBOL_FORCEWRITE;
+
+	menu = rootmenu.list;
+	while (menu) {
+		sym = menu->sym;
+		if (!sym) {
+			if (!menu_is_visible(menu))
+				goto next;
+			str = menu_get_prompt(menu);
+			fprintf(out, "\n"
+				     "#\n"
+				     "# %s\n"
+				     "#\n", str);
+			if (out_h)
+				fprintf(out_h, "\n"
+					       "/*\n"
+					       " * %s\n"
+					       " */\n", str);
+		} else if (!(sym->flags & SYMBOL_CHOICE)) {
+			sym_calc_value(sym);
+			if (!(sym->flags & SYMBOL_FORCEWRITE))
+				goto next;
+
+			sym->flags &= ~SYMBOL_FORCEWRITE;
+			type = sym->type;
+			if (type == S_TRISTATE) {
+				sym_calc_value(modules_sym);
+				if (modules_sym->curr.tri == no)
+					type = S_BOOLEAN;
+			}
+
+			/* busybox`s code */
+			opt_name = strchr(sym->name, '_');
+			if(opt_name == NULL)
+				opt_name = sym->name;
+			else
+				opt_name++;
+			use_flg = 1;
+			/* end busybox`s code */
+
+			switch (type) {
+			case S_BOOLEAN:
+			case S_TRISTATE:
+				switch (sym_get_tristate_value(sym)) {
+				case no:
+					fprintf(out, "# %s is not set\n", sym->name);
+					if (out_h)
+						fprintf(out_h, "#undef %s\n", sym->name);
+					use_flg = 0;    /* busybox`s code */
+					break;
+				case mod:
+#if 0   /* busybox`s code */
+					fprintf(out, "%s=m\n", sym->name);
+					if (out_h)
+						fprintf(out_h, "#define %s_MODULE 1\n", sym->name);
+#endif  /* busybox`s code */
+					break;
+				case yes:
+					fprintf(out, "%s=y\n", sym->name);
+					if (out_h)
+						fprintf(out_h, "#define %s 1\n", sym->name);
+					break;
+				}
+				break;
+			case S_STRING:
+				// fix me
+				str = sym_get_string_value(sym);
+				fprintf(out, "%s=\"", sym->name);
+				if (out_h)
+					fprintf(out_h, "#define %s \"", sym->name);
+				do {
+					l = strcspn(str, "\"\\");
+					if (l) {
+						fwrite(str, l, 1, out);
+						if (out_h)
+							fwrite(str, l, 1, out_h);
+					}
+					str += l;
+					while (*str == '\\' || *str == '"') {
+						fprintf(out, "\\%c", *str);
+						if (out_h)
+							fprintf(out_h, "\\%c", *str);
+						str++;
+					}
+				} while (*str);
+				fputs("\"\n", out);
+				if (out_h)
+					fputs("\"\n", out_h);
+				break;
+			case S_HEX:
+				str = sym_get_string_value(sym);
+				if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
+					fprintf(out, "%s=%s\n", sym->name, *str ? str : "0");
+					if (out_h)
+						fprintf(out_h, "#define %s 0x%s\n", sym->name, str);
+					break;
+				}
+			case S_INT:
+				str = sym_get_string_value(sym);
+				fprintf(out, "%s=%s\n", sym->name, *str ? str : "0");
+				if (out_h)
+					fprintf(out_h, "#define %s %s\n", sym->name, str);
+				break;
+			}
+			/* busybox`s code */
+			if (out_h) {
+				fprintf(out_h, "#define ENABLE_%s %d\n", opt_name, use_flg);
+				fprintf(out_h, "#define USE_%s(...)%s\n", opt_name,
+					(use_flg ? "  __VA_ARGS__" : ""));
+				fprintf(out_h, "#define SKIP_%s(...)%s\n\n", opt_name,
+					(use_flg ? "" : "  __VA_ARGS__"));
+			}
+			/* end busybox`s code */
+		}
+next:
+		menu = next_menu(menu);
+	}
+	fclose(out);
+	if (out_h) {
+		fprintf(out_h, "#endif /* BB_CONFIG_H */\n");   /* busybox`s code */
+		fclose(out_h);
+		rename(".tmpconfig.h", "include/bb_config.h");  /* busybox`s config name */
+		file_write_dep(NULL);
+	}
+	if (!name || basename != conf_def_filename) {
+		if (!name)
+			name = conf_def_filename;
+		sprintf(tmpname, "%s.old", name);
+		rename(name, tmpname);
+	}
+	sprintf(tmpname, "%s%s", dirname, basename);
+	if (rename(newname, tmpname))
+		return 1;
+
+	sym_change_count = 0;
+
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/expr.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/expr.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/expr.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1099 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+#define DEBUG_EXPR	0
+
+struct expr *expr_alloc_symbol(struct symbol *sym)
+{
+	struct expr *e = malloc(sizeof(*e));
+	memset(e, 0, sizeof(*e));
+	e->type = E_SYMBOL;
+	e->left.sym = sym;
+	return e;
+}
+
+struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
+{
+	struct expr *e = malloc(sizeof(*e));
+	memset(e, 0, sizeof(*e));
+	e->type = type;
+	e->left.expr = ce;
+	return e;
+}
+
+struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
+{
+	struct expr *e = malloc(sizeof(*e));
+	memset(e, 0, sizeof(*e));
+	e->type = type;
+	e->left.expr = e1;
+	e->right.expr = e2;
+	return e;
+}
+
+struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
+{
+	struct expr *e = malloc(sizeof(*e));
+	memset(e, 0, sizeof(*e));
+	e->type = type;
+	e->left.sym = s1;
+	e->right.sym = s2;
+	return e;
+}
+
+struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
+{
+	if (!e1)
+		return e2;
+	return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
+}
+
+struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
+{
+	if (!e1)
+		return e2;
+	return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
+}
+
+struct expr *expr_copy(struct expr *org)
+{
+	struct expr *e;
+
+	if (!org)
+		return NULL;
+
+	e = malloc(sizeof(*org));
+	memcpy(e, org, sizeof(*org));
+	switch (org->type) {
+	case E_SYMBOL:
+		e->left = org->left;
+		break;
+	case E_NOT:
+		e->left.expr = expr_copy(org->left.expr);
+		break;
+	case E_EQUAL:
+	case E_UNEQUAL:
+		e->left.sym = org->left.sym;
+		e->right.sym = org->right.sym;
+		break;
+	case E_AND:
+	case E_OR:
+	case E_CHOICE:
+		e->left.expr = expr_copy(org->left.expr);
+		e->right.expr = expr_copy(org->right.expr);
+		break;
+	default:
+		printf("can't copy type %d\n", e->type);
+		free(e);
+		e = NULL;
+		break;
+	}
+
+	return e;
+}
+
+void expr_free(struct expr *e)
+{
+	if (!e)
+		return;
+
+	switch (e->type) {
+	case E_SYMBOL:
+		break;
+	case E_NOT:
+		expr_free(e->left.expr);
+		return;
+	case E_EQUAL:
+	case E_UNEQUAL:
+		break;
+	case E_OR:
+	case E_AND:
+		expr_free(e->left.expr);
+		expr_free(e->right.expr);
+		break;
+	default:
+		printf("how to free type %d?\n", e->type);
+		break;
+	}
+	free(e);
+}
+
+static int trans_count;
+
+#define e1 (*ep1)
+#define e2 (*ep2)
+
+static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
+{
+	if (e1->type == type) {
+		__expr_eliminate_eq(type, &e1->left.expr, &e2);
+		__expr_eliminate_eq(type, &e1->right.expr, &e2);
+		return;
+	}
+	if (e2->type == type) {
+		__expr_eliminate_eq(type, &e1, &e2->left.expr);
+		__expr_eliminate_eq(type, &e1, &e2->right.expr);
+		return;
+	}
+	if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
+	    e1->left.sym == e2->left.sym && (e1->left.sym->flags & (SYMBOL_YES|SYMBOL_NO)))
+		return;
+	if (!expr_eq(e1, e2))
+		return;
+	trans_count++;
+	expr_free(e1); expr_free(e2);
+	switch (type) {
+	case E_OR:
+		e1 = expr_alloc_symbol(&symbol_no);
+		e2 = expr_alloc_symbol(&symbol_no);
+		break;
+	case E_AND:
+		e1 = expr_alloc_symbol(&symbol_yes);
+		e2 = expr_alloc_symbol(&symbol_yes);
+		break;
+	default:
+		;
+	}
+}
+
+void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
+{
+	if (!e1 || !e2)
+		return;
+	switch (e1->type) {
+	case E_OR:
+	case E_AND:
+		__expr_eliminate_eq(e1->type, ep1, ep2);
+	default:
+		;
+	}
+	if (e1->type != e2->type) switch (e2->type) {
+	case E_OR:
+	case E_AND:
+		__expr_eliminate_eq(e2->type, ep1, ep2);
+	default:
+		;
+	}
+	e1 = expr_eliminate_yn(e1);
+	e2 = expr_eliminate_yn(e2);
+}
+
+#undef e1
+#undef e2
+
+int expr_eq(struct expr *e1, struct expr *e2)
+{
+	int res, old_count;
+
+	if (e1->type != e2->type)
+		return 0;
+	switch (e1->type) {
+	case E_EQUAL:
+	case E_UNEQUAL:
+		return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
+	case E_SYMBOL:
+		return e1->left.sym == e2->left.sym;
+	case E_NOT:
+		return expr_eq(e1->left.expr, e2->left.expr);
+	case E_AND:
+	case E_OR:
+		e1 = expr_copy(e1);
+		e2 = expr_copy(e2);
+		old_count = trans_count;
+		expr_eliminate_eq(&e1, &e2);
+		res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
+		       e1->left.sym == e2->left.sym);
+		expr_free(e1);
+		expr_free(e2);
+		trans_count = old_count;
+		return res;
+	case E_CHOICE:
+	case E_RANGE:
+	case E_NONE:
+		/* panic */;
+	}
+
+	if (DEBUG_EXPR) {
+		expr_fprint(e1, stdout);
+		printf(" = ");
+		expr_fprint(e2, stdout);
+		printf(" ?\n");
+	}
+
+	return 0;
+}
+
+struct expr *expr_eliminate_yn(struct expr *e)
+{
+	struct expr *tmp;
+
+	if (e) switch (e->type) {
+	case E_AND:
+		e->left.expr = expr_eliminate_yn(e->left.expr);
+		e->right.expr = expr_eliminate_yn(e->right.expr);
+		if (e->left.expr->type == E_SYMBOL) {
+			if (e->left.expr->left.sym == &symbol_no) {
+				expr_free(e->left.expr);
+				expr_free(e->right.expr);
+				e->type = E_SYMBOL;
+				e->left.sym = &symbol_no;
+				e->right.expr = NULL;
+				return e;
+			} else if (e->left.expr->left.sym == &symbol_yes) {
+				free(e->left.expr);
+				tmp = e->right.expr;
+				*e = *(e->right.expr);
+				free(tmp);
+				return e;
+			}
+		}
+		if (e->right.expr->type == E_SYMBOL) {
+			if (e->right.expr->left.sym == &symbol_no) {
+				expr_free(e->left.expr);
+				expr_free(e->right.expr);
+				e->type = E_SYMBOL;
+				e->left.sym = &symbol_no;
+				e->right.expr = NULL;
+				return e;
+			} else if (e->right.expr->left.sym == &symbol_yes) {
+				free(e->right.expr);
+				tmp = e->left.expr;
+				*e = *(e->left.expr);
+				free(tmp);
+				return e;
+			}
+		}
+		break;
+	case E_OR:
+		e->left.expr = expr_eliminate_yn(e->left.expr);
+		e->right.expr = expr_eliminate_yn(e->right.expr);
+		if (e->left.expr->type == E_SYMBOL) {
+			if (e->left.expr->left.sym == &symbol_no) {
+				free(e->left.expr);
+				tmp = e->right.expr;
+				*e = *(e->right.expr);
+				free(tmp);
+				return e;
+			} else if (e->left.expr->left.sym == &symbol_yes) {
+				expr_free(e->left.expr);
+				expr_free(e->right.expr);
+				e->type = E_SYMBOL;
+				e->left.sym = &symbol_yes;
+				e->right.expr = NULL;
+				return e;
+			}
+		}
+		if (e->right.expr->type == E_SYMBOL) {
+			if (e->right.expr->left.sym == &symbol_no) {
+				free(e->right.expr);
+				tmp = e->left.expr;
+				*e = *(e->left.expr);
+				free(tmp);
+				return e;
+			} else if (e->right.expr->left.sym == &symbol_yes) {
+				expr_free(e->left.expr);
+				expr_free(e->right.expr);
+				e->type = E_SYMBOL;
+				e->left.sym = &symbol_yes;
+				e->right.expr = NULL;
+				return e;
+			}
+		}
+		break;
+	default:
+		;
+	}
+	return e;
+}
+
+/*
+ * bool FOO!=n => FOO
+ */
+struct expr *expr_trans_bool(struct expr *e)
+{
+	if (!e)
+		return NULL;
+	switch (e->type) {
+	case E_AND:
+	case E_OR:
+	case E_NOT:
+		e->left.expr = expr_trans_bool(e->left.expr);
+		e->right.expr = expr_trans_bool(e->right.expr);
+		break;
+	case E_UNEQUAL:
+		// FOO!=n -> FOO
+		if (e->left.sym->type == S_TRISTATE) {
+			if (e->right.sym == &symbol_no) {
+				e->type = E_SYMBOL;
+				e->right.sym = NULL;
+			}
+		}
+		break;
+	default:
+		;
+	}
+	return e;
+}
+
+/*
+ * e1 || e2 -> ?
+ */
+struct expr *expr_join_or(struct expr *e1, struct expr *e2)
+{
+	struct expr *tmp;
+	struct symbol *sym1, *sym2;
+
+	if (expr_eq(e1, e2))
+		return expr_copy(e1);
+	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
+		return NULL;
+	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
+		return NULL;
+	if (e1->type == E_NOT) {
+		tmp = e1->left.expr;
+		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
+			return NULL;
+		sym1 = tmp->left.sym;
+	} else
+		sym1 = e1->left.sym;
+	if (e2->type == E_NOT) {
+		if (e2->left.expr->type != E_SYMBOL)
+			return NULL;
+		sym2 = e2->left.expr->left.sym;
+	} else
+		sym2 = e2->left.sym;
+	if (sym1 != sym2)
+		return NULL;
+	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
+		return NULL;
+	if (sym1->type == S_TRISTATE) {
+		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
+		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
+		     (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
+			// (a='y') || (a='m') -> (a!='n')
+			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
+		}
+		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
+		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
+		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
+			// (a='y') || (a='n') -> (a!='m')
+			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
+		}
+		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
+		    ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
+		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
+			// (a='m') || (a='n') -> (a!='y')
+			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
+		}
+	}
+	if (sym1->type == S_BOOLEAN && sym1 == sym2) {
+		if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
+		    (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
+			return expr_alloc_symbol(&symbol_yes);
+	}
+
+	if (DEBUG_EXPR) {
+		printf("optimize (");
+		expr_fprint(e1, stdout);
+		printf(") || (");
+		expr_fprint(e2, stdout);
+		printf(")?\n");
+	}
+	return NULL;
+}
+
+struct expr *expr_join_and(struct expr *e1, struct expr *e2)
+{
+	struct expr *tmp;
+	struct symbol *sym1, *sym2;
+
+	if (expr_eq(e1, e2))
+		return expr_copy(e1);
+	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
+		return NULL;
+	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
+		return NULL;
+	if (e1->type == E_NOT) {
+		tmp = e1->left.expr;
+		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
+			return NULL;
+		sym1 = tmp->left.sym;
+	} else
+		sym1 = e1->left.sym;
+	if (e2->type == E_NOT) {
+		if (e2->left.expr->type != E_SYMBOL)
+			return NULL;
+		sym2 = e2->left.expr->left.sym;
+	} else
+		sym2 = e2->left.sym;
+	if (sym1 != sym2)
+		return NULL;
+	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
+		return NULL;
+
+	if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
+	    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
+		// (a) && (a='y') -> (a='y')
+		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
+
+	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
+	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
+		// (a) && (a!='n') -> (a)
+		return expr_alloc_symbol(sym1);
+
+	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
+	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
+		// (a) && (a!='m') -> (a='y')
+		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
+
+	if (sym1->type == S_TRISTATE) {
+		if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
+			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
+			sym2 = e1->right.sym;
+			if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
+				return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
+							     : expr_alloc_symbol(&symbol_no);
+		}
+		if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
+			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
+			sym2 = e2->right.sym;
+			if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
+				return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
+							     : expr_alloc_symbol(&symbol_no);
+		}
+		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
+			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
+			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
+			// (a!='y') && (a!='n') -> (a='m')
+			return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
+
+		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
+			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
+			    (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
+			// (a!='y') && (a!='m') -> (a='n')
+			return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
+
+		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
+			   ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
+			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
+			// (a!='m') && (a!='n') -> (a='m')
+			return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
+
+		if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
+		    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
+		    (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
+		    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
+			return NULL;
+	}
+
+	if (DEBUG_EXPR) {
+		printf("optimize (");
+		expr_fprint(e1, stdout);
+		printf(") && (");
+		expr_fprint(e2, stdout);
+		printf(")?\n");
+	}
+	return NULL;
+}
+
+static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+	struct expr *tmp;
+
+	if (e1->type == type) {
+		expr_eliminate_dups1(type, &e1->left.expr, &e2);
+		expr_eliminate_dups1(type, &e1->right.expr, &e2);
+		return;
+	}
+	if (e2->type == type) {
+		expr_eliminate_dups1(type, &e1, &e2->left.expr);
+		expr_eliminate_dups1(type, &e1, &e2->right.expr);
+		return;
+	}
+	if (e1 == e2)
+		return;
+
+	switch (e1->type) {
+	case E_OR: case E_AND:
+		expr_eliminate_dups1(e1->type, &e1, &e1);
+	default:
+		;
+	}
+
+	switch (type) {
+	case E_OR:
+		tmp = expr_join_or(e1, e2);
+		if (tmp) {
+			expr_free(e1); expr_free(e2);
+			e1 = expr_alloc_symbol(&symbol_no);
+			e2 = tmp;
+			trans_count++;
+		}
+		break;
+	case E_AND:
+		tmp = expr_join_and(e1, e2);
+		if (tmp) {
+			expr_free(e1); expr_free(e2);
+			e1 = expr_alloc_symbol(&symbol_yes);
+			e2 = tmp;
+			trans_count++;
+		}
+		break;
+	default:
+		;
+	}
+#undef e1
+#undef e2
+}
+
+static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+	struct expr *tmp, *tmp1, *tmp2;
+
+	if (e1->type == type) {
+		expr_eliminate_dups2(type, &e1->left.expr, &e2);
+		expr_eliminate_dups2(type, &e1->right.expr, &e2);
+		return;
+	}
+	if (e2->type == type) {
+		expr_eliminate_dups2(type, &e1, &e2->left.expr);
+		expr_eliminate_dups2(type, &e1, &e2->right.expr);
+	}
+	if (e1 == e2)
+		return;
+
+	switch (e1->type) {
+	case E_OR:
+		expr_eliminate_dups2(e1->type, &e1, &e1);
+		// (FOO || BAR) && (!FOO && !BAR) -> n
+		tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
+		tmp2 = expr_copy(e2);
+		tmp = expr_extract_eq_and(&tmp1, &tmp2);
+		if (expr_is_yes(tmp1)) {
+			expr_free(e1);
+			e1 = expr_alloc_symbol(&symbol_no);
+			trans_count++;
+		}
+		expr_free(tmp2);
+		expr_free(tmp1);
+		expr_free(tmp);
+		break;
+	case E_AND:
+		expr_eliminate_dups2(e1->type, &e1, &e1);
+		// (FOO && BAR) || (!FOO || !BAR) -> y
+		tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
+		tmp2 = expr_copy(e2);
+		tmp = expr_extract_eq_or(&tmp1, &tmp2);
+		if (expr_is_no(tmp1)) {
+			expr_free(e1);
+			e1 = expr_alloc_symbol(&symbol_yes);
+			trans_count++;
+		}
+		expr_free(tmp2);
+		expr_free(tmp1);
+		expr_free(tmp);
+		break;
+	default:
+		;
+	}
+#undef e1
+#undef e2
+}
+
+struct expr *expr_eliminate_dups(struct expr *e)
+{
+	int oldcount;
+	if (!e)
+		return e;
+
+	oldcount = trans_count;
+	while (1) {
+		trans_count = 0;
+		switch (e->type) {
+		case E_OR: case E_AND:
+			expr_eliminate_dups1(e->type, &e, &e);
+			expr_eliminate_dups2(e->type, &e, &e);
+		default:
+			;
+		}
+		if (!trans_count)
+			break;
+		e = expr_eliminate_yn(e);
+	}
+	trans_count = oldcount;
+	return e;
+}
+
+struct expr *expr_transform(struct expr *e)
+{
+	struct expr *tmp;
+
+	if (!e)
+		return NULL;
+	switch (e->type) {
+	case E_EQUAL:
+	case E_UNEQUAL:
+	case E_SYMBOL:
+	case E_CHOICE:
+		break;
+	default:
+		e->left.expr = expr_transform(e->left.expr);
+		e->right.expr = expr_transform(e->right.expr);
+	}
+
+	switch (e->type) {
+	case E_EQUAL:
+		if (e->left.sym->type != S_BOOLEAN)
+			break;
+		if (e->right.sym == &symbol_no) {
+			e->type = E_NOT;
+			e->left.expr = expr_alloc_symbol(e->left.sym);
+			e->right.sym = NULL;
+			break;
+		}
+		if (e->right.sym == &symbol_mod) {
+			printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
+			e->type = E_SYMBOL;
+			e->left.sym = &symbol_no;
+			e->right.sym = NULL;
+			break;
+		}
+		if (e->right.sym == &symbol_yes) {
+			e->type = E_SYMBOL;
+			e->right.sym = NULL;
+			break;
+		}
+		break;
+	case E_UNEQUAL:
+		if (e->left.sym->type != S_BOOLEAN)
+			break;
+		if (e->right.sym == &symbol_no) {
+			e->type = E_SYMBOL;
+			e->right.sym = NULL;
+			break;
+		}
+		if (e->right.sym == &symbol_mod) {
+			printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
+			e->type = E_SYMBOL;
+			e->left.sym = &symbol_yes;
+			e->right.sym = NULL;
+			break;
+		}
+		if (e->right.sym == &symbol_yes) {
+			e->type = E_NOT;
+			e->left.expr = expr_alloc_symbol(e->left.sym);
+			e->right.sym = NULL;
+			break;
+		}
+		break;
+	case E_NOT:
+		switch (e->left.expr->type) {
+		case E_NOT:
+			// !!a -> a
+			tmp = e->left.expr->left.expr;
+			free(e->left.expr);
+			free(e);
+			e = tmp;
+			e = expr_transform(e);
+			break;
+		case E_EQUAL:
+		case E_UNEQUAL:
+			// !a='x' -> a!='x'
+			tmp = e->left.expr;
+			free(e);
+			e = tmp;
+			e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
+			break;
+		case E_OR:
+			// !(a || b) -> !a && !b
+			tmp = e->left.expr;
+			e->type = E_AND;
+			e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
+			tmp->type = E_NOT;
+			tmp->right.expr = NULL;
+			e = expr_transform(e);
+			break;
+		case E_AND:
+			// !(a && b) -> !a || !b
+			tmp = e->left.expr;
+			e->type = E_OR;
+			e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
+			tmp->type = E_NOT;
+			tmp->right.expr = NULL;
+			e = expr_transform(e);
+			break;
+		case E_SYMBOL:
+			if (e->left.expr->left.sym == &symbol_yes) {
+				// !'y' -> 'n'
+				tmp = e->left.expr;
+				free(e);
+				e = tmp;
+				e->type = E_SYMBOL;
+				e->left.sym = &symbol_no;
+				break;
+			}
+			if (e->left.expr->left.sym == &symbol_mod) {
+				// !'m' -> 'm'
+				tmp = e->left.expr;
+				free(e);
+				e = tmp;
+				e->type = E_SYMBOL;
+				e->left.sym = &symbol_mod;
+				break;
+			}
+			if (e->left.expr->left.sym == &symbol_no) {
+				// !'n' -> 'y'
+				tmp = e->left.expr;
+				free(e);
+				e = tmp;
+				e->type = E_SYMBOL;
+				e->left.sym = &symbol_yes;
+				break;
+			}
+			break;
+		default:
+			;
+		}
+		break;
+	default:
+		;
+	}
+	return e;
+}
+
+int expr_contains_symbol(struct expr *dep, struct symbol *sym)
+{
+	if (!dep)
+		return 0;
+
+	switch (dep->type) {
+	case E_AND:
+	case E_OR:
+		return expr_contains_symbol(dep->left.expr, sym) ||
+		       expr_contains_symbol(dep->right.expr, sym);
+	case E_SYMBOL:
+		return dep->left.sym == sym;
+	case E_EQUAL:
+	case E_UNEQUAL:
+		return dep->left.sym == sym ||
+		       dep->right.sym == sym;
+	case E_NOT:
+		return expr_contains_symbol(dep->left.expr, sym);
+	default:
+		;
+	}
+	return 0;
+}
+
+bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
+{
+	if (!dep)
+		return false;
+
+	switch (dep->type) {
+	case E_AND:
+		return expr_depends_symbol(dep->left.expr, sym) ||
+		       expr_depends_symbol(dep->right.expr, sym);
+	case E_SYMBOL:
+		return dep->left.sym == sym;
+	case E_EQUAL:
+		if (dep->left.sym == sym) {
+			if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
+				return true;
+		}
+		break;
+	case E_UNEQUAL:
+		if (dep->left.sym == sym) {
+			if (dep->right.sym == &symbol_no)
+				return true;
+		}
+		break;
+	default:
+		;
+	}
+	return false;
+}
+
+struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2)
+{
+	struct expr *tmp = NULL;
+	expr_extract_eq(E_AND, &tmp, ep1, ep2);
+	if (tmp) {
+		*ep1 = expr_eliminate_yn(*ep1);
+		*ep2 = expr_eliminate_yn(*ep2);
+	}
+	return tmp;
+}
+
+struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2)
+{
+	struct expr *tmp = NULL;
+	expr_extract_eq(E_OR, &tmp, ep1, ep2);
+	if (tmp) {
+		*ep1 = expr_eliminate_yn(*ep1);
+		*ep2 = expr_eliminate_yn(*ep2);
+	}
+	return tmp;
+}
+
+void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+	if (e1->type == type) {
+		expr_extract_eq(type, ep, &e1->left.expr, &e2);
+		expr_extract_eq(type, ep, &e1->right.expr, &e2);
+		return;
+	}
+	if (e2->type == type) {
+		expr_extract_eq(type, ep, ep1, &e2->left.expr);
+		expr_extract_eq(type, ep, ep1, &e2->right.expr);
+		return;
+	}
+	if (expr_eq(e1, e2)) {
+		*ep = *ep ? expr_alloc_two(type, *ep, e1) : e1;
+		expr_free(e2);
+		if (type == E_AND) {
+			e1 = expr_alloc_symbol(&symbol_yes);
+			e2 = expr_alloc_symbol(&symbol_yes);
+		} else if (type == E_OR) {
+			e1 = expr_alloc_symbol(&symbol_no);
+			e2 = expr_alloc_symbol(&symbol_no);
+		}
+	}
+#undef e1
+#undef e2
+}
+
+struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
+{
+	struct expr *e1, *e2;
+
+	if (!e) {
+		e = expr_alloc_symbol(sym);
+		if (type == E_UNEQUAL)
+			e = expr_alloc_one(E_NOT, e);
+		return e;
+	}
+	switch (e->type) {
+	case E_AND:
+		e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
+		e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
+		if (sym == &symbol_yes)
+			e = expr_alloc_two(E_AND, e1, e2);
+		if (sym == &symbol_no)
+			e = expr_alloc_two(E_OR, e1, e2);
+		if (type == E_UNEQUAL)
+			e = expr_alloc_one(E_NOT, e);
+		return e;
+	case E_OR:
+		e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
+		e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
+		if (sym == &symbol_yes)
+			e = expr_alloc_two(E_OR, e1, e2);
+		if (sym == &symbol_no)
+			e = expr_alloc_two(E_AND, e1, e2);
+		if (type == E_UNEQUAL)
+			e = expr_alloc_one(E_NOT, e);
+		return e;
+	case E_NOT:
+		return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
+	case E_UNEQUAL:
+	case E_EQUAL:
+		if (type == E_EQUAL) {
+			if (sym == &symbol_yes)
+				return expr_copy(e);
+			if (sym == &symbol_mod)
+				return expr_alloc_symbol(&symbol_no);
+			if (sym == &symbol_no)
+				return expr_alloc_one(E_NOT, expr_copy(e));
+		} else {
+			if (sym == &symbol_yes)
+				return expr_alloc_one(E_NOT, expr_copy(e));
+			if (sym == &symbol_mod)
+				return expr_alloc_symbol(&symbol_yes);
+			if (sym == &symbol_no)
+				return expr_copy(e);
+		}
+		break;
+	case E_SYMBOL:
+		return expr_alloc_comp(type, e->left.sym, sym);
+	case E_CHOICE:
+	case E_RANGE:
+	case E_NONE:
+		/* panic */;
+	}
+	return NULL;
+}
+
+tristate expr_calc_value(struct expr *e)
+{
+	tristate val1, val2;
+	const char *str1, *str2;
+
+	if (!e)
+		return yes;
+
+	switch (e->type) {
+	case E_SYMBOL:
+		sym_calc_value(e->left.sym);
+		return e->left.sym->curr.tri;
+	case E_AND:
+		val1 = expr_calc_value(e->left.expr);
+		val2 = expr_calc_value(e->right.expr);
+		return E_AND(val1, val2);
+	case E_OR:
+		val1 = expr_calc_value(e->left.expr);
+		val2 = expr_calc_value(e->right.expr);
+		return E_OR(val1, val2);
+	case E_NOT:
+		val1 = expr_calc_value(e->left.expr);
+		return E_NOT(val1);
+	case E_EQUAL:
+		sym_calc_value(e->left.sym);
+		sym_calc_value(e->right.sym);
+		str1 = sym_get_string_value(e->left.sym);
+		str2 = sym_get_string_value(e->right.sym);
+		return !strcmp(str1, str2) ? yes : no;
+	case E_UNEQUAL:
+		sym_calc_value(e->left.sym);
+		sym_calc_value(e->right.sym);
+		str1 = sym_get_string_value(e->left.sym);
+		str2 = sym_get_string_value(e->right.sym);
+		return !strcmp(str1, str2) ? no : yes;
+	default:
+		printf("expr_calc_value: %d?\n", e->type);
+		return no;
+	}
+}
+
+int expr_compare_type(enum expr_type t1, enum expr_type t2)
+{
+#if 0
+	return 1;
+#else
+	if (t1 == t2)
+		return 0;
+	switch (t1) {
+	case E_EQUAL:
+	case E_UNEQUAL:
+		if (t2 == E_NOT)
+			return 1;
+	case E_NOT:
+		if (t2 == E_AND)
+			return 1;
+	case E_AND:
+		if (t2 == E_OR)
+			return 1;
+	case E_OR:
+		if (t2 == E_CHOICE)
+			return 1;
+	case E_CHOICE:
+		if (t2 == 0)
+			return 1;
+	default:
+		return -1;
+	}
+	printf("[%dgt%d?]", t1, t2);
+	return 0;
+#endif
+}
+
+void expr_print(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken)
+{
+	if (!e) {
+		fn(data, "y");
+		return;
+	}
+
+	if (expr_compare_type(prevtoken, e->type) > 0)
+		fn(data, "(");
+	switch (e->type) {
+	case E_SYMBOL:
+		if (e->left.sym->name)
+			fn(data, e->left.sym->name);
+		else
+			fn(data, "<choice>");
+		break;
+	case E_NOT:
+		fn(data, "!");
+		expr_print(e->left.expr, fn, data, E_NOT);
+		break;
+	case E_EQUAL:
+		fn(data, e->left.sym->name);
+		fn(data, "=");
+		fn(data, e->right.sym->name);
+		break;
+	case E_UNEQUAL:
+		fn(data, e->left.sym->name);
+		fn(data, "!=");
+		fn(data, e->right.sym->name);
+		break;
+	case E_OR:
+		expr_print(e->left.expr, fn, data, E_OR);
+		fn(data, " || ");
+		expr_print(e->right.expr, fn, data, E_OR);
+		break;
+	case E_AND:
+		expr_print(e->left.expr, fn, data, E_AND);
+		fn(data, " && ");
+		expr_print(e->right.expr, fn, data, E_AND);
+		break;
+	case E_CHOICE:
+		fn(data, e->right.sym->name);
+		if (e->left.expr) {
+			fn(data, " ^ ");
+			expr_print(e->left.expr, fn, data, E_CHOICE);
+		}
+		break;
+	case E_RANGE:
+		fn(data, "[");
+		fn(data, e->left.sym->name);
+		fn(data, " ");
+		fn(data, e->right.sym->name);
+		fn(data, "]");
+		break;
+	default:
+	  {
+		char buf[32];
+		sprintf(buf, "<unknown type %d>", e->type);
+		fn(data, buf);
+		break;
+	  }
+	}
+	if (expr_compare_type(prevtoken, e->type) > 0)
+		fn(data, ")");
+}
+
+static void expr_print_file_helper(void *data, const char *str)
+{
+	fwrite(str, strlen(str), 1, data);
+}
+
+void expr_fprint(struct expr *e, FILE *out)
+{
+	expr_print(e, expr_print_file_helper, out, E_NONE);
+}
+
+static void expr_print_gstr_helper(void *data, const char *str)
+{
+	str_append((struct gstr*)data, str);
+}
+
+void expr_gstr_print(struct expr *e, struct gstr *gs)
+{
+	expr_print(e, expr_print_gstr_helper, gs, E_NONE);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/expr.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/expr.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/expr.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#ifndef EXPR_H
+#define EXPR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
+
+struct file {
+	struct file *next;
+	struct file *parent;
+	char *name;
+	int lineno;
+	int flags;
+};
+
+#define FILE_BUSY		0x0001
+#define FILE_SCANNED		0x0002
+#define FILE_PRINTED		0x0004
+
+typedef enum tristate {
+	no, mod, yes
+} tristate;
+
+enum expr_type {
+	E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_CHOICE, E_SYMBOL, E_RANGE
+};
+
+union expr_data {
+	struct expr *expr;
+	struct symbol *sym;
+};
+
+struct expr {
+	enum expr_type type;
+	union expr_data left, right;
+};
+
+#define E_OR(dep1, dep2)	(((dep1)>(dep2))?(dep1):(dep2))
+#define E_AND(dep1, dep2)	(((dep1)<(dep2))?(dep1):(dep2))
+#define E_NOT(dep)		(2-(dep))
+
+struct expr_value {
+	struct expr *expr;
+	tristate tri;
+};
+
+struct symbol_value {
+	void *val;
+	tristate tri;
+};
+
+enum symbol_type {
+	S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
+};
+
+struct symbol {
+	struct symbol *next;
+	char *name;
+	char *help;
+	enum symbol_type type;
+	struct symbol_value curr, user;
+	tristate visible;
+	int flags;
+	struct property *prop;
+	struct expr *dep, *dep2;
+	struct expr_value rev_dep;
+};
+
+#define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
+
+#define SYMBOL_YES		0x0001
+#define SYMBOL_MOD		0x0002
+#define SYMBOL_NO		0x0004
+#define SYMBOL_CONST		0x0007
+#define SYMBOL_CHECK		0x0008
+#define SYMBOL_CHOICE		0x0010
+#define SYMBOL_CHOICEVAL	0x0020
+#define SYMBOL_PRINTED		0x0040
+#define SYMBOL_VALID		0x0080
+#define SYMBOL_OPTIONAL		0x0100
+#define SYMBOL_WRITE		0x0200
+#define SYMBOL_CHANGED		0x0400
+#define SYMBOL_NEW		0x0800
+#define SYMBOL_AUTO		0x1000
+#define SYMBOL_CHECKED		0x2000
+#define SYMBOL_CHECK_DONE	0x4000
+#define SYMBOL_WARNED		0x8000
+
+#define SYMBOL_MAXLENGTH	256
+#define SYMBOL_HASHSIZE		257
+#define SYMBOL_HASHMASK		0xff
+
+enum prop_type {
+	P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE, P_SELECT, P_RANGE
+};
+
+struct property {
+	struct property *next;
+	struct symbol *sym;
+	enum prop_type type;
+	const char *text;
+	struct expr_value visible;
+	struct expr *expr;
+	struct menu *menu;
+	struct file *file;
+	int lineno;
+};
+
+#define for_all_properties(sym, st, tok) \
+	for (st = sym->prop; st; st = st->next) \
+		if (st->type == (tok))
+#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)
+#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)
+#define for_all_prompts(sym, st) \
+	for (st = sym->prop; st; st = st->next) \
+		if (st->text)
+
+struct menu {
+	struct menu *next;
+	struct menu *parent;
+	struct menu *list;
+	struct symbol *sym;
+	struct property *prompt;
+	struct expr *dep;
+	unsigned int flags;
+	//char *help;
+	struct file *file;
+	int lineno;
+	void *data;
+};
+
+#define MENU_CHANGED		0x0001
+#define MENU_ROOT		0x0002
+
+#ifndef SWIG
+
+extern struct file *file_list;
+extern struct file *current_file;
+struct file *lookup_file(const char *name);
+
+extern struct symbol symbol_yes, symbol_no, symbol_mod;
+extern struct symbol *modules_sym;
+extern int cdebug;
+struct expr *expr_alloc_symbol(struct symbol *sym);
+struct expr *expr_alloc_one(enum expr_type type, struct expr *ce);
+struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2);
+struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
+struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
+struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
+struct expr *expr_copy(struct expr *org);
+void expr_free(struct expr *e);
+int expr_eq(struct expr *e1, struct expr *e2);
+void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
+tristate expr_calc_value(struct expr *e);
+struct expr *expr_eliminate_yn(struct expr *e);
+struct expr *expr_trans_bool(struct expr *e);
+struct expr *expr_eliminate_dups(struct expr *e);
+struct expr *expr_transform(struct expr *e);
+int expr_contains_symbol(struct expr *dep, struct symbol *sym);
+bool expr_depends_symbol(struct expr *dep, struct symbol *sym);
+struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2);
+struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2);
+void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2);
+struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
+
+void expr_fprint(struct expr *e, FILE *out);
+struct gstr; /* forward */
+void expr_gstr_print(struct expr *e, struct gstr *gs);
+
+static inline int expr_is_yes(struct expr *e)
+{
+	return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);
+}
+
+static inline int expr_is_no(struct expr *e)
+{
+	return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EXPR_H */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lex.zconf.c_shipped
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lex.zconf.c_shipped	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lex.zconf.c_shipped	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3688 @@
+
+#line 3 "lex.zconf.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 31
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_CONST
+
+#endif	/* __STDC__ */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE zconfrestart(zconfin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int zconfleng;
+
+extern FILE *zconfin, *zconfout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    #define YY_LESS_LINENO(n)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up zconftext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up zconftext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef unsigned int yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via zconfrestart()), so that the user can continue scanning by
+	 * just pointing zconfin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when zconftext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int zconfleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow zconfwrap()'s to do buffer switches
+ * instead of setting up a fresh zconfin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void zconfrestart (FILE *input_file  );
+void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE zconf_create_buffer (FILE *file,int size  );
+void zconf_delete_buffer (YY_BUFFER_STATE b  );
+void zconf_flush_buffer (YY_BUFFER_STATE b  );
+void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void zconfpop_buffer_state (void );
+
+static void zconfensure_buffer_stack (void );
+static void zconf_load_buffer_state (void );
+static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len  );
+
+void *zconfalloc (yy_size_t  );
+void *zconfrealloc (void *,yy_size_t  );
+void zconffree (void *  );
+
+#define yy_new_buffer zconf_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        zconfensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            zconf_create_buffer(zconfin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        zconfensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            zconf_create_buffer(zconfin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define zconfwrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int zconflineno;
+
+int zconflineno = 1;
+
+extern char *zconftext;
+#define yytext_ptr zconftext
+static yyconst flex_int16_t yy_nxt[][38] =
+    {
+    {
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0
+    },
+
+    {
+       11,   12,   13,   14,   12,   12,   15,   12,   12,   12,
+       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
+       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
+       12,   12,   12,   12,   12,   12,   12,   12
+    },
+
+    {
+       11,   12,   13,   14,   12,   12,   15,   12,   12,   12,
+       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
+
+       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
+       12,   12,   12,   12,   12,   12,   12,   12
+    },
+
+    {
+       11,   16,   16,   17,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   18,   16,   16,   18,   18,   19,   20,
+       21,   22,   18,   18,   23,   24,   18,   25,   18,   26,
+       27,   18,   28,   29,   30,   18,   18,   16
+    },
+
+    {
+       11,   16,   16,   17,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   18,   16,   16,   18,   18,   19,   20,
+       21,   22,   18,   18,   23,   24,   18,   25,   18,   26,
+       27,   18,   28,   29,   30,   18,   18,   16
+
+    },
+
+    {
+       11,   31,   32,   33,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31
+    },
+
+    {
+       11,   31,   32,   33,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31
+    },
+
+    {
+       11,   34,   34,   35,   34,   36,   34,   34,   36,   34,
+       34,   34,   34,   34,   34,   37,   34,   34,   34,   34,
+
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34
+    },
+
+    {
+       11,   34,   34,   35,   34,   36,   34,   34,   36,   34,
+       34,   34,   34,   34,   34,   37,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34
+    },
+
+    {
+       11,   38,   38,   39,   40,   41,   42,   43,   41,   44,
+       45,   46,   47,   47,   48,   49,   47,   47,   47,   47,
+       47,   47,   47,   47,   47,   50,   47,   47,   47,   51,
+       47,   47,   47,   47,   47,   47,   47,   52
+
+    },
+
+    {
+       11,   38,   38,   39,   40,   41,   42,   43,   41,   44,
+       45,   46,   47,   47,   48,   49,   47,   47,   47,   47,
+       47,   47,   47,   47,   47,   50,   47,   47,   47,   51,
+       47,   47,   47,   47,   47,   47,   47,   52
+    },
+
+    {
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11
+    },
+
+    {
+       11,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
+      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
+
+      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
+      -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12
+    },
+
+    {
+       11,  -13,   53,   54,  -13,  -13,   55,  -13,  -13,  -13,
+      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
+      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
+      -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13
+    },
+
+    {
+       11,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+      -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14
+
+    },
+
+    {
+       11,   56,   56,   57,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56
+    },
+
+    {
+       11,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16
+    },
+
+    {
+       11,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17
+    },
+
+    {
+       11,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,   58,  -18,  -18,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -18
+    },
+
+    {
+       11,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,  -19,
+      -19,  -19,  -19,   58,  -19,  -19,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   59,
+       58,   58,   58,   58,   58,   58,   58,  -19
+
+    },
+
+    {
+       11,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,   58,  -20,  -20,   58,   58,   58,   58,
+       58,   58,   58,   58,   60,   58,   58,   58,   58,   61,
+       58,   58,   58,   58,   58,   58,   58,  -20
+    },
+
+    {
+       11,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,  -21,
+      -21,  -21,  -21,   58,  -21,  -21,   58,   58,   58,   58,
+       58,   62,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -21
+    },
+
+    {
+       11,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,  -22,
+      -22,  -22,  -22,   58,  -22,  -22,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   63,   58,
+       58,   58,   58,   58,   58,   58,   58,  -22
+    },
+
+    {
+       11,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,   58,  -23,  -23,   58,   58,   58,   58,
+       58,   64,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -23
+    },
+
+    {
+       11,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
+      -24,  -24,  -24,   58,  -24,  -24,   58,   58,   58,   58,
+       58,   58,   65,   58,   58,   58,   58,   58,   66,   58,
+       58,   58,   58,   58,   58,   58,   58,  -24
+
+    },
+
+    {
+       11,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
+      -25,  -25,  -25,   58,  -25,  -25,   58,   67,   58,   58,
+       58,   68,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -25
+    },
+
+    {
+       11,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
+      -26,  -26,  -26,   58,  -26,  -26,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       69,   58,   58,   58,   58,   58,   58,  -26
+    },
+
+    {
+       11,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
+      -27,  -27,  -27,   58,  -27,  -27,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   70,   58,   58,   58,   58,  -27
+    },
+
+    {
+       11,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
+      -28,  -28,  -28,   58,  -28,  -28,   58,   71,   58,   58,
+       58,   72,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -28
+    },
+
+    {
+       11,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
+      -29,  -29,  -29,   58,  -29,  -29,   58,   58,   58,   58,
+       58,   73,   58,   58,   58,   58,   58,   58,   58,   74,
+       58,   58,   58,   58,   75,   58,   58,  -29
+
+    },
+
+    {
+       11,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,   58,  -30,  -30,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   76,   58,   58,   58,   58,  -30
+    },
+
+    {
+       11,   77,   77,  -31,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77
+    },
+
+    {
+       11,  -32,   78,   79,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32
+    },
+
+    {
+       11,   80,  -33,  -33,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80
+    },
+
+    {
+       11,   81,   81,   82,   81,  -34,   81,   81,  -34,   81,
+       81,   81,   81,   81,   81,  -34,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81
+
+    },
+
+    {
+       11,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35
+    },
+
+    {
+       11,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36
+    },
+
+    {
+       11,   83,   83,   84,   83,   83,   83,   83,   83,   83,
+       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
+
+       83,   83,   83,   83,   83,   83,   83,   83,   83,   83,
+       83,   83,   83,   83,   83,   83,   83,   83
+    },
+
+    {
+       11,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38
+    },
+
+    {
+       11,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39
+
+    },
+
+    {
+       11,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,   85,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40
+    },
+
+    {
+       11,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41,
+      -41,  -41,  -41,  -41,  -41,  -41,  -41,  -41
+    },
+
+    {
+       11,   86,   86,  -42,   86,   86,   86,   86,   86,   86,
+       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
+
+       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
+       86,   86,   86,   86,   86,   86,   86,   86
+    },
+
+    {
+       11,  -43,  -43,  -43,  -43,  -43,  -43,   87,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43
+    },
+
+    {
+       11,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44
+
+    },
+
+    {
+       11,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45,
+      -45,  -45,  -45,  -45,  -45,  -45,  -45,  -45
+    },
+
+    {
+       11,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,   88,   89,   89,  -46,  -46,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,  -46
+    },
+
+    {
+       11,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,  -47,
+      -47,   89,   89,   89,  -47,  -47,   89,   89,   89,   89,
+
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,  -47
+    },
+
+    {
+       11,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48
+    },
+
+    {
+       11,  -49,  -49,   90,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49,
+      -49,  -49,  -49,  -49,  -49,  -49,  -49,  -49
+
+    },
+
+    {
+       11,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,   89,   89,   89,  -50,  -50,   89,   89,   89,   89,
+       89,   89,   91,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,  -50
+    },
+
+    {
+       11,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,   89,   89,   89,  -51,  -51,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   92,   89,
+       89,   89,   89,   89,   89,   89,   89,  -51
+    },
+
+    {
+       11,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52,   93
+    },
+
+    {
+       11,  -53,   53,   54,  -53,  -53,   55,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53
+    },
+
+    {
+       11,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
+      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54
+
+    },
+
+    {
+       11,   56,   56,   57,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56
+    },
+
+    {
+       11,   56,   56,   57,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56
+    },
+
+    {
+       11,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57
+    },
+
+    {
+       11,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,   58,  -58,  -58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -58
+    },
+
+    {
+       11,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
+      -59,  -59,  -59,   58,  -59,  -59,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   94,
+       58,   58,   58,   58,   58,   58,   58,  -59
+
+    },
+
+    {
+       11,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
+      -60,  -60,  -60,   58,  -60,  -60,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   95,
+       58,   58,   58,   58,   58,   58,   58,  -60
+    },
+
+    {
+       11,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,  -61,
+      -61,  -61,  -61,   58,  -61,  -61,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   96,   97,   58,
+       58,   58,   58,   58,   58,   58,   58,  -61
+    },
+
+    {
+       11,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,  -62,
+      -62,  -62,  -62,   58,  -62,  -62,   58,   58,   58,   58,
+
+       58,   58,   98,   58,   58,   58,   58,   58,   58,   58,
+       99,   58,   58,   58,   58,   58,   58,  -62
+    },
+
+    {
+       11,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,  -63,
+      -63,  -63,  -63,   58,  -63,  -63,   58,  100,   58,   58,
+      101,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -63
+    },
+
+    {
+       11,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,  -64,
+      -64,  -64,  -64,   58,  -64,  -64,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  102,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  103,  -64
+
+    },
+
+    {
+       11,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,  -65,
+      -65,  -65,  -65,   58,  -65,  -65,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -65
+    },
+
+    {
+       11,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,  -66,
+      -66,  -66,  -66,   58,  -66,  -66,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  104,   58,   58,  -66
+    },
+
+    {
+       11,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,  -67,
+      -67,  -67,  -67,   58,  -67,  -67,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,  105,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -67
+    },
+
+    {
+       11,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,  -68,
+      -68,  -68,  -68,   58,  -68,  -68,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,  106,   58,
+       58,   58,   58,   58,   58,   58,   58,  -68
+    },
+
+    {
+       11,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,  -69,
+      -69,  -69,  -69,   58,  -69,  -69,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  107,   58,   58,  -69
+
+    },
+
+    {
+       11,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,  -70,
+      -70,  -70,  -70,   58,  -70,  -70,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,  108,
+       58,   58,   58,   58,   58,   58,   58,  -70
+    },
+
+    {
+       11,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,  -71,
+      -71,  -71,  -71,   58,  -71,  -71,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,  109,   58,
+       58,   58,   58,   58,   58,   58,   58,  -71
+    },
+
+    {
+       11,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,  -72,
+      -72,  -72,  -72,   58,  -72,  -72,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,  110,   58,   58,   58,   58,   58,  -72
+    },
+
+    {
+       11,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,  -73,
+      -73,  -73,  -73,   58,  -73,  -73,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  111,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -73
+    },
+
+    {
+       11,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,  -74,
+      -74,  -74,  -74,   58,  -74,  -74,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,  112,   58,  -74
+
+    },
+
+    {
+       11,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,  -75,
+      -75,  -75,  -75,   58,  -75,  -75,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,  113,   58,   58,   58,   58,  -75
+    },
+
+    {
+       11,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,  -76,
+      -76,  -76,  -76,   58,  -76,  -76,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,  114,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -76
+    },
+
+    {
+       11,   77,   77,  -77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+
+       77,   77,   77,   77,   77,   77,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   77
+    },
+
+    {
+       11,  -78,   78,   79,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78,
+      -78,  -78,  -78,  -78,  -78,  -78,  -78,  -78
+    },
+
+    {
+       11,   80,  -79,  -79,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80
+
+    },
+
+    {
+       11,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80,
+      -80,  -80,  -80,  -80,  -80,  -80,  -80,  -80
+    },
+
+    {
+       11,   81,   81,   82,   81,  -81,   81,   81,  -81,   81,
+       81,   81,   81,   81,   81,  -81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   81,   81,
+       81,   81,   81,   81,   81,   81,   81,   81
+    },
+
+    {
+       11,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82,
+      -82,  -82,  -82,  -82,  -82,  -82,  -82,  -82
+    },
+
+    {
+       11,  -83,  -83,   84,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83,
+      -83,  -83,  -83,  -83,  -83,  -83,  -83,  -83
+    },
+
+    {
+       11,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84,
+      -84,  -84,  -84,  -84,  -84,  -84,  -84,  -84
+
+    },
+
+    {
+       11,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85,
+      -85,  -85,  -85,  -85,  -85,  -85,  -85,  -85
+    },
+
+    {
+       11,   86,   86,  -86,   86,   86,   86,   86,   86,   86,
+       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
+       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
+       86,   86,   86,   86,   86,   86,   86,   86
+    },
+
+    {
+       11,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87,
+      -87,  -87,  -87,  -87,  -87,  -87,  -87,  -87
+    },
+
+    {
+       11,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,  -88,
+      -88,  115,   89,   89,  -88,  -88,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,  -88
+    },
+
+    {
+       11,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,  -89,
+      -89,   89,   89,   89,  -89,  -89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,  -89
+
+    },
+
+    {
+       11,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90,
+      -90,  -90,  -90,  -90,  -90,  -90,  -90,  -90
+    },
+
+    {
+       11,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,  -91,
+      -91,   89,   89,   89,  -91,  -91,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,  -91
+    },
+
+    {
+       11,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,  -92,
+      -92,   89,   89,   89,  -92,  -92,   89,   89,   89,   89,
+
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,  -92
+    },
+
+    {
+       11,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93,
+      -93,  -93,  -93,  -93,  -93,  -93,  -93,  -93
+    },
+
+    {
+       11,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,  -94,
+      -94,  -94,  -94,   58,  -94,  -94,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  116,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -94
+
+    },
+
+    {
+       11,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,  -95,
+      -95,  -95,  -95,   58,  -95,  -95,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,  117,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -95
+    },
+
+    {
+       11,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,  -96,
+      -96,  -96,  -96,   58,  -96,  -96,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  118,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -96
+    },
+
+    {
+       11,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,  -97,
+      -97,  -97,  -97,   58,  -97,  -97,   58,   58,   58,   58,
+
+       58,   58,  119,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -97
+    },
+
+    {
+       11,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,  -98,
+      -98,  -98,  -98,   58,  -98,  -98,  120,  121,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -98
+    },
+
+    {
+       11,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,  -99,
+      -99,  -99,  -99,   58,  -99,  -99,   58,   58,   58,   58,
+       58,  122,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  -99
+
+    },
+
+    {
+       11, -100, -100, -100, -100, -100, -100, -100, -100, -100,
+     -100, -100, -100,   58, -100, -100,   58,   58,  123,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -100
+    },
+
+    {
+       11, -101, -101, -101, -101, -101, -101, -101, -101, -101,
+     -101, -101, -101,   58, -101, -101,   58,   58,   58,  124,
+       58,   58,   58,   58,   58,  125,   58,  126,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -101
+    },
+
+    {
+       11, -102, -102, -102, -102, -102, -102, -102, -102, -102,
+     -102, -102, -102,   58, -102, -102,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+      127,   58,   58,   58,   58,   58,   58, -102
+    },
+
+    {
+       11, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+     -103, -103, -103,   58, -103, -103,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -103
+    },
+
+    {
+       11, -104, -104, -104, -104, -104, -104, -104, -104, -104,
+     -104, -104, -104,   58, -104, -104,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -104
+
+    },
+
+    {
+       11, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+     -105, -105, -105,   58, -105, -105,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,  128,   58,
+       58,   58,   58,   58,   58,   58,   58, -105
+    },
+
+    {
+       11, -106, -106, -106, -106, -106, -106, -106, -106, -106,
+     -106, -106, -106,   58, -106, -106,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,  129,   58, -106
+    },
+
+    {
+       11, -107, -107, -107, -107, -107, -107, -107, -107, -107,
+     -107, -107, -107,   58, -107, -107,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,  130,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -107
+    },
+
+    {
+       11, -108, -108, -108, -108, -108, -108, -108, -108, -108,
+     -108, -108, -108,   58, -108, -108,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  131,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -108
+    },
+
+    {
+       11, -109, -109, -109, -109, -109, -109, -109, -109, -109,
+     -109, -109, -109,   58, -109, -109,   58,   58,   58,   58,
+       58,   58,   58,  132,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -109
+
+    },
+
+    {
+       11, -110, -110, -110, -110, -110, -110, -110, -110, -110,
+     -110, -110, -110,   58, -110, -110,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,  133,   58, -110
+    },
+
+    {
+       11, -111, -111, -111, -111, -111, -111, -111, -111, -111,
+     -111, -111, -111,   58, -111, -111,   58,   58,   58,   58,
+       58,  134,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -111
+    },
+
+    {
+       11, -112, -112, -112, -112, -112, -112, -112, -112, -112,
+     -112, -112, -112,   58, -112, -112,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,  135,   58,   58,   58,   58, -112
+    },
+
+    {
+       11, -113, -113, -113, -113, -113, -113, -113, -113, -113,
+     -113, -113, -113,   58, -113, -113,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,  136,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -113
+    },
+
+    {
+       11, -114, -114, -114, -114, -114, -114, -114, -114, -114,
+     -114, -114, -114,   58, -114, -114,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,  137,   58,   58,   58, -114
+
+    },
+
+    {
+       11, -115, -115, -115, -115, -115, -115, -115, -115, -115,
+     -115,   89,   89,   89, -115, -115,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89, -115
+    },
+
+    {
+       11, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+     -116, -116, -116,   58, -116, -116,   58,   58,   58,   58,
+       58,  138,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -116
+    },
+
+    {
+       11, -117, -117, -117, -117, -117, -117, -117, -117, -117,
+     -117, -117, -117,   58, -117, -117,   58,   58,   58,  139,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -117
+    },
+
+    {
+       11, -118, -118, -118, -118, -118, -118, -118, -118, -118,
+     -118, -118, -118,   58, -118, -118,   58,   58,   58,   58,
+       58,  140,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -118
+    },
+
+    {
+       11, -119, -119, -119, -119, -119, -119, -119, -119, -119,
+     -119, -119, -119,   58, -119, -119,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,  141,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -119
+
+    },
+
+    {
+       11, -120, -120, -120, -120, -120, -120, -120, -120, -120,
+     -120, -120, -120,   58, -120, -120,   58,   58,  142,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  143,   58,   58, -120
+    },
+
+    {
+       11, -121, -121, -121, -121, -121, -121, -121, -121, -121,
+     -121, -121, -121,   58, -121, -121,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,  144,   58, -121
+    },
+
+    {
+       11, -122, -122, -122, -122, -122, -122, -122, -122, -122,
+     -122, -122, -122,   58, -122, -122,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,  145,   58,
+       58,   58,   58,   58,   58,   58,   58, -122
+    },
+
+    {
+       11, -123, -123, -123, -123, -123, -123, -123, -123, -123,
+     -123, -123, -123,   58, -123, -123,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  146,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -123
+    },
+
+    {
+       11, -124, -124, -124, -124, -124, -124, -124, -124, -124,
+     -124, -124, -124,   58, -124, -124,   58,   58,   58,   58,
+       58,   58,   58,   58,  147,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -124
+
+    },
+
+    {
+       11, -125, -125, -125, -125, -125, -125, -125, -125, -125,
+     -125, -125, -125,   58, -125, -125,   58,   58,   58,   58,
+       58,   58,  148,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -125
+    },
+
+    {
+       11, -126, -126, -126, -126, -126, -126, -126, -126, -126,
+     -126, -126, -126,   58, -126, -126,   58,   58,   58,   58,
+       58,  149,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -126
+    },
+
+    {
+       11, -127, -127, -127, -127, -127, -127, -127, -127, -127,
+     -127, -127, -127,   58, -127, -127,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -127
+    },
+
+    {
+       11, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+     -128, -128, -128,   58, -128, -128,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,  150,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -128
+    },
+
+    {
+       11, -129, -129, -129, -129, -129, -129, -129, -129, -129,
+     -129, -129, -129,   58, -129, -129,   58,   58,   58,  151,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -129
+
+    },
+
+    {
+       11, -130, -130, -130, -130, -130, -130, -130, -130, -130,
+     -130, -130, -130,   58, -130, -130,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,  152,
+       58,   58,   58,   58,   58,   58,   58, -130
+    },
+
+    {
+       11, -131, -131, -131, -131, -131, -131, -131, -131, -131,
+     -131, -131, -131,   58, -131, -131,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+      153,   58,   58,   58,   58,   58,   58, -131
+    },
+
+    {
+       11, -132, -132, -132, -132, -132, -132, -132, -132, -132,
+     -132, -132, -132,   58, -132, -132,   58,   58,   58,   58,
+
+       58,  154,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -132
+    },
+
+    {
+       11, -133, -133, -133, -133, -133, -133, -133, -133, -133,
+     -133, -133, -133,   58, -133, -133,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,  155,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -133
+    },
+
+    {
+       11, -134, -134, -134, -134, -134, -134, -134, -134, -134,
+     -134, -134, -134,   58, -134, -134,   58,   58,   58,  156,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -134
+
+    },
+
+    {
+       11, -135, -135, -135, -135, -135, -135, -135, -135, -135,
+     -135, -135, -135,   58, -135, -135,   58,   58,   58,  157,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -135
+    },
+
+    {
+       11, -136, -136, -136, -136, -136, -136, -136, -136, -136,
+     -136, -136, -136,   58, -136, -136,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,  158,   58,
+       58,   58,   58,   58,   58,   58,   58, -136
+    },
+
+    {
+       11, -137, -137, -137, -137, -137, -137, -137, -137, -137,
+     -137, -137, -137,   58, -137, -137,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  159,   58,   58, -137
+    },
+
+    {
+       11, -138, -138, -138, -138, -138, -138, -138, -138, -138,
+     -138, -138, -138,   58, -138, -138,   58,  160,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -138
+    },
+
+    {
+       11, -139, -139, -139, -139, -139, -139, -139, -139, -139,
+     -139, -139, -139,   58, -139, -139,   58,   58,   58,   58,
+       58,  161,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -139
+
+    },
+
+    {
+       11, -140, -140, -140, -140, -140, -140, -140, -140, -140,
+     -140, -140, -140,   58, -140, -140,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,  162,   58,
+       58,   58,   58,   58,   58,   58,   58, -140
+    },
+
+    {
+       11, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+     -141, -141, -141,   58, -141, -141,   58,   58,   58,   58,
+       58,   58,   58,  163,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -141
+    },
+
+    {
+       11, -142, -142, -142, -142, -142, -142, -142, -142, -142,
+     -142, -142, -142,   58, -142, -142,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,  164,
+       58,   58,   58,   58,   58,   58,   58, -142
+    },
+
+    {
+       11, -143, -143, -143, -143, -143, -143, -143, -143, -143,
+     -143, -143, -143,   58, -143, -143,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,  165,   58,   58,   58,   58, -143
+    },
+
+    {
+       11, -144, -144, -144, -144, -144, -144, -144, -144, -144,
+     -144, -144, -144,   58, -144, -144,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  166,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -144
+
+    },
+
+    {
+       11, -145, -145, -145, -145, -145, -145, -145, -145, -145,
+     -145, -145, -145,   58, -145, -145,   58,   58,   58,   58,
+      167,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -145
+    },
+
+    {
+       11, -146, -146, -146, -146, -146, -146, -146, -146, -146,
+     -146, -146, -146,   58, -146, -146,   58,   58,   58,   58,
+       58,  168,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -146
+    },
+
+    {
+       11, -147, -147, -147, -147, -147, -147, -147, -147, -147,
+     -147, -147, -147,   58, -147, -147,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,  169,
+       58,   58,   58,   58,   58,   58,   58, -147
+    },
+
+    {
+       11, -148, -148, -148, -148, -148, -148, -148, -148, -148,
+     -148, -148, -148,   58, -148, -148,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -148
+    },
+
+    {
+       11, -149, -149, -149, -149, -149, -149, -149, -149, -149,
+     -149, -149, -149,   58, -149, -149,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,  170,   58,
+       58,   58,   58,   58,   58,   58,   58, -149
+
+    },
+
+    {
+       11, -150, -150, -150, -150, -150, -150, -150, -150, -150,
+     -150, -150, -150,   58, -150, -150,   58,   58,   58,   58,
+       58,  171,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -150
+    },
+
+    {
+       11, -151, -151, -151, -151, -151, -151, -151, -151, -151,
+     -151, -151, -151,   58, -151, -151,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,  172,
+       58,   58,   58,   58,   58,   58,   58, -151
+    },
+
+    {
+       11, -152, -152, -152, -152, -152, -152, -152, -152, -152,
+     -152, -152, -152,   58, -152, -152,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,  173,   58,
+       58,   58,   58,   58,   58,   58,   58, -152
+    },
+
+    {
+       11, -153, -153, -153, -153, -153, -153, -153, -153, -153,
+     -153, -153, -153,   58, -153, -153,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  174,   58,   58, -153
+    },
+
+    {
+       11, -154, -154, -154, -154, -154, -154, -154, -154, -154,
+     -154, -154, -154,   58, -154, -154,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -154
+
+    },
+
+    {
+       11, -155, -155, -155, -155, -155, -155, -155, -155, -155,
+     -155, -155, -155,   58, -155, -155,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,  175,   58,   58,   58,   58, -155
+    },
+
+    {
+       11, -156, -156, -156, -156, -156, -156, -156, -156, -156,
+     -156, -156, -156,   58, -156, -156,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  176,   58,   58, -156
+    },
+
+    {
+       11, -157, -157, -157, -157, -157, -157, -157, -157, -157,
+     -157, -157, -157,   58, -157, -157,   58,   58,   58,   58,
+
+       58,  177,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -157
+    },
+
+    {
+       11, -158, -158, -158, -158, -158, -158, -158, -158, -158,
+     -158, -158, -158,   58, -158, -158,   58,   58,   58,   58,
+       58,   58,   58,  178,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -158
+    },
+
+    {
+       11, -159, -159, -159, -159, -159, -159, -159, -159, -159,
+     -159, -159, -159,   58, -159, -159,   58,  179,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -159
+
+    },
+
+    {
+       11, -160, -160, -160, -160, -160, -160, -160, -160, -160,
+     -160, -160, -160,   58, -160, -160,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,  180,   58,
+       58,   58,   58,   58,   58,   58,   58, -160
+    },
+
+    {
+       11, -161, -161, -161, -161, -161, -161, -161, -161, -161,
+     -161, -161, -161,   58, -161, -161,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -161
+    },
+
+    {
+       11, -162, -162, -162, -162, -162, -162, -162, -162, -162,
+     -162, -162, -162,   58, -162, -162,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  181,   58,   58, -162
+    },
+
+    {
+       11, -163, -163, -163, -163, -163, -163, -163, -163, -163,
+     -163, -163, -163,   58, -163, -163,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -163
+    },
+
+    {
+       11, -164, -164, -164, -164, -164, -164, -164, -164, -164,
+     -164, -164, -164,   58, -164, -164,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,  182,
+       58,   58,   58,   58,   58,   58,   58, -164
+
+    },
+
+    {
+       11, -165, -165, -165, -165, -165, -165, -165, -165, -165,
+     -165, -165, -165,   58, -165, -165,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,  183,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -165
+    },
+
+    {
+       11, -166, -166, -166, -166, -166, -166, -166, -166, -166,
+     -166, -166, -166,   58, -166, -166,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  184,   58,   58, -166
+    },
+
+    {
+       11, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+     -167, -167, -167,   58, -167, -167,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,  185,   58,   58,   58, -167
+    },
+
+    {
+       11, -168, -168, -168, -168, -168, -168, -168, -168, -168,
+     -168, -168, -168,   58, -168, -168,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -168
+    },
+
+    {
+       11, -169, -169, -169, -169, -169, -169, -169, -169, -169,
+     -169, -169, -169,   58, -169, -169,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,  186,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -169
+
+    },
+
+    {
+       11, -170, -170, -170, -170, -170, -170, -170, -170, -170,
+     -170, -170, -170,   58, -170, -170,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,  187,   58, -170
+    },
+
+    {
+       11, -171, -171, -171, -171, -171, -171, -171, -171, -171,
+     -171, -171, -171,   58, -171, -171,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,  188,   58,
+       58,   58,   58,   58,   58,   58,   58, -171
+    },
+
+    {
+       11, -172, -172, -172, -172, -172, -172, -172, -172, -172,
+     -172, -172, -172,   58, -172, -172,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,  189,   58,
+       58,   58,   58,   58,   58,   58,   58, -172
+    },
+
+    {
+       11, -173, -173, -173, -173, -173, -173, -173, -173, -173,
+     -173, -173, -173,   58, -173, -173,   58,  190,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -173
+    },
+
+    {
+       11, -174, -174, -174, -174, -174, -174, -174, -174, -174,
+     -174, -174, -174,   58, -174, -174,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -174
+
+    },
+
+    {
+       11, -175, -175, -175, -175, -175, -175, -175, -175, -175,
+     -175, -175, -175,   58, -175, -175,   58,   58,   58,   58,
+       58,  191,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -175
+    },
+
+    {
+       11, -176, -176, -176, -176, -176, -176, -176, -176, -176,
+     -176, -176, -176,   58, -176, -176,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -176
+    },
+
+    {
+       11, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+     -177, -177, -177,   58, -177, -177,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -177
+    },
+
+    {
+       11, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+     -178, -178, -178,   58, -178, -178,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -178
+    },
+
+    {
+       11, -179, -179, -179, -179, -179, -179, -179, -179, -179,
+     -179, -179, -179,   58, -179, -179,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  192,   58,   58, -179
+
+    },
+
+    {
+       11, -180, -180, -180, -180, -180, -180, -180, -180, -180,
+     -180, -180, -180,   58, -180, -180,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -180
+    },
+
+    {
+       11, -181, -181, -181, -181, -181, -181, -181, -181, -181,
+     -181, -181, -181,   58, -181, -181,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -181
+    },
+
+    {
+       11, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+     -182, -182, -182,   58, -182, -182,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,  193,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -182
+    },
+
+    {
+       11, -183, -183, -183, -183, -183, -183, -183, -183, -183,
+     -183, -183, -183,   58, -183, -183,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,  194,   58,   58,   58, -183
+    },
+
+    {
+       11, -184, -184, -184, -184, -184, -184, -184, -184, -184,
+     -184, -184, -184,   58, -184, -184,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -184
+
+    },
+
+    {
+       11, -185, -185, -185, -185, -185, -185, -185, -185, -185,
+     -185, -185, -185,   58, -185, -185,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -185
+    },
+
+    {
+       11, -186, -186, -186, -186, -186, -186, -186, -186, -186,
+     -186, -186, -186,   58, -186, -186,   58,   58,   58,  195,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -186
+    },
+
+    {
+       11, -187, -187, -187, -187, -187, -187, -187, -187, -187,
+     -187, -187, -187,   58, -187, -187,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -187
+    },
+
+    {
+       11, -188, -188, -188, -188, -188, -188, -188, -188, -188,
+     -188, -188, -188,   58, -188, -188,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,  196,   58, -188
+    },
+
+    {
+       11, -189, -189, -189, -189, -189, -189, -189, -189, -189,
+     -189, -189, -189,   58, -189, -189,   58,   58,   58,   58,
+       58,   58,  197,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -189
+
+    },
+
+    {
+       11, -190, -190, -190, -190, -190, -190, -190, -190, -190,
+     -190, -190, -190,   58, -190, -190,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,  198,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -190
+    },
+
+    {
+       11, -191, -191, -191, -191, -191, -191, -191, -191, -191,
+     -191, -191, -191,   58, -191, -191,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,  199,   58,   58,   58, -191
+    },
+
+    {
+       11, -192, -192, -192, -192, -192, -192, -192, -192, -192,
+     -192, -192, -192,   58, -192, -192,   58,   58,   58,   58,
+
+       58,  200,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -192
+    },
+
+    {
+       11, -193, -193, -193, -193, -193, -193, -193, -193, -193,
+     -193, -193, -193,   58, -193, -193,   58,   58,   58,   58,
+       58,  201,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -193
+    },
+
+    {
+       11, -194, -194, -194, -194, -194, -194, -194, -194, -194,
+     -194, -194, -194,   58, -194, -194,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  202,   58,   58, -194
+
+    },
+
+    {
+       11, -195, -195, -195, -195, -195, -195, -195, -195, -195,
+     -195, -195, -195,   58, -195, -195,   58,   58,   58,   58,
+       58,  203,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -195
+    },
+
+    {
+       11, -196, -196, -196, -196, -196, -196, -196, -196, -196,
+     -196, -196, -196,   58, -196, -196,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -196
+    },
+
+    {
+       11, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+     -197, -197, -197,   58, -197, -197,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,  204,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -197
+    },
+
+    {
+       11, -198, -198, -198, -198, -198, -198, -198, -198, -198,
+     -198, -198, -198,   58, -198, -198,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -198
+    },
+
+    {
+       11, -199, -199, -199, -199, -199, -199, -199, -199, -199,
+     -199, -199, -199,   58, -199, -199,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -199
+
+    },
+
+    {
+       11, -200, -200, -200, -200, -200, -200, -200, -200, -200,
+     -200, -200, -200,   58, -200, -200,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -200
+    },
+
+    {
+       11, -201, -201, -201, -201, -201, -201, -201, -201, -201,
+     -201, -201, -201,   58, -201, -201,   58,  205,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -201
+    },
+
+    {
+       11, -202, -202, -202, -202, -202, -202, -202, -202, -202,
+     -202, -202, -202,   58, -202, -202,   58,  206,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -202
+    },
+
+    {
+       11, -203, -203, -203, -203, -203, -203, -203, -203, -203,
+     -203, -203, -203,   58, -203, -203,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -203
+    },
+
+    {
+       11, -204, -204, -204, -204, -204, -204, -204, -204, -204,
+     -204, -204, -204,   58, -204, -204,   58,   58,   58,   58,
+       58,   58,   58,  207,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -204
+
+    },
+
+    {
+       11, -205, -205, -205, -205, -205, -205, -205, -205, -205,
+     -205, -205, -205,   58, -205, -205,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,  208,   58,
+       58,   58,   58,   58,   58,   58,   58, -205
+    },
+
+    {
+       11, -206, -206, -206, -206, -206, -206, -206, -206, -206,
+     -206, -206, -206,   58, -206, -206,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,  209,   58,   58, -206
+    },
+
+    {
+       11, -207, -207, -207, -207, -207, -207, -207, -207, -207,
+     -207, -207, -207,   58, -207, -207,   58,   58,   58,   58,
+
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -207
+    },
+
+    {
+       11, -208, -208, -208, -208, -208, -208, -208, -208, -208,
+     -208, -208, -208,   58, -208, -208,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -208
+    },
+
+    {
+       11, -209, -209, -209, -209, -209, -209, -209, -209, -209,
+     -209, -209, -209,   58, -209, -209,   58,   58,   58,   58,
+       58,  210,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -209
+
+    },
+
+    {
+       11, -210, -210, -210, -210, -210, -210, -210, -210, -210,
+     -210, -210, -210,   58, -210, -210,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58, -210
+    },
+
+    } ;
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up zconftext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	zconfleng = (size_t) (yy_cp - yy_bp); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 64
+#define YY_END_OF_BUFFER 65
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[211] =
+    {   0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+       65,    5,    4,    3,    2,   36,   37,   35,   35,   35,
+       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
+       63,   60,   62,   55,   59,   58,   57,   53,   48,   42,
+       47,   51,   53,   40,   41,   50,   50,   43,   53,   50,
+       50,   53,    4,    3,    2,    2,    1,   35,   35,   35,
+       35,   35,   35,   35,   16,   35,   35,   35,   35,   35,
+       35,   35,   35,   35,   35,   35,   63,   60,   62,   61,
+       55,   54,   57,   56,   44,   51,   38,   50,   50,   52,
+       45,   46,   39,   35,   35,   35,   35,   35,   35,   35,
+
+       35,   35,   30,   29,   35,   35,   35,   35,   35,   35,
+       35,   35,   35,   35,   49,   25,   35,   35,   35,   35,
+       35,   35,   35,   35,   35,   35,   15,   35,    7,   35,
+       35,   35,   35,   35,   35,   35,   35,   35,   35,   35,
+       35,   35,   35,   35,   35,   35,   35,   17,   35,   35,
+       35,   35,   35,   34,   35,   35,   35,   35,   35,   35,
+       10,   35,   13,   35,   35,   35,   35,   33,   35,   35,
+       35,   35,   35,   22,   35,   32,    9,   31,   35,   26,
+       12,   35,   35,   21,   18,   35,    8,   35,   35,   35,
+       35,   35,   27,   35,   35,    6,   35,   20,   19,   23,
+
+       35,   35,   11,   35,   35,   35,   14,   28,   35,   24
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    4,    5,    6,    1,    1,    7,    8,    9,
+       10,    1,    1,    1,   11,   12,   12,   13,   13,   13,
+       13,   13,   13,   13,   13,   13,   13,    1,    1,    1,
+       14,    1,    1,    1,   13,   13,   13,   13,   13,   13,
+       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
+       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
+        1,   15,    1,    1,   16,    1,   17,   18,   19,   20,
+
+       21,   22,   23,   24,   25,   13,   13,   26,   27,   28,
+       29,   30,   31,   32,   33,   34,   35,   13,   13,   36,
+       13,   13,    1,   37,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+extern int zconf_flex_debug;
+int zconf_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *zconftext;
+
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+#define START_STRSIZE	16
+
+char *text;
+static char *text_ptr;
+static int text_size, text_asize;
+
+struct buffer {
+        struct buffer *parent;
+        YY_BUFFER_STATE state;
+};
+
+struct buffer *current_buf;
+
+static int last_ts, first_ts;
+
+static void zconf_endhelp(void);
+static struct buffer *zconf_endfile(void);
+
+void new_string(void)
+{
+	text = malloc(START_STRSIZE);
+	text_asize = START_STRSIZE;
+	text_ptr = text;
+	text_size = 0;
+	*text_ptr = 0;
+}
+
+void append_string(const char *str, int size)
+{
+	int new_size = text_size + size + 1;
+	if (new_size > text_asize) {
+		text = realloc(text, new_size);
+		text_asize = new_size;
+		text_ptr = text + text_size;
+	}
+	memcpy(text_ptr, str, size);
+	text_ptr += size;
+	text_size += size;
+	*text_ptr = 0;
+}
+
+void alloc_string(const char *str, int size)
+{
+	text = malloc(size + 1);
+	memcpy(text, str, size);
+	text[size] = 0;
+}
+
+#define INITIAL 0
+#define COMMAND 1
+#define HELP 2
+#define STRING 3
+#define PARAM 4
+
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int zconfwrap (void );
+#else
+extern int zconfwrap (void );
+#endif
+#endif
+
+    static void yyunput (int c,char *buf_ptr  );
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( zconftext, zconfleng, 1, zconfout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	errno=0; \
+	while ( (result = read( fileno(zconfin), (char *) buf, max_size )) < 0 ) \
+	{ \
+		if( errno != EINTR) \
+		{ \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+			break; \
+		} \
+		errno=0; \
+		clearerr(zconfin); \
+	}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int zconflex (void);
+
+#define YY_DECL int zconflex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after zconftext and zconfleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+
+	int str = 0;
+	int ts, i;
+
+	if ( (yy_init) )
+		{
+		(yy_init) = 0;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! zconfin )
+			zconfin = stdin;
+
+		if ( ! zconfout )
+			zconfout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			zconfensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				zconf_create_buffer(zconfin,YY_BUF_SIZE );
+		}
+
+		zconf_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of zconftext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+yy_match:
+		while ( (yy_current_state = yy_nxt[yy_current_state][ yy_ec[YY_SC_TO_UI(*yy_cp)]  ]) > 0 )
+			++yy_cp;
+
+		yy_current_state = -yy_current_state;
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+case 1:
+/* rule 1 can match eol */
+YY_RULE_SETUP
+current_file->lineno++;
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+
+	YY_BREAK
+case 3:
+/* rule 3 can match eol */
+YY_RULE_SETUP
+current_file->lineno++; return T_EOL;
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+{
+	BEGIN(COMMAND);
+}
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+{
+	unput(zconftext[0]);
+	BEGIN(COMMAND);
+}
+	YY_BREAK
+
+case 6:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_MAINMENU;
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_MENU;
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_ENDMENU;
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_SOURCE;
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_CHOICE;
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_ENDCHOICE;
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_COMMENT;
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_CONFIG;
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_MENUCONFIG;
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_HELP;
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_IF;
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_ENDIF;
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_DEPENDS;
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_REQUIRES;
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_OPTIONAL;
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_DEFAULT;
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_PROMPT;
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_TRISTATE;
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_DEF_TRISTATE;
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_BOOLEAN;
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_BOOLEAN;
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_DEF_BOOLEAN;
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_DEF_BOOLEAN;
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_INT;
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_HEX;
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_STRING;
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_SELECT;
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_SELECT;
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+BEGIN(PARAM); return T_RANGE;
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+{
+		alloc_string(zconftext, zconfleng);
+		zconflval.string = text;
+		return T_WORD;
+	}
+	YY_BREAK
+case 36:
+YY_RULE_SETUP
+
+	YY_BREAK
+case 37:
+/* rule 37 can match eol */
+YY_RULE_SETUP
+current_file->lineno++; BEGIN(INITIAL);
+	YY_BREAK
+
+case 38:
+YY_RULE_SETUP
+return T_AND;
+	YY_BREAK
+case 39:
+YY_RULE_SETUP
+return T_OR;
+	YY_BREAK
+case 40:
+YY_RULE_SETUP
+return T_OPEN_PAREN;
+	YY_BREAK
+case 41:
+YY_RULE_SETUP
+return T_CLOSE_PAREN;
+	YY_BREAK
+case 42:
+YY_RULE_SETUP
+return T_NOT;
+	YY_BREAK
+case 43:
+YY_RULE_SETUP
+return T_EQUAL;
+	YY_BREAK
+case 44:
+YY_RULE_SETUP
+return T_UNEQUAL;
+	YY_BREAK
+case 45:
+YY_RULE_SETUP
+return T_IF;
+	YY_BREAK
+case 46:
+YY_RULE_SETUP
+return T_ON;
+	YY_BREAK
+case 47:
+YY_RULE_SETUP
+{
+		str = zconftext[0];
+		new_string();
+		BEGIN(STRING);
+	}
+	YY_BREAK
+case 48:
+/* rule 48 can match eol */
+YY_RULE_SETUP
+BEGIN(INITIAL); current_file->lineno++; return T_EOL;
+	YY_BREAK
+case 49:
+YY_RULE_SETUP
+/* ignore */
+	YY_BREAK
+case 50:
+YY_RULE_SETUP
+{
+		alloc_string(zconftext, zconfleng);
+		zconflval.string = text;
+		return T_WORD;
+	}
+	YY_BREAK
+case 51:
+YY_RULE_SETUP
+/* comment */
+	YY_BREAK
+case 52:
+/* rule 52 can match eol */
+YY_RULE_SETUP
+current_file->lineno++;
+	YY_BREAK
+case 53:
+YY_RULE_SETUP
+
+	YY_BREAK
+case YY_STATE_EOF(PARAM):
+{
+		BEGIN(INITIAL);
+	}
+	YY_BREAK
+
+case 54:
+/* rule 54 can match eol */
+*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up zconftext again */
+YY_RULE_SETUP
+{
+		append_string(zconftext, zconfleng);
+		zconflval.string = text;
+		return T_WORD_QUOTE;
+	}
+	YY_BREAK
+case 55:
+YY_RULE_SETUP
+{
+		append_string(zconftext, zconfleng);
+	}
+	YY_BREAK
+case 56:
+/* rule 56 can match eol */
+*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up zconftext again */
+YY_RULE_SETUP
+{
+		append_string(zconftext + 1, zconfleng - 1);
+		zconflval.string = text;
+		return T_WORD_QUOTE;
+	}
+	YY_BREAK
+case 57:
+YY_RULE_SETUP
+{
+		append_string(zconftext + 1, zconfleng - 1);
+	}
+	YY_BREAK
+case 58:
+YY_RULE_SETUP
+{
+		if (str == zconftext[0]) {
+			BEGIN(PARAM);
+			zconflval.string = text;
+			return T_WORD_QUOTE;
+		} else
+			append_string(zconftext, 1);
+	}
+	YY_BREAK
+case 59:
+/* rule 59 can match eol */
+YY_RULE_SETUP
+{
+		printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
+		current_file->lineno++;
+		BEGIN(INITIAL);
+		return T_EOL;
+	}
+	YY_BREAK
+case YY_STATE_EOF(STRING):
+{
+		BEGIN(INITIAL);
+	}
+	YY_BREAK
+
+case 60:
+YY_RULE_SETUP
+{
+		ts = 0;
+		for (i = 0; i < zconfleng; i++) {
+			if (zconftext[i] == '\t')
+				ts = (ts & ~7) + 8;
+			else
+				ts++;
+		}
+		last_ts = ts;
+		if (first_ts) {
+			if (ts < first_ts) {
+				zconf_endhelp();
+				return T_HELPTEXT;
+			}
+			ts -= first_ts;
+			while (ts > 8) {
+				append_string("        ", 8);
+				ts -= 8;
+			}
+			append_string("        ", ts);
+		}
+	}
+	YY_BREAK
+case 61:
+/* rule 61 can match eol */
+*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up zconftext again */
+YY_RULE_SETUP
+{
+		current_file->lineno++;
+		zconf_endhelp();
+		return T_HELPTEXT;
+	}
+	YY_BREAK
+case 62:
+/* rule 62 can match eol */
+YY_RULE_SETUP
+{
+		current_file->lineno++;
+		append_string("\n", 1);
+	}
+	YY_BREAK
+case 63:
+YY_RULE_SETUP
+{
+		append_string(zconftext, zconfleng);
+		if (!first_ts)
+			first_ts = last_ts;
+	}
+	YY_BREAK
+case YY_STATE_EOF(HELP):
+{
+		zconf_endhelp();
+		return T_HELPTEXT;
+	}
+	YY_BREAK
+
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(COMMAND):
+{
+	if (current_buf) {
+		zconf_endfile();
+		return T_EOF;
+	}
+	fclose(zconfin);
+	yyterminate();
+}
+	YY_BREAK
+case 64:
+YY_RULE_SETUP
+YY_FATAL_ERROR( "flex scanner jammed" );
+	YY_BREAK
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed zconfin at a new source and called
+			 * zconflex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = zconfin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( zconfwrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * zconftext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of zconflex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			size_t num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					zconfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			zconfrestart(zconfin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+
+	yy_current_state = (yy_start);
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+
+	yy_current_state = yy_nxt[yy_current_state][1];
+	yy_is_jam = (yy_current_state <= 0);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+    static void yyunput (int c, register char * yy_bp )
+{
+	register char *yy_cp;
+
+    yy_cp = (yy_c_buf_p);
+
+	/* undo effects of setting up zconftext */
+	*yy_cp = (yy_hold_char);
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = (yy_n_chars) + 2;
+		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		register char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+	(yytext_ptr) = yy_bp;
+	(yy_hold_char) = *yy_cp;
+	(yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					zconfrestart(zconfin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( zconfwrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve zconftext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void zconfrestart  (FILE * input_file )
+{
+
+	if ( ! YY_CURRENT_BUFFER ){
+        zconfensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            zconf_create_buffer(zconfin,YY_BUF_SIZE );
+	}
+
+	zconf_init_buffer(YY_CURRENT_BUFFER,input_file );
+	zconf_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+    void zconf_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		zconfpop_buffer_state();
+	 *		zconfpush_buffer_state(new_buffer);
+     */
+	zconfensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	zconf_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (zconfwrap()) processing, but the only time this flag
+	 * is looked at is after zconfwrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void zconf_load_buffer_state  (void)
+{
+	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	zconfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE zconf_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+
+	b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) zconfalloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	zconf_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with zconf_create_buffer()
+ *
+ */
+    void zconf_delete_buffer (YY_BUFFER_STATE  b )
+{
+
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		zconffree((void *) b->yy_ch_buf  );
+
+	zconffree((void *) b  );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a zconfrestart() or at EOF.
+ */
+    static void zconf_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+
+	zconf_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then zconf_init_buffer was _probably_
+     * called from zconfrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+    void zconf_flush_buffer (YY_BUFFER_STATE  b )
+{
+	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		zconf_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *
+ */
+void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+	if (new_buffer == NULL)
+		return;
+
+	zconfensure_buffer_stack();
+
+	/* This block is copied from zconf_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from zconf_switch_to_buffer. */
+	zconf_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *
+ */
+void zconfpop_buffer_state (void)
+{
+	if (!YY_CURRENT_BUFFER)
+		return;
+
+	zconf_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		zconf_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void zconfensure_buffer_stack (void)
+{
+	int num_to_alloc;
+
+	if (!(yy_buffer_stack)) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		(yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)zconfrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_buffer_stack_max) = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE zconf_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	zconf_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to zconflex() will
+ * scan from a @e copy of @a str.
+ * @param str a NUL-terminated string to scan
+ *
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       zconf_scan_bytes() instead.
+ */
+YY_BUFFER_STATE zconf_scan_string (yyconst char * str )
+{
+
+	return zconf_scan_bytes(str,strlen(str) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE zconf_scan_bytes  (yyconst char * bytes, int  len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = len + 2;
+	buf = (char *) zconfalloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" );
+
+	for ( i = 0; i < len; ++i )
+		buf[i] = bytes[i];
+
+	buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = zconf_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in zconf_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up zconftext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		zconftext[zconfleng] = (yy_hold_char); \
+		(yy_c_buf_p) = zconftext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		zconfleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ *
+ */
+int zconfget_lineno  (void)
+{
+
+    return zconflineno;
+}
+
+/** Get the input stream.
+ *
+ */
+FILE *zconfget_in  (void)
+{
+        return zconfin;
+}
+
+/** Get the output stream.
+ *
+ */
+FILE *zconfget_out  (void)
+{
+        return zconfout;
+}
+
+/** Get the length of the current token.
+ *
+ */
+int zconfget_leng  (void)
+{
+        return zconfleng;
+}
+
+/** Get the current token.
+ *
+ */
+
+char *zconfget_text  (void)
+{
+        return zconftext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ *
+ */
+void zconfset_lineno (int  line_number )
+{
+
+    zconflineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ *
+ * @see zconf_switch_to_buffer
+ */
+void zconfset_in (FILE *  in_str )
+{
+        zconfin = in_str ;
+}
+
+void zconfset_out (FILE *  out_str )
+{
+        zconfout = out_str ;
+}
+
+int zconfget_debug  (void)
+{
+        return zconf_flex_debug;
+}
+
+void zconfset_debug (int  bdebug )
+{
+        zconf_flex_debug = bdebug ;
+}
+
+/* zconflex_destroy is for both reentrant and non-reentrant scanners. */
+int zconflex_destroy  (void)
+{
+
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		zconf_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		zconfpop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	zconffree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *zconfalloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *zconfrealloc  (void * ptr, yy_size_t  size )
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void zconffree (void * ptr )
+{
+	free( (char *) ptr );	/* see zconfrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#undef YY_NEW_FILE
+#undef YY_FLUSH_BUFFER
+#undef yy_set_bol
+#undef yy_new_buffer
+#undef yy_set_interactive
+#undef yytext_ptr
+#undef YY_DO_BEFORE_ACTION
+
+#ifdef YY_DECL_IS_OURS
+#undef YY_DECL_IS_OURS
+#undef YY_DECL
+#endif
+
+void zconf_starthelp(void)
+{
+	new_string();
+	last_ts = first_ts = 0;
+	BEGIN(HELP);
+}
+
+static void zconf_endhelp(void)
+{
+	zconflval.string = text;
+	BEGIN(INITIAL);
+}
+
+/*
+ * Try to open specified file with following names:
+ * ./name
+ * $(srctree)/name
+ * The latter is used when srctree is separate from objtree
+ * when compiling the kernel.
+ * Return NULL if file is not found.
+ */
+FILE *zconf_fopen(const char *name)
+{
+	char *env, fullname[PATH_MAX+1];
+	FILE *f;
+
+	f = fopen(name, "r");
+	if (!f && name[0] != '/') {
+		env = getenv(SRCTREE);
+		if (env) {
+			sprintf(fullname, "%s/%s", env, name);
+			f = fopen(fullname, "r");
+		}
+	}
+	return f;
+}
+
+void zconf_initscan(const char *name)
+{
+	zconfin = zconf_fopen(name);
+	if (!zconfin) {
+		printf("can't find file %s\n", name);
+		exit(1);
+	}
+
+	current_buf = malloc(sizeof(*current_buf));
+	memset(current_buf, 0, sizeof(*current_buf));
+
+	current_file = file_lookup(name);
+	current_file->lineno = 1;
+	current_file->flags = FILE_BUSY;
+}
+
+void zconf_nextfile(const char *name)
+{
+	struct file *file = file_lookup(name);
+	struct buffer *buf = malloc(sizeof(*buf));
+	memset(buf, 0, sizeof(*buf));
+
+	current_buf->state = YY_CURRENT_BUFFER;
+	zconfin = zconf_fopen(name);
+	if (!zconfin) {
+		printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
+		exit(1);
+	}
+	zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE));
+	buf->parent = current_buf;
+	current_buf = buf;
+
+	if (file->flags & FILE_BUSY) {
+		printf("recursive scan (%s)?\n", name);
+		exit(1);
+	}
+	if (file->flags & FILE_SCANNED) {
+		printf("file %s already scanned?\n", name);
+		exit(1);
+	}
+	file->flags |= FILE_BUSY;
+	file->lineno = 1;
+	file->parent = current_file;
+	current_file = file;
+}
+
+static struct buffer *zconf_endfile(void)
+{
+	struct buffer *parent;
+
+	current_file->flags |= FILE_SCANNED;
+	current_file->flags &= ~FILE_BUSY;
+	current_file = current_file->parent;
+
+	parent = current_buf->parent;
+	if (parent) {
+		fclose(zconfin);
+		zconf_delete_buffer(YY_CURRENT_BUFFER);
+		zconf_switch_to_buffer(parent->state);
+	}
+	free(current_buf);
+	current_buf = parent;
+
+	return parent;
+}
+
+int zconf_lineno(void)
+{
+	if (current_buf)
+		return current_file->lineno - 1;
+	else
+		return 0;
+}
+
+char *zconf_curname(void)
+{
+	if (current_buf)
+		return current_file->name;
+	else
+		return "<none>";
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lkc.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lkc.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lkc.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#ifndef LKC_H
+#define LKC_H
+
+#include "expr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef LKC_DIRECT_LINK
+#define P(name,type,arg)	extern type name arg
+#else
+#include "lkc_defs.h"
+#define P(name,type,arg)	extern type (*name ## _p) arg
+#endif
+#include "lkc_proto.h"
+#undef P
+
+#define SRCTREE "srctree"
+
+int zconfparse(void);
+void zconfdump(FILE *out);
+
+extern int zconfdebug;
+void zconf_starthelp(void);
+FILE *zconf_fopen(const char *name);
+void zconf_initscan(const char *name);
+void zconf_nextfile(const char *name);
+int zconf_lineno(void);
+char *zconf_curname(void);
+
+/* confdata.c */
+extern const char conf_def_filename[];
+extern char conf_filename[];
+
+char *conf_get_default_confname(void);
+
+/* kconfig_load.c */
+void kconfig_load(void);
+
+/* menu.c */
+void menu_init(void);
+void menu_add_menu(void);
+void menu_end_menu(void);
+void menu_add_entry(struct symbol *sym);
+void menu_end_entry(void);
+void menu_add_dep(struct expr *dep);
+struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);
+void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
+void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
+void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
+void menu_finalize(struct menu *parent);
+void menu_set_type(int type);
+
+/* util.c */
+struct file *file_lookup(const char *name);
+int file_write_dep(const char *name);
+
+struct gstr {
+	size_t len;
+	char  *s;
+};
+struct gstr str_new(void);
+struct gstr str_assign(const char *s);
+void str_free(struct gstr *gs);
+void str_append(struct gstr *gs, const char *s);
+void str_printf(struct gstr *gs, const char *fmt, ...);
+const char *str_get(struct gstr *gs);
+
+/* symbol.c */
+void sym_init(void);
+void sym_clear_all_valid(void);
+void sym_set_changed(struct symbol *sym);
+struct symbol *sym_check_deps(struct symbol *sym);
+struct property *prop_alloc(enum prop_type type, struct symbol *sym);
+struct symbol *prop_get_symbol(struct property *prop);
+
+static inline tristate sym_get_tristate_value(struct symbol *sym)
+{
+	return sym->curr.tri;
+}
+
+
+static inline struct symbol *sym_get_choice_value(struct symbol *sym)
+{
+	return (struct symbol *)sym->curr.val;
+}
+
+static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval)
+{
+	return sym_set_tristate_value(chval, yes);
+}
+
+static inline bool sym_is_choice(struct symbol *sym)
+{
+	return sym->flags & SYMBOL_CHOICE ? true : false;
+}
+
+static inline bool sym_is_choice_value(struct symbol *sym)
+{
+	return sym->flags & SYMBOL_CHOICEVAL ? true : false;
+}
+
+static inline bool sym_is_optional(struct symbol *sym)
+{
+	return sym->flags & SYMBOL_OPTIONAL ? true : false;
+}
+
+static inline bool sym_has_value(struct symbol *sym)
+{
+	return sym->flags & SYMBOL_NEW ? false : true;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LKC_H */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lkc_proto.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lkc_proto.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lkc_proto.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,40 @@
+
+/* confdata.c */
+P(conf_parse,void,(const char *name));
+P(conf_read,int,(const char *name));
+P(conf_write,int,(const char *name));
+
+/* menu.c */
+P(rootmenu,struct menu,);
+
+P(menu_is_visible,bool,(struct menu *menu));
+P(menu_get_prompt,const char *,(struct menu *menu));
+P(menu_get_root_menu,struct menu *,(struct menu *menu));
+P(menu_get_parent_menu,struct menu *,(struct menu *menu));
+
+/* symbol.c */
+P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
+P(sym_change_count,int,);
+
+P(sym_lookup,struct symbol *,(const char *name, int isconst));
+P(sym_find,struct symbol *,(const char *name));
+P(sym_re_search,struct symbol **,(const char *pattern));
+P(sym_type_name,const char *,(enum symbol_type type));
+P(sym_calc_value,void,(struct symbol *sym));
+P(sym_get_type,enum symbol_type,(struct symbol *sym));
+P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri));
+P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri));
+P(sym_toggle_tristate_value,tristate,(struct symbol *sym));
+P(sym_string_valid,bool,(struct symbol *sym, const char *newval));
+P(sym_string_within_range,bool,(struct symbol *sym, const char *str));
+P(sym_set_string_value,bool,(struct symbol *sym, const char *newval));
+P(sym_is_changable,bool,(struct symbol *sym));
+P(sym_get_choice_prop,struct property *,(struct symbol *sym));
+P(sym_get_default_prop,struct property *,(struct symbol *sym));
+P(sym_get_string_value,const char *,(struct symbol *sym));
+
+P(prop_get_type_name,const char *,(enum prop_type type));
+
+/* expr.c */
+P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2));
+P(expr_print,void,(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken));

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/BIG.FAT.WARNING
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/BIG.FAT.WARNING	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/BIG.FAT.WARNING	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+This is NOT the official version of dialog.  This version has been
+significantly modified from the original.  It is for use by the Linux
+kernel configuration script.  Please do not bother Savio Lam with 
+questions about this program.

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/checklist.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/checklist.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/checklist.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,372 @@
+/*
+ *  checklist.c -- implements the checklist box
+ *
+ *  ORIGINAL AUTHOR: Savio Lam (lam836 at cs.cuhk.hk)
+ *     Stuart Herbert - S.Herbert at sheffield.ac.uk: radiolist extension
+ *     Alessandro Rubini - rubini at ipvvis.unipv.it: merged the two
+ *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap at cfw.com)
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+static int list_width, check_x, item_x, checkflag;
+
+/*
+ * Print list item
+ */
+static void
+print_item (WINDOW * win, const char *item, int status,
+	    int choice, int selected)
+{
+    int i;
+
+    /* Clear 'residue' of last item */
+    wattrset (win, menubox_attr);
+    wmove (win, choice, 0);
+    for (i = 0; i < list_width; i++)
+	waddch (win, ' ');
+
+    wmove (win, choice, check_x);
+    wattrset (win, selected ? check_selected_attr : check_attr);
+    if (checkflag == FLAG_CHECK)
+	wprintw (win, "[%c]", status ? 'X' : ' ');
+    else
+	wprintw (win, "(%c)", status ? 'X' : ' ');
+
+    wattrset (win, selected ? tag_selected_attr : tag_attr);
+    mvwaddch(win, choice, item_x, item[0]);
+    wattrset (win, selected ? item_selected_attr : item_attr);
+    waddstr (win, (char *)item+1);
+    if (selected) {
+	wmove (win, choice, check_x+1);
+	wrefresh (win);
+    }
+}
+
+/*
+ * Print the scroll indicators.
+ */
+static void
+print_arrows (WINDOW * win, int choice, int item_no, int scroll,
+		int y, int x, int height)
+{
+    wmove(win, y, x);
+
+    if (scroll > 0) {
+	wattrset (win, uarrow_attr);
+	waddch (win, ACS_UARROW);
+	waddstr (win, "(-)");
+    }
+    else {
+	wattrset (win, menubox_attr);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+    }
+
+   y = y + height + 1;
+   wmove(win, y, x);
+
+   if ((height < item_no) && (scroll + choice < item_no - 1)) {
+	wattrset (win, darrow_attr);
+	waddch (win, ACS_DARROW);
+	waddstr (win, "(+)");
+    }
+    else {
+	wattrset (win, menubox_border_attr);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+   }
+}
+
+/*
+ *  Display the termination buttons
+ */
+static void
+print_buttons( WINDOW *dialog, int height, int width, int selected)
+{
+    int x = width / 2 - 11;
+    int y = height - 2;
+
+    print_button (dialog, "Select", y, x, selected == 0);
+    print_button (dialog, " Help ", y, x + 14, selected == 1);
+
+    wmove(dialog, y, x+1 + 14*selected);
+    wrefresh (dialog);
+}
+
+/*
+ * Display a dialog box with a list of options that can be turned on or off
+ * The `flag' parameter is used to select between radiolist and checklist.
+ */
+int
+dialog_checklist (const char *title, const char *prompt, int height, int width,
+	int list_height, int item_no, struct dialog_list_item ** items,
+	int flag)
+
+{
+    int i, x, y, box_x, box_y;
+    int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status;
+    WINDOW *dialog, *list;
+
+    checkflag = flag;
+
+    /* Allocate space for storing item on/off status */
+    if ((status = malloc (sizeof (int) * item_no)) == NULL) {
+	endwin ();
+	fprintf (stderr,
+		 "\nCan't allocate memory in dialog_checklist().\n");
+	exit (-1);
+    }
+
+    /* Initializes status */
+    for (i = 0; i < item_no; i++) {
+	status[i] = (items[i]->selected == 1); /* ON */
+	if ((!choice && status[i]) || items[i]->selected == 2) /* SELECTED */
+	    choice = i + 1;
+    }
+    if (choice)
+	    choice--;
+
+    max_choice = MIN (list_height, item_no);
+
+    /* center dialog box on screen */
+    x = (COLS - width) / 2;
+    y = (LINES - height) / 2;
+
+    draw_shadow (stdscr, y, x, height, width);
+
+    dialog = newwin (height, width, y, x);
+    keypad (dialog, TRUE);
+
+    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+    wattrset (dialog, border_attr);
+    mvwaddch (dialog, height-3, 0, ACS_LTEE);
+    for (i = 0; i < width - 2; i++)
+	waddch (dialog, ACS_HLINE);
+    wattrset (dialog, dialog_attr);
+    waddch (dialog, ACS_RTEE);
+
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
+    if (title != NULL) {
+	wattrset (dialog, title_attr);
+	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+	waddstr (dialog, (char *)title);
+	waddch (dialog, ' ');
+    }
+
+    wattrset (dialog, dialog_attr);
+    print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+    list_width = width - 6;
+    box_y = height - list_height - 5;
+    box_x = (width - list_width) / 2 - 1;
+
+    /* create new window for the list */
+    list = subwin (dialog, list_height, list_width, y+box_y+1, x+box_x+1);
+
+    keypad (list, TRUE);
+
+    /* draw a box around the list items */
+    draw_box (dialog, box_y, box_x, list_height + 2, list_width + 2,
+	      menubox_border_attr, menubox_attr);
+
+    /* Find length of longest item in order to center checklist */
+    check_x = 0;
+    for (i = 0; i < item_no; i++)
+	check_x = MAX (check_x, + strlen (items[i]->name) + 4);
+
+    check_x = (list_width - check_x) / 2;
+    item_x = check_x + 4;
+
+    if (choice >= list_height) {
+	scroll = choice - list_height + 1;
+	choice -= scroll;
+    }
+
+    /* Print the list */
+    for (i = 0; i < max_choice; i++) {
+	print_item (list, items[scroll + i]->name,
+		    status[i+scroll], i, i == choice);
+    }
+
+    print_arrows(dialog, choice, item_no, scroll,
+			box_y, box_x + check_x + 5, list_height);
+
+    print_buttons(dialog, height, width, 0);
+
+    wnoutrefresh (list);
+    wnoutrefresh (dialog);
+    doupdate ();
+
+    while (key != ESC) {
+	key = wgetch (dialog);
+
+	for (i = 0; i < max_choice; i++)
+	    if (toupper(key) == toupper(items[scroll + i]->name[0]))
+		break;
+
+
+	if ( i < max_choice || key == KEY_UP || key == KEY_DOWN ||
+	    key == '+' || key == '-' ) {
+	    if (key == KEY_UP || key == '-') {
+		if (!choice) {
+		    if (!scroll)
+			continue;
+		    /* Scroll list down */
+		    if (list_height > 1) {
+			/* De-highlight current first item */
+			print_item (list, items[scroll]->name,
+					status[scroll], 0, FALSE);
+			scrollok (list, TRUE);
+			wscrl (list, -1);
+			scrollok (list, FALSE);
+		    }
+		    scroll--;
+		    print_item (list, items[scroll]->name,
+				status[scroll], 0, TRUE);
+		    wnoutrefresh (list);
+
+		    print_arrows(dialog, choice, item_no, scroll,
+				box_y, box_x + check_x + 5, list_height);
+
+		    wrefresh (dialog);
+
+		    continue;	/* wait for another key press */
+		} else
+		    i = choice - 1;
+	    } else if (key == KEY_DOWN || key == '+') {
+		if (choice == max_choice - 1) {
+		    if (scroll + choice >= item_no - 1)
+			continue;
+		    /* Scroll list up */
+		    if (list_height > 1) {
+			/* De-highlight current last item before scrolling up */
+			print_item (list, items[scroll + max_choice - 1]->name,
+				    status[scroll + max_choice - 1],
+				    max_choice - 1, FALSE);
+			scrollok (list, TRUE);
+			scroll (list);
+			scrollok (list, FALSE);
+		    }
+		    scroll++;
+		    print_item (list, items[scroll + max_choice - 1]->name,
+				status[scroll + max_choice - 1],
+				max_choice - 1, TRUE);
+		    wnoutrefresh (list);
+
+		    print_arrows(dialog, choice, item_no, scroll,
+				box_y, box_x + check_x + 5, list_height);
+
+		    wrefresh (dialog);
+
+		    continue;	/* wait for another key press */
+		} else
+		    i = choice + 1;
+	    }
+	    if (i != choice) {
+		/* De-highlight current item */
+		print_item (list, items[scroll + choice]->name,
+			    status[scroll + choice], choice, FALSE);
+		/* Highlight new item */
+		choice = i;
+		print_item (list, items[scroll + choice]->name,
+			    status[scroll + choice], choice, TRUE);
+		wnoutrefresh (list);
+		wrefresh (dialog);
+	    }
+	    continue;		/* wait for another key press */
+	}
+	switch (key) {
+	case 'H':
+	case 'h':
+	case '?':
+	    for (i = 0; i < item_no; i++)
+		items[i]->selected = 0;
+	    items[scroll + choice]->selected = 1;
+	    delwin (dialog);
+	    free (status);
+	    return 1;
+	case TAB:
+	case KEY_LEFT:
+	case KEY_RIGHT:
+	    button = ((key == KEY_LEFT ? --button : ++button) < 0)
+			? 1 : (button > 1 ? 0 : button);
+
+	    print_buttons(dialog, height, width, button);
+	    wrefresh (dialog);
+	    break;
+	case 'S':
+	case 's':
+	case ' ':
+	case '\n':
+	    if (!button) {
+		if (flag == FLAG_CHECK) {
+		    status[scroll + choice] = !status[scroll + choice];
+		    wmove (list, choice, check_x);
+		    wattrset (list, check_selected_attr);
+		    wprintw (list, "[%c]", status[scroll + choice] ? 'X' : ' ');
+		} else {
+		    if (!status[scroll + choice]) {
+			for (i = 0; i < item_no; i++)
+			    status[i] = 0;
+			status[scroll + choice] = 1;
+			for (i = 0; i < max_choice; i++)
+			    print_item (list, items[scroll + i]->name,
+					status[scroll + i], i, i == choice);
+		    }
+		}
+		wnoutrefresh (list);
+		wrefresh (dialog);
+
+		for (i = 0; i < item_no; i++) {
+			items[i]->selected = status[i];
+		}
+	    } else {
+		    for (i = 0; i < item_no; i++)
+			    items[i]->selected = 0;
+		    items[scroll + choice]->selected = 1;
+	    }
+	    delwin (dialog);
+	    free (status);
+	    return button;
+	case 'X':
+	case 'x':
+	    key = ESC;
+	case ESC:
+	    break;
+	}
+
+	/* Now, update everything... */
+	doupdate ();
+    }
+
+
+    delwin (dialog);
+    free (status);
+    return -1;			/* ESC pressed */
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/colors.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/colors.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/colors.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,161 @@
+/*
+ *  colors.h -- color attribute definitions
+ *
+ *  AUTHOR: Savio Lam (lam836 at cs.cuhk.hk)
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ *   Default color definitions
+ *
+ *   *_FG = foreground
+ *   *_BG = background
+ *   *_HL = highlight?
+ */
+#define SCREEN_FG                    COLOR_CYAN
+#define SCREEN_BG                    COLOR_BLUE
+#define SCREEN_HL                    TRUE
+
+#define SHADOW_FG                    COLOR_BLACK
+#define SHADOW_BG                    COLOR_BLACK
+#define SHADOW_HL                    TRUE
+
+#define DIALOG_FG                    COLOR_BLACK
+#define DIALOG_BG                    COLOR_WHITE
+#define DIALOG_HL                    FALSE
+
+#define TITLE_FG                     COLOR_YELLOW
+#define TITLE_BG                     COLOR_WHITE
+#define TITLE_HL                     TRUE
+
+#define BORDER_FG                    COLOR_WHITE
+#define BORDER_BG                    COLOR_WHITE
+#define BORDER_HL                    TRUE
+
+#define BUTTON_ACTIVE_FG             COLOR_WHITE
+#define BUTTON_ACTIVE_BG             COLOR_BLUE
+#define BUTTON_ACTIVE_HL             TRUE
+
+#define BUTTON_INACTIVE_FG           COLOR_BLACK
+#define BUTTON_INACTIVE_BG           COLOR_WHITE
+#define BUTTON_INACTIVE_HL           FALSE
+
+#define BUTTON_KEY_ACTIVE_FG         COLOR_WHITE
+#define BUTTON_KEY_ACTIVE_BG         COLOR_BLUE
+#define BUTTON_KEY_ACTIVE_HL         TRUE
+
+#define BUTTON_KEY_INACTIVE_FG       COLOR_RED
+#define BUTTON_KEY_INACTIVE_BG       COLOR_WHITE
+#define BUTTON_KEY_INACTIVE_HL       FALSE
+
+#define BUTTON_LABEL_ACTIVE_FG       COLOR_YELLOW
+#define BUTTON_LABEL_ACTIVE_BG       COLOR_BLUE
+#define BUTTON_LABEL_ACTIVE_HL       TRUE
+
+#define BUTTON_LABEL_INACTIVE_FG     COLOR_BLACK
+#define BUTTON_LABEL_INACTIVE_BG     COLOR_WHITE
+#define BUTTON_LABEL_INACTIVE_HL     TRUE
+
+#define INPUTBOX_FG                  COLOR_BLACK
+#define INPUTBOX_BG                  COLOR_WHITE
+#define INPUTBOX_HL                  FALSE
+
+#define INPUTBOX_BORDER_FG           COLOR_BLACK
+#define INPUTBOX_BORDER_BG           COLOR_WHITE
+#define INPUTBOX_BORDER_HL           FALSE
+
+#define SEARCHBOX_FG                 COLOR_BLACK
+#define SEARCHBOX_BG                 COLOR_WHITE
+#define SEARCHBOX_HL                 FALSE
+
+#define SEARCHBOX_TITLE_FG           COLOR_YELLOW
+#define SEARCHBOX_TITLE_BG           COLOR_WHITE
+#define SEARCHBOX_TITLE_HL           TRUE
+
+#define SEARCHBOX_BORDER_FG          COLOR_WHITE
+#define SEARCHBOX_BORDER_BG          COLOR_WHITE
+#define SEARCHBOX_BORDER_HL          TRUE
+
+#define POSITION_INDICATOR_FG        COLOR_YELLOW
+#define POSITION_INDICATOR_BG        COLOR_WHITE
+#define POSITION_INDICATOR_HL        TRUE
+
+#define MENUBOX_FG                   COLOR_BLACK
+#define MENUBOX_BG                   COLOR_WHITE
+#define MENUBOX_HL                   FALSE
+
+#define MENUBOX_BORDER_FG            COLOR_WHITE
+#define MENUBOX_BORDER_BG            COLOR_WHITE
+#define MENUBOX_BORDER_HL            TRUE
+
+#define ITEM_FG                      COLOR_BLACK
+#define ITEM_BG                      COLOR_WHITE
+#define ITEM_HL                      FALSE
+
+#define ITEM_SELECTED_FG             COLOR_WHITE
+#define ITEM_SELECTED_BG             COLOR_BLUE
+#define ITEM_SELECTED_HL             TRUE
+
+#define TAG_FG                       COLOR_YELLOW
+#define TAG_BG                       COLOR_WHITE
+#define TAG_HL                       TRUE
+
+#define TAG_SELECTED_FG              COLOR_YELLOW
+#define TAG_SELECTED_BG              COLOR_BLUE
+#define TAG_SELECTED_HL              TRUE
+
+#define TAG_KEY_FG                   COLOR_YELLOW
+#define TAG_KEY_BG                   COLOR_WHITE
+#define TAG_KEY_HL                   TRUE
+
+#define TAG_KEY_SELECTED_FG          COLOR_YELLOW
+#define TAG_KEY_SELECTED_BG          COLOR_BLUE
+#define TAG_KEY_SELECTED_HL          TRUE
+
+#define CHECK_FG                     COLOR_BLACK
+#define CHECK_BG                     COLOR_WHITE
+#define CHECK_HL                     FALSE
+
+#define CHECK_SELECTED_FG            COLOR_WHITE
+#define CHECK_SELECTED_BG            COLOR_BLUE
+#define CHECK_SELECTED_HL            TRUE
+
+#define UARROW_FG                    COLOR_GREEN
+#define UARROW_BG                    COLOR_WHITE
+#define UARROW_HL                    TRUE
+
+#define DARROW_FG                    COLOR_GREEN
+#define DARROW_BG                    COLOR_WHITE
+#define DARROW_HL                    TRUE
+
+/* End of default color definitions */
+
+#define C_ATTR(x,y)                  ((x ? A_BOLD : 0) | COLOR_PAIR((y)))
+#define COLOR_NAME_LEN               10
+#define COLOR_COUNT                  8
+
+/*
+ * Global variables
+ */
+
+typedef struct {
+    char name[COLOR_NAME_LEN];
+    int value;
+} color_names_st;
+
+extern color_names_st color_names[];
+extern int color_table[][3];

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/dialog.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/dialog.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/dialog.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,199 @@
+
+/*
+ *  dialog.h -- common declarations for all dialog modules
+ *
+ *  AUTHOR: Savio Lam (lam836 at cs.cuhk.hk)
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef CURSES_LOC
+#ifdef __sun__
+#define CURS_MACROS
+#endif
+#include CURSES_LOC
+
+/*
+ * Colors in ncurses 1.9.9e do not work properly since foreground and
+ * background colors are OR'd rather than separately masked.  This version
+ * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible
+ * with standard curses.  The simplest fix (to make this work with standard
+ * curses) uses the wbkgdset() function, not used in the original hack.
+ * Turn it off if we're building with 1.9.9e, since it just confuses things.
+ */
+#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
+#define OLD_NCURSES 1
+#undef  wbkgdset
+#define wbkgdset(w,p) /*nothing*/
+#else
+#define OLD_NCURSES 0
+#endif
+
+#define TR(params) _tracef params
+
+#define ESC 27
+#define TAB 9
+#define MAX_LEN 2048
+#define BUF_SIZE (10*1024)
+#define MIN(x,y) (x < y ? x : y)
+#define MAX(x,y) (x > y ? x : y)
+
+
+#ifndef ACS_ULCORNER
+#define ACS_ULCORNER '+'
+#endif
+#ifndef ACS_LLCORNER
+#define ACS_LLCORNER '+'
+#endif
+#ifndef ACS_URCORNER
+#define ACS_URCORNER '+'
+#endif
+#ifndef ACS_LRCORNER
+#define ACS_LRCORNER '+'
+#endif
+#ifndef ACS_HLINE
+#define ACS_HLINE '-'
+#endif
+#ifndef ACS_VLINE
+#define ACS_VLINE '|'
+#endif
+#ifndef ACS_LTEE
+#define ACS_LTEE '+'
+#endif
+#ifndef ACS_RTEE
+#define ACS_RTEE '+'
+#endif
+#ifndef ACS_UARROW
+#define ACS_UARROW '^'
+#endif
+#ifndef ACS_DARROW
+#define ACS_DARROW 'v'
+#endif
+
+/*
+ * Attribute names
+ */
+#define screen_attr                   attributes[0]
+#define shadow_attr                   attributes[1]
+#define dialog_attr                   attributes[2]
+#define title_attr                    attributes[3]
+#define border_attr                   attributes[4]
+#define button_active_attr            attributes[5]
+#define button_inactive_attr          attributes[6]
+#define button_key_active_attr        attributes[7]
+#define button_key_inactive_attr      attributes[8]
+#define button_label_active_attr      attributes[9]
+#define button_label_inactive_attr    attributes[10]
+#define inputbox_attr                 attributes[11]
+#define inputbox_border_attr          attributes[12]
+#define searchbox_attr                attributes[13]
+#define searchbox_title_attr          attributes[14]
+#define searchbox_border_attr         attributes[15]
+#define position_indicator_attr       attributes[16]
+#define menubox_attr                  attributes[17]
+#define menubox_border_attr           attributes[18]
+#define item_attr                     attributes[19]
+#define item_selected_attr            attributes[20]
+#define tag_attr                      attributes[21]
+#define tag_selected_attr             attributes[22]
+#define tag_key_attr                  attributes[23]
+#define tag_key_selected_attr         attributes[24]
+#define check_attr                    attributes[25]
+#define check_selected_attr           attributes[26]
+#define uarrow_attr                   attributes[27]
+#define darrow_attr                   attributes[28]
+
+/* number of attributes */
+#define ATTRIBUTE_COUNT               29
+
+/*
+ * Global variables
+ */
+extern bool use_colors;
+
+extern chtype attributes[];
+#endif
+
+extern const char *backtitle;
+
+struct dialog_list_item {
+	char *name;
+	int namelen;
+	char *tag;
+	int selected; /* Set to 1 by dialog_*() function. */
+};
+
+/*
+ * Function prototypes
+ */
+
+void init_dialog (void);
+void end_dialog (void);
+void dialog_clear (void);
+#ifdef CURSES_LOC
+void attr_clear (WINDOW * win, int height, int width, chtype attr);
+void color_setup (void);
+void print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x);
+void print_button (WINDOW * win, const char *label, int y, int x, int selected);
+void draw_box (WINDOW * win, int y, int x, int height, int width, chtype box,
+		chtype border);
+void draw_shadow (WINDOW * win, int y, int x, int height, int width);
+#endif
+
+int first_alpha (const char *string, const char *exempt);
+int dialog_yesno (const char *title, const char *prompt, int height, int width);
+int dialog_msgbox (const char *title, const char *prompt, int height,
+		int width, int pause);
+int dialog_textbox (const char *title, const char *file, int height, int width);
+int dialog_menu (const char *title, const char *prompt, int height, int width,
+		int menu_height, const char *choice, int item_no,
+		struct dialog_list_item ** items);
+int dialog_checklist (const char *title, const char *prompt, int height,
+		int width, int list_height, int item_no,
+		struct dialog_list_item ** items, int flag);
+extern char dialog_input_result[];
+int dialog_inputbox (const char *title, const char *prompt, int height,
+		int width, const char *init);
+
+struct dialog_list_item *first_sel_item(int item_no,
+		struct dialog_list_item ** items);
+
+/*
+ * This is the base for fictitious keys, which activate
+ * the buttons.
+ *
+ * Mouse-generated keys are the following:
+ *   -- the first 32 are used as numbers, in addition to '0'-'9'
+ *   -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
+ *   -- uppercase chars are used to invoke the button (M_EVENT + 'O')
+ */
+#ifdef CURSES_LOC
+#define M_EVENT (KEY_MAX+1)
+#endif
+
+
+/*
+ * The `flag' parameter in checklist is used to select between
+ * radiolist and checklist
+ */
+#define FLAG_CHECK 1
+#define FLAG_RADIO 0

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/inputbox.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/inputbox.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/inputbox.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,240 @@
+/*
+ *  inputbox.c -- implements the input box
+ *
+ *  ORIGINAL AUTHOR: Savio Lam (lam836 at cs.cuhk.hk)
+ *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap at cfw.com)
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+char dialog_input_result[MAX_LEN + 1];
+
+/*
+ *  Print the termination buttons
+ */
+static void
+print_buttons(WINDOW *dialog, int height, int width, int selected)
+{
+    int x = width / 2 - 11;
+    int y = height - 2;
+
+    print_button (dialog, "  Ok  ", y, x, selected==0);
+    print_button (dialog, " Help ", y, x + 14, selected==1);
+
+    wmove(dialog, y, x+1+14*selected);
+    wrefresh(dialog);
+}
+
+/*
+ * Display a dialog box for inputing a string
+ */
+int
+dialog_inputbox (const char *title, const char *prompt, int height, int width,
+		 const char *init)
+{
+    int i, x, y, box_y, box_x, box_width;
+    int input_x = 0, scroll = 0, key = 0, button = -1;
+    char *instr = dialog_input_result;
+    WINDOW *dialog;
+
+    /* center dialog box on screen */
+    x = (COLS - width) / 2;
+    y = (LINES - height) / 2;
+
+
+    draw_shadow (stdscr, y, x, height, width);
+
+    dialog = newwin (height, width, y, x);
+    keypad (dialog, TRUE);
+
+    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+    wattrset (dialog, border_attr);
+    mvwaddch (dialog, height-3, 0, ACS_LTEE);
+    for (i = 0; i < width - 2; i++)
+	waddch (dialog, ACS_HLINE);
+    wattrset (dialog, dialog_attr);
+    waddch (dialog, ACS_RTEE);
+
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
+    if (title != NULL) {
+	wattrset (dialog, title_attr);
+	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+	waddstr (dialog, (char *)title);
+	waddch (dialog, ' ');
+    }
+
+    wattrset (dialog, dialog_attr);
+    print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+    /* Draw the input field box */
+    box_width = width - 6;
+    getyx (dialog, y, x);
+    box_y = y + 2;
+    box_x = (width - box_width) / 2;
+    draw_box (dialog, y + 1, box_x - 1, 3, box_width + 2,
+	      border_attr, dialog_attr);
+
+    print_buttons(dialog, height, width, 0);
+
+    /* Set up the initial value */
+    wmove (dialog, box_y, box_x);
+    wattrset (dialog, inputbox_attr);
+
+    if (!init)
+	instr[0] = '\0';
+    else
+	strcpy (instr, init);
+
+    input_x = strlen (instr);
+
+    if (input_x >= box_width) {
+	scroll = input_x - box_width + 1;
+	input_x = box_width - 1;
+	for (i = 0; i < box_width - 1; i++)
+	    waddch (dialog, instr[scroll + i]);
+    } else
+	waddstr (dialog, instr);
+
+    wmove (dialog, box_y, box_x + input_x);
+
+    wrefresh (dialog);
+
+    while (key != ESC) {
+	key = wgetch (dialog);
+
+	if (button == -1) {	/* Input box selected */
+	    switch (key) {
+	    case TAB:
+	    case KEY_UP:
+	    case KEY_DOWN:
+		break;
+	    case KEY_LEFT:
+		continue;
+	    case KEY_RIGHT:
+		continue;
+	    case KEY_BACKSPACE:
+	    case 127:
+		if (input_x || scroll) {
+		    wattrset (dialog, inputbox_attr);
+		    if (!input_x) {
+			scroll = scroll < box_width - 1 ?
+			    0 : scroll - (box_width - 1);
+			wmove (dialog, box_y, box_x);
+			for (i = 0; i < box_width; i++)
+			    waddch (dialog, instr[scroll + input_x + i] ?
+				    instr[scroll + input_x + i] : ' ');
+			input_x = strlen (instr) - scroll;
+		    } else
+			input_x--;
+		    instr[scroll + input_x] = '\0';
+		    mvwaddch (dialog, box_y, input_x + box_x, ' ');
+		    wmove (dialog, box_y, input_x + box_x);
+		    wrefresh (dialog);
+		}
+		continue;
+	    default:
+		if (key < 0x100 && isprint (key)) {
+		    if (scroll + input_x < MAX_LEN) {
+			wattrset (dialog, inputbox_attr);
+			instr[scroll + input_x] = key;
+			instr[scroll + input_x + 1] = '\0';
+			if (input_x == box_width - 1) {
+			    scroll++;
+			    wmove (dialog, box_y, box_x);
+			    for (i = 0; i < box_width - 1; i++)
+				waddch (dialog, instr[scroll + i]);
+			} else {
+			    wmove (dialog, box_y, input_x++ + box_x);
+			    waddch (dialog, key);
+			}
+			wrefresh (dialog);
+		    } else
+			flash ();	/* Alarm user about overflow */
+		    continue;
+		}
+	    }
+	}
+	switch (key) {
+	case 'O':
+	case 'o':
+	    delwin (dialog);
+	    return 0;
+	case 'H':
+	case 'h':
+	    delwin (dialog);
+	    return 1;
+	case KEY_UP:
+	case KEY_LEFT:
+	    switch (button) {
+	    case -1:
+		button = 1;	/* Indicates "Cancel" button is selected */
+		print_buttons(dialog, height, width, 1);
+		break;
+	    case 0:
+		button = -1;	/* Indicates input box is selected */
+		print_buttons(dialog, height, width, 0);
+		wmove (dialog, box_y, box_x + input_x);
+		wrefresh (dialog);
+		break;
+	    case 1:
+		button = 0;	/* Indicates "OK" button is selected */
+		print_buttons(dialog, height, width, 0);
+		break;
+	    }
+	    break;
+	case TAB:
+	case KEY_DOWN:
+	case KEY_RIGHT:
+	    switch (button) {
+	    case -1:
+		button = 0;	/* Indicates "OK" button is selected */
+		print_buttons(dialog, height, width, 0);
+		break;
+	    case 0:
+		button = 1;	/* Indicates "Cancel" button is selected */
+		print_buttons(dialog, height, width, 1);
+		break;
+	    case 1:
+		button = -1;	/* Indicates input box is selected */
+		print_buttons(dialog, height, width, 0);
+		wmove (dialog, box_y, box_x + input_x);
+		wrefresh (dialog);
+		break;
+	    }
+	    break;
+	case ' ':
+	case '\n':
+	    delwin (dialog);
+	    return (button == -1 ? 0 : button);
+	case 'X':
+	case 'x':
+	    key = ESC;
+	case ESC:
+	    break;
+	}
+    }
+
+    delwin (dialog);
+    return -1;			/* ESC pressed */
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/menubox.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/menubox.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/menubox.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,438 @@
+/*
+ *  menubox.c -- implements the menu box
+ *
+ *  ORIGINAL AUTHOR: Savio Lam (lam836 at cs.cuhk.hk)
+ *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw at cfw.com)
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *  Changes by Clifford Wolf (god at clifford.at)
+ *
+ *  [ 1998-06-13 ]
+ *
+ *    *)  A bugfix for the Page-Down problem
+ *
+ *    *)  Formerly when I used Page Down and Page Up, the cursor would be set
+ *        to the first position in the menu box.  Now lxdialog is a bit
+ *        smarter and works more like other menu systems (just have a look at
+ *        it).
+ *
+ *    *)  Formerly if I selected something my scrolling would be broken because
+ *        lxdialog is re-invoked by the Menuconfig shell script, can't
+ *        remember the last scrolling position, and just sets it so that the
+ *        cursor is at the bottom of the box.  Now it writes the temporary file
+ *        lxdialog.scrltmp which contains this information. The file is
+ *        deleted by lxdialog if the user leaves a submenu or enters a new
+ *        one, but it would be nice if Menuconfig could make another "rm -f"
+ *        just to be sure.  Just try it out - you will recognise a difference!
+ *
+ *  [ 1998-06-14 ]
+ *
+ *    *)  Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
+ *        and menus change their size on the fly.
+ *
+ *    *)  If for some reason the last scrolling position is not saved by
+ *        lxdialog, it sets the scrolling so that the selected item is in the
+ *        middle of the menu box, not at the bottom.
+ *
+ * 02 January 1999, Michael Elizabeth Chastain (mec at shout.net)
+ * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
+ * This fixes a bug in Menuconfig where using ' ' to descend into menus
+ * would leave mis-synchronized lxdialog.scrltmp files lying around,
+ * fscanf would read in 'scroll', and eventually that value would get used.
+ */
+
+#include "dialog.h"
+
+static int menu_width, item_x;
+
+/*
+ * Print menu item
+ */
+static void
+print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey)
+{
+    int j;
+    char menu_item[menu_width+1];
+
+    strncpy(menu_item, item, menu_width);
+    menu_item[menu_width] = 0;
+    j = first_alpha(menu_item, "YyNnMmHh");
+
+    /* Clear 'residue' of last item */
+    wattrset (win, menubox_attr);
+    wmove (win, choice, 0);
+#if OLD_NCURSES
+    {
+	int i;
+	for (i = 0; i < menu_width; i++)
+	    waddch (win, ' ');
+    }
+#else
+    wclrtoeol(win);
+#endif
+    wattrset (win, selected ? item_selected_attr : item_attr);
+    mvwaddstr (win, choice, item_x, menu_item);
+    if (hotkey) {
+	wattrset (win, selected ? tag_key_selected_attr : tag_key_attr);
+	mvwaddch(win, choice, item_x+j, menu_item[j]);
+    }
+    if (selected) {
+	wmove (win, choice, item_x+1);
+	wrefresh (win);
+    }
+}
+
+/*
+ * Print the scroll indicators.
+ */
+static void
+print_arrows (WINDOW * win, int item_no, int scroll,
+		int y, int x, int height)
+{
+    int cur_y, cur_x;
+
+    getyx(win, cur_y, cur_x);
+
+    wmove(win, y, x);
+
+    if (scroll > 0) {
+	wattrset (win, uarrow_attr);
+	waddch (win, ACS_UARROW);
+	waddstr (win, "(-)");
+    }
+    else {
+	wattrset (win, menubox_attr);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+    }
+
+   y = y + height + 1;
+   wmove(win, y, x);
+
+   if ((height < item_no) && (scroll + height < item_no)) {
+	wattrset (win, darrow_attr);
+	waddch (win, ACS_DARROW);
+	waddstr (win, "(+)");
+    }
+    else {
+	wattrset (win, menubox_border_attr);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+	waddch (win, ACS_HLINE);
+   }
+
+   wmove(win, cur_y, cur_x);
+}
+
+/*
+ * Display the termination buttons.
+ */
+static void
+print_buttons (WINDOW *win, int height, int width, int selected)
+{
+    int x = width / 2 - 16;
+    int y = height - 2;
+
+    print_button (win, "Select", y, x, selected == 0);
+    print_button (win, " Exit ", y, x + 12, selected == 1);
+    print_button (win, " Help ", y, x + 24, selected == 2);
+
+    wmove(win, y, x+1+12*selected);
+    wrefresh (win);
+}
+
+/*
+ * Display a menu for choosing among a number of options
+ */
+int
+dialog_menu (const char *title, const char *prompt, int height, int width,
+		int menu_height, const char *current, int item_no,
+		struct dialog_list_item ** items)
+{
+    int i, j, x, y, box_x, box_y;
+    int key = 0, button = 0, scroll = 0, choice = 0, first_item = 0, max_choice;
+    WINDOW *dialog, *menu;
+    FILE *f;
+
+    max_choice = MIN (menu_height, item_no);
+
+    /* center dialog box on screen */
+    x = (COLS - width) / 2;
+    y = (LINES - height) / 2;
+
+    draw_shadow (stdscr, y, x, height, width);
+
+    dialog = newwin (height, width, y, x);
+    keypad (dialog, TRUE);
+
+    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+    wattrset (dialog, border_attr);
+    mvwaddch (dialog, height - 3, 0, ACS_LTEE);
+    for (i = 0; i < width - 2; i++)
+	waddch (dialog, ACS_HLINE);
+    wattrset (dialog, dialog_attr);
+    wbkgdset (dialog, dialog_attr & A_COLOR);
+    waddch (dialog, ACS_RTEE);
+
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
+    if (title != NULL) {
+	wattrset (dialog, title_attr);
+	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+	waddstr (dialog, (char *)title);
+	waddch (dialog, ' ');
+    }
+
+    wattrset (dialog, dialog_attr);
+    print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+    menu_width = width - 6;
+    box_y = height - menu_height - 5;
+    box_x = (width - menu_width) / 2 - 1;
+
+    /* create new window for the menu */
+    menu = subwin (dialog, menu_height, menu_width,
+		y + box_y + 1, x + box_x + 1);
+    keypad (menu, TRUE);
+
+    /* draw a box around the menu items */
+    draw_box (dialog, box_y, box_x, menu_height + 2, menu_width + 2,
+	      menubox_border_attr, menubox_attr);
+
+    /*
+     * Find length of longest item in order to center menu.
+     * Set 'choice' to default item.
+     */
+    item_x = 0;
+    for (i = 0; i < item_no; i++) {
+	item_x = MAX (item_x, MIN(menu_width, strlen (items[i]->name) + 2));
+	if (strcmp(current, items[i]->tag) == 0) choice = i;
+    }
+
+    item_x = (menu_width - item_x) / 2;
+
+    /* get the scroll info from the temp file */
+    if ( (f=fopen("lxdialog.scrltmp","r")) != NULL ) {
+	if ( (fscanf(f,"%d\n",&scroll) == 1) && (scroll <= choice) &&
+	     (scroll+max_choice > choice) && (scroll >= 0) &&
+	     (scroll+max_choice <= item_no) ) {
+	    first_item = scroll;
+	    choice = choice - scroll;
+	    fclose(f);
+	} else {
+	    scroll=0;
+	    remove("lxdialog.scrltmp");
+	    fclose(f);
+	    f=NULL;
+	}
+    }
+    if ( (choice >= max_choice) || (f==NULL && choice >= max_choice/2) ) {
+	if (choice >= item_no-max_choice/2)
+	    scroll = first_item = item_no-max_choice;
+	else
+	    scroll = first_item = choice - max_choice/2;
+	choice = choice - scroll;
+    }
+
+    /* Print the menu */
+    for (i=0; i < max_choice; i++) {
+	print_item (menu, items[first_item + i]->name, i, i == choice,
+		    (items[first_item + i]->tag[0] != ':'));
+    }
+
+    wnoutrefresh (menu);
+
+    print_arrows(dialog, item_no, scroll,
+		 box_y, box_x+item_x+1, menu_height);
+
+    print_buttons (dialog, height, width, 0);
+    wmove (menu, choice, item_x+1);
+    wrefresh (menu);
+
+    while (key != ESC) {
+	key = wgetch(menu);
+
+	if (key < 256 && isalpha(key)) key = tolower(key);
+
+	if (strchr("ynmh", key))
+		i = max_choice;
+	else {
+	for (i = choice+1; i < max_choice; i++) {
+		j = first_alpha(items[scroll + i]->name, "YyNnMmHh");
+		if (key == tolower(items[scroll + i]->name[j]))
+			break;
+	}
+	if (i == max_choice)
+		for (i = 0; i < max_choice; i++) {
+			j = first_alpha(items[scroll + i]->name, "YyNnMmHh");
+			if (key == tolower(items[scroll + i]->name[j]))
+				break;
+		}
+	}
+
+	if (i < max_choice ||
+	    key == KEY_UP || key == KEY_DOWN ||
+	    key == '-' || key == '+' ||
+	    key == KEY_PPAGE || key == KEY_NPAGE) {
+
+	    print_item (menu, items[scroll + choice]->name, choice, FALSE,
+		       (items[scroll + choice]->tag[0] != ':'));
+
+	    if (key == KEY_UP || key == '-') {
+		if (choice < 2 && scroll) {
+	            /* Scroll menu down */
+		    scrollok (menu, TRUE);
+		    wscrl (menu, -1);
+		    scrollok (menu, FALSE);
+
+		    scroll--;
+
+		    print_item (menu, items[scroll]->name, 0, FALSE,
+			       (items[scroll]->tag[0] != ':'));
+		} else
+		    choice = MAX(choice - 1, 0);
+
+	    } else if (key == KEY_DOWN || key == '+')  {
+
+		print_item (menu, items[scroll + choice]->name, choice, FALSE,
+				(items[scroll + choice]->tag[0] != ':'));
+
+		if ((choice > max_choice-3) &&
+		    (scroll + max_choice < item_no)
+		   ) {
+		    /* Scroll menu up */
+		    scrollok (menu, TRUE);
+		    scroll (menu);
+		    scrollok (menu, FALSE);
+
+		    scroll++;
+
+		    print_item (menu, items[scroll + max_choice - 1]->name,
+			       max_choice-1, FALSE,
+			       (items[scroll + max_choice - 1]->tag[0] != ':'));
+		} else
+		    choice = MIN(choice+1, max_choice-1);
+
+	    } else if (key == KEY_PPAGE) {
+	        scrollok (menu, TRUE);
+		for (i=0; (i < max_choice); i++) {
+		    if (scroll > 0) {
+			wscrl (menu, -1);
+			scroll--;
+			print_item (menu, items[scroll]->name, 0, FALSE,
+			(items[scroll]->tag[0] != ':'));
+		    } else {
+			if (choice > 0)
+			    choice--;
+		    }
+		}
+		scrollok (menu, FALSE);
+
+	    } else if (key == KEY_NPAGE) {
+		for (i=0; (i < max_choice); i++) {
+		    if (scroll+max_choice < item_no) {
+			scrollok (menu, TRUE);
+			scroll(menu);
+			scrollok (menu, FALSE);
+			scroll++;
+			print_item (menu, items[scroll + max_choice - 1]->name,
+			            max_choice-1, FALSE,
+			            (items[scroll + max_choice - 1]->tag[0] != ':'));
+		    } else {
+			if (choice+1 < max_choice)
+			    choice++;
+		    }
+		}
+
+	    } else
+		choice = i;
+
+	    print_item (menu, items[scroll + choice]->name, choice, TRUE,
+		       (items[scroll + choice]->tag[0] != ':'));
+
+	    print_arrows(dialog, item_no, scroll,
+			 box_y, box_x+item_x+1, menu_height);
+
+	    wnoutrefresh (dialog);
+	    wrefresh (menu);
+
+	    continue;		/* wait for another key press */
+	}
+
+	switch (key) {
+	case KEY_LEFT:
+	case TAB:
+	case KEY_RIGHT:
+	    button = ((key == KEY_LEFT ? --button : ++button) < 0)
+			? 2 : (button > 2 ? 0 : button);
+
+	    print_buttons(dialog, height, width, button);
+	    wrefresh (menu);
+	    break;
+	case ' ':
+	case 's':
+	case 'y':
+	case 'n':
+	case 'm':
+	case '/':
+	    /* save scroll info */
+	    if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) {
+		fprintf(f,"%d\n",scroll);
+		fclose(f);
+	    }
+	    delwin (dialog);
+	    items[scroll + choice]->selected = 1;
+	    switch (key) {
+	    case 's': return 3;
+	    case 'y': return 3;
+	    case 'n': return 4;
+	    case 'm': return 5;
+	    case ' ': return 6;
+	    case '/': return 7;
+	    }
+	    return 0;
+	case 'h':
+	case '?':
+	    button = 2;
+	case '\n':
+	    delwin (dialog);
+	    items[scroll + choice]->selected = 1;
+
+	    remove("lxdialog.scrltmp");
+	    return button;
+	case 'e':
+	case 'x':
+	    key = ESC;
+	case ESC:
+	    break;
+	}
+    }
+
+    delwin (dialog);
+    remove("lxdialog.scrltmp");
+    return -1;			/* ESC pressed */
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/msgbox.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/msgbox.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/msgbox.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,85 @@
+/*
+ *  msgbox.c -- implements the message box and info box
+ *
+ *  ORIGINAL AUTHOR: Savio Lam (lam836 at cs.cuhk.hk)
+ *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw at cfw.com)
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+/*
+ * Display a message box. Program will pause and display an "OK" button
+ * if the parameter 'pause' is non-zero.
+ */
+int
+dialog_msgbox (const char *title, const char *prompt, int height, int width,
+		int pause)
+{
+    int i, x, y, key = 0;
+    WINDOW *dialog;
+
+    /* center dialog box on screen */
+    x = (COLS - width) / 2;
+    y = (LINES - height) / 2;
+
+    draw_shadow (stdscr, y, x, height, width);
+
+    dialog = newwin (height, width, y, x);
+    keypad (dialog, TRUE);
+
+    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
+    if (title != NULL) {
+	wattrset (dialog, title_attr);
+	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+	waddstr (dialog, (char *)title);
+	waddch (dialog, ' ');
+    }
+    wattrset (dialog, dialog_attr);
+    print_autowrap (dialog, prompt, width - 2, 1, 2);
+
+    if (pause) {
+	wattrset (dialog, border_attr);
+	mvwaddch (dialog, height - 3, 0, ACS_LTEE);
+	for (i = 0; i < width - 2; i++)
+	    waddch (dialog, ACS_HLINE);
+	wattrset (dialog, dialog_attr);
+	waddch (dialog, ACS_RTEE);
+
+	print_button (dialog, "  Ok  ",
+		      height - 2, width / 2 - 4, TRUE);
+
+	wrefresh (dialog);
+	while (key != ESC && key != '\n' && key != ' ' &&
+	       key != 'O' && key != 'o' && key != 'X' && key != 'x')
+	    key = wgetch (dialog);
+    } else {
+	key = '\n';
+	wrefresh (dialog);
+    }
+
+    delwin (dialog);
+    return key == ESC ? -1 : 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/textbox.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/textbox.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/textbox.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,556 @@
+/*
+ *  textbox.c -- implements the text box
+ *
+ *  ORIGINAL AUTHOR: Savio Lam (lam836 at cs.cuhk.hk)
+ *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap at cfw.com)
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+static void back_lines (int n);
+static void print_page (WINDOW * win, int height, int width);
+static void print_line (WINDOW * win, int row, int width);
+static char *get_line (void);
+static void print_position (WINDOW * win, int height, int width);
+
+static int hscroll, fd, file_size, bytes_read;
+static int begin_reached = 1, end_reached, page_length;
+static char *buf, *page;
+
+/*
+ * Display text from a file in a dialog box.
+ */
+int
+dialog_textbox (const char *title, const char *file, int height, int width)
+{
+    int i, x, y, cur_x, cur_y, fpos, key = 0;
+    int passed_end;
+    char search_term[MAX_LEN + 1];
+    WINDOW *dialog, *text;
+
+    search_term[0] = '\0';	/* no search term entered yet */
+
+    /* Open input file for reading */
+    if ((fd = open (file, O_RDONLY)) == -1) {
+	endwin ();
+	fprintf (stderr,
+		 "\nCan't open input file in dialog_textbox().\n");
+	exit (-1);
+    }
+    /* Get file size. Actually, 'file_size' is the real file size - 1,
+       since it's only the last byte offset from the beginning */
+    if ((file_size = lseek (fd, 0, SEEK_END)) == -1) {
+	endwin ();
+	fprintf (stderr, "\nError getting file size in dialog_textbox().\n");
+	exit (-1);
+    }
+    /* Restore file pointer to beginning of file after getting file size */
+    if (lseek (fd, 0, SEEK_SET) == -1) {
+	endwin ();
+	fprintf (stderr, "\nError moving file pointer in dialog_textbox().\n");
+	exit (-1);
+    }
+    /* Allocate space for read buffer */
+    if ((buf = malloc (BUF_SIZE + 1)) == NULL) {
+	endwin ();
+	fprintf (stderr, "\nCan't allocate memory in dialog_textbox().\n");
+	exit (-1);
+    }
+    if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+	endwin ();
+	fprintf (stderr, "\nError reading file in dialog_textbox().\n");
+	exit (-1);
+    }
+    buf[bytes_read] = '\0';	/* mark end of valid data */
+    page = buf;			/* page is pointer to start of page to be displayed */
+
+    /* center dialog box on screen */
+    x = (COLS - width) / 2;
+    y = (LINES - height) / 2;
+
+
+    draw_shadow (stdscr, y, x, height, width);
+
+    dialog = newwin (height, width, y, x);
+    keypad (dialog, TRUE);
+
+    /* Create window for text region, used for scrolling text */
+    text = subwin (dialog, height - 4, width - 2, y + 1, x + 1);
+    wattrset (text, dialog_attr);
+    wbkgdset (text, dialog_attr & A_COLOR);
+
+    keypad (text, TRUE);
+
+    /* register the new window, along with its borders */
+    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+    wattrset (dialog, border_attr);
+    mvwaddch (dialog, height-3, 0, ACS_LTEE);
+    for (i = 0; i < width - 2; i++)
+	waddch (dialog, ACS_HLINE);
+    wattrset (dialog, dialog_attr);
+    wbkgdset (dialog, dialog_attr & A_COLOR);
+    waddch (dialog, ACS_RTEE);
+
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
+    if (title != NULL) {
+	wattrset (dialog, title_attr);
+	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+	waddstr (dialog, (char *)title);
+	waddch (dialog, ' ');
+    }
+    print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
+    wnoutrefresh (dialog);
+    getyx (dialog, cur_y, cur_x);	/* Save cursor position */
+
+    /* Print first page of text */
+    attr_clear (text, height - 4, width - 2, dialog_attr);
+    print_page (text, height - 4, width - 2);
+    print_position (dialog, height, width);
+    wmove (dialog, cur_y, cur_x);	/* Restore cursor position */
+    wrefresh (dialog);
+
+    while ((key != ESC) && (key != '\n')) {
+	key = wgetch (dialog);
+	switch (key) {
+	case 'E':		/* Exit */
+	case 'e':
+	case 'X':
+	case 'x':
+	    delwin (dialog);
+	    free (buf);
+	    close (fd);
+	    return 0;
+	case 'g':		/* First page */
+	case KEY_HOME:
+	    if (!begin_reached) {
+		begin_reached = 1;
+		/* First page not in buffer? */
+		if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+		    endwin ();
+		    fprintf (stderr,
+		      "\nError moving file pointer in dialog_textbox().\n");
+		    exit (-1);
+		}
+		if (fpos > bytes_read) {	/* Yes, we have to read it in */
+		    if (lseek (fd, 0, SEEK_SET) == -1) {
+			endwin ();
+			fprintf (stderr, "\nError moving file pointer in "
+				 "dialog_textbox().\n");
+			exit (-1);
+		    }
+		    if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+			endwin ();
+			fprintf (stderr,
+			     "\nError reading file in dialog_textbox().\n");
+			exit (-1);
+		    }
+		    buf[bytes_read] = '\0';
+		}
+		page = buf;
+		print_page (text, height - 4, width - 2);
+		print_position (dialog, height, width);
+		wmove (dialog, cur_y, cur_x);	/* Restore cursor position */
+		wrefresh (dialog);
+	    }
+	    break;
+	case 'G':		/* Last page */
+	case KEY_END:
+
+	    end_reached = 1;
+	    /* Last page not in buffer? */
+	    if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+		endwin ();
+		fprintf (stderr,
+		      "\nError moving file pointer in dialog_textbox().\n");
+		exit (-1);
+	    }
+	    if (fpos < file_size) {	/* Yes, we have to read it in */
+		if (lseek (fd, -BUF_SIZE, SEEK_END) == -1) {
+		    endwin ();
+		    fprintf (stderr,
+		      "\nError moving file pointer in dialog_textbox().\n");
+		    exit (-1);
+		}
+		if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+		    endwin ();
+		    fprintf (stderr,
+			     "\nError reading file in dialog_textbox().\n");
+		    exit (-1);
+		}
+		buf[bytes_read] = '\0';
+	    }
+	    page = buf + bytes_read;
+	    back_lines (height - 4);
+	    print_page (text, height - 4, width - 2);
+	    print_position (dialog, height, width);
+	    wmove (dialog, cur_y, cur_x);	/* Restore cursor position */
+	    wrefresh (dialog);
+	    break;
+	case 'K':		/* Previous line */
+	case 'k':
+	case KEY_UP:
+	    if (!begin_reached) {
+		back_lines (page_length + 1);
+
+		/* We don't call print_page() here but use scrolling to ensure
+		   faster screen update. However, 'end_reached' and
+		   'page_length' should still be updated, and 'page' should
+		   point to start of next page. This is done by calling
+		   get_line() in the following 'for' loop. */
+		scrollok (text, TRUE);
+		wscrl (text, -1);	/* Scroll text region down one line */
+		scrollok (text, FALSE);
+		page_length = 0;
+		passed_end = 0;
+		for (i = 0; i < height - 4; i++) {
+		    if (!i) {
+			/* print first line of page */
+			print_line (text, 0, width - 2);
+			wnoutrefresh (text);
+		    } else
+			/* Called to update 'end_reached' and 'page' */
+			get_line ();
+		    if (!passed_end)
+			page_length++;
+		    if (end_reached && !passed_end)
+			passed_end = 1;
+		}
+
+		print_position (dialog, height, width);
+		wmove (dialog, cur_y, cur_x);	/* Restore cursor position */
+		wrefresh (dialog);
+	    }
+	    break;
+	case 'B':		/* Previous page */
+	case 'b':
+	case KEY_PPAGE:
+	    if (begin_reached)
+		break;
+	    back_lines (page_length + height - 4);
+	    print_page (text, height - 4, width - 2);
+	    print_position (dialog, height, width);
+	    wmove (dialog, cur_y, cur_x);
+	    wrefresh (dialog);
+	    break;
+	case 'J':		/* Next line */
+	case 'j':
+	case KEY_DOWN:
+	    if (!end_reached) {
+		begin_reached = 0;
+		scrollok (text, TRUE);
+		scroll (text);	/* Scroll text region up one line */
+		scrollok (text, FALSE);
+		print_line (text, height - 5, width - 2);
+		wnoutrefresh (text);
+		print_position (dialog, height, width);
+		wmove (dialog, cur_y, cur_x);	/* Restore cursor position */
+		wrefresh (dialog);
+	    }
+	    break;
+	case KEY_NPAGE:		/* Next page */
+	case ' ':
+	    if (end_reached)
+		break;
+
+	    begin_reached = 0;
+	    print_page (text, height - 4, width - 2);
+	    print_position (dialog, height, width);
+	    wmove (dialog, cur_y, cur_x);
+	    wrefresh (dialog);
+	    break;
+	case '0':		/* Beginning of line */
+	case 'H':		/* Scroll left */
+	case 'h':
+	case KEY_LEFT:
+	    if (hscroll <= 0)
+		break;
+
+	    if (key == '0')
+		hscroll = 0;
+	    else
+		hscroll--;
+	    /* Reprint current page to scroll horizontally */
+	    back_lines (page_length);
+	    print_page (text, height - 4, width - 2);
+	    wmove (dialog, cur_y, cur_x);
+	    wrefresh (dialog);
+	    break;
+	case 'L':		/* Scroll right */
+	case 'l':
+	case KEY_RIGHT:
+	    if (hscroll >= MAX_LEN)
+		break;
+	    hscroll++;
+	    /* Reprint current page to scroll horizontally */
+	    back_lines (page_length);
+	    print_page (text, height - 4, width - 2);
+	    wmove (dialog, cur_y, cur_x);
+	    wrefresh (dialog);
+	    break;
+	case ESC:
+	    break;
+	}
+    }
+
+    delwin (dialog);
+    free (buf);
+    close (fd);
+    return 1;			/* ESC pressed */
+}
+
+/*
+ * Go back 'n' lines in text file. Called by dialog_textbox().
+ * 'page' will be updated to point to the desired line in 'buf'.
+ */
+static void
+back_lines (int n)
+{
+    int i, fpos;
+
+    begin_reached = 0;
+    /* We have to distinguish between end_reached and !end_reached
+       since at end of file, the line is not ended by a '\n'.
+       The code inside 'if' basically does a '--page' to move one
+       character backward so as to skip '\n' of the previous line */
+    if (!end_reached) {
+	/* Either beginning of buffer or beginning of file reached? */
+	if (page == buf) {
+	    if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+		endwin ();
+		fprintf (stderr, "\nError moving file pointer in "
+			 "back_lines().\n");
+		exit (-1);
+	    }
+	    if (fpos > bytes_read) {	/* Not beginning of file yet */
+		/* We've reached beginning of buffer, but not beginning of
+		   file yet, so read previous part of file into buffer.
+		   Note that we only move backward for BUF_SIZE/2 bytes,
+		   but not BUF_SIZE bytes to avoid re-reading again in
+		   print_page() later */
+		/* Really possible to move backward BUF_SIZE/2 bytes? */
+		if (fpos < BUF_SIZE / 2 + bytes_read) {
+		    /* No, move less then */
+		    if (lseek (fd, 0, SEEK_SET) == -1) {
+			endwin ();
+			fprintf (stderr, "\nError moving file pointer in "
+				 "back_lines().\n");
+			exit (-1);
+		    }
+		    page = buf + fpos - bytes_read;
+		} else {	/* Move backward BUF_SIZE/2 bytes */
+		    if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR)
+			== -1) {
+			endwin ();
+			fprintf (stderr, "\nError moving file pointer "
+				 "in back_lines().\n");
+			exit (-1);
+		    }
+		    page = buf + BUF_SIZE / 2;
+		}
+		if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+		    endwin ();
+		    fprintf (stderr, "\nError reading file in back_lines().\n");
+		    exit (-1);
+		}
+		buf[bytes_read] = '\0';
+	    } else {		/* Beginning of file reached */
+		begin_reached = 1;
+		return;
+	    }
+	}
+	if (*(--page) != '\n') {	/* '--page' here */
+	    /* Something's wrong... */
+	    endwin ();
+	    fprintf (stderr, "\nInternal error in back_lines().\n");
+	    exit (-1);
+	}
+    }
+    /* Go back 'n' lines */
+    for (i = 0; i < n; i++)
+	do {
+	    if (page == buf) {
+		if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+		    endwin ();
+		    fprintf (stderr,
+			  "\nError moving file pointer in back_lines().\n");
+		    exit (-1);
+		}
+		if (fpos > bytes_read) {
+		    /* Really possible to move backward BUF_SIZE/2 bytes? */
+		    if (fpos < BUF_SIZE / 2 + bytes_read) {
+			/* No, move less then */
+			if (lseek (fd, 0, SEEK_SET) == -1) {
+			    endwin ();
+			    fprintf (stderr, "\nError moving file pointer "
+				     "in back_lines().\n");
+			    exit (-1);
+			}
+			page = buf + fpos - bytes_read;
+		    } else {	/* Move backward BUF_SIZE/2 bytes */
+			if (lseek (fd, -(BUF_SIZE / 2 + bytes_read),
+				   SEEK_CUR) == -1) {
+			    endwin ();
+			    fprintf (stderr, "\nError moving file pointer"
+				     " in back_lines().\n");
+			    exit (-1);
+			}
+			page = buf + BUF_SIZE / 2;
+		    }
+		    if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+			endwin ();
+			fprintf (stderr, "\nError reading file in "
+				 "back_lines().\n");
+			exit (-1);
+		    }
+		    buf[bytes_read] = '\0';
+		} else {	/* Beginning of file reached */
+		    begin_reached = 1;
+		    return;
+		}
+	    }
+	} while (*(--page) != '\n');
+    page++;
+}
+
+/*
+ * Print a new page of text. Called by dialog_textbox().
+ */
+static void
+print_page (WINDOW * win, int height, int width)
+{
+    int i, passed_end = 0;
+
+    page_length = 0;
+    for (i = 0; i < height; i++) {
+	print_line (win, i, width);
+	if (!passed_end)
+	    page_length++;
+	if (end_reached && !passed_end)
+	    passed_end = 1;
+    }
+    wnoutrefresh (win);
+}
+
+/*
+ * Print a new line of text. Called by dialog_textbox() and print_page().
+ */
+static void
+print_line (WINDOW * win, int row, int width)
+{
+    int y, x;
+    char *line;
+
+    line = get_line ();
+    line += MIN (strlen (line), hscroll);	/* Scroll horizontally */
+    wmove (win, row, 0);	/* move cursor to correct line */
+    waddch (win, ' ');
+    waddnstr (win, line, MIN (strlen (line), width - 2));
+
+    getyx (win, y, x);
+    /* Clear 'residue' of previous line */
+#if OLD_NCURSES
+    {
+	int i;
+	for (i = 0; i < width - x; i++)
+	    waddch (win, ' ');
+    }
+#else
+    wclrtoeol(win);
+#endif
+}
+
+/*
+ * Return current line of text. Called by dialog_textbox() and print_line().
+ * 'page' should point to start of current line before calling, and will be
+ * updated to point to start of next line.
+ */
+static char *
+get_line (void)
+{
+    int i = 0, fpos;
+    static char line[MAX_LEN + 1];
+
+    end_reached = 0;
+    while (*page != '\n') {
+	if (*page == '\0') {
+	    /* Either end of file or end of buffer reached */
+	    if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+		endwin ();
+		fprintf (stderr, "\nError moving file pointer in "
+			 "get_line().\n");
+		exit (-1);
+	    }
+	    if (fpos < file_size) {	/* Not end of file yet */
+		/* We've reached end of buffer, but not end of file yet,
+		   so read next part of file into buffer */
+		if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+		    endwin ();
+		    fprintf (stderr, "\nError reading file in get_line().\n");
+		    exit (-1);
+		}
+		buf[bytes_read] = '\0';
+		page = buf;
+	    } else {
+		if (!end_reached)
+		    end_reached = 1;
+		break;
+	    }
+	} else if (i < MAX_LEN)
+	    line[i++] = *(page++);
+	else {
+	    /* Truncate lines longer than MAX_LEN characters */
+	    if (i == MAX_LEN)
+		line[i++] = '\0';
+	    page++;
+	}
+    }
+    if (i <= MAX_LEN)
+	line[i] = '\0';
+    if (!end_reached)
+	page++;			/* move pass '\n' */
+
+    return line;
+}
+
+/*
+ * Print current position
+ */
+static void
+print_position (WINDOW * win, int height, int width)
+{
+    int fpos, percent;
+
+    if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+	endwin ();
+	fprintf (stderr, "\nError moving file pointer in print_position().\n");
+	exit (-1);
+    }
+    wattrset (win, position_indicator_attr);
+    wbkgdset (win, position_indicator_attr & A_COLOR);
+    percent = !file_size ?
+	100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
+    wmove (win, height - 3, width - 9);
+    wprintw (win, "(%3d%%)", percent);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/util.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/util.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/util.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,375 @@
+/*
+ *  util.c
+ *
+ *  ORIGINAL AUTHOR: Savio Lam (lam836 at cs.cuhk.hk)
+ *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap at cfw.com)
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+
+/* use colors by default? */
+bool use_colors = 1;
+
+const char *backtitle = NULL;
+
+const char *dialog_result;
+
+/*
+ * Attribute values, default is for mono display
+ */
+chtype attributes[] =
+{
+    A_NORMAL,			/* screen_attr */
+    A_NORMAL,			/* shadow_attr */
+    A_NORMAL,			/* dialog_attr */
+    A_BOLD,			/* title_attr */
+    A_NORMAL,			/* border_attr */
+    A_REVERSE,			/* button_active_attr */
+    A_DIM,			/* button_inactive_attr */
+    A_REVERSE,			/* button_key_active_attr */
+    A_BOLD,			/* button_key_inactive_attr */
+    A_REVERSE,			/* button_label_active_attr */
+    A_NORMAL,			/* button_label_inactive_attr */
+    A_NORMAL,			/* inputbox_attr */
+    A_NORMAL,			/* inputbox_border_attr */
+    A_NORMAL,			/* searchbox_attr */
+    A_BOLD,			/* searchbox_title_attr */
+    A_NORMAL,			/* searchbox_border_attr */
+    A_BOLD,			/* position_indicator_attr */
+    A_NORMAL,			/* menubox_attr */
+    A_NORMAL,			/* menubox_border_attr */
+    A_NORMAL,			/* item_attr */
+    A_REVERSE,			/* item_selected_attr */
+    A_BOLD,			/* tag_attr */
+    A_REVERSE,			/* tag_selected_attr */
+    A_BOLD,			/* tag_key_attr */
+    A_REVERSE,			/* tag_key_selected_attr */
+    A_BOLD,			/* check_attr */
+    A_REVERSE,			/* check_selected_attr */
+    A_BOLD,			/* uarrow_attr */
+    A_BOLD			/* darrow_attr */
+};
+
+
+#include "colors.h"
+
+/*
+ * Table of color values
+ */
+int color_table[][3] =
+{
+    {SCREEN_FG, SCREEN_BG, SCREEN_HL},
+    {SHADOW_FG, SHADOW_BG, SHADOW_HL},
+    {DIALOG_FG, DIALOG_BG, DIALOG_HL},
+    {TITLE_FG, TITLE_BG, TITLE_HL},
+    {BORDER_FG, BORDER_BG, BORDER_HL},
+    {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL},
+    {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL},
+    {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL},
+    {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL},
+    {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL},
+    {BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG,
+     BUTTON_LABEL_INACTIVE_HL},
+    {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL},
+    {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL},
+    {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL},
+    {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL},
+    {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL},
+    {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL},
+    {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL},
+    {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL},
+    {ITEM_FG, ITEM_BG, ITEM_HL},
+    {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL},
+    {TAG_FG, TAG_BG, TAG_HL},
+    {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL},
+    {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL},
+    {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL},
+    {CHECK_FG, CHECK_BG, CHECK_HL},
+    {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL},
+    {UARROW_FG, UARROW_BG, UARROW_HL},
+    {DARROW_FG, DARROW_BG, DARROW_HL},
+};				/* color_table */
+
+/*
+ * Set window to attribute 'attr'
+ */
+void
+attr_clear (WINDOW * win, int height, int width, chtype attr)
+{
+    int i, j;
+
+    wattrset (win, attr);
+    for (i = 0; i < height; i++) {
+	wmove (win, i, 0);
+	for (j = 0; j < width; j++)
+	    waddch (win, ' ');
+    }
+    touchwin (win);
+}
+
+void dialog_clear (void)
+{
+    attr_clear (stdscr, LINES, COLS, screen_attr);
+    /* Display background title if it exists ... - SLH */
+    if (backtitle != NULL) {
+	int i;
+
+	wattrset (stdscr, screen_attr);
+	mvwaddstr (stdscr, 0, 1, (char *)backtitle);
+	wmove (stdscr, 1, 1);
+	for (i = 1; i < COLS - 1; i++)
+	    waddch (stdscr, ACS_HLINE);
+    }
+    wnoutrefresh (stdscr);
+}
+
+/*
+ * Do some initialization for dialog
+ */
+void
+init_dialog (void)
+{
+    initscr ();			/* Init curses */
+    keypad (stdscr, TRUE);
+    cbreak ();
+    noecho ();
+
+
+    if (use_colors)	/* Set up colors */
+	color_setup ();
+
+
+    dialog_clear ();
+}
+
+/*
+ * Setup for color display
+ */
+void
+color_setup (void)
+{
+    int i;
+
+    if (has_colors ()) {	/* Terminal supports color? */
+	start_color ();
+
+	/* Initialize color pairs */
+	for (i = 0; i < ATTRIBUTE_COUNT; i++)
+	    init_pair (i + 1, color_table[i][0], color_table[i][1]);
+
+	/* Setup color attributes */
+	for (i = 0; i < ATTRIBUTE_COUNT; i++)
+	    attributes[i] = C_ATTR (color_table[i][2], i + 1);
+    }
+}
+
+/*
+ * End using dialog functions.
+ */
+void
+end_dialog (void)
+{
+    endwin ();
+}
+
+
+/*
+ * Print a string of text in a window, automatically wrap around to the
+ * next line if the string is too long to fit on one line. Newline
+ * characters '\n' are replaced by spaces.  We start on a new line
+ * if there is no room for at least 4 nonblanks following a double-space.
+ */
+void
+print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x)
+{
+    int newl, cur_x, cur_y;
+    int i, prompt_len, room, wlen;
+    char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
+
+    strcpy (tempstr, prompt);
+
+    prompt_len = strlen(tempstr);
+
+    /*
+     * Remove newlines
+     */
+    for(i=0; i<prompt_len; i++) {
+	if(tempstr[i] == '\n') tempstr[i] = ' ';
+    }
+
+    if (prompt_len <= width - x * 2) {	/* If prompt is short */
+	wmove (win, y, (width - prompt_len) / 2);
+	waddstr (win, tempstr);
+    } else {
+	cur_x = x;
+	cur_y = y;
+	newl = 1;
+	word = tempstr;
+	while (word && *word) {
+	    sp = strchr(word, ' ');
+	    if (sp)
+	        *sp++ = 0;
+
+	    /* Wrap to next line if either the word does not fit,
+	       or it is the first word of a new sentence, and it is
+	       short, and the next word does not fit. */
+	    room = width - cur_x;
+	    wlen = strlen(word);
+	    if (wlen > room ||
+	       (newl && wlen < 4 && sp && wlen+1+strlen(sp) > room
+		     && (!(sp2 = strchr(sp, ' ')) || wlen+1+(sp2-sp) > room))) {
+		cur_y++;
+		cur_x = x;
+	    }
+	    wmove (win, cur_y, cur_x);
+	    waddstr (win, word);
+	    getyx (win, cur_y, cur_x);
+	    cur_x++;
+	    if (sp && *sp == ' ') {
+	        cur_x++;	/* double space */
+		while (*++sp == ' ');
+		newl = 1;
+	    } else
+	        newl = 0;
+	    word = sp;
+	}
+    }
+}
+
+/*
+ * Print a button
+ */
+void
+print_button (WINDOW * win, const char *label, int y, int x, int selected)
+{
+    int i, temp;
+
+    wmove (win, y, x);
+    wattrset (win, selected ? button_active_attr : button_inactive_attr);
+    waddstr (win, "<");
+    temp = strspn (label, " ");
+    label += temp;
+    wattrset (win, selected ? button_label_active_attr
+	      : button_label_inactive_attr);
+    for (i = 0; i < temp; i++)
+	waddch (win, ' ');
+    wattrset (win, selected ? button_key_active_attr
+	      : button_key_inactive_attr);
+    waddch (win, label[0]);
+    wattrset (win, selected ? button_label_active_attr
+	      : button_label_inactive_attr);
+    waddstr (win, (char *)label + 1);
+    wattrset (win, selected ? button_active_attr : button_inactive_attr);
+    waddstr (win, ">");
+    wmove (win, y, x + temp + 1);
+}
+
+/*
+ * Draw a rectangular box with line drawing characters
+ */
+void
+draw_box (WINDOW * win, int y, int x, int height, int width,
+	  chtype box, chtype border)
+{
+    int i, j;
+
+    wattrset (win, 0);
+    for (i = 0; i < height; i++) {
+	wmove (win, y + i, x);
+	for (j = 0; j < width; j++)
+	    if (!i && !j)
+		waddch (win, border | ACS_ULCORNER);
+	    else if (i == height - 1 && !j)
+		waddch (win, border | ACS_LLCORNER);
+	    else if (!i && j == width - 1)
+		waddch (win, box | ACS_URCORNER);
+	    else if (i == height - 1 && j == width - 1)
+		waddch (win, box | ACS_LRCORNER);
+	    else if (!i)
+		waddch (win, border | ACS_HLINE);
+	    else if (i == height - 1)
+		waddch (win, box | ACS_HLINE);
+	    else if (!j)
+		waddch (win, border | ACS_VLINE);
+	    else if (j == width - 1)
+		waddch (win, box | ACS_VLINE);
+	    else
+		waddch (win, box | ' ');
+    }
+}
+
+/*
+ * Draw shadows along the right and bottom edge to give a more 3D look
+ * to the boxes
+ */
+void
+draw_shadow (WINDOW * win, int y, int x, int height, int width)
+{
+    int i;
+
+    if (has_colors ()) {	/* Whether terminal supports color? */
+	wattrset (win, shadow_attr);
+	wmove (win, y + height, x + 2);
+	for (i = 0; i < width; i++)
+	    waddch (win, winch (win) & A_CHARTEXT);
+	for (i = y + 1; i < y + height + 1; i++) {
+	    wmove (win, i, x + width);
+	    waddch (win, winch (win) & A_CHARTEXT);
+	    waddch (win, winch (win) & A_CHARTEXT);
+	}
+	wnoutrefresh (win);
+    }
+}
+
+/*
+ *  Return the position of the first alphabetic character in a string.
+ */
+int
+first_alpha(const char *string, const char *exempt)
+{
+	int i, in_paren=0, c;
+
+	for (i = 0; i < strlen(string); i++) {
+		c = tolower(string[i]);
+
+		if (strchr("<[(", c)) ++in_paren;
+		if (strchr(">])", c) && in_paren > 0) --in_paren;
+
+		if ((! in_paren) && isalpha(c) &&
+		     strchr(exempt, c) == 0)
+			return i;
+	}
+
+	return 0;
+}
+
+/*
+ * Get the first selected item in the dialog_list_item list.
+ */
+struct dialog_list_item *
+first_sel_item(int item_no, struct dialog_list_item ** items)
+{
+	int i;
+
+	for (i = 0; i < item_no; i++) {
+		if (items[i]->selected)
+			return items[i];
+	}
+
+	return NULL;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/yesno.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/yesno.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/lxdialog/yesno.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,118 @@
+/*
+ *  yesno.c -- implements the yes/no box
+ *
+ *  ORIGINAL AUTHOR: Savio Lam (lam836 at cs.cuhk.hk)
+ *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap at cfw.com)
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+/*
+ * Display termination buttons
+ */
+static void
+print_buttons(WINDOW *dialog, int height, int width, int selected)
+{
+    int x = width / 2 - 10;
+    int y = height - 2;
+
+    print_button (dialog, " Yes ", y, x, selected == 0);
+    print_button (dialog, "  No  ", y, x + 13, selected == 1);
+
+    wmove(dialog, y, x+1 + 13*selected );
+    wrefresh (dialog);
+}
+
+/*
+ * Display a dialog box with two buttons - Yes and No
+ */
+int
+dialog_yesno (const char *title, const char *prompt, int height, int width)
+{
+    int i, x, y, key = 0, button = 0;
+    WINDOW *dialog;
+
+    /* center dialog box on screen */
+    x = (COLS - width) / 2;
+    y = (LINES - height) / 2;
+
+    draw_shadow (stdscr, y, x, height, width);
+
+    dialog = newwin (height, width, y, x);
+    keypad (dialog, TRUE);
+
+    draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+    wattrset (dialog, border_attr);
+    mvwaddch (dialog, height-3, 0, ACS_LTEE);
+    for (i = 0; i < width - 2; i++)
+	waddch (dialog, ACS_HLINE);
+    wattrset (dialog, dialog_attr);
+    waddch (dialog, ACS_RTEE);
+
+    if (title != NULL && strlen(title) >= width-2 ) {
+	/* truncate long title -- mec */
+	char * title2 = malloc(width-2+1);
+	memcpy( title2, title, width-2 );
+	title2[width-2] = '\0';
+	title = title2;
+    }
+
+    if (title != NULL) {
+	wattrset (dialog, title_attr);
+	mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+	waddstr (dialog, (char *)title);
+	waddch (dialog, ' ');
+    }
+
+    wattrset (dialog, dialog_attr);
+    print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+    print_buttons(dialog, height, width, 0);
+
+    while (key != ESC) {
+	key = wgetch (dialog);
+	switch (key) {
+	case 'Y':
+	case 'y':
+	    delwin (dialog);
+	    return 0;
+	case 'N':
+	case 'n':
+	    delwin (dialog);
+	    return 1;
+
+	case TAB:
+	case KEY_LEFT:
+	case KEY_RIGHT:
+	    button = ((key == KEY_LEFT ? --button : ++button) < 0)
+			? 1 : (button > 1 ? 0 : button);
+
+	    print_buttons(dialog, height, width, button);
+	    wrefresh (dialog);
+	    break;
+	case ' ':
+	case '\n':
+	    delwin (dialog);
+	    return button;
+	case ESC:
+	    break;
+	}
+    }
+
+    delwin (dialog);
+    return -1;			/* ESC pressed */
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/mconf.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/mconf.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/mconf.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,975 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ *
+ * Introduced single menu mode (show all sub-menus in one large tree).
+ * 2002-11-06 Petr Baudis <pasky at ucw.cz>
+ *
+ * Directly use liblxdialog library routines.
+ * 2002-11-14 Petr Baudis <pasky at ucw.cz>
+ */
+
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "lxdialog/dialog.h"
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+static char menu_backtitle[128];
+static const char mconf_readme[] =
+"Overview\n"
+"--------\n"
+"Some features may be built directly into BusyBox.  Some features\n"
+"may be completely removed altogether.  There are also certain\n"
+"parameters which are not really features, but must be\n"
+"entered in as decimal or hexadecimal numbers or possibly text.\n"
+"\n"
+"Menu items beginning with [*] or [ ] represent features\n"
+"configured to be built in or removed respectively.\n"
+"\n"
+"To change any of these features, highlight it with the cursor\n"
+"keys and press <Y> to build it in or <N> to removed it.\n"
+"You may also press the <Space Bar> to cycle\n"
+"through the available options (ie. Y->N->Y).\n"
+"\n"
+"Some additional keyboard hints:\n"
+"\n"
+"Menus\n"
+"----------\n"
+"o  Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
+"   you wish to change or submenu wish to select and press <Enter>.\n"
+"   Submenus are designated by \"--->\".\n"
+"\n"
+"   Shortcut: Press the option's highlighted letter (hotkey).\n"
+"             Pressing a hotkey more than once will sequence\n"
+"             through all visible items which use that hotkey.\n"
+"\n"
+"   You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
+"   unseen options into view.\n"
+"\n"
+"o  To exit a menu use the cursor keys to highlight the <Exit> button\n"
+"   and press <ENTER>.\n"
+"\n"
+"   Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
+"             using those letters.  You may press a single <ESC>, but\n"
+"             there is a delayed response which you may find annoying.\n"
+"\n"
+"   Also, the <TAB> and cursor keys will cycle between <Select>,\n"
+"   <Exit> and <Help>\n"
+"\n"
+"o  To get help with an item, use the cursor keys to highlight <Help>\n"
+"   and Press <ENTER>.\n"
+"\n"
+"   Shortcut: Press <H> or <?>.\n"
+"\n"
+"\n"
+"Radiolists  (Choice lists)\n"
+"-----------\n"
+"o  Use the cursor keys to select the option you wish to set and press\n"
+"   <S> or the <SPACE BAR>.\n"
+"\n"
+"   Shortcut: Press the first letter of the option you wish to set then\n"
+"             press <S> or <SPACE BAR>.\n"
+"\n"
+"o  To see available help for the item, use the cursor keys to highlight\n"
+"   <Help> and Press <ENTER>.\n"
+"\n"
+"   Shortcut: Press <H> or <?>.\n"
+"\n"
+"   Also, the <TAB> and cursor keys will cycle between <Select> and\n"
+"   <Help>\n"
+"\n"
+"\n"
+"Data Entry\n"
+"-----------\n"
+"o  Enter the requested information and press <ENTER>\n"
+"   If you are entering hexadecimal values, it is not necessary to\n"
+"   add the '0x' prefix to the entry.\n"
+"\n"
+"o  For help, use the <TAB> or cursor keys to highlight the help option\n"
+"   and press <ENTER>.  You can try <TAB><H> as well.\n"
+"\n"
+"\n"
+"Text Box    (Help Window)\n"
+"--------\n"
+"o  Use the cursor keys to scroll up/down/left/right.  The VI editor\n"
+"   keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n"
+"   who are familiar with less and lynx.\n"
+"\n"
+"o  Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n"
+"\n"
+"\n"
+"Alternate Configuration Files\n"
+"-----------------------------\n"
+"Menuconfig supports the use of alternate configuration files for\n"
+"those who, for various reasons, find it necessary to switch\n"
+"between different configurations.\n"
+"\n"
+"At the end of the main menu you will find two options.  One is\n"
+"for saving the current configuration to a file of your choosing.\n"
+"The other option is for loading a previously saved alternate\n"
+"configuration.\n"
+"\n"
+"Even if you don't use alternate configuration files, but you\n"
+"find during a Menuconfig session that you have completely messed\n"
+"up your settings, you may use the \"Load Alternate...\" option to\n"
+"restore your previously saved settings from \".config\" without\n"
+"restarting Menuconfig.\n"
+"\n"
+"Other information\n"
+"-----------------\n"
+"If you use Menuconfig in an XTERM window make sure you have your\n"
+"$TERM variable set to point to a xterm definition which supports color.\n"
+"Otherwise, Menuconfig will look rather bad.  Menuconfig will not\n"
+"display correctly in a RXVT window because rxvt displays only one\n"
+"intensity of color, bright.\n"
+"\n"
+"Menuconfig will display larger menus on screens or xterms which are\n"
+"set to display more than the standard 25 row by 80 column geometry.\n"
+"In order for this to work, the \"stty size\" command must be able to\n"
+"display the screen's current row and column geometry.  I STRONGLY\n"
+"RECOMMEND that you make sure you do NOT have the shell variables\n"
+"LINES and COLUMNS exported into your environment.  Some distributions\n"
+"export those variables via /etc/profile.  Some ncurses programs can\n"
+"become confused when those variables (LINES & COLUMNS) don't reflect\n"
+"the true screen size.\n"
+"\n"
+"Optional personality available\n"
+"------------------------------\n"
+"If you prefer to have all of the options listed in a single\n"
+"menu, rather than the default multimenu hierarchy, run the menuconfig\n"
+"with MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
+"\n"
+"make MENUCONFIG_MODE=single_menu menuconfig\n"
+"\n"
+"<Enter> will then unroll the appropriate category, or enfold it if it\n"
+"is already unrolled.\n"
+"\n"
+"Note that this mode can eventually be a little more CPU expensive\n"
+"(especially with a larger number of unrolled categories) than the\n"
+"default mode.\n",
+menu_instructions[] =
+	"Arrow keys navigate the menu.  "
+	"<Enter> selects submenus --->.  "
+	"Highlighted letters are hotkeys.  "
+	"Pressing <Y> selectes a feature, while <N> will exclude a feature.  "
+	"Press <Esc><Esc> to exit, <?> for Help, </> for Search.  "
+	"Legend: [*] feature is selected  [ ] feature is excluded",
+radiolist_instructions[] =
+	"Use the arrow keys to navigate this window or "
+	"press the hotkey of the item you wish to select "
+	"followed by the <SPACE BAR>. "
+	"Press <?> for additional information about this option.",
+inputbox_instructions_int[] =
+	"Please enter a decimal value. "
+	"Fractions will not be accepted.  "
+	"Use the <TAB> key to move from the input field to the buttons below it.",
+inputbox_instructions_hex[] =
+	"Please enter a hexadecimal value. "
+	"Use the <TAB> key to move from the input field to the buttons below it.",
+inputbox_instructions_string[] =
+	"Please enter a string value. "
+	"Use the <TAB> key to move from the input field to the buttons below it.",
+setmod_text[] =
+	"This feature depends on another which has been configured as a module.\n"
+	"As a result, this feature will be built as a module.",
+nohelp_text[] =
+	"There is no help available for this option.\n",
+load_config_text[] =
+	"Enter the name of the configuration file you wish to load.  "
+	"Accept the name shown to restore the configuration you "
+	"last retrieved.  Leave blank to abort.",
+load_config_help[] =
+	"\n"
+	"For various reasons, one may wish to keep several different BusyBox\n"
+	"configurations available on a single machine.\n"
+	"\n"
+	"If you have saved a previous configuration in a file other than the\n"
+	"BusyBox's default, entering the name of the file here will allow you\n"
+	"to modify that configuration.\n"
+	"\n"
+	"If you are uncertain, then you have probably never used alternate\n"
+	"configuration files.  You should therefor leave this blank to abort.\n",
+save_config_text[] =
+	"Enter a filename to which this configuration should be saved "
+	"as an alternate.  Leave blank to abort.",
+save_config_help[] =
+	"\n"
+	"For various reasons, one may wish to keep different BusyBox\n"
+	"configurations available on a single machine.\n"
+	"\n"
+	"Entering a file name here will allow you to later retrieve, modify\n"
+	"and use the current configuration as an alternate to whatever\n"
+	"configuration options you have selected at that time.\n"
+	"\n"
+	"If you are uncertain what all this means then you should probably\n"
+	"leave this blank.\n",
+search_help[] =
+	"\n"
+	"Search for CONFIG_ symbols and display their relations.\n"
+	"Example: search for \"^FOO\"\n"
+	"Result:\n"
+	"-----------------------------------------------------------------\n"
+	"Symbol: FOO [=m]\n"
+	"Prompt: Foo bus is used to drive the bar HW\n"
+	"Defined at drivers/pci/Kconfig:47\n"
+	"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
+	"Location:\n"
+	"  -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
+	"    -> PCI support (PCI [=y])\n"
+	"      -> PCI access mode (<choice> [=y])\n"
+	"Selects: LIBCRC32\n"
+	"Selected by: BAR\n"
+	"-----------------------------------------------------------------\n"
+	"o The line 'Prompt:' shows the text used in the menu structure for\n"
+	"  this CONFIG_ symbol\n"
+	"o The 'Defined at' line tell at what file / line number the symbol\n"
+	"  is defined\n"
+	"o The 'Depends on:' line tell what symbols needs to be defined for\n"
+	"  this symbol to be visible in the menu (selectable)\n"
+	"o The 'Location:' lines tell where in the menu structure this symbol\n"
+	"  is located\n"
+	"    A location followed by a [=y] indicate that this is a selectable\n"
+	"    menu item - and current value is displayed inside brackets.\n"
+	"o The 'Selects:' line tell what symbol will be automatically\n"
+	"  selected if this symbol is selected (y or m)\n"
+	"o The 'Selected by' line tell what symbol has selected this symbol\n"
+	"\n"
+	"Only relevant lines are shown.\n"
+	"\n\n"
+	"Search examples:\n"
+	"Examples: USB	=> find all CONFIG_ symbols containing USB\n"
+	"          ^USB => find all CONFIG_ symbols starting with USB\n"
+	"          USB$ => find all CONFIG_ symbols ending with USB\n"
+	"\n";
+
+static char filename[PATH_MAX+1] = ".config";
+static int indent;
+static struct termios ios_org;
+static int rows = 0, cols = 0;
+static struct menu *current_menu;
+static int child_count;
+static int single_menu_mode;
+
+static struct dialog_list_item *items[16384]; /* FIXME: This ought to be dynamic. */
+static int item_no;
+
+static void conf(struct menu *menu);
+static void conf_choice(struct menu *menu);
+static void conf_string(struct menu *menu);
+static void conf_load(void);
+static void conf_save(void);
+static void show_textbox(const char *title, const char *text, int r, int c);
+static void show_helptext(const char *title, const char *text);
+static void show_help(struct menu *menu);
+static void show_file(const char *filename, const char *title, int r, int c);
+
+static void init_wsize(void)
+{
+	struct winsize ws;
+	char *env;
+
+	if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)) {
+		rows = ws.ws_row;
+		cols = ws.ws_col;
+	}
+
+	if (!rows) {
+		env = getenv("LINES");
+		if (env)
+			rows = atoi(env);
+		if (!rows)
+			rows = 24;
+	}
+	if (!cols) {
+		env = getenv("COLUMNS");
+		if (env)
+			cols = atoi(env);
+		if (!cols)
+			cols = 80;
+	}
+
+	if (rows < 19 || cols < 80) {
+		fprintf(stderr, "Your display is too small to run Menuconfig!\n");
+		fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
+		exit(1);
+	}
+
+	rows -= 4;
+	cols -= 5;
+}
+
+static void cinit(void)
+{
+	item_no = 0;
+}
+
+static void cmake(void)
+{
+	items[item_no] = malloc(sizeof(struct dialog_list_item));
+	memset(items[item_no], 0, sizeof(struct dialog_list_item));
+	items[item_no]->tag = malloc(32); items[item_no]->tag[0] = 0;
+	items[item_no]->name = malloc(512); items[item_no]->name[0] = 0;
+	items[item_no]->namelen = 0;
+	item_no++;
+}
+
+static int cprint_name(const char *fmt, ...)
+{
+	va_list ap;
+	int res;
+
+	if (!item_no)
+		cmake();
+	va_start(ap, fmt);
+	res = vsnprintf(items[item_no - 1]->name + items[item_no - 1]->namelen,
+			512 - items[item_no - 1]->namelen, fmt, ap);
+	if (res > 0)
+		items[item_no - 1]->namelen += res;
+	va_end(ap);
+
+	return res;
+}
+
+static int cprint_tag(const char *fmt, ...)
+{
+	va_list ap;
+	int res;
+
+	if (!item_no)
+		cmake();
+	va_start(ap, fmt);
+	res = vsnprintf(items[item_no - 1]->tag, 32, fmt, ap);
+	va_end(ap);
+
+	return res;
+}
+
+static void cdone(void)
+{
+	int i;
+
+	for (i = 0; i < item_no; i++) {
+		free(items[i]->tag);
+		free(items[i]->name);
+		free(items[i]);
+	}
+
+	item_no = 0;
+}
+
+static void get_prompt_str(struct gstr *r, struct property *prop)
+{
+	int i, j;
+	struct menu *submenu[8], *menu;
+
+	str_printf(r, "Prompt: %s\n", prop->text);
+	str_printf(r, "  Defined at %s:%d\n", prop->menu->file->name,
+		prop->menu->lineno);
+	if (!expr_is_yes(prop->visible.expr)) {
+		str_append(r, "  Depends on: ");
+		expr_gstr_print(prop->visible.expr, r);
+		str_append(r, "\n");
+	}
+	menu = prop->menu->parent;
+	for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
+		submenu[i++] = menu;
+	if (i > 0) {
+		str_printf(r, "  Location:\n");
+		for (j = 4; --i >= 0; j += 2) {
+			menu = submenu[i];
+			str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu));
+			if (menu->sym) {
+				str_printf(r, " (%s [=%s])", menu->sym->name ?
+					menu->sym->name : "<choice>",
+					sym_get_string_value(menu->sym));
+			}
+			str_append(r, "\n");
+		}
+	}
+}
+
+static void get_symbol_str(struct gstr *r, struct symbol *sym)
+{
+	bool hit;
+	struct property *prop;
+
+	str_printf(r, "Symbol: %s [=%s]\n", sym->name,
+	                               sym_get_string_value(sym));
+	for_all_prompts(sym, prop)
+		get_prompt_str(r, prop);
+	hit = false;
+	for_all_properties(sym, prop, P_SELECT) {
+		if (!hit) {
+			str_append(r, "  Selects: ");
+			hit = true;
+		} else
+			str_printf(r, " && ");
+		expr_gstr_print(prop->expr, r);
+	}
+	if (hit)
+		str_append(r, "\n");
+	if (sym->rev_dep.expr) {
+		str_append(r, "  Selected by: ");
+		expr_gstr_print(sym->rev_dep.expr, r);
+		str_append(r, "\n");
+	}
+	str_append(r, "\n\n");
+}
+
+static struct gstr get_relations_str(struct symbol **sym_arr)
+{
+	struct symbol *sym;
+	struct gstr res = str_new();
+	int i;
+
+	for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
+		get_symbol_str(&res, sym);
+	if (!i)
+		str_append(&res, "No matches found.\n");
+	return res;
+}
+
+static void search_conf(void)
+{
+	struct symbol **sym_arr;
+	struct gstr res;
+
+again:
+	switch (dialog_inputbox("Search Configuration Parameter",
+				"Enter Keyword", 10, 75,
+				NULL)) {
+	case 0:
+		break;
+	case 1:
+		show_helptext("Search Configuration", search_help);
+		goto again;
+	default:
+		return;
+	}
+
+	sym_arr = sym_re_search(dialog_input_result);
+	res = get_relations_str(sym_arr);
+	free(sym_arr);
+	show_textbox("Search Results", str_get(&res), 0, 0);
+	str_free(&res);
+}
+
+static void build_conf(struct menu *menu)
+{
+	struct symbol *sym;
+	struct property *prop;
+	struct menu *child;
+	int type, tmp, doint = 2;
+	tristate val;
+	char ch;
+
+	if (!menu_is_visible(menu))
+		return;
+
+	sym = menu->sym;
+	prop = menu->prompt;
+	if (!sym) {
+		if (prop && menu != current_menu) {
+			const char *prompt = menu_get_prompt(menu);
+			switch (prop->type) {
+			case P_MENU:
+				child_count++;
+				cmake();
+				cprint_tag("m%p", menu);
+
+				if (single_menu_mode) {
+					cprint_name("%s%*c%s",
+						menu->data ? "-->" : "++>",
+						indent + 1, ' ', prompt);
+				} else {
+					cprint_name("   %*c%s  --->", indent + 1, ' ', prompt);
+				}
+
+				if (single_menu_mode && menu->data)
+					goto conf_childs;
+				return;
+			default:
+				if (prompt) {
+					child_count++;
+					cmake();
+					cprint_tag(":%p", menu);
+					cprint_name("---%*c%s", indent + 1, ' ', prompt);
+				}
+			}
+		} else
+			doint = 0;
+		goto conf_childs;
+	}
+
+	cmake();
+	type = sym_get_type(sym);
+	if (sym_is_choice(sym)) {
+		struct symbol *def_sym = sym_get_choice_value(sym);
+		struct menu *def_menu = NULL;
+
+		child_count++;
+		for (child = menu->list; child; child = child->next) {
+			if (menu_is_visible(child) && child->sym == def_sym)
+				def_menu = child;
+		}
+
+		val = sym_get_tristate_value(sym);
+		if (sym_is_changable(sym)) {
+			cprint_tag("t%p", menu);
+			switch (type) {
+			case S_BOOLEAN:
+				cprint_name("[%c]", val == no ? ' ' : '*');
+				break;
+			case S_TRISTATE:
+				switch (val) {
+				case yes: ch = '*'; break;
+				case mod: ch = 'M'; break;
+				default:  ch = ' '; break;
+				}
+				cprint_name("<%c>", ch);
+				break;
+			}
+		} else {
+			cprint_tag("%c%p", def_menu ? 't' : ':', menu);
+			cprint_name("   ");
+		}
+
+		cprint_name("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
+		if (val == yes) {
+			if (def_menu) {
+				cprint_name(" (%s)", menu_get_prompt(def_menu));
+				cprint_name("  --->");
+				if (def_menu->list) {
+					indent += 2;
+					build_conf(def_menu);
+					indent -= 2;
+				}
+			}
+			return;
+		}
+	} else {
+		if (menu == current_menu) {
+			cprint_tag(":%p", menu);
+			cprint_name("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
+			goto conf_childs;
+		}
+		child_count++;
+		val = sym_get_tristate_value(sym);
+		if (sym_is_choice_value(sym) && val == yes) {
+			cprint_tag(":%p", menu);
+			cprint_name("   ");
+		} else {
+			switch (type) {
+			case S_BOOLEAN:
+				cprint_tag("t%p", menu);
+				if (sym_is_changable(sym))
+					cprint_name("[%c]", val == no ? ' ' : '*');
+				else
+					cprint_name("---");
+				break;
+			case S_TRISTATE:
+				cprint_tag("t%p", menu);
+				switch (val) {
+				case yes: ch = '*'; break;
+				case mod: ch = 'M'; break;
+				default:  ch = ' '; break;
+				}
+				if (sym_is_changable(sym))
+					cprint_name("<%c>", ch);
+				else
+					cprint_name("---");
+				break;
+			default:
+				cprint_tag("s%p", menu);
+				tmp = cprint_name("(%s)", sym_get_string_value(sym));
+				tmp = indent - tmp + 4;
+				if (tmp < 0)
+					tmp = 0;
+				cprint_name("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
+					(sym_has_value(sym) || !sym_is_changable(sym)) ?
+					"" : " (NEW)");
+				goto conf_childs;
+			}
+		}
+		cprint_name("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
+			(sym_has_value(sym) || !sym_is_changable(sym)) ?
+			"" : " (NEW)");
+		if (menu->prompt->type == P_MENU) {
+			cprint_name("  --->");
+			return;
+		}
+	}
+
+conf_childs:
+	indent += doint;
+	for (child = menu->list; child; child = child->next)
+		build_conf(child);
+	indent -= doint;
+}
+
+static void conf(struct menu *menu)
+{
+	struct dialog_list_item *active_item = NULL;
+	struct menu *submenu;
+	const char *prompt = menu_get_prompt(menu);
+	struct symbol *sym;
+	char active_entry[40];
+	int stat, type;
+
+	unlink("lxdialog.scrltmp");
+	active_entry[0] = 0;
+	while (1) {
+		indent = 0;
+		child_count = 0;
+		current_menu = menu;
+		cdone(); cinit();
+		build_conf(menu);
+		if (!child_count)
+			break;
+		if (menu == &rootmenu) {
+			cmake(); cprint_tag(":"); cprint_name("--- ");
+			cmake(); cprint_tag("L"); cprint_name("Load an Alternate Configuration File");
+			cmake(); cprint_tag("S"); cprint_name("Save Configuration to an Alternate File");
+		}
+		dialog_clear();
+		stat = dialog_menu(prompt ? prompt : "Main Menu",
+				menu_instructions, rows, cols, rows - 10,
+				active_entry, item_no, items);
+		if (stat < 0)
+			return;
+
+		if (stat == 1 || stat == 255)
+			break;
+
+		active_item = first_sel_item(item_no, items);
+		if (!active_item)
+			continue;
+		active_item->selected = 0;
+		strncpy(active_entry, active_item->tag, sizeof(active_entry));
+		active_entry[sizeof(active_entry)-1] = 0;
+		type = active_entry[0];
+		if (!type)
+			continue;
+
+		sym = NULL;
+		submenu = NULL;
+		if (sscanf(active_entry + 1, "%p", &submenu) == 1)
+			sym = submenu->sym;
+
+		switch (stat) {
+		case 0:
+			switch (type) {
+			case 'm':
+				if (single_menu_mode)
+					submenu->data = (void *) (long) !submenu->data;
+				else
+					conf(submenu);
+				break;
+			case 't':
+				if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
+					conf_choice(submenu);
+				else if (submenu->prompt->type == P_MENU)
+					conf(submenu);
+				break;
+			case 's':
+				conf_string(submenu);
+				break;
+			case 'L':
+				conf_load();
+				break;
+			case 'S':
+				conf_save();
+				break;
+			}
+			break;
+		case 2:
+			if (sym)
+				show_help(submenu);
+			else
+				show_helptext("README", mconf_readme);
+			break;
+		case 3:
+			if (type == 't') {
+				if (sym_set_tristate_value(sym, yes))
+					break;
+				if (sym_set_tristate_value(sym, mod))
+					show_textbox(NULL, setmod_text, 6, 74);
+			}
+			break;
+		case 4:
+			if (type == 't')
+				sym_set_tristate_value(sym, no);
+			break;
+		case 5:
+			if (type == 't')
+				sym_set_tristate_value(sym, mod);
+			break;
+		case 6:
+			if (type == 't')
+				sym_toggle_tristate_value(sym);
+			else if (type == 'm')
+				conf(submenu);
+			break;
+		case 7:
+			search_conf();
+			break;
+		}
+	}
+}
+
+static void show_textbox(const char *title, const char *text, int r, int c)
+{
+	int fd;
+
+	fd = creat(".help.tmp", 0777);
+	write(fd, text, strlen(text));
+	close(fd);
+	show_file(".help.tmp", title, r, c);
+	unlink(".help.tmp");
+}
+
+static void show_helptext(const char *title, const char *text)
+{
+	show_textbox(title, text, 0, 0);
+}
+
+static void show_help(struct menu *menu)
+{
+	struct gstr help = str_new();
+	struct symbol *sym = menu->sym;
+
+	if (sym->help)
+	{
+		if (sym->name) {
+			str_printf(&help, "%s:\n\n", sym->name);
+			str_append(&help, sym->help);
+			str_append(&help, "\n");
+		}
+	} else {
+		str_append(&help, nohelp_text);
+	}
+	get_symbol_str(&help, sym);
+	show_helptext(menu_get_prompt(menu), str_get(&help));
+	str_free(&help);
+}
+
+static void show_file(const char *filename, const char *title, int r, int c)
+{
+	while (dialog_textbox(title, filename, r ? r : rows, c ? c : cols) < 0)
+		;
+}
+
+static void conf_choice(struct menu *menu)
+{
+	const char *prompt = menu_get_prompt(menu);
+	struct menu *child;
+	struct symbol *active;
+
+	active = sym_get_choice_value(menu->sym);
+	while (1) {
+		current_menu = menu;
+		cdone(); cinit();
+		for (child = menu->list; child; child = child->next) {
+			if (!menu_is_visible(child))
+				continue;
+			cmake();
+			cprint_tag("%p", child);
+			cprint_name("%s", menu_get_prompt(child));
+			if (child->sym == sym_get_choice_value(menu->sym))
+				items[item_no - 1]->selected = 1; /* ON */
+			else if (child->sym == active)
+				items[item_no - 1]->selected = 2; /* SELECTED */
+			else
+				items[item_no - 1]->selected = 0; /* OFF */
+		}
+
+		switch (dialog_checklist(prompt ? prompt : "Main Menu",
+					radiolist_instructions, 15, 70, 6,
+					item_no, items, FLAG_RADIO)) {
+		case 0:
+			if (sscanf(first_sel_item(item_no, items)->tag, "%p", &child) != 1)
+				break;
+			sym_set_tristate_value(child->sym, yes);
+			return;
+		case 1:
+			if (sscanf(first_sel_item(item_no, items)->tag, "%p", &child) == 1) {
+				show_help(child);
+				active = child->sym;
+			} else
+				show_help(menu);
+			break;
+		case 255:
+			return;
+		}
+	}
+}
+
+static void conf_string(struct menu *menu)
+{
+	const char *prompt = menu_get_prompt(menu);
+
+	while (1) {
+		char *heading;
+
+		switch (sym_get_type(menu->sym)) {
+		case S_INT:
+			heading = (char *) inputbox_instructions_int;
+			break;
+		case S_HEX:
+			heading = (char *) inputbox_instructions_hex;
+			break;
+		case S_STRING:
+			heading = (char *) inputbox_instructions_string;
+			break;
+		default:
+			heading = "Internal mconf error!";
+			/* panic? */;
+		}
+
+		switch (dialog_inputbox(prompt ? prompt : "Main Menu",
+					heading, 10, 75,
+					sym_get_string_value(menu->sym))) {
+		case 0:
+			if (sym_set_string_value(menu->sym, dialog_input_result))
+				return;
+			show_textbox(NULL, "You have made an invalid entry.", 5, 43);
+			break;
+		case 1:
+			show_help(menu);
+			break;
+		case 255:
+			return;
+		}
+	}
+}
+
+static void conf_load(void)
+{
+	while (1) {
+		switch (dialog_inputbox(NULL, load_config_text, 11, 55,
+					filename)) {
+		case 0:
+			if (!dialog_input_result[0])
+				return;
+			if (!conf_read(dialog_input_result))
+				return;
+			show_textbox(NULL, "File does not exist!", 5, 38);
+			break;
+		case 1:
+			show_helptext("Load Alternate Configuration", load_config_help);
+			break;
+		case 255:
+			return;
+		}
+	}
+}
+
+static void conf_save(void)
+{
+	while (1) {
+		switch (dialog_inputbox(NULL, save_config_text, 11, 55,
+					filename)) {
+		case 0:
+			if (!dialog_input_result[0])
+				return;
+			if (!conf_write(dialog_input_result))
+				return;
+			show_textbox(NULL, "Can't create file!  Probably a nonexistent directory.", 5, 60);
+			break;
+		case 1:
+			show_helptext("Save Alternate Configuration", save_config_help);
+			break;
+		case 255:
+			return;
+		}
+	}
+}
+
+static void conf_cleanup(void)
+{
+	tcsetattr(1, TCSAFLUSH, &ios_org);
+	unlink(".help.tmp");
+}
+
+static void winch_handler(int sig)
+{
+	struct winsize ws;
+
+	if (ioctl(1, TIOCGWINSZ, &ws) == -1) {
+		rows = 24;
+		cols = 80;
+	} else {
+		rows = ws.ws_row;
+		cols = ws.ws_col;
+	}
+
+	if (rows < 19 || cols < 80) {
+		end_dialog();
+		fprintf(stderr, "Your display is too small to run Menuconfig!\n");
+		fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
+		exit(1);
+	}
+
+	rows -= 4;
+	cols -= 5;
+
+}
+
+int main(int ac, char **av)
+{
+	struct symbol *sym;
+	char *mode;
+	int stat;
+
+	conf_parse(av[1]);
+	conf_read(NULL);
+
+	sym = sym_lookup("VERSION", 0);
+	sym_calc_value(sym);
+	snprintf(menu_backtitle, 128, "BusyBox v%s Configuration",
+		sym_get_string_value(sym));
+
+	mode = getenv("MENUCONFIG_MODE");
+	if (mode) {
+		if (!strcasecmp(mode, "single_menu"))
+			single_menu_mode = 1;
+	}
+
+	tcgetattr(1, &ios_org);
+	atexit(conf_cleanup);
+	init_wsize();
+	init_dialog();
+	signal(SIGWINCH, winch_handler);
+	conf(&rootmenu);
+	end_dialog();
+
+	/* Restart dialog to act more like when lxdialog was still separate */
+	init_dialog();
+	do {
+		stat = dialog_yesno(NULL,
+				    "Do you wish to save your new BusyBox configuration?", 5, 60);
+	} while (stat < 0);
+	end_dialog();
+
+	if (stat == 0) {
+		conf_write(NULL);
+		printf("\n"
+			"*** End of BusyBox configuration.\n");
+	} else
+		printf("\n\nYour BusyBox configuration changes were NOT saved.\n\n");
+
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/menu.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/menu.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/menu.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+struct menu rootmenu;
+static struct menu **last_entry_ptr;
+
+struct file *file_list;
+struct file *current_file;
+
+static void menu_warn(struct menu *menu, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
+	vfprintf(stderr, fmt, ap);
+	fprintf(stderr, "\n");
+	va_end(ap);
+}
+
+static void prop_warn(struct property *prop, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
+	vfprintf(stderr, fmt, ap);
+	fprintf(stderr, "\n");
+	va_end(ap);
+}
+
+void menu_init(void)
+{
+	current_entry = current_menu = &rootmenu;
+	last_entry_ptr = &rootmenu.list;
+}
+
+void menu_add_entry(struct symbol *sym)
+{
+	struct menu *menu;
+
+	menu = malloc(sizeof(*menu));
+	memset(menu, 0, sizeof(*menu));
+	menu->sym = sym;
+	menu->parent = current_menu;
+	menu->file = current_file;
+	menu->lineno = zconf_lineno();
+
+	*last_entry_ptr = menu;
+	last_entry_ptr = &menu->next;
+	current_entry = menu;
+}
+
+void menu_end_entry(void)
+{
+}
+
+void menu_add_menu(void)
+{
+	current_menu = current_entry;
+	last_entry_ptr = &current_entry->list;
+}
+
+void menu_end_menu(void)
+{
+	last_entry_ptr = &current_menu->next;
+	current_menu = current_menu->parent;
+}
+
+struct expr *menu_check_dep(struct expr *e)
+{
+	if (!e)
+		return e;
+
+	switch (e->type) {
+	case E_NOT:
+		e->left.expr = menu_check_dep(e->left.expr);
+		break;
+	case E_OR:
+	case E_AND:
+		e->left.expr = menu_check_dep(e->left.expr);
+		e->right.expr = menu_check_dep(e->right.expr);
+		break;
+	case E_SYMBOL:
+		/* change 'm' into 'm' && MODULES */
+		if (e->left.sym == &symbol_mod)
+			return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
+		break;
+	default:
+		break;
+	}
+	return e;
+}
+
+void menu_add_dep(struct expr *dep)
+{
+	current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
+}
+
+void menu_set_type(int type)
+{
+	struct symbol *sym = current_entry->sym;
+
+	if (sym->type == type)
+		return;
+	if (sym->type == S_UNKNOWN) {
+		sym->type = type;
+		return;
+	}
+	menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'\n",
+	    sym->name ? sym->name : "<choice>",
+	    sym_type_name(sym->type), sym_type_name(type));
+}
+
+struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
+{
+	struct property *prop = prop_alloc(type, current_entry->sym);
+
+	prop->menu = current_entry;
+	prop->text = prompt;
+	prop->expr = expr;
+	prop->visible.expr = menu_check_dep(dep);
+
+	if (prompt) {
+		if (current_entry->prompt)
+			menu_warn(current_entry, "prompt redefined\n");
+		current_entry->prompt = prop;
+	}
+
+	return prop;
+}
+
+void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
+{
+	menu_add_prop(type, prompt, NULL, dep);
+}
+
+void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
+{
+	menu_add_prop(type, NULL, expr, dep);
+}
+
+void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
+{
+	menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
+}
+
+void sym_check_prop(struct symbol *sym)
+{
+	struct property *prop;
+	struct symbol *sym2;
+	for (prop = sym->prop; prop; prop = prop->next) {
+		switch (prop->type) {
+		case P_DEFAULT:
+			if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
+			    prop->expr->type != E_SYMBOL)
+				prop_warn(prop,
+				    "default for config symbol '%'"
+				    " must be a single symbol", sym->name);
+			break;
+		case P_SELECT:
+			sym2 = prop_get_symbol(prop);
+			if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
+				prop_warn(prop,
+				    "config symbol '%s' uses select, but is "
+				    "not boolean or tristate", sym->name);
+			else if (sym2->type == S_UNKNOWN)
+				prop_warn(prop,
+				    "'select' used by config symbol '%s' "
+				    "refer to undefined symbol '%s'",
+				    sym->name, sym2->name);
+			else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)
+				prop_warn(prop,
+				    "'%s' has wrong type. 'select' only "
+				    "accept arguments of boolean and "
+				    "tristate type", sym2->name);
+			break;
+		case P_RANGE:
+			if (sym->type != S_INT && sym->type != S_HEX)
+				prop_warn(prop, "range is only allowed "
+				                "for int or hex symbols");
+			if (!sym_string_valid(sym, prop->expr->left.sym->name) ||
+			    !sym_string_valid(sym, prop->expr->right.sym->name))
+				prop_warn(prop, "range is invalid");
+			break;
+		default:
+			;
+		}
+	}
+}
+
+void menu_finalize(struct menu *parent)
+{
+	struct menu *menu, *last_menu;
+	struct symbol *sym;
+	struct property *prop;
+	struct expr *parentdep, *basedep, *dep, *dep2, **ep;
+
+	sym = parent->sym;
+	if (parent->list) {
+		if (sym && sym_is_choice(sym)) {
+			/* find the first choice value and find out choice type */
+			for (menu = parent->list; menu; menu = menu->next) {
+				if (menu->sym) {
+					current_entry = parent;
+					menu_set_type(menu->sym->type);
+					current_entry = menu;
+					menu_set_type(sym->type);
+					break;
+				}
+			}
+			parentdep = expr_alloc_symbol(sym);
+		} else if (parent->prompt)
+			parentdep = parent->prompt->visible.expr;
+		else
+			parentdep = parent->dep;
+
+		for (menu = parent->list; menu; menu = menu->next) {
+			basedep = expr_transform(menu->dep);
+			basedep = expr_alloc_and(expr_copy(parentdep), basedep);
+			basedep = expr_eliminate_dups(basedep);
+			menu->dep = basedep;
+			if (menu->sym)
+				prop = menu->sym->prop;
+			else
+				prop = menu->prompt;
+			for (; prop; prop = prop->next) {
+				if (prop->menu != menu)
+					continue;
+				dep = expr_transform(prop->visible.expr);
+				dep = expr_alloc_and(expr_copy(basedep), dep);
+				dep = expr_eliminate_dups(dep);
+				if (menu->sym && menu->sym->type != S_TRISTATE)
+					dep = expr_trans_bool(dep);
+				prop->visible.expr = dep;
+				if (prop->type == P_SELECT) {
+					struct symbol *es = prop_get_symbol(prop);
+					es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
+							expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
+				}
+			}
+		}
+		for (menu = parent->list; menu; menu = menu->next)
+			menu_finalize(menu);
+	} else if (sym) {
+		basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
+		basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
+		basedep = expr_eliminate_dups(expr_transform(basedep));
+		last_menu = NULL;
+		for (menu = parent->next; menu; menu = menu->next) {
+			dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
+			if (!expr_contains_symbol(dep, sym))
+				break;
+			if (expr_depends_symbol(dep, sym))
+				goto next;
+			dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
+			dep = expr_eliminate_dups(expr_transform(dep));
+			dep2 = expr_copy(basedep);
+			expr_eliminate_eq(&dep, &dep2);
+			expr_free(dep);
+			if (!expr_is_yes(dep2)) {
+				expr_free(dep2);
+				break;
+			}
+			expr_free(dep2);
+		next:
+			menu_finalize(menu);
+			menu->parent = parent;
+			last_menu = menu;
+		}
+		if (last_menu) {
+			parent->list = parent->next;
+			parent->next = last_menu->next;
+			last_menu->next = NULL;
+		}
+	}
+	for (menu = parent->list; menu; menu = menu->next) {
+		if (sym && sym_is_choice(sym) && menu->sym) {
+			menu->sym->flags |= SYMBOL_CHOICEVAL;
+			if (!menu->prompt)
+				menu_warn(menu, "choice value must have a prompt");
+			for (prop = menu->sym->prop; prop; prop = prop->next) {
+				if (prop->type == P_PROMPT && prop->menu != menu) {
+					prop_warn(prop, "choice values "
+					    "currently only support a "
+					    "single prompt");
+				}
+				if (prop->type == P_DEFAULT)
+					prop_warn(prop, "defaults for choice "
+					    "values not supported");
+			}
+			current_entry = menu;
+			menu_set_type(sym->type);
+			menu_add_symbol(P_CHOICE, sym, NULL);
+			prop = sym_get_choice_prop(sym);
+			for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
+				;
+			*ep = expr_alloc_one(E_CHOICE, NULL);
+			(*ep)->right.sym = menu->sym;
+		}
+		if (menu->list && (!menu->prompt || !menu->prompt->text)) {
+			for (last_menu = menu->list; ; last_menu = last_menu->next) {
+				last_menu->parent = parent;
+				if (!last_menu->next)
+					break;
+			}
+			last_menu->next = menu->next;
+			menu->next = menu->list;
+			menu->list = NULL;
+		}
+	}
+
+	if (sym && !(sym->flags & SYMBOL_WARNED)) {
+		if (sym->type == S_UNKNOWN)
+			menu_warn(parent, "config symbol defined "
+			    "without type\n");
+
+		if (sym_is_choice(sym) && !parent->prompt)
+			menu_warn(parent, "choice must have a prompt\n");
+
+		/* Check properties connected to this symbol */
+		sym_check_prop(sym);
+		sym->flags |= SYMBOL_WARNED;
+	}
+
+	if (sym && !sym_is_optional(sym) && parent->prompt) {
+		sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
+				expr_alloc_and(parent->prompt->visible.expr,
+					expr_alloc_symbol(&symbol_mod)));
+	}
+}
+
+bool menu_is_visible(struct menu *menu)
+{
+	struct menu *child;
+	struct symbol *sym;
+	tristate visible;
+
+	if (!menu->prompt)
+		return false;
+	sym = menu->sym;
+	if (sym) {
+		sym_calc_value(sym);
+		visible = menu->prompt->visible.tri;
+	} else
+		visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
+
+	if (visible != no)
+		return true;
+	if (!sym || sym_get_tristate_value(menu->sym) == no)
+		return false;
+
+	for (child = menu->list; child; child = child->next)
+		if (menu_is_visible(child))
+			return true;
+	return false;
+}
+
+const char *menu_get_prompt(struct menu *menu)
+{
+	if (menu->prompt)
+		return menu->prompt->text;
+	else if (menu->sym)
+		return menu->sym->name;
+	return NULL;
+}
+
+struct menu *menu_get_root_menu(struct menu *menu)
+{
+	return &rootmenu;
+}
+
+struct menu *menu_get_parent_menu(struct menu *menu)
+{
+	enum prop_type type;
+
+	for (; menu != &rootmenu; menu = menu->parent) {
+		type = menu->prompt ? menu->prompt->type : 0;
+		if (type == P_MENU)
+			break;
+	}
+	return menu;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/mkconfigs
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/mkconfigs	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/mkconfigs	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,51 @@
+#!/bin/sh
+#
+# Copyright (C) 2002 Khalid Aziz <khalid_aziz at hp.com>
+# Copyright (C) 2002 Randy Dunlap <rddunlap at osdl.org>
+# Copyright (C) 2002 Al Stone <ahs3 at fc.hp.com>
+# Copyright (C) 2002 Hewlett-Packard Company
+#
+#   This program is free software; you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation; either version 2 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program; if not, write to the Free Software
+#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#   Busybox version by Matteo Croce <3297627799 at wind.it>
+#
+# Rules to generate bbconfig.h from .config:
+#      - Retain lines that begin with "CONFIG_"
+#      - Retain lines that begin with "# CONFIG_"
+#      - lines that use double-quotes must \\-escape-quote them
+
+if [ $# -lt 1 ]
+then
+	config=.config
+else	config=$1
+fi
+
+echo "#ifndef _BBCONFIGOPTS_H"
+echo "#define _BBCONFIGOPTS_H"
+echo \
+"/*
+ * busybox configuration settings.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * This file is generated automatically by scripts/config/mkconfigs.
+ * Do not edit.
+ *
+ */"
+
+echo "static const char * const bbconfig_config ="
+echo "`sed 's/\"/\\\\\"/g' $config | grep "^#\? \?CONFIG_" | awk '{print "\\"" $0 "\\\\n\\"";}'`"
+echo ";"
+echo "#endif /* _BBCONFIGOPTS_H */"


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/mkconfigs
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/symbol.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/symbol.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/symbol.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,809 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <regex.h>
+#include <sys/utsname.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+struct symbol symbol_yes = {
+	.name = "y",
+	.curr = { "y", yes },
+	.flags = SYMBOL_YES|SYMBOL_VALID,
+}, symbol_mod = {
+	.name = "m",
+	.curr = { "m", mod },
+	.flags = SYMBOL_MOD|SYMBOL_VALID,
+}, symbol_no = {
+	.name = "n",
+	.curr = { "n", no },
+	.flags = SYMBOL_NO|SYMBOL_VALID,
+}, symbol_empty = {
+	.name = "",
+	.curr = { "", no },
+	.flags = SYMBOL_VALID,
+};
+
+int sym_change_count;
+struct symbol *modules_sym;
+tristate modules_val;
+
+void sym_add_default(struct symbol *sym, const char *def)
+{
+	struct property *prop = prop_alloc(P_DEFAULT, sym);
+
+	prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
+}
+
+void sym_init(void)
+{
+	struct symbol *sym;
+	char *p;
+	static bool inited = false;
+
+	if (inited)
+		return;
+	inited = true;
+
+	sym = sym_lookup("VERSION", 0);
+	sym->type = S_STRING;
+	sym->flags |= SYMBOL_AUTO;
+	p = getenv("VERSION");
+	if (p)
+		sym_add_default(sym, p);
+
+	sym = sym_lookup("TARGET_ARCH", 0);
+	sym->type = S_STRING;
+	sym->flags |= SYMBOL_AUTO;
+	p = getenv("TARGET_ARCH");
+	if (p)
+		sym_add_default(sym, p);
+
+}
+
+enum symbol_type sym_get_type(struct symbol *sym)
+{
+	enum symbol_type type = sym->type;
+
+	if (type == S_TRISTATE) {
+		if (sym_is_choice_value(sym) && sym->visible == yes)
+			type = S_BOOLEAN;
+		else if (modules_val == no)
+			type = S_BOOLEAN;
+	}
+	return type;
+}
+
+const char *sym_type_name(enum symbol_type type)
+{
+	switch (type) {
+	case S_BOOLEAN:
+		return "boolean";
+	case S_TRISTATE:
+		return "tristate";
+	case S_INT:
+		return "integer";
+	case S_HEX:
+		return "hex";
+	case S_STRING:
+		return "string";
+	case S_UNKNOWN:
+		return "unknown";
+	case S_OTHER:
+		break;
+	}
+	return "???";
+}
+
+struct property *sym_get_choice_prop(struct symbol *sym)
+{
+	struct property *prop;
+
+	for_all_choices(sym, prop)
+		return prop;
+	return NULL;
+}
+
+struct property *sym_get_default_prop(struct symbol *sym)
+{
+	struct property *prop;
+
+	for_all_defaults(sym, prop) {
+		prop->visible.tri = expr_calc_value(prop->visible.expr);
+		if (prop->visible.tri != no)
+			return prop;
+	}
+	return NULL;
+}
+
+struct property *sym_get_range_prop(struct symbol *sym)
+{
+	struct property *prop;
+
+	for_all_properties(sym, prop, P_RANGE) {
+		prop->visible.tri = expr_calc_value(prop->visible.expr);
+		if (prop->visible.tri != no)
+			return prop;
+	}
+	return NULL;
+}
+
+static void sym_calc_visibility(struct symbol *sym)
+{
+	struct property *prop;
+	tristate tri;
+
+	/* any prompt visible? */
+	tri = no;
+	for_all_prompts(sym, prop) {
+		prop->visible.tri = expr_calc_value(prop->visible.expr);
+		tri = E_OR(tri, prop->visible.tri);
+	}
+	if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
+		tri = yes;
+	if (sym->visible != tri) {
+		sym->visible = tri;
+		sym_set_changed(sym);
+	}
+	if (sym_is_choice_value(sym))
+		return;
+	tri = no;
+	if (sym->rev_dep.expr)
+		tri = expr_calc_value(sym->rev_dep.expr);
+	if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
+		tri = yes;
+	if (sym->rev_dep.tri != tri) {
+		sym->rev_dep.tri = tri;
+		sym_set_changed(sym);
+	}
+}
+
+static struct symbol *sym_calc_choice(struct symbol *sym)
+{
+	struct symbol *def_sym;
+	struct property *prop;
+	struct expr *e;
+
+	/* is the user choice visible? */
+	def_sym = sym->user.val;
+	if (def_sym) {
+		sym_calc_visibility(def_sym);
+		if (def_sym->visible != no)
+			return def_sym;
+	}
+
+	/* any of the defaults visible? */
+	for_all_defaults(sym, prop) {
+		prop->visible.tri = expr_calc_value(prop->visible.expr);
+		if (prop->visible.tri == no)
+			continue;
+		def_sym = prop_get_symbol(prop);
+		sym_calc_visibility(def_sym);
+		if (def_sym->visible != no)
+			return def_sym;
+	}
+
+	/* just get the first visible value */
+	prop = sym_get_choice_prop(sym);
+	for (e = prop->expr; e; e = e->left.expr) {
+		def_sym = e->right.sym;
+		sym_calc_visibility(def_sym);
+		if (def_sym->visible != no)
+			return def_sym;
+	}
+
+	/* no choice? reset tristate value */
+	sym->curr.tri = no;
+	return NULL;
+}
+
+void sym_calc_value(struct symbol *sym)
+{
+	struct symbol_value newval, oldval;
+	struct property *prop;
+	struct expr *e;
+
+	if (!sym)
+		return;
+
+	if (sym->flags & SYMBOL_VALID)
+		return;
+	sym->flags |= SYMBOL_VALID;
+
+	oldval = sym->curr;
+
+	switch (sym->type) {
+	case S_INT:
+	case S_HEX:
+	case S_STRING:
+		newval = symbol_empty.curr;
+		break;
+	case S_BOOLEAN:
+	case S_TRISTATE:
+		newval = symbol_no.curr;
+		break;
+	default:
+		sym->curr.val = sym->name;
+		sym->curr.tri = no;
+		return;
+	}
+	if (!sym_is_choice_value(sym))
+		sym->flags &= ~SYMBOL_WRITE;
+
+	sym_calc_visibility(sym);
+
+	/* set default if recursively called */
+	sym->curr = newval;
+
+	switch (sym_get_type(sym)) {
+	case S_BOOLEAN:
+	case S_TRISTATE:
+		if (sym_is_choice_value(sym) && sym->visible == yes) {
+			prop = sym_get_choice_prop(sym);
+			newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
+		} else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
+			sym->flags |= SYMBOL_WRITE;
+			if (sym_has_value(sym))
+				newval.tri = sym->user.tri;
+			else if (!sym_is_choice(sym)) {
+				prop = sym_get_default_prop(sym);
+				if (prop)
+					newval.tri = expr_calc_value(prop->expr);
+			}
+			newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
+		} else if (!sym_is_choice(sym)) {
+			prop = sym_get_default_prop(sym);
+			if (prop) {
+				sym->flags |= SYMBOL_WRITE;
+				newval.tri = expr_calc_value(prop->expr);
+			}
+		}
+		if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
+			newval.tri = yes;
+		break;
+	case S_STRING:
+	case S_HEX:
+	case S_INT:
+		if (sym->visible != no) {
+			sym->flags |= SYMBOL_WRITE;
+			if (sym_has_value(sym)) {
+				newval.val = sym->user.val;
+				break;
+			}
+		}
+		prop = sym_get_default_prop(sym);
+		if (prop) {
+			struct symbol *ds = prop_get_symbol(prop);
+			if (ds) {
+				sym->flags |= SYMBOL_WRITE;
+				sym_calc_value(ds);
+				newval.val = ds->curr.val;
+			}
+		}
+		break;
+	default:
+		;
+	}
+
+	sym->curr = newval;
+	if (sym_is_choice(sym) && newval.tri == yes)
+		sym->curr.val = sym_calc_choice(sym);
+
+	if (memcmp(&oldval, &sym->curr, sizeof(oldval)))
+		sym_set_changed(sym);
+	if (modules_sym == sym)
+		modules_val = modules_sym->curr.tri;
+
+	if (sym_is_choice(sym)) {
+		int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
+		prop = sym_get_choice_prop(sym);
+		for (e = prop->expr; e; e = e->left.expr) {
+			e->right.sym->flags |= flags;
+			if (flags & SYMBOL_CHANGED)
+				sym_set_changed(e->right.sym);
+		}
+	}
+}
+
+void sym_clear_all_valid(void)
+{
+	struct symbol *sym;
+	int i;
+
+	for_all_symbols(i, sym)
+		sym->flags &= ~SYMBOL_VALID;
+	sym_change_count++;
+	if (modules_sym)
+		sym_calc_value(modules_sym);
+}
+
+void sym_set_changed(struct symbol *sym)
+{
+	struct property *prop;
+
+	sym->flags |= SYMBOL_CHANGED;
+	for (prop = sym->prop; prop; prop = prop->next) {
+		if (prop->menu)
+			prop->menu->flags |= MENU_CHANGED;
+	}
+}
+
+void sym_set_all_changed(void)
+{
+	struct symbol *sym;
+	int i;
+
+	for_all_symbols(i, sym)
+		sym_set_changed(sym);
+}
+
+bool sym_tristate_within_range(struct symbol *sym, tristate val)
+{
+	int type = sym_get_type(sym);
+
+	if (sym->visible == no)
+		return false;
+
+	if (type != S_BOOLEAN && type != S_TRISTATE)
+		return false;
+
+	if (type == S_BOOLEAN && val == mod)
+		return false;
+	if (sym->visible <= sym->rev_dep.tri)
+		return false;
+	if (sym_is_choice_value(sym) && sym->visible == yes)
+		return val == yes;
+	return val >= sym->rev_dep.tri && val <= sym->visible;
+}
+
+bool sym_set_tristate_value(struct symbol *sym, tristate val)
+{
+	tristate oldval = sym_get_tristate_value(sym);
+
+	if (oldval != val && !sym_tristate_within_range(sym, val))
+		return false;
+
+	if (sym->flags & SYMBOL_NEW) {
+		sym->flags &= ~SYMBOL_NEW;
+		sym_set_changed(sym);
+	}
+	if (sym_is_choice_value(sym) && val == yes) {
+		struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
+
+		cs->user.val = sym;
+		cs->flags &= ~SYMBOL_NEW;
+	}
+
+	sym->user.tri = val;
+	if (oldval != val) {
+		sym_clear_all_valid();
+		if (sym == modules_sym)
+			sym_set_all_changed();
+	}
+
+	return true;
+}
+
+tristate sym_toggle_tristate_value(struct symbol *sym)
+{
+	tristate oldval, newval;
+
+	oldval = newval = sym_get_tristate_value(sym);
+	do {
+		switch (newval) {
+		case no:
+			newval = mod;
+			break;
+		case mod:
+			newval = yes;
+			break;
+		case yes:
+			newval = no;
+			break;
+		}
+		if (sym_set_tristate_value(sym, newval))
+			break;
+	} while (oldval != newval);
+	return newval;
+}
+
+bool sym_string_valid(struct symbol *sym, const char *str)
+{
+	signed char ch;
+
+	switch (sym->type) {
+	case S_STRING:
+		return true;
+	case S_INT:
+		ch = *str++;
+		if (ch == '-')
+			ch = *str++;
+		if (!isdigit(ch))
+			return false;
+		if (ch == '0' && *str != 0)
+			return false;
+		while ((ch = *str++)) {
+			if (!isdigit(ch))
+				return false;
+		}
+		return true;
+	case S_HEX:
+		if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
+			str += 2;
+		ch = *str++;
+		do {
+			if (!isxdigit(ch))
+				return false;
+		} while ((ch = *str++));
+		return true;
+	case S_BOOLEAN:
+	case S_TRISTATE:
+		switch (str[0]) {
+		case 'y': case 'Y':
+		case 'm': case 'M':
+		case 'n': case 'N':
+			return true;
+		}
+		return false;
+	default:
+		return false;
+	}
+}
+
+bool sym_string_within_range(struct symbol *sym, const char *str)
+{
+	struct property *prop;
+	int val;
+
+	switch (sym->type) {
+	case S_STRING:
+		return sym_string_valid(sym, str);
+	case S_INT:
+		if (!sym_string_valid(sym, str))
+			return false;
+		prop = sym_get_range_prop(sym);
+		if (!prop)
+			return true;
+		val = strtol(str, NULL, 10);
+		return val >= strtol(prop->expr->left.sym->name, NULL, 10) &&
+		       val <= strtol(prop->expr->right.sym->name, NULL, 10);
+	case S_HEX:
+		if (!sym_string_valid(sym, str))
+			return false;
+		prop = sym_get_range_prop(sym);
+		if (!prop)
+			return true;
+		val = strtol(str, NULL, 16);
+		return val >= strtol(prop->expr->left.sym->name, NULL, 16) &&
+		       val <= strtol(prop->expr->right.sym->name, NULL, 16);
+	case S_BOOLEAN:
+	case S_TRISTATE:
+		switch (str[0]) {
+		case 'y': case 'Y':
+			return sym_tristate_within_range(sym, yes);
+		case 'm': case 'M':
+			return sym_tristate_within_range(sym, mod);
+		case 'n': case 'N':
+			return sym_tristate_within_range(sym, no);
+		}
+		return false;
+	default:
+		return false;
+	}
+}
+
+bool sym_set_string_value(struct symbol *sym, const char *newval)
+{
+	const char *oldval;
+	char *val;
+	int size;
+
+	switch (sym->type) {
+	case S_BOOLEAN:
+	case S_TRISTATE:
+		switch (newval[0]) {
+		case 'y': case 'Y':
+			return sym_set_tristate_value(sym, yes);
+		case 'm': case 'M':
+			return sym_set_tristate_value(sym, mod);
+		case 'n': case 'N':
+			return sym_set_tristate_value(sym, no);
+		}
+		return false;
+	default:
+		;
+	}
+
+	if (!sym_string_within_range(sym, newval))
+		return false;
+
+	if (sym->flags & SYMBOL_NEW) {
+		sym->flags &= ~SYMBOL_NEW;
+		sym_set_changed(sym);
+	}
+
+	oldval = sym->user.val;
+	size = strlen(newval) + 1;
+	if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
+		size += 2;
+		sym->user.val = val = malloc(size);
+		*val++ = '0';
+		*val++ = 'x';
+	} else if (!oldval || strcmp(oldval, newval))
+		sym->user.val = val = malloc(size);
+	else
+		return true;
+
+	strcpy(val, newval);
+	free((void *)oldval);
+	sym_clear_all_valid();
+
+	return true;
+}
+
+const char *sym_get_string_value(struct symbol *sym)
+{
+	tristate val;
+
+	switch (sym->type) {
+	case S_BOOLEAN:
+	case S_TRISTATE:
+		val = sym_get_tristate_value(sym);
+		switch (val) {
+		case no:
+			return "n";
+		case mod:
+			return "m";
+		case yes:
+			return "y";
+		}
+		break;
+	default:
+		;
+	}
+	return (const char *)sym->curr.val;
+}
+
+bool sym_is_changable(struct symbol *sym)
+{
+	return sym->visible > sym->rev_dep.tri;
+}
+
+struct symbol *sym_lookup(const char *name, int isconst)
+{
+	struct symbol *symbol;
+	const char *ptr;
+	char *new_name;
+	int hash = 0;
+
+	if (name) {
+		if (name[0] && !name[1]) {
+			switch (name[0]) {
+			case 'y': return &symbol_yes;
+			case 'm': return &symbol_mod;
+			case 'n': return &symbol_no;
+			}
+		}
+		for (ptr = name; *ptr; ptr++)
+			hash += *ptr;
+		hash &= 0xff;
+
+		for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
+			if (!strcmp(symbol->name, name)) {
+				if ((isconst && symbol->flags & SYMBOL_CONST) ||
+				    (!isconst && !(symbol->flags & SYMBOL_CONST)))
+					return symbol;
+			}
+		}
+		new_name = strdup(name);
+	} else {
+		new_name = NULL;
+		hash = 256;
+	}
+
+	symbol = malloc(sizeof(*symbol));
+	memset(symbol, 0, sizeof(*symbol));
+	symbol->name = new_name;
+	symbol->type = S_UNKNOWN;
+	symbol->flags = SYMBOL_NEW;
+	if (isconst)
+		symbol->flags |= SYMBOL_CONST;
+
+	symbol->next = symbol_hash[hash];
+	symbol_hash[hash] = symbol;
+
+	return symbol;
+}
+
+struct symbol *sym_find(const char *name)
+{
+	struct symbol *symbol = NULL;
+	const char *ptr;
+	int hash = 0;
+
+	if (!name)
+		return NULL;
+
+	if (name[0] && !name[1]) {
+		switch (name[0]) {
+		case 'y': return &symbol_yes;
+		case 'm': return &symbol_mod;
+		case 'n': return &symbol_no;
+		}
+	}
+	for (ptr = name; *ptr; ptr++)
+		hash += *ptr;
+	hash &= 0xff;
+
+	for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
+		if (!strcmp(symbol->name, name) &&
+		    !(symbol->flags & SYMBOL_CONST))
+				break;
+	}
+
+	return symbol;
+}
+
+struct symbol **sym_re_search(const char *pattern)
+{
+	struct symbol *sym, **sym_arr = NULL;
+	int i, cnt, size;
+	regex_t re;
+
+	cnt = size = 0;
+	/* Skip if empty */
+	if (strlen(pattern) == 0)
+		return NULL;
+	if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
+		return NULL;
+
+	for_all_symbols(i, sym) {
+		if (sym->flags & SYMBOL_CONST || !sym->name)
+			continue;
+		if (regexec(&re, sym->name, 0, NULL, 0))
+			continue;
+		if (cnt + 1 >= size) {
+			void *tmp = sym_arr;
+			size += 16;
+			sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
+			if (!sym_arr) {
+				free(tmp);
+				return NULL;
+			}
+		}
+		sym_arr[cnt++] = sym;
+	}
+	if (sym_arr)
+		sym_arr[cnt] = NULL;
+	regfree(&re);
+
+	return sym_arr;
+}
+
+
+struct symbol *sym_check_deps(struct symbol *sym);
+
+static struct symbol *sym_check_expr_deps(struct expr *e)
+{
+	struct symbol *sym;
+
+	if (!e)
+		return NULL;
+	switch (e->type) {
+	case E_OR:
+	case E_AND:
+		sym = sym_check_expr_deps(e->left.expr);
+		if (sym)
+			return sym;
+		return sym_check_expr_deps(e->right.expr);
+	case E_NOT:
+		return sym_check_expr_deps(e->left.expr);
+	case E_EQUAL:
+	case E_UNEQUAL:
+		sym = sym_check_deps(e->left.sym);
+		if (sym)
+			return sym;
+		return sym_check_deps(e->right.sym);
+	case E_SYMBOL:
+		return sym_check_deps(e->left.sym);
+	default:
+		break;
+	}
+	printf("Oops! How to check %d?\n", e->type);
+	return NULL;
+}
+
+struct symbol *sym_check_deps(struct symbol *sym)
+{
+	struct symbol *sym2;
+	struct property *prop;
+
+	if (sym->flags & SYMBOL_CHECK_DONE)
+		return NULL;
+	if (sym->flags & SYMBOL_CHECK) {
+		printf("Warning! Found recursive dependency: %s", sym->name);
+		return sym;
+	}
+
+	sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
+	sym2 = sym_check_expr_deps(sym->rev_dep.expr);
+	if (sym2)
+		goto out;
+
+	for (prop = sym->prop; prop; prop = prop->next) {
+		if (prop->type == P_CHOICE || prop->type == P_SELECT)
+			continue;
+		sym2 = sym_check_expr_deps(prop->visible.expr);
+		if (sym2)
+			goto out;
+		if (prop->type != P_DEFAULT || sym_is_choice(sym))
+			continue;
+		sym2 = sym_check_expr_deps(prop->expr);
+		if (sym2)
+			goto out;
+	}
+out:
+	if (sym2)
+		printf(" %s", sym->name);
+	sym->flags &= ~SYMBOL_CHECK;
+	return sym2;
+}
+
+struct property *prop_alloc(enum prop_type type, struct symbol *sym)
+{
+	struct property *prop;
+	struct property **propp;
+
+	prop = malloc(sizeof(*prop));
+	memset(prop, 0, sizeof(*prop));
+	prop->type = type;
+	prop->sym = sym;
+	prop->file = current_file;
+	prop->lineno = zconf_lineno();
+
+	/* append property to the prop list of symbol */
+	if (sym) {
+		for (propp = &sym->prop; *propp; propp = &(*propp)->next)
+			;
+		*propp = prop;
+	}
+
+	return prop;
+}
+
+struct symbol *prop_get_symbol(struct property *prop)
+{
+	if (prop->expr && (prop->expr->type == E_SYMBOL ||
+			   prop->expr->type == E_CHOICE))
+		return prop->expr->left.sym;
+	return NULL;
+}
+
+const char *prop_get_type_name(enum prop_type type)
+{
+	switch (type) {
+	case P_PROMPT:
+		return "prompt";
+	case P_COMMENT:
+		return "comment";
+	case P_MENU:
+		return "menu";
+	case P_DEFAULT:
+		return "default";
+	case P_CHOICE:
+		return "choice";
+	case P_SELECT:
+		return "select";
+	case P_RANGE:
+		return "range";
+	case P_UNKNOWN:
+		break;
+	}
+	return "unknown";
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/util.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/util.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/util.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2002-2005 Roman Zippel <zippel at linux-m68k.org>
+ * Copyright (C) 2002-2005 Sam Ravnborg <sam at ravnborg.org>
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <string.h>
+#include "lkc.h"
+
+/* file already present in list? If not add it */
+struct file *file_lookup(const char *name)
+{
+	struct file *file;
+
+	for (file = file_list; file; file = file->next) {
+		if (!strcmp(name, file->name))
+			return file;
+	}
+
+	file = malloc(sizeof(*file));
+	memset(file, 0, sizeof(*file));
+	file->name = strdup(name);
+	file->next = file_list;
+	file_list = file;
+	return file;
+}
+
+/* write a dependency file as used by kbuild to track dependencies */
+int file_write_dep(const char *name)
+{
+	struct file *file;
+	FILE *out;
+
+	if (!name)
+		name = ".config.cmd";
+	out = fopen(".config.tmp", "w");
+	if (!out)
+		return 1;
+	fprintf(out, "deps_config := \\\n");
+	for (file = file_list; file; file = file->next) {
+		if (file->next)
+			fprintf(out, "\t%s \\\n", file->name);
+		else
+			fprintf(out, "\t%s\n", file->name);
+	}
+	fprintf(out, "\n.config include/config.h: $(deps_config)\n\n$(deps_config):\n");
+	fclose(out);
+	rename(".config.tmp", name);
+	return 0;
+}
+
+
+/* Allocate initial growable sting */
+struct gstr str_new(void)
+{
+	struct gstr gs;
+	gs.s = malloc(sizeof(char) * 64);
+	gs.len = 16;
+	strcpy(gs.s, "\0");
+	return gs;
+}
+
+/* Allocate and assign growable string */
+struct gstr str_assign(const char *s)
+{
+	struct gstr gs;
+	gs.s = strdup(s);
+	gs.len = strlen(s) + 1;
+	return gs;
+}
+
+/* Free storage for growable string */
+void str_free(struct gstr *gs)
+{
+	if (gs->s)
+		free(gs->s);
+	gs->s = NULL;
+	gs->len = 0;
+}
+
+/* Append to growable string */
+void str_append(struct gstr *gs, const char *s)
+{
+	size_t l = strlen(gs->s) + strlen(s) + 1;
+	if (l > gs->len) {
+		gs->s   = realloc(gs->s, l);
+		gs->len = l;
+	}
+	strcat(gs->s, s);
+}
+
+/* Append printf formatted string to growable string */
+void str_printf(struct gstr *gs, const char *fmt, ...)
+{
+	va_list ap;
+	char s[10000]; /* big enough... */
+	va_start(ap, fmt);
+	vsnprintf(s, sizeof(s), fmt, ap);
+	str_append(gs, s);
+	va_end(ap);
+}
+
+/* Retreive value of growable string */
+const char *str_get(struct gstr *gs)
+{
+	return gs->s;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/zconf.l
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/zconf.l	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/zconf.l	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,366 @@
+%option backup nostdinit noyywrap never-interactive full ecs
+%option 8bit backup nodefault perf-report perf-report
+%x COMMAND HELP STRING PARAM
+%{
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+#define START_STRSIZE	16
+
+char *text;
+static char *text_ptr;
+static int text_size, text_asize;
+
+struct buffer {
+        struct buffer *parent;
+        YY_BUFFER_STATE state;
+};
+
+struct buffer *current_buf;
+
+static int last_ts, first_ts;
+
+static void zconf_endhelp(void);
+static struct buffer *zconf_endfile(void);
+
+void new_string(void)
+{
+	text = malloc(START_STRSIZE);
+	text_asize = START_STRSIZE;
+	text_ptr = text;
+	text_size = 0;
+	*text_ptr = 0;
+}
+
+void append_string(const char *str, int size)
+{
+	int new_size = text_size + size + 1;
+	if (new_size > text_asize) {
+		text = realloc(text, new_size);
+		text_asize = new_size;
+		text_ptr = text + text_size;
+	}
+	memcpy(text_ptr, str, size);
+	text_ptr += size;
+	text_size += size;
+	*text_ptr = 0;
+}
+
+void alloc_string(const char *str, int size)
+{
+	text = malloc(size + 1);
+	memcpy(text, str, size);
+	text[size] = 0;
+}
+%}
+
+ws	[ \n\t]
+n	[A-Za-z0-9_]
+
+%%
+	int str = 0;
+	int ts, i;
+
+[ \t]*#.*\n	current_file->lineno++;
+[ \t]*#.*
+
+[ \t]*\n	current_file->lineno++; return T_EOL;
+
+[ \t]+	{
+	BEGIN(COMMAND);
+}
+
+.	{
+	unput(yytext[0]);
+	BEGIN(COMMAND);
+}
+
+
+<COMMAND>{
+	"mainmenu"		BEGIN(PARAM); return T_MAINMENU;
+	"menu"			BEGIN(PARAM); return T_MENU;
+	"endmenu"		BEGIN(PARAM); return T_ENDMENU;
+	"source"		BEGIN(PARAM); return T_SOURCE;
+	"choice"		BEGIN(PARAM); return T_CHOICE;
+	"endchoice"		BEGIN(PARAM); return T_ENDCHOICE;
+	"comment"		BEGIN(PARAM); return T_COMMENT;
+	"config"		BEGIN(PARAM); return T_CONFIG;
+	"menuconfig"		BEGIN(PARAM); return T_MENUCONFIG;
+	"help"			BEGIN(PARAM); return T_HELP;
+	"if"			BEGIN(PARAM); return T_IF;
+	"endif"			BEGIN(PARAM); return T_ENDIF;
+	"depends"		BEGIN(PARAM); return T_DEPENDS;
+	"requires"		BEGIN(PARAM); return T_REQUIRES;
+	"optional"		BEGIN(PARAM); return T_OPTIONAL;
+	"default"		BEGIN(PARAM); return T_DEFAULT;
+	"prompt"		BEGIN(PARAM); return T_PROMPT;
+	"tristate"		BEGIN(PARAM); return T_TRISTATE;
+	"def_tristate"		BEGIN(PARAM); return T_DEF_TRISTATE;
+	"bool"			BEGIN(PARAM); return T_BOOLEAN;
+	"boolean"		BEGIN(PARAM); return T_BOOLEAN;
+	"def_bool"		BEGIN(PARAM); return T_DEF_BOOLEAN;
+	"def_boolean"		BEGIN(PARAM); return T_DEF_BOOLEAN;
+	"int"			BEGIN(PARAM); return T_INT;
+	"hex"			BEGIN(PARAM); return T_HEX;
+	"string"		BEGIN(PARAM); return T_STRING;
+	"select"		BEGIN(PARAM); return T_SELECT;
+	"enable"		BEGIN(PARAM); return T_SELECT;
+	"range"			BEGIN(PARAM); return T_RANGE;
+	{n}+	{
+		alloc_string(yytext, yyleng);
+		zconflval.string = text;
+		return T_WORD;
+	}
+	.
+	\n	current_file->lineno++; BEGIN(INITIAL);
+}
+
+<PARAM>{
+	"&&"	return T_AND;
+	"||"	return T_OR;
+	"("	return T_OPEN_PAREN;
+	")"	return T_CLOSE_PAREN;
+	"!"	return T_NOT;
+	"="	return T_EQUAL;
+	"!="	return T_UNEQUAL;
+	"if"	return T_IF;
+	"on"	return T_ON;
+	\"|\'	{
+		str = yytext[0];
+		new_string();
+		BEGIN(STRING);
+	}
+	\n	BEGIN(INITIAL); current_file->lineno++; return T_EOL;
+	---	/* ignore */
+	({n}|[-/.])+	{
+		alloc_string(yytext, yyleng);
+		zconflval.string = text;
+		return T_WORD;
+	}
+	#.*	/* comment */
+	\\\n	current_file->lineno++;
+	.
+	<<EOF>> {
+		BEGIN(INITIAL);
+	}
+}
+
+<STRING>{
+	[^'"\\\n]+/\n	{
+		append_string(yytext, yyleng);
+		zconflval.string = text;
+		return T_WORD_QUOTE;
+	}
+	[^'"\\\n]+	{
+		append_string(yytext, yyleng);
+	}
+	\\.?/\n	{
+		append_string(yytext + 1, yyleng - 1);
+		zconflval.string = text;
+		return T_WORD_QUOTE;
+	}
+	\\.?	{
+		append_string(yytext + 1, yyleng - 1);
+	}
+	\'|\"	{
+		if (str == yytext[0]) {
+			BEGIN(PARAM);
+			zconflval.string = text;
+			return T_WORD_QUOTE;
+		} else
+			append_string(yytext, 1);
+	}
+	\n	{
+		printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
+		current_file->lineno++;
+		BEGIN(INITIAL);
+		return T_EOL;
+	}
+	<<EOF>>	{
+		BEGIN(INITIAL);
+	}
+}
+
+<HELP>{
+	[ \t]+	{
+		ts = 0;
+		for (i = 0; i < yyleng; i++) {
+			if (yytext[i] == '\t')
+				ts = (ts & ~7) + 8;
+			else
+				ts++;
+		}
+		last_ts = ts;
+		if (first_ts) {
+			if (ts < first_ts) {
+				zconf_endhelp();
+				return T_HELPTEXT;
+			}
+			ts -= first_ts;
+			while (ts > 8) {
+				append_string("        ", 8);
+				ts -= 8;
+			}
+			append_string("        ", ts);
+		}
+	}
+	[ \t]*\n/[^ \t\n] {
+		current_file->lineno++;
+		zconf_endhelp();
+		return T_HELPTEXT;
+	}
+	[ \t]*\n	{
+		current_file->lineno++;
+		append_string("\n", 1);
+	}
+	[^ \t\n].* {
+		append_string(yytext, yyleng);
+		if (!first_ts)
+			first_ts = last_ts;
+	}
+	<<EOF>>	{
+		zconf_endhelp();
+		return T_HELPTEXT;
+	}
+}
+
+<<EOF>>	{
+	if (current_buf) {
+		zconf_endfile();
+		return T_EOF;
+	}
+	fclose(yyin);
+	yyterminate();
+}
+
+%%
+void zconf_starthelp(void)
+{
+	new_string();
+	last_ts = first_ts = 0;
+	BEGIN(HELP);
+}
+
+static void zconf_endhelp(void)
+{
+	zconflval.string = text;
+	BEGIN(INITIAL);
+}
+
+
+/*
+ * Try to open specified file with following names:
+ * ./name
+ * $(srctree)/name
+ * The latter is used when srctree is separate from objtree
+ * when compiling the kernel.
+ * Return NULL if file is not found.
+ */
+FILE *zconf_fopen(const char *name)
+{
+	char *env, fullname[PATH_MAX+1];
+	FILE *f;
+
+	f = fopen(name, "r");
+	if (!f && name[0] != '/') {
+		env = getenv(SRCTREE);
+		if (env) {
+			sprintf(fullname, "%s/%s", env, name);
+			f = fopen(fullname, "r");
+		}
+	}
+	return f;
+}
+
+void zconf_initscan(const char *name)
+{
+	yyin = zconf_fopen(name);
+	if (!yyin) {
+		printf("can't find file %s\n", name);
+		exit(1);
+	}
+
+	current_buf = malloc(sizeof(*current_buf));
+	memset(current_buf, 0, sizeof(*current_buf));
+
+	current_file = file_lookup(name);
+	current_file->lineno = 1;
+	current_file->flags = FILE_BUSY;
+}
+
+void zconf_nextfile(const char *name)
+{
+	struct file *file = file_lookup(name);
+	struct buffer *buf = malloc(sizeof(*buf));
+	memset(buf, 0, sizeof(*buf));
+
+	current_buf->state = YY_CURRENT_BUFFER;
+	yyin = zconf_fopen(name);
+	if (!yyin) {
+		printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
+		exit(1);
+	}
+	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+	buf->parent = current_buf;
+	current_buf = buf;
+
+	if (file->flags & FILE_BUSY) {
+		printf("recursive scan (%s)?\n", name);
+		exit(1);
+	}
+	if (file->flags & FILE_SCANNED) {
+		printf("file %s already scanned?\n", name);
+		exit(1);
+	}
+	file->flags |= FILE_BUSY;
+	file->lineno = 1;
+	file->parent = current_file;
+	current_file = file;
+}
+
+static struct buffer *zconf_endfile(void)
+{
+	struct buffer *parent;
+
+	current_file->flags |= FILE_SCANNED;
+	current_file->flags &= ~FILE_BUSY;
+	current_file = current_file->parent;
+
+	parent = current_buf->parent;
+	if (parent) {
+		fclose(yyin);
+		yy_delete_buffer(YY_CURRENT_BUFFER);
+		yy_switch_to_buffer(parent->state);
+	}
+	free(current_buf);
+	current_buf = parent;
+
+	return parent;
+}
+
+int zconf_lineno(void)
+{
+	if (current_buf)
+		return current_file->lineno - 1;
+	else
+		return 0;
+}
+
+char *zconf_curname(void)
+{
+	if (current_buf)
+		return current_file->name;
+	else
+		return "<none>";
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/zconf.tab.c_shipped
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/zconf.tab.c_shipped	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/zconf.tab.c_shipped	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2130 @@
+/* A Bison parser, made by GNU Bison 1.875a.  */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+/* Written by Richard Stallman by simplifying the original so called
+   ``semantic'' parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+/* If NAME_PREFIX is specified substitute the variables and functions
+   names.  */
+#define yyparse zconfparse
+#define yylex   zconflex
+#define yyerror zconferror
+#define yylval  zconflval
+#define yychar  zconfchar
+#define yydebug zconfdebug
+#define yynerrs zconfnerrs
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     T_MAINMENU = 258,
+     T_MENU = 259,
+     T_ENDMENU = 260,
+     T_SOURCE = 261,
+     T_CHOICE = 262,
+     T_ENDCHOICE = 263,
+     T_COMMENT = 264,
+     T_CONFIG = 265,
+     T_MENUCONFIG = 266,
+     T_HELP = 267,
+     T_HELPTEXT = 268,
+     T_IF = 269,
+     T_ENDIF = 270,
+     T_DEPENDS = 271,
+     T_REQUIRES = 272,
+     T_OPTIONAL = 273,
+     T_PROMPT = 274,
+     T_DEFAULT = 275,
+     T_TRISTATE = 276,
+     T_DEF_TRISTATE = 277,
+     T_BOOLEAN = 278,
+     T_DEF_BOOLEAN = 279,
+     T_STRING = 280,
+     T_INT = 281,
+     T_HEX = 282,
+     T_WORD = 283,
+     T_WORD_QUOTE = 284,
+     T_UNEQUAL = 285,
+     T_EOF = 286,
+     T_EOL = 287,
+     T_CLOSE_PAREN = 288,
+     T_OPEN_PAREN = 289,
+     T_ON = 290,
+     T_SELECT = 291,
+     T_RANGE = 292,
+     T_OR = 293,
+     T_AND = 294,
+     T_EQUAL = 295,
+     T_NOT = 296
+   };
+#endif
+#define T_MAINMENU 258
+#define T_MENU 259
+#define T_ENDMENU 260
+#define T_SOURCE 261
+#define T_CHOICE 262
+#define T_ENDCHOICE 263
+#define T_COMMENT 264
+#define T_CONFIG 265
+#define T_MENUCONFIG 266
+#define T_HELP 267
+#define T_HELPTEXT 268
+#define T_IF 269
+#define T_ENDIF 270
+#define T_DEPENDS 271
+#define T_REQUIRES 272
+#define T_OPTIONAL 273
+#define T_PROMPT 274
+#define T_DEFAULT 275
+#define T_TRISTATE 276
+#define T_DEF_TRISTATE 277
+#define T_BOOLEAN 278
+#define T_DEF_BOOLEAN 279
+#define T_STRING 280
+#define T_INT 281
+#define T_HEX 282
+#define T_WORD 283
+#define T_WORD_QUOTE 284
+#define T_UNEQUAL 285
+#define T_EOF 286
+#define T_EOL 287
+#define T_CLOSE_PAREN 288
+#define T_OPEN_PAREN 289
+#define T_ON 290
+#define T_SELECT 291
+#define T_RANGE 292
+#define T_OR 293
+#define T_AND 294
+#define T_EQUAL 295
+#define T_NOT 296
+
+
+
+
+/* Copy the first part of user declarations.  */
+
+
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
+
+#define PRINTD		0x0001
+#define DEBUG_PARSE	0x0002
+
+int cdebug = PRINTD;
+
+extern int zconflex(void);
+static void zconfprint(const char *err, ...);
+static void zconferror(const char *err);
+static bool zconf_endtoken(int token, int starttoken, int endtoken);
+
+struct symbol *symbol_hash[257];
+
+static struct menu *current_menu, *current_entry;
+
+#define YYERROR_VERBOSE
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+
+typedef union YYSTYPE {
+	int token;
+	char *string;
+	struct symbol *symbol;
+	struct expr *expr;
+	struct menu *menu;
+} YYSTYPE;
+/* Line 191 of yacc.c.  */
+
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations.  */
+
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+
+/* Line 214 of yacc.c.  */
+
+
+#if ! defined (yyoverflow) || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# if YYSTACK_USE_ALLOCA
+#  define YYSTACK_ALLOC alloca
+# else
+#  ifndef YYSTACK_USE_ALLOCA
+#   if defined (alloca) || (defined (_ALLOCA_H) && defined (__GNUC__))
+#    define YYSTACK_ALLOC alloca
+#   else
+#    ifdef __GNUC__
+#     define YYSTACK_ALLOC __builtin_alloca
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning. */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+#  if defined (__STDC__) || defined (__cplusplus)
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   define YYSIZE_T size_t
+#  endif
+#  define YYSTACK_ALLOC malloc
+#  define YYSTACK_FREE free
+# endif
+#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+
+
+#if (! defined (yyoverflow) \
+     && (! defined (__cplusplus) \
+	 || (YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  short yyss;
+  YYSTYPE yyvs;
+  };
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE))				\
+      + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  register YYSIZE_T yyi;		\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (0)
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)					\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack, Stack, yysize);				\
+	Stack = &yyptr->Stack;						\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (0)
+
+#endif
+
+#if defined (__STDC__) || defined (__cplusplus)
+   typedef signed char yysigned_char;
+#else
+   typedef short yysigned_char;
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL  2
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   201
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS  42
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS  41
+/* YYNRULES -- Number of rules. */
+#define YYNRULES  104
+/* YYNRULES -- Number of states. */
+#define YYNSTATES  182
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   296
+
+#define YYTRANSLATE(YYX)						\
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const unsigned char yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const unsigned short yyprhs[] =
+{
+       0,     0,     3,     4,     7,     9,    11,    13,    17,    19,
+      21,    23,    26,    28,    30,    32,    34,    36,    38,    42,
+      45,    49,    52,    53,    56,    59,    62,    65,    69,    74,
+      78,    83,    87,    91,    95,   100,   105,   110,   116,   119,
+     122,   124,   128,   131,   132,   135,   138,   141,   144,   149,
+     153,   157,   160,   165,   166,   169,   173,   175,   179,   182,
+     183,   186,   189,   192,   196,   199,   201,   205,   208,   209,
+     212,   215,   218,   222,   226,   228,   232,   235,   238,   241,
+     242,   245,   248,   253,   257,   261,   262,   265,   267,   269,
+     272,   275,   278,   280,   282,   283,   286,   288,   292,   296,
+     300,   303,   307,   311,   313
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yysigned_char yyrhs[] =
+{
+      43,     0,    -1,    -1,    43,    44,    -1,    45,    -1,    55,
+      -1,    66,    -1,     3,    77,    79,    -1,     5,    -1,    15,
+      -1,     8,    -1,     1,    79,    -1,    61,    -1,    71,    -1,
+      47,    -1,    49,    -1,    69,    -1,    79,    -1,    10,    28,
+      32,    -1,    46,    50,    -1,    11,    28,    32,    -1,    48,
+      50,    -1,    -1,    50,    51,    -1,    50,    75,    -1,    50,
+      73,    -1,    50,    32,    -1,    21,    76,    32,    -1,    22,
+      81,    80,    32,    -1,    23,    76,    32,    -1,    24,    81,
+      80,    32,    -1,    26,    76,    32,    -1,    27,    76,    32,
+      -1,    25,    76,    32,    -1,    19,    77,    80,    32,    -1,
+      20,    81,    80,    32,    -1,    36,    28,    80,    32,    -1,
+      37,    82,    82,    80,    32,    -1,     7,    32,    -1,    52,
+      56,    -1,    78,    -1,    53,    58,    54,    -1,    53,    58,
+      -1,    -1,    56,    57,    -1,    56,    75,    -1,    56,    73,
+      -1,    56,    32,    -1,    19,    77,    80,    32,    -1,    21,
+      76,    32,    -1,    23,    76,    32,    -1,    18,    32,    -1,
+      20,    28,    80,    32,    -1,    -1,    58,    45,    -1,    14,
+      81,    32,    -1,    78,    -1,    59,    62,    60,    -1,    59,
+      62,    -1,    -1,    62,    45,    -1,    62,    66,    -1,    62,
+      55,    -1,     4,    77,    32,    -1,    63,    74,    -1,    78,
+      -1,    64,    67,    65,    -1,    64,    67,    -1,    -1,    67,
+      45,    -1,    67,    66,    -1,    67,    55,    -1,    67,     1,
+      32,    -1,     6,    77,    32,    -1,    68,    -1,     9,    77,
+      32,    -1,    70,    74,    -1,    12,    32,    -1,    72,    13,
+      -1,    -1,    74,    75,    -1,    74,    32,    -1,    16,    35,
+      81,    32,    -1,    16,    81,    32,    -1,    17,    81,    32,
+      -1,    -1,    77,    80,    -1,    28,    -1,    29,    -1,     5,
+      79,    -1,     8,    79,    -1,    15,    79,    -1,    32,    -1,
+      31,    -1,    -1,    14,    81,    -1,    82,    -1,    82,    40,
+      82,    -1,    82,    30,    82,    -1,    34,    81,    33,    -1,
+      41,    81,    -1,    81,    38,    81,    -1,    81,    39,    81,
+      -1,    28,    -1,    29,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const unsigned short yyrline[] =
+{
+       0,    94,    94,    95,    98,    99,   100,   101,   102,   103,
+     104,   105,   109,   110,   111,   112,   113,   114,   120,   128,
+     134,   142,   152,   154,   155,   156,   157,   160,   166,   173,
+     179,   186,   192,   198,   204,   210,   216,   222,   230,   239,
+     245,   254,   255,   261,   263,   264,   265,   266,   269,   275,
+     281,   287,   293,   299,   301,   306,   315,   324,   325,   331,
+     333,   334,   335,   340,   347,   353,   362,   363,   369,   371,
+     372,   373,   374,   377,   383,   390,   397,   404,   410,   417,
+     418,   419,   422,   427,   432,   440,   442,   447,   448,   451,
+     452,   453,   457,   457,   459,   460,   463,   464,   465,   466,
+     467,   468,   469,   472,   473
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE
+/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU",
+  "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG",
+  "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS",
+  "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_DEFAULT", "T_TRISTATE",
+  "T_DEF_TRISTATE", "T_BOOLEAN", "T_DEF_BOOLEAN", "T_STRING", "T_INT",
+  "T_HEX", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", "T_EOF", "T_EOL",
+  "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_ON", "T_SELECT", "T_RANGE", "T_OR",
+  "T_AND", "T_EQUAL", "T_NOT", "$accept", "input", "block",
+  "common_block", "config_entry_start", "config_stmt",
+  "menuconfig_entry_start", "menuconfig_stmt", "config_option_list",
+  "config_option", "choice", "choice_entry", "choice_end", "choice_stmt",
+  "choice_option_list", "choice_option", "choice_block", "if", "if_end",
+  "if_stmt", "if_block", "menu", "menu_entry", "menu_end", "menu_stmt",
+  "menu_block", "source", "source_stmt", "comment", "comment_stmt",
+  "help_start", "help", "depends_list", "depends", "prompt_stmt_opt",
+  "prompt", "end", "nl_or_eof", "if_expr", "expr", "symbol", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const unsigned short yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295,   296
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const unsigned char yyr1[] =
+{
+       0,    42,    43,    43,    44,    44,    44,    44,    44,    44,
+      44,    44,    45,    45,    45,    45,    45,    45,    46,    47,
+      48,    49,    50,    50,    50,    50,    50,    51,    51,    51,
+      51,    51,    51,    51,    51,    51,    51,    51,    52,    53,
+      54,    55,    55,    56,    56,    56,    56,    56,    57,    57,
+      57,    57,    57,    58,    58,    59,    60,    61,    61,    62,
+      62,    62,    62,    63,    64,    65,    66,    66,    67,    67,
+      67,    67,    67,    68,    69,    70,    71,    72,    73,    74,
+      74,    74,    75,    75,    75,    76,    76,    77,    77,    78,
+      78,    78,    79,    79,    80,    80,    81,    81,    81,    81,
+      81,    81,    81,    82,    82
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const unsigned char yyr2[] =
+{
+       0,     2,     0,     2,     1,     1,     1,     3,     1,     1,
+       1,     2,     1,     1,     1,     1,     1,     1,     3,     2,
+       3,     2,     0,     2,     2,     2,     2,     3,     4,     3,
+       4,     3,     3,     3,     4,     4,     4,     5,     2,     2,
+       1,     3,     2,     0,     2,     2,     2,     2,     4,     3,
+       3,     2,     4,     0,     2,     3,     1,     3,     2,     0,
+       2,     2,     2,     3,     2,     1,     3,     2,     0,     2,
+       2,     2,     3,     3,     1,     3,     2,     2,     2,     0,
+       2,     2,     4,     3,     3,     0,     2,     1,     1,     2,
+       2,     2,     1,     1,     0,     2,     1,     3,     3,     3,
+       2,     3,     3,     1,     1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const unsigned char yydefact[] =
+{
+       2,     0,     1,     0,     0,     0,     8,     0,     0,    10,
+       0,     0,     0,     0,     9,    93,    92,     3,     4,    22,
+      14,    22,    15,    43,    53,     5,    59,    12,    79,    68,
+       6,    74,    16,    79,    13,    17,    11,    87,    88,     0,
+       0,     0,    38,     0,     0,     0,   103,   104,     0,     0,
+       0,    96,    19,    21,    39,    42,    58,    64,     0,    76,
+       7,    63,    73,    75,    18,    20,     0,   100,    55,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    85,     0,
+      85,     0,    85,    85,    85,    26,     0,     0,    23,     0,
+      25,    24,     0,     0,     0,    85,    85,    47,    44,    46,
+      45,     0,     0,     0,    54,    41,    40,    60,    62,    57,
+      61,    56,    81,    80,     0,    69,    71,    66,    70,    65,
+      99,   101,   102,    98,    97,    77,     0,     0,     0,    94,
+      94,     0,    94,    94,     0,    94,     0,     0,     0,    94,
+       0,    78,    51,    94,    94,     0,     0,    89,    90,    91,
+      72,     0,    83,    84,     0,     0,     0,    27,    86,     0,
+      29,     0,    33,    31,    32,     0,    94,     0,     0,    49,
+      50,    82,    95,    34,    35,    28,    30,    36,     0,    48,
+      52,    37
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const short yydefgoto[] =
+{
+      -1,     1,    17,    18,    19,    20,    21,    22,    52,    88,
+      23,    24,   105,    25,    54,    98,    55,    26,   109,    27,
+      56,    28,    29,   117,    30,    58,    31,    32,    33,    34,
+      89,    90,    57,    91,   131,   132,   106,    35,   155,    50,
+      51
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -99
+static const short yypact[] =
+{
+     -99,    48,   -99,    38,    46,    46,   -99,    46,   -29,   -99,
+      46,   -17,    -3,   -11,   -99,   -99,   -99,   -99,   -99,   -99,
+     -99,   -99,   -99,   -99,   -99,   -99,   -99,   -99,   -99,   -99,
+     -99,   -99,   -99,   -99,   -99,   -99,   -99,   -99,   -99,    38,
+      12,    15,   -99,    18,    51,    62,   -99,   -99,   -11,   -11,
+       4,   -24,   138,   138,   160,   121,   110,    -4,    81,    -4,
+     -99,   -99,   -99,   -99,   -99,   -99,   -19,   -99,   -99,   -11,
+     -11,    70,    70,    73,    32,   -11,    46,   -11,    46,   -11,
+      46,   -11,    46,    46,    46,   -99,    36,    70,   -99,    95,
+     -99,   -99,    96,    46,   106,    46,    46,   -99,   -99,   -99,
+     -99,    38,    38,    38,   -99,   -99,   -99,   -99,   -99,   -99,
+     -99,   -99,   -99,   -99,   112,   -99,   -99,   -99,   -99,   -99,
+     -99,   117,   -99,   -99,   -99,   -99,   -11,    33,    65,   131,
+       1,   119,   131,     1,   136,     1,   153,   154,   155,   131,
+      70,   -99,   -99,   131,   131,   156,   157,   -99,   -99,   -99,
+     -99,   101,   -99,   -99,   -11,   158,   159,   -99,   -99,   161,
+     -99,   162,   -99,   -99,   -99,   163,   131,   164,   165,   -99,
+     -99,   -99,    99,   -99,   -99,   -99,   -99,   -99,   166,   -99,
+     -99,   -99
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const short yypgoto[] =
+{
+     -99,   -99,   -99,   111,   -99,   -99,   -99,   -99,   178,   -99,
+     -99,   -99,   -99,    91,   -99,   -99,   -99,   -99,   -99,   -99,
+     -99,   -99,   -99,   -99,   115,   -99,   -99,   -99,   -99,   -99,
+     -99,   146,   168,    89,    27,     0,   126,    -1,   -98,   -48,
+     -63
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -68
+static const short yytable[] =
+{
+      66,    67,    36,    42,    39,    40,    71,    41,   123,   124,
+      43,    44,    74,    75,   120,   154,    72,    46,    47,    69,
+      70,   121,   122,    48,   140,    45,   127,   128,   112,   130,
+      49,   133,   156,   135,   158,   159,    68,   161,    60,    69,
+      70,   165,    69,    70,    61,   167,   168,    62,     2,     3,
+      63,     4,     5,     6,     7,     8,     9,    10,    11,    12,
+      46,    47,    13,    14,   139,   152,    48,   126,   178,    15,
+      16,    69,    70,    49,    37,    38,   129,   166,   151,    15,
+      16,   -67,   114,    64,   -67,     5,   101,     7,     8,   102,
+      10,    11,    12,   143,    65,    13,   103,   153,    46,    47,
+     147,   148,   149,    69,    70,   125,   172,   134,   141,   136,
+     137,   138,    15,    16,     5,   101,     7,     8,   102,    10,
+      11,    12,   145,   146,    13,   103,   101,     7,   142,   102,
+      10,    11,    12,   171,   144,    13,   103,    69,    70,    69,
+      70,    15,    16,   100,   150,   154,   113,   108,   113,   116,
+      73,   157,    15,    16,    74,    75,    70,    76,    77,    78,
+      79,    80,    81,    82,    83,    84,   104,   107,   160,   115,
+      85,   110,    73,   118,    86,    87,    74,    75,    92,    93,
+      94,    95,   111,    96,   119,   162,   163,   164,   169,   170,
+     173,   174,    97,   175,   176,   177,   179,   180,   181,    53,
+      99,    59
+};
+
+static const unsigned char yycheck[] =
+{
+      48,    49,     3,    32,     4,     5,    30,     7,    71,    72,
+      10,    28,    16,    17,    33,    14,    40,    28,    29,    38,
+      39,    69,    70,    34,    87,    28,    74,    75,    32,    77,
+      41,    79,   130,    81,   132,   133,    32,   135,    39,    38,
+      39,   139,    38,    39,    32,   143,   144,    32,     0,     1,
+      32,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+      28,    29,    14,    15,    28,    32,    34,    35,   166,    31,
+      32,    38,    39,    41,    28,    29,    76,   140,   126,    31,
+      32,     0,     1,    32,     3,     4,     5,     6,     7,     8,
+       9,    10,    11,    93,    32,    14,    15,    32,    28,    29,
+     101,   102,   103,    38,    39,    32,   154,    80,    13,    82,
+      83,    84,    31,    32,     4,     5,     6,     7,     8,     9,
+      10,    11,    95,    96,    14,    15,     5,     6,    32,     8,
+       9,    10,    11,    32,    28,    14,    15,    38,    39,    38,
+      39,    31,    32,    54,    32,    14,    57,    56,    59,    58,
+      12,    32,    31,    32,    16,    17,    39,    19,    20,    21,
+      22,    23,    24,    25,    26,    27,    55,    56,    32,    58,
+      32,    56,    12,    58,    36,    37,    16,    17,    18,    19,
+      20,    21,    56,    23,    58,    32,    32,    32,    32,    32,
+      32,    32,    32,    32,    32,    32,    32,    32,    32,    21,
+      54,    33
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const unsigned char yystos[] =
+{
+       0,    43,     0,     1,     3,     4,     5,     6,     7,     8,
+       9,    10,    11,    14,    15,    31,    32,    44,    45,    46,
+      47,    48,    49,    52,    53,    55,    59,    61,    63,    64,
+      66,    68,    69,    70,    71,    79,    79,    28,    29,    77,
+      77,    77,    32,    77,    28,    28,    28,    29,    34,    41,
+      81,    82,    50,    50,    56,    58,    62,    74,    67,    74,
+      79,    32,    32,    32,    32,    32,    81,    81,    32,    38,
+      39,    30,    40,    12,    16,    17,    19,    20,    21,    22,
+      23,    24,    25,    26,    27,    32,    36,    37,    51,    72,
+      73,    75,    18,    19,    20,    21,    23,    32,    57,    73,
+      75,     5,     8,    15,    45,    54,    78,    45,    55,    60,
+      66,    78,    32,    75,     1,    45,    55,    65,    66,    78,
+      33,    81,    81,    82,    82,    32,    35,    81,    81,    77,
+      81,    76,    77,    81,    76,    81,    76,    76,    76,    28,
+      82,    13,    32,    77,    28,    76,    76,    79,    79,    79,
+      32,    81,    32,    32,    14,    80,    80,    32,    80,    80,
+      32,    80,    32,    32,    32,    80,    82,    80,    80,    32,
+      32,    32,    81,    32,    32,    32,    32,    32,    80,    32,
+      32,    32
+};
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		(-2)
+#define YYEOF		0
+
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT		goto yyabortlab
+#define YYERROR		goto yyerrlab1
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL		goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)					\
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    {								\
+      yychar = (Token);						\
+      yylval = (Value);						\
+      yytoken = YYTRANSLATE (yychar);				\
+      YYPOPSTACK;						\
+      goto yybackup;						\
+    }								\
+  else								\
+    {								\
+      yyerror ("syntax error: cannot back up");\
+      YYERROR;							\
+    }								\
+while (0)
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+   are run).  */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)         \
+  Current.first_line   = Rhs[1].first_line;      \
+  Current.first_column = Rhs[1].first_column;    \
+  Current.last_line    = Rhs[N].last_line;       \
+  Current.last_column  = Rhs[N].last_column;
+#endif
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)			\
+do {						\
+  if (yydebug)					\
+    YYFPRINTF Args;				\
+} while (0)
+
+# define YYDSYMPRINT(Args)			\
+do {						\
+  if (yydebug)					\
+    yysymprint Args;				\
+} while (0)
+
+# define YYDSYMPRINTF(Title, Token, Value, Location)		\
+do {								\
+  if (yydebug)							\
+    {								\
+      YYFPRINTF (stderr, "%s ", Title);				\
+      yysymprint (stderr,					\
+                  Token, Value);	\
+      YYFPRINTF (stderr, "\n");					\
+    }								\
+} while (0)
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (cinluded).                                                   |
+`------------------------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_stack_print (short *bottom, short *top)
+#else
+static void
+yy_stack_print (bottom, top)
+    short *bottom;
+    short *top;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (/* Nothing. */; bottom <= top; ++bottom)
+    YYFPRINTF (stderr, " %d", *bottom);
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)				\
+do {								\
+  if (yydebug)							\
+    yy_stack_print ((Bottom), (Top));				\
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_reduce_print (int yyrule)
+#else
+static void
+yy_reduce_print (yyrule)
+    int yyrule;
+#endif
+{
+  int yyi;
+  unsigned int yylineno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+             yyrule - 1, yylineno);
+  /* Print the symbols being reduced, and their result.  */
+  for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
+    YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
+  YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+}
+
+# define YY_REDUCE_PRINT(Rule)		\
+do {					\
+  if (yydebug)				\
+    yy_reduce_print (Rule);		\
+} while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YYDSYMPRINT(Args)
+# define YYDSYMPRINTF(Title, Token, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef	YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#if YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined (__GLIBC__) && defined (_STRING_H)
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+#   if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+#   else
+yystrlen (yystr)
+     const char *yystr;
+#   endif
+{
+  register const char *yys = yystr;
+
+  while (*yys++ != '\0')
+    continue;
+
+  return yys - yystr - 1;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+#   if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+#   else
+yystpcpy (yydest, yysrc)
+     char *yydest;
+     const char *yysrc;
+#   endif
+{
+  register char *yyd = yydest;
+  register const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+#endif /* !YYERROR_VERBOSE */
+
+
+
+#if YYDEBUG
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yysymprint (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE *yyvaluep;
+#endif
+{
+  /* Pacify ``unused variable'' warnings.  */
+  (void) yyvaluep;
+
+  if (yytype < YYNTOKENS)
+    {
+      YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+# ifdef YYPRINT
+      YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+    }
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  switch (yytype)
+    {
+      default:
+        break;
+    }
+  YYFPRINTF (yyoutput, ")");
+}
+
+#endif /* ! YYDEBUG */
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yydestruct (int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yytype, yyvaluep)
+    int yytype;
+    YYSTYPE *yyvaluep;
+#endif
+{
+  /* Pacify ``unused variable'' warnings.  */
+  (void) yyvaluep;
+
+  switch (yytype)
+    {
+
+      default:
+        break;
+    }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM);
+# else
+int yyparse ();
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The lookahead symbol.  */
+int yychar;
+
+/* The semantic value of the lookahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM)
+# else
+int yyparse (YYPARSE_PARAM)
+  void *YYPARSE_PARAM;
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+  register int yystate;
+  register int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  short	yyssa[YYINITDEPTH];
+  short *yyss = yyssa;
+  register short *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  register YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK   (yyvsp--, yyssp--)
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+
+  /* When reducing, the number of symbols on the RHS of the reduced
+     rule.  */
+  int yylen;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;		/* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed. so pushing a state here evens the stacks.
+     */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+	/* Give user a chance to reallocate the stack. Use copies of
+	   these so that the &'s don't force the real ones into
+	   memory.  */
+	YYSTYPE *yyvs1 = yyvs;
+	short *yyss1 = yyss;
+
+
+	/* Each stack pointer address is followed by the size of the
+	   data in use in that stack, in bytes.  This used to be a
+	   conditional around just the two extra args, but that might
+	   be undefined if yyoverflow is a macro.  */
+	yyoverflow ("parser stack overflow",
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+
+		    &yystacksize);
+
+	yyss = yyss1;
+	yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyoverflowlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+	goto yyoverflowlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+	yystacksize = YYMAXDEPTH;
+
+      {
+	short *yyss1 = yyss;
+	union yyalloc *yyptr =
+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+	if (! yyptr)
+	  goto yyoverflowlab;
+	YYSTACK_RELOCATE (yyss);
+	YYSTACK_RELOCATE (yyvs);
+
+#  undef YYSTACK_RELOCATE
+	if (yyss1 != yyssa)
+	  YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+		  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+	YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+  YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 8:
+
+    { zconfprint("unexpected 'endmenu' statement"); ;}
+    break;
+
+  case 9:
+
+    { zconfprint("unexpected 'endif' statement"); ;}
+    break;
+
+  case 10:
+
+    { zconfprint("unexpected 'endchoice' statement"); ;}
+    break;
+
+  case 11:
+
+    { zconfprint("syntax error"); yyerrok; ;}
+    break;
+
+  case 18:
+
+    {
+	struct symbol *sym = sym_lookup(yyvsp[-1].string, 0);
+	sym->flags |= SYMBOL_OPTIONAL;
+	menu_add_entry(sym);
+	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string);
+;}
+    break;
+
+  case 19:
+
+    {
+	menu_end_entry();
+	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 20:
+
+    {
+	struct symbol *sym = sym_lookup(yyvsp[-1].string, 0);
+	sym->flags |= SYMBOL_OPTIONAL;
+	menu_add_entry(sym);
+	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string);
+;}
+    break;
+
+  case 21:
+
+    {
+	if (current_entry->prompt)
+		current_entry->prompt->type = P_MENU;
+	else
+		zconfprint("warning: menuconfig statement without prompt");
+	menu_end_entry();
+	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 27:
+
+    {
+	menu_set_type(S_TRISTATE);
+	printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 28:
+
+    {
+	menu_add_expr(P_DEFAULT, yyvsp[-2].expr, yyvsp[-1].expr);
+	menu_set_type(S_TRISTATE);
+	printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 29:
+
+    {
+	menu_set_type(S_BOOLEAN);
+	printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 30:
+
+    {
+	menu_add_expr(P_DEFAULT, yyvsp[-2].expr, yyvsp[-1].expr);
+	menu_set_type(S_BOOLEAN);
+	printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 31:
+
+    {
+	menu_set_type(S_INT);
+	printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 32:
+
+    {
+	menu_set_type(S_HEX);
+	printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 33:
+
+    {
+	menu_set_type(S_STRING);
+	printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 34:
+
+    {
+	menu_add_prompt(P_PROMPT, yyvsp[-2].string, yyvsp[-1].expr);
+	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 35:
+
+    {
+	menu_add_expr(P_DEFAULT, yyvsp[-2].expr, yyvsp[-1].expr);
+	printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 36:
+
+    {
+	menu_add_symbol(P_SELECT, sym_lookup(yyvsp[-2].string, 0), yyvsp[-1].expr);
+	printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 37:
+
+    {
+	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,yyvsp[-3].symbol, yyvsp[-2].symbol), yyvsp[-1].expr);
+	printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 38:
+
+    {
+	struct symbol *sym = sym_lookup(NULL, 0);
+	sym->flags |= SYMBOL_CHOICE;
+	menu_add_entry(sym);
+	menu_add_expr(P_CHOICE, NULL, NULL);
+	printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 39:
+
+    {
+	menu_end_entry();
+	menu_add_menu();
+;}
+    break;
+
+  case 40:
+
+    {
+	if (zconf_endtoken(yyvsp[0].token, T_CHOICE, T_ENDCHOICE)) {
+		menu_end_menu();
+		printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
+	}
+;}
+    break;
+
+  case 42:
+
+    {
+	printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno);
+	zconfnerrs++;
+;}
+    break;
+
+  case 48:
+
+    {
+	menu_add_prompt(P_PROMPT, yyvsp[-2].string, yyvsp[-1].expr);
+	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 49:
+
+    {
+	menu_set_type(S_TRISTATE);
+	printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 50:
+
+    {
+	menu_set_type(S_BOOLEAN);
+	printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 51:
+
+    {
+	current_entry->sym->flags |= SYMBOL_OPTIONAL;
+	printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 52:
+
+    {
+	menu_add_symbol(P_DEFAULT, sym_lookup(yyvsp[-2].string, 0), yyvsp[-1].expr);
+	printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 55:
+
+    {
+	printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
+	menu_add_entry(NULL);
+	menu_add_dep(yyvsp[-1].expr);
+	menu_end_entry();
+	menu_add_menu();
+;}
+    break;
+
+  case 56:
+
+    {
+	if (zconf_endtoken(yyvsp[0].token, T_IF, T_ENDIF)) {
+		menu_end_menu();
+		printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
+	}
+;}
+    break;
+
+  case 58:
+
+    {
+	printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno);
+	zconfnerrs++;
+;}
+    break;
+
+  case 63:
+
+    {
+	menu_add_entry(NULL);
+	menu_add_prop(P_MENU, yyvsp[-1].string, NULL, NULL);
+	printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 64:
+
+    {
+	menu_end_entry();
+	menu_add_menu();
+;}
+    break;
+
+  case 65:
+
+    {
+	if (zconf_endtoken(yyvsp[0].token, T_MENU, T_ENDMENU)) {
+		menu_end_menu();
+		printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
+	}
+;}
+    break;
+
+  case 67:
+
+    {
+	printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno);
+	zconfnerrs++;
+;}
+    break;
+
+  case 72:
+
+    { zconfprint("invalid menu option"); yyerrok; ;}
+    break;
+
+  case 73:
+
+    {
+	yyval.string = yyvsp[-1].string;
+	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string);
+;}
+    break;
+
+  case 74:
+
+    {
+	zconf_nextfile(yyvsp[0].string);
+;}
+    break;
+
+  case 75:
+
+    {
+	menu_add_entry(NULL);
+	menu_add_prop(P_COMMENT, yyvsp[-1].string, NULL, NULL);
+	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 76:
+
+    {
+	menu_end_entry();
+;}
+    break;
+
+  case 77:
+
+    {
+	printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
+	zconf_starthelp();
+;}
+    break;
+
+  case 78:
+
+    {
+	current_entry->sym->help = yyvsp[0].string;
+;}
+    break;
+
+  case 82:
+
+    {
+	menu_add_dep(yyvsp[-1].expr);
+	printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 83:
+
+    {
+	menu_add_dep(yyvsp[-1].expr);
+	printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 84:
+
+    {
+	menu_add_dep(yyvsp[-1].expr);
+	printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
+;}
+    break;
+
+  case 86:
+
+    {
+	menu_add_prop(P_PROMPT, yyvsp[-1].string, NULL, yyvsp[0].expr);
+;}
+    break;
+
+  case 89:
+
+    { yyval.token = T_ENDMENU; ;}
+    break;
+
+  case 90:
+
+    { yyval.token = T_ENDCHOICE; ;}
+    break;
+
+  case 91:
+
+    { yyval.token = T_ENDIF; ;}
+    break;
+
+  case 94:
+
+    { yyval.expr = NULL; ;}
+    break;
+
+  case 95:
+
+    { yyval.expr = yyvsp[0].expr; ;}
+    break;
+
+  case 96:
+
+    { yyval.expr = expr_alloc_symbol(yyvsp[0].symbol); ;}
+    break;
+
+  case 97:
+
+    { yyval.expr = expr_alloc_comp(E_EQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); ;}
+    break;
+
+  case 98:
+
+    { yyval.expr = expr_alloc_comp(E_UNEQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); ;}
+    break;
+
+  case 99:
+
+    { yyval.expr = yyvsp[-1].expr; ;}
+    break;
+
+  case 100:
+
+    { yyval.expr = expr_alloc_one(E_NOT, yyvsp[0].expr); ;}
+    break;
+
+  case 101:
+
+    { yyval.expr = expr_alloc_two(E_OR, yyvsp[-2].expr, yyvsp[0].expr); ;}
+    break;
+
+  case 102:
+
+    { yyval.expr = expr_alloc_two(E_AND, yyvsp[-2].expr, yyvsp[0].expr); ;}
+    break;
+
+  case 103:
+
+    { yyval.symbol = sym_lookup(yyvsp[0].string, 0); free(yyvsp[0].string); ;}
+    break;
+
+  case 104:
+
+    { yyval.symbol = sym_lookup(yyvsp[0].string, 1); free(yyvsp[0].string); ;}
+    break;
+
+
+    }
+
+/* Line 999 of yacc.c.  */
+
+
+  yyvsp -= yylen;
+  yyssp -= yylen;
+
+
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (YYPACT_NINF < yyn && yyn < YYLAST)
+	{
+	  YYSIZE_T yysize = 0;
+	  int yytype = YYTRANSLATE (yychar);
+	  char *yymsg;
+	  int yyx, yycount;
+
+	  yycount = 0;
+	  /* Start YYX at -YYN if negative to avoid negative indexes in
+	     YYCHECK.  */
+	  for (yyx = yyn < 0 ? -yyn : 0;
+	       yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
+	    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+	      yysize += yystrlen (yytname[yyx]) + 15, yycount++;
+	  yysize += yystrlen ("syntax error, unexpected ") + 1;
+	  yysize += yystrlen (yytname[yytype]);
+	  yymsg = (char *) YYSTACK_ALLOC (yysize);
+	  if (yymsg != 0)
+	    {
+	      char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
+	      yyp = yystpcpy (yyp, yytname[yytype]);
+
+	      if (yycount < 5)
+		{
+		  yycount = 0;
+		  for (yyx = yyn < 0 ? -yyn : 0;
+		       yyx < (int) (sizeof (yytname) / sizeof (char *));
+		       yyx++)
+		    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+		      {
+			const char *yyq = ! yycount ? ", expecting " : " or ";
+			yyp = yystpcpy (yyp, yyq);
+			yyp = yystpcpy (yyp, yytname[yyx]);
+			yycount++;
+		      }
+		}
+	      yyerror (yymsg);
+	      YYSTACK_FREE (yymsg);
+	    }
+	  else
+	    yyerror ("syntax error; also virtual memory exhausted");
+	}
+      else
+#endif /* YYERROR_VERBOSE */
+	yyerror ("syntax error");
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+	 error, discard it.  */
+
+      /* Return failure if at end of input.  */
+      if (yychar == YYEOF)
+        {
+	  /* Pop the error token.  */
+          YYPOPSTACK;
+	  /* Pop the rest of the stack.  */
+	  while (yyss < yyssp)
+	    {
+	      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+	      yydestruct (yystos[*yyssp], yyvsp);
+	      YYPOPSTACK;
+	    }
+	  YYABORT;
+        }
+
+      YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
+      yydestruct (yytoken, &yylval);
+      yychar = YYEMPTY;
+
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*----------------------------------------------------.
+| yyerrlab1 -- error raised explicitly by an action.  |
+`----------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+	{
+	  yyn += YYTERROR;
+	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+	    {
+	      yyn = yytable[yyn];
+	      if (0 < yyn)
+		break;
+	    }
+	}
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+	YYABORT;
+
+      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+      yydestruct (yystos[yystate], yyvsp);
+      yyvsp--;
+      yystate = *--yyssp;
+
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  YYDPRINTF ((stderr, "Shifting error token, "));
+
+  *++yyvsp = yylval;
+
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#ifndef yyoverflow
+/*----------------------------------------------.
+| yyoverflowlab -- parser overflow comes here.  |
+`----------------------------------------------*/
+yyoverflowlab:
+  yyerror ("parser stack overflow");
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+  return yyresult;
+}
+
+
+
+
+
+void conf_parse(const char *name)
+{
+	struct symbol *sym;
+	int i;
+
+	zconf_initscan(name);
+
+	sym_init();
+	menu_init();
+	modules_sym = sym_lookup("MODULES", 0);
+	rootmenu.prompt = menu_add_prop(P_MENU, "BusyBox Configuration", NULL, NULL);
+
+	//zconfdebug = 1;
+	zconfparse();
+	if (zconfnerrs)
+		exit(1);
+	menu_finalize(&rootmenu);
+	for_all_symbols(i, sym) {
+                if (!(sym->flags & SYMBOL_CHECKED) && sym_check_deps(sym))
+                        printf("\n");
+		else
+			sym->flags |= SYMBOL_CHECK_DONE;
+        }
+
+	sym_change_count = 1;
+}
+
+const char *zconf_tokenname(int token)
+{
+	switch (token) {
+	case T_MENU:		return "menu";
+	case T_ENDMENU:		return "endmenu";
+	case T_CHOICE:		return "choice";
+	case T_ENDCHOICE:	return "endchoice";
+	case T_IF:		return "if";
+	case T_ENDIF:		return "endif";
+	}
+	return "<token>";
+}
+
+static bool zconf_endtoken(int token, int starttoken, int endtoken)
+{
+	if (token != endtoken) {
+		zconfprint("unexpected '%s' within %s block", zconf_tokenname(token), zconf_tokenname(starttoken));
+		zconfnerrs++;
+		return false;
+	}
+	if (current_menu->file != current_file) {
+		zconfprint("'%s' in different file than '%s'", zconf_tokenname(token), zconf_tokenname(starttoken));
+		zconfprint("location of the '%s'", zconf_tokenname(starttoken));
+		zconfnerrs++;
+		return false;
+	}
+	return true;
+}
+
+static void zconfprint(const char *err, ...)
+{
+	va_list ap;
+
+	fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno() + 1);
+	va_start(ap, err);
+	vfprintf(stderr, err, ap);
+	va_end(ap);
+	fprintf(stderr, "\n");
+}
+
+static void zconferror(const char *err)
+{
+	fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
+}
+
+void print_quoted_string(FILE *out, const char *str)
+{
+	const char *p;
+	int len;
+
+	putc('"', out);
+	while ((p = strchr(str, '"'))) {
+		len = p - str;
+		if (len)
+			fprintf(out, "%.*s", len, str);
+		fputs("\\\"", out);
+		str = p + 1;
+	}
+	fputs(str, out);
+	putc('"', out);
+}
+
+void print_symbol(FILE *out, struct menu *menu)
+{
+	struct symbol *sym = menu->sym;
+	struct property *prop;
+
+	if (sym_is_choice(sym))
+		fprintf(out, "choice\n");
+	else
+		fprintf(out, "config %s\n", sym->name);
+	switch (sym->type) {
+	case S_BOOLEAN:
+		fputs("  boolean\n", out);
+		break;
+	case S_TRISTATE:
+		fputs("  tristate\n", out);
+		break;
+	case S_STRING:
+		fputs("  string\n", out);
+		break;
+	case S_INT:
+		fputs("  integer\n", out);
+		break;
+	case S_HEX:
+		fputs("  hex\n", out);
+		break;
+	default:
+		fputs("  ???\n", out);
+		break;
+	}
+	for (prop = sym->prop; prop; prop = prop->next) {
+		if (prop->menu != menu)
+			continue;
+		switch (prop->type) {
+		case P_PROMPT:
+			fputs("  prompt ", out);
+			print_quoted_string(out, prop->text);
+			if (!expr_is_yes(prop->visible.expr)) {
+				fputs(" if ", out);
+				expr_fprint(prop->visible.expr, out);
+			}
+			fputc('\n', out);
+			break;
+		case P_DEFAULT:
+			fputs( "  default ", out);
+			expr_fprint(prop->expr, out);
+			if (!expr_is_yes(prop->visible.expr)) {
+				fputs(" if ", out);
+				expr_fprint(prop->visible.expr, out);
+			}
+			fputc('\n', out);
+			break;
+		case P_CHOICE:
+			fputs("  #choice value\n", out);
+			break;
+		default:
+			fprintf(out, "  unknown prop %d!\n", prop->type);
+			break;
+		}
+	}
+	if (sym->help) {
+		int len = strlen(sym->help);
+		while (sym->help[--len] == '\n')
+			sym->help[len] = 0;
+		fprintf(out, "  help\n%s\n", sym->help);
+	}
+	fputc('\n', out);
+}
+
+void zconfdump(FILE *out)
+{
+	struct property *prop;
+	struct symbol *sym;
+	struct menu *menu;
+
+	menu = rootmenu.list;
+	while (menu) {
+		if ((sym = menu->sym))
+			print_symbol(out, menu);
+		else if ((prop = menu->prompt)) {
+			switch (prop->type) {
+			case P_COMMENT:
+				fputs("\ncomment ", out);
+				print_quoted_string(out, prop->text);
+				fputs("\n", out);
+				break;
+			case P_MENU:
+				fputs("\nmenu ", out);
+				print_quoted_string(out, prop->text);
+				fputs("\n", out);
+				break;
+			default:
+				;
+			}
+			if (!expr_is_yes(prop->visible.expr)) {
+				fputs("  depends ", out);
+				expr_fprint(prop->visible.expr, out);
+				fputc('\n', out);
+			}
+			fputs("\n", out);
+		}
+
+		if (menu->list)
+			menu = menu->list;
+		else if (menu->next)
+			menu = menu->next;
+		else while ((menu = menu->parent)) {
+			if (menu->prompt && menu->prompt->type == P_MENU)
+				fputs("\nendmenu\n", out);
+			if (menu->next) {
+				menu = menu->next;
+				break;
+			}
+		}
+	}
+}
+
+#include "lex.zconf.c"
+#include "util.c"
+#include "confdata.c"
+#include "expr.c"
+#include "symbol.c"
+#include "menu.c"
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/zconf.tab.h_shipped
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/zconf.tab.h_shipped	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/zconf.tab.h_shipped	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,125 @@
+/* A Bison parser, made from zconf.y, by GNU bison 1.75.  */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+#ifndef BISON_ZCONF_TAB_H
+# define BISON_ZCONF_TAB_H
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     T_MAINMENU = 258,
+     T_MENU = 259,
+     T_ENDMENU = 260,
+     T_SOURCE = 261,
+     T_CHOICE = 262,
+     T_ENDCHOICE = 263,
+     T_COMMENT = 264,
+     T_CONFIG = 265,
+     T_HELP = 266,
+     T_HELPTEXT = 267,
+     T_IF = 268,
+     T_ENDIF = 269,
+     T_DEPENDS = 270,
+     T_REQUIRES = 271,
+     T_OPTIONAL = 272,
+     T_PROMPT = 273,
+     T_DEFAULT = 274,
+     T_TRISTATE = 275,
+     T_BOOLEAN = 276,
+     T_INT = 277,
+     T_HEX = 278,
+     T_WORD = 279,
+     T_STRING = 280,
+     T_UNEQUAL = 281,
+     T_EOF = 282,
+     T_EOL = 283,
+     T_CLOSE_PAREN = 284,
+     T_OPEN_PAREN = 285,
+     T_ON = 286,
+     T_OR = 287,
+     T_AND = 288,
+     T_EQUAL = 289,
+     T_NOT = 290
+   };
+#endif
+#define T_MAINMENU 258
+#define T_MENU 259
+#define T_ENDMENU 260
+#define T_SOURCE 261
+#define T_CHOICE 262
+#define T_ENDCHOICE 263
+#define T_COMMENT 264
+#define T_CONFIG 265
+#define T_HELP 266
+#define T_HELPTEXT 267
+#define T_IF 268
+#define T_ENDIF 269
+#define T_DEPENDS 270
+#define T_REQUIRES 271
+#define T_OPTIONAL 272
+#define T_PROMPT 273
+#define T_DEFAULT 274
+#define T_TRISTATE 275
+#define T_BOOLEAN 276
+#define T_INT 277
+#define T_HEX 278
+#define T_WORD 279
+#define T_STRING 280
+#define T_UNEQUAL 281
+#define T_EOF 282
+#define T_EOL 283
+#define T_CLOSE_PAREN 284
+#define T_OPEN_PAREN 285
+#define T_ON 286
+#define T_OR 287
+#define T_AND 288
+#define T_EQUAL 289
+#define T_NOT 290
+
+
+
+
+#ifndef YYSTYPE
+#line 33 "zconf.y"
+typedef union {
+	int token;
+	char *string;
+	struct symbol *symbol;
+	struct expr *expr;
+	struct menu *menu;
+} yystype;
+/* Line 1281 of /usr/share/bison/yacc.c.  */
+#line 118 "zconf.tab.h"
+# define YYSTYPE yystype
+#endif
+
+extern YYSTYPE zconflval;
+
+
+#endif /* not BISON_ZCONF_TAB_H */
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/zconf.y
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/zconf.y	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/config/zconf.y	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,690 @@
+%{
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel at linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
+
+#define PRINTD		0x0001
+#define DEBUG_PARSE	0x0002
+
+int cdebug = PRINTD;
+
+extern int zconflex(void);
+static void zconfprint(const char *err, ...);
+static void zconferror(const char *err);
+static bool zconf_endtoken(int token, int starttoken, int endtoken);
+
+struct symbol *symbol_hash[257];
+
+static struct menu *current_menu, *current_entry;
+
+#define YYERROR_VERBOSE
+%}
+%expect 40
+
+%union
+{
+	int token;
+	char *string;
+	struct symbol *symbol;
+	struct expr *expr;
+	struct menu *menu;
+}
+
+%token T_MAINMENU
+%token T_MENU
+%token T_ENDMENU
+%token T_SOURCE
+%token T_CHOICE
+%token T_ENDCHOICE
+%token T_COMMENT
+%token T_CONFIG
+%token T_MENUCONFIG
+%token T_HELP
+%token <string> T_HELPTEXT
+%token T_IF
+%token T_ENDIF
+%token T_DEPENDS
+%token T_REQUIRES
+%token T_OPTIONAL
+%token T_PROMPT
+%token T_DEFAULT
+%token T_TRISTATE
+%token T_DEF_TRISTATE
+%token T_BOOLEAN
+%token T_DEF_BOOLEAN
+%token T_STRING
+%token T_INT
+%token T_HEX
+%token <string> T_WORD
+%token <string> T_WORD_QUOTE
+%token T_UNEQUAL
+%token T_EOF
+%token T_EOL
+%token T_CLOSE_PAREN
+%token T_OPEN_PAREN
+%token T_ON
+%token T_SELECT
+%token T_RANGE
+
+%left T_OR
+%left T_AND
+%left T_EQUAL T_UNEQUAL
+%nonassoc T_NOT
+
+%type <string> prompt
+%type <string> source
+%type <symbol> symbol
+%type <expr> expr
+%type <expr> if_expr
+%type <token> end
+
+%{
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+%}
+%%
+input:	  /* empty */
+	| input block
+;
+
+block:	  common_block
+	| choice_stmt
+	| menu_stmt
+	| T_MAINMENU prompt nl_or_eof
+	| T_ENDMENU		{ zconfprint("unexpected 'endmenu' statement"); }
+	| T_ENDIF		{ zconfprint("unexpected 'endif' statement"); }
+	| T_ENDCHOICE		{ zconfprint("unexpected 'endchoice' statement"); }
+	| error nl_or_eof	{ zconfprint("syntax error"); yyerrok; }
+;
+
+common_block:
+	  if_stmt
+	| comment_stmt
+	| config_stmt
+	| menuconfig_stmt
+	| source_stmt
+	| nl_or_eof
+;
+
+
+/* config/menuconfig entry */
+
+config_entry_start: T_CONFIG T_WORD T_EOL
+{
+	struct symbol *sym = sym_lookup($2, 0);
+	sym->flags |= SYMBOL_OPTIONAL;
+	menu_add_entry(sym);
+	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
+};
+
+config_stmt: config_entry_start config_option_list
+{
+	menu_end_entry();
+	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+};
+
+menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL
+{
+	struct symbol *sym = sym_lookup($2, 0);
+	sym->flags |= SYMBOL_OPTIONAL;
+	menu_add_entry(sym);
+	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
+};
+
+menuconfig_stmt: menuconfig_entry_start config_option_list
+{
+	if (current_entry->prompt)
+		current_entry->prompt->type = P_MENU;
+	else
+		zconfprint("warning: menuconfig statement without prompt");
+	menu_end_entry();
+	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+};
+
+config_option_list:
+	  /* empty */
+	| config_option_list config_option
+	| config_option_list depends
+	| config_option_list help
+	| config_option_list T_EOL
+;
+
+config_option: T_TRISTATE prompt_stmt_opt T_EOL
+{
+	menu_set_type(S_TRISTATE);
+	printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_DEF_TRISTATE expr if_expr T_EOL
+{
+	menu_add_expr(P_DEFAULT, $2, $3);
+	menu_set_type(S_TRISTATE);
+	printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_BOOLEAN prompt_stmt_opt T_EOL
+{
+	menu_set_type(S_BOOLEAN);
+	printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_DEF_BOOLEAN expr if_expr T_EOL
+{
+	menu_add_expr(P_DEFAULT, $2, $3);
+	menu_set_type(S_BOOLEAN);
+	printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_INT prompt_stmt_opt T_EOL
+{
+	menu_set_type(S_INT);
+	printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_HEX prompt_stmt_opt T_EOL
+{
+	menu_set_type(S_HEX);
+	printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_STRING prompt_stmt_opt T_EOL
+{
+	menu_set_type(S_STRING);
+	printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_PROMPT prompt if_expr T_EOL
+{
+	menu_add_prompt(P_PROMPT, $2, $3);
+	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_DEFAULT expr if_expr T_EOL
+{
+	menu_add_expr(P_DEFAULT, $2, $3);
+	printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_SELECT T_WORD if_expr T_EOL
+{
+	menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
+	printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_RANGE symbol symbol if_expr T_EOL
+{
+	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
+	printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
+};
+
+/* choice entry */
+
+choice: T_CHOICE T_EOL
+{
+	struct symbol *sym = sym_lookup(NULL, 0);
+	sym->flags |= SYMBOL_CHOICE;
+	menu_add_entry(sym);
+	menu_add_expr(P_CHOICE, NULL, NULL);
+	printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
+};
+
+choice_entry: choice choice_option_list
+{
+	menu_end_entry();
+	menu_add_menu();
+};
+
+choice_end: end
+{
+	if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {
+		menu_end_menu();
+		printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
+	}
+};
+
+choice_stmt:
+	  choice_entry choice_block choice_end
+	| choice_entry choice_block
+{
+	printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno);
+	zconfnerrs++;
+};
+
+choice_option_list:
+	  /* empty */
+	| choice_option_list choice_option
+	| choice_option_list depends
+	| choice_option_list help
+	| choice_option_list T_EOL
+;
+
+choice_option: T_PROMPT prompt if_expr T_EOL
+{
+	menu_add_prompt(P_PROMPT, $2, $3);
+	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+};
+
+choice_option: T_TRISTATE prompt_stmt_opt T_EOL
+{
+	menu_set_type(S_TRISTATE);
+	printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
+};
+
+choice_option: T_BOOLEAN prompt_stmt_opt T_EOL
+{
+	menu_set_type(S_BOOLEAN);
+	printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
+};
+
+choice_option: T_OPTIONAL T_EOL
+{
+	current_entry->sym->flags |= SYMBOL_OPTIONAL;
+	printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
+};
+
+choice_option: T_DEFAULT T_WORD if_expr T_EOL
+{
+	menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
+	printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
+};
+
+choice_block:
+	  /* empty */
+	| choice_block common_block
+;
+
+/* if entry */
+
+if: T_IF expr T_EOL
+{
+	printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
+	menu_add_entry(NULL);
+	menu_add_dep($2);
+	menu_end_entry();
+	menu_add_menu();
+};
+
+if_end: end
+{
+	if (zconf_endtoken($1, T_IF, T_ENDIF)) {
+		menu_end_menu();
+		printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
+	}
+};
+
+if_stmt:
+	  if if_block if_end
+	| if if_block
+{
+	printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno);
+	zconfnerrs++;
+};
+
+if_block:
+	  /* empty */
+	| if_block common_block
+	| if_block menu_stmt
+	| if_block choice_stmt
+;
+
+/* menu entry */
+
+menu: T_MENU prompt T_EOL
+{
+	menu_add_entry(NULL);
+	menu_add_prop(P_MENU, $2, NULL, NULL);
+	printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
+};
+
+menu_entry: menu depends_list
+{
+	menu_end_entry();
+	menu_add_menu();
+};
+
+menu_end: end
+{
+	if (zconf_endtoken($1, T_MENU, T_ENDMENU)) {
+		menu_end_menu();
+		printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
+	}
+};
+
+menu_stmt:
+	  menu_entry menu_block menu_end
+	| menu_entry menu_block
+{
+	printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno);
+	zconfnerrs++;
+};
+
+menu_block:
+	  /* empty */
+	| menu_block common_block
+	| menu_block menu_stmt
+	| menu_block choice_stmt
+	| menu_block error T_EOL		{ zconfprint("invalid menu option"); yyerrok; }
+;
+
+source: T_SOURCE prompt T_EOL
+{
+	$$ = $2;
+	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
+};
+
+source_stmt: source
+{
+	zconf_nextfile($1);
+};
+
+/* comment entry */
+
+comment: T_COMMENT prompt T_EOL
+{
+	menu_add_entry(NULL);
+	menu_add_prop(P_COMMENT, $2, NULL, NULL);
+	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
+};
+
+comment_stmt: comment depends_list
+{
+	menu_end_entry();
+};
+
+/* help option */
+
+help_start: T_HELP T_EOL
+{
+	printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
+	zconf_starthelp();
+};
+
+help: help_start T_HELPTEXT
+{
+	current_entry->sym->help = $2;
+};
+
+/* depends option */
+
+depends_list:	  /* empty */
+		| depends_list depends
+		| depends_list T_EOL
+;
+
+depends: T_DEPENDS T_ON expr T_EOL
+{
+	menu_add_dep($3);
+	printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
+}
+	| T_DEPENDS expr T_EOL
+{
+	menu_add_dep($2);
+	printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
+}
+	| T_REQUIRES expr T_EOL
+{
+	menu_add_dep($2);
+	printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
+};
+
+/* prompt statement */
+
+prompt_stmt_opt:
+	  /* empty */
+	| prompt if_expr
+{
+	menu_add_prop(P_PROMPT, $1, NULL, $2);
+};
+
+prompt:	  T_WORD
+	| T_WORD_QUOTE
+;
+
+end:	  T_ENDMENU nl_or_eof	{ $$ = T_ENDMENU; }
+	| T_ENDCHOICE nl_or_eof	{ $$ = T_ENDCHOICE; }
+	| T_ENDIF nl_or_eof	{ $$ = T_ENDIF; }
+;
+
+nl_or_eof:
+	T_EOL | T_EOF;
+
+if_expr:  /* empty */			{ $$ = NULL; }
+	| T_IF expr			{ $$ = $2; }
+;
+
+expr:	  symbol				{ $$ = expr_alloc_symbol($1); }
+	| symbol T_EQUAL symbol			{ $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
+	| symbol T_UNEQUAL symbol		{ $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
+	| T_OPEN_PAREN expr T_CLOSE_PAREN	{ $$ = $2; }
+	| T_NOT expr				{ $$ = expr_alloc_one(E_NOT, $2); }
+	| expr T_OR expr			{ $$ = expr_alloc_two(E_OR, $1, $3); }
+	| expr T_AND expr			{ $$ = expr_alloc_two(E_AND, $1, $3); }
+;
+
+symbol:	  T_WORD	{ $$ = sym_lookup($1, 0); free($1); }
+	| T_WORD_QUOTE	{ $$ = sym_lookup($1, 1); free($1); }
+;
+
+%%
+
+void conf_parse(const char *name)
+{
+	struct symbol *sym;
+	int i;
+
+	zconf_initscan(name);
+
+	sym_init();
+	menu_init();
+	modules_sym = sym_lookup("MODULES", 0);
+	rootmenu.prompt = menu_add_prop(P_MENU, "BusyBox Configuration", NULL, NULL);
+
+	//zconfdebug = 1;
+	zconfparse();
+	if (zconfnerrs)
+		exit(1);
+	menu_finalize(&rootmenu);
+	for_all_symbols(i, sym) {
+                if (!(sym->flags & SYMBOL_CHECKED) && sym_check_deps(sym))
+                        printf("\n");
+		else
+			sym->flags |= SYMBOL_CHECK_DONE;
+        }
+
+	sym_change_count = 1;
+}
+
+const char *zconf_tokenname(int token)
+{
+	switch (token) {
+	case T_MENU:		return "menu";
+	case T_ENDMENU:		return "endmenu";
+	case T_CHOICE:		return "choice";
+	case T_ENDCHOICE:	return "endchoice";
+	case T_IF:		return "if";
+	case T_ENDIF:		return "endif";
+	}
+	return "<token>";
+}
+
+static bool zconf_endtoken(int token, int starttoken, int endtoken)
+{
+	if (token != endtoken) {
+		zconfprint("unexpected '%s' within %s block", zconf_tokenname(token), zconf_tokenname(starttoken));
+		zconfnerrs++;
+		return false;
+	}
+	if (current_menu->file != current_file) {
+		zconfprint("'%s' in different file than '%s'", zconf_tokenname(token), zconf_tokenname(starttoken));
+		zconfprint("location of the '%s'", zconf_tokenname(starttoken));
+		zconfnerrs++;
+		return false;
+	}
+	return true;
+}
+
+static void zconfprint(const char *err, ...)
+{
+	va_list ap;
+
+	fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno() + 1);
+	va_start(ap, err);
+	vfprintf(stderr, err, ap);
+	va_end(ap);
+	fprintf(stderr, "\n");
+}
+
+static void zconferror(const char *err)
+{
+	fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
+}
+
+void print_quoted_string(FILE *out, const char *str)
+{
+	const char *p;
+	int len;
+
+	putc('"', out);
+	while ((p = strchr(str, '"'))) {
+		len = p - str;
+		if (len)
+			fprintf(out, "%.*s", len, str);
+		fputs("\\\"", out);
+		str = p + 1;
+	}
+	fputs(str, out);
+	putc('"', out);
+}
+
+void print_symbol(FILE *out, struct menu *menu)
+{
+	struct symbol *sym = menu->sym;
+	struct property *prop;
+
+	if (sym_is_choice(sym))
+		fprintf(out, "choice\n");
+	else
+		fprintf(out, "config %s\n", sym->name);
+	switch (sym->type) {
+	case S_BOOLEAN:
+		fputs("  boolean\n", out);
+		break;
+	case S_TRISTATE:
+		fputs("  tristate\n", out);
+		break;
+	case S_STRING:
+		fputs("  string\n", out);
+		break;
+	case S_INT:
+		fputs("  integer\n", out);
+		break;
+	case S_HEX:
+		fputs("  hex\n", out);
+		break;
+	default:
+		fputs("  ???\n", out);
+		break;
+	}
+	for (prop = sym->prop; prop; prop = prop->next) {
+		if (prop->menu != menu)
+			continue;
+		switch (prop->type) {
+		case P_PROMPT:
+			fputs("  prompt ", out);
+			print_quoted_string(out, prop->text);
+			if (!expr_is_yes(prop->visible.expr)) {
+				fputs(" if ", out);
+				expr_fprint(prop->visible.expr, out);
+			}
+			fputc('\n', out);
+			break;
+		case P_DEFAULT:
+			fputs( "  default ", out);
+			expr_fprint(prop->expr, out);
+			if (!expr_is_yes(prop->visible.expr)) {
+				fputs(" if ", out);
+				expr_fprint(prop->visible.expr, out);
+			}
+			fputc('\n', out);
+			break;
+		case P_CHOICE:
+			fputs("  #choice value\n", out);
+			break;
+		default:
+			fprintf(out, "  unknown prop %d!\n", prop->type);
+			break;
+		}
+	}
+	if (sym->help) {
+		int len = strlen(sym->help);
+		while (sym->help[--len] == '\n')
+			sym->help[len] = 0;
+		fprintf(out, "  help\n%s\n", sym->help);
+	}
+	fputc('\n', out);
+}
+
+void zconfdump(FILE *out)
+{
+	struct property *prop;
+	struct symbol *sym;
+	struct menu *menu;
+
+	menu = rootmenu.list;
+	while (menu) {
+		if ((sym = menu->sym))
+			print_symbol(out, menu);
+		else if ((prop = menu->prompt)) {
+			switch (prop->type) {
+			case P_COMMENT:
+				fputs("\ncomment ", out);
+				print_quoted_string(out, prop->text);
+				fputs("\n", out);
+				break;
+			case P_MENU:
+				fputs("\nmenu ", out);
+				print_quoted_string(out, prop->text);
+				fputs("\n", out);
+				break;
+			default:
+				;
+			}
+			if (!expr_is_yes(prop->visible.expr)) {
+				fputs("  depends ", out);
+				expr_fprint(prop->visible.expr, out);
+				fputc('\n', out);
+			}
+			fputs("\n", out);
+		}
+
+		if (menu->list)
+			menu = menu->list;
+		else if (menu->next)
+			menu = menu->next;
+		else while ((menu = menu->parent)) {
+			if (menu->prompt && menu->prompt->type == P_MENU)
+				fputs("\nendmenu\n", out);
+			if (menu->next) {
+				menu = menu->next;
+				break;
+			}
+		}
+	}
+}
+
+#include "lex.zconf.c"
+#include "util.c"
+#include "confdata.c"
+#include "expr.c"
+#include "symbol.c"
+#include "menu.c"

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/objsizes
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/objsizes	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/objsizes	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+printf "%9s %11s %9s %9s %s\n" "text+data" text+rodata rwdata bss filename
+find -name '*.o' | sed 's:^\./::' | xargs size | grep '^ *[0-9]' \
+| while read text data bss dec hex filename; do
+    printf "%9d %11d %9d %9d %s\n" $((text+data)) $text $data $bss "$filename"
+done \
+| sort


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/objsizes
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/showasm
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/showasm	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/showasm	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Copyright 2006 Rob Landley <rob at landley.net>
+# Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+
+# Dumb little utility function to print out the assembly dump of a single
+# function, or list the functions so dumpable in an executable.  You'd think
+# there would be a way to get objdump to do this, but I can't find it.
+
+[ $# -lt 1 ] || [ $# -gt 2 ] && { echo "usage: showasm file function"; exit 1; }
+
+[ ! -f $1 ] && { echo "File $1 not found"; exit 1; }
+
+if [ $# -eq 1 ]
+then
+  objdump -d $1 | sed -n -e 's/^[0-9a-fA-F]* <\(.*\)>:$/\1/p'
+  exit 0
+fi
+
+objdump -d $1 | sed -n -e '/./{H;$!d}' -e "x;/^.[0-9a-fA-F]* <$2>:/p"
+


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/showasm
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/usage.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/usage.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/usage.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,14 @@
+#include <unistd.h>
+#include "busybox.h"
+
+static const char usage_messages[] =
+#define MAKE_USAGE
+#include "usage.h"
+#include "applets.h"
+;
+
+int main(void)
+{
+	write(1, usage_messages, sizeof(usage_messages));
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/usage_compressed
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/usage_compressed	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/scripts/usage_compressed	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+loc="$1"
+
+test "$loc" || loc=.
+test -x "$loc/usage" || exit 1
+
+echo 'static const char packed_usage[] = '
+"$loc"/usage | bzip2 -1 | od -v -t x1 \
+| $SED -e 's/^[^ ]*//' -e 's/ \(..\)/\\x\1/g' -e 's/^\(.*\)$/"\1"/' || exit 1
+echo ';'
+sz=`"$loc"/usage | wc -c` || exit 1
+echo '#define SIZEOF_usage_messages' `expr 0 + $sz`

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,294 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Shells"
+
+choice
+	prompt "Choose your default shell"
+	default CONFIG_FEATURE_SH_IS_NONE
+	help
+	  Choose a shell. The ash shell is the most bash compatible
+	  and full featured one.
+
+config CONFIG_FEATURE_SH_IS_ASH
+	select CONFIG_ASH
+	bool "ash"
+
+config CONFIG_FEATURE_SH_IS_HUSH
+	select CONFIG_HUSH
+	bool "hush"
+
+config CONFIG_FEATURE_SH_IS_LASH
+	select CONFIG_LASH
+	bool "lash"
+
+config CONFIG_FEATURE_SH_IS_MSH
+	select CONFIG_MSH
+	bool "msh"
+
+config CONFIG_FEATURE_SH_IS_NONE
+	bool "none"
+
+endchoice
+
+config CONFIG_ASH
+	bool "ash"
+	default n
+	select CONFIG_TEST
+	help
+	  Tha 'ash' shell adds about 60k in the default configuration and is
+	  the most complete and most pedantically correct shell included with
+	  busybox.  This shell is actually a derivative of the Debian 'dash'
+	  shell (by Herbert Xu), which was created by porting the 'ash' shell
+	  (written by Kenneth Almquist) from NetBSD.
+
+comment "Ash Shell Options"
+	depends on CONFIG_ASH
+
+config CONFIG_ASH_JOB_CONTROL
+	bool "Job control"
+	default y
+	depends on CONFIG_ASH
+	help
+	  Enable job control in the ash shell.
+
+config CONFIG_ASH_READ_NCHARS
+	bool "'read -n N' and 'read -s' support"
+	default n
+	depends on CONFIG_ASH
+	help
+	  'read -n N' will return a value after N characters have been read.
+	  'read -s' will read without echoing the user's input.
+
+config CONFIG_ASH_READ_TIMEOUT
+	bool "'read -t S' support."
+	default n
+	depends on CONFIG_ASH
+	help
+	  'read -t S' will return a value after S seconds have passed.
+	  This implementation will allow fractional seconds, expressed
+	  as a decimal fraction, e.g. 'read -t 2.5 foo'.
+
+config CONFIG_ASH_ALIAS
+	bool "alias support"
+	default y
+	depends on CONFIG_ASH
+	help
+	  Enable alias support in the ash shell.
+
+config CONFIG_ASH_MATH_SUPPORT
+	bool "Posix math support"
+	default y
+	depends on CONFIG_ASH
+	help
+	  Enable math support in the ash shell.
+
+config CONFIG_ASH_MATH_SUPPORT_64
+	bool "Extend Posix math support to 64 bit"
+	default n
+	depends on CONFIG_ASH_MATH_SUPPORT
+	help
+	  Enable 64-bit math support in the ash shell.  This will make
+	  the shell slightly larger, but will allow computation with very
+	  large numbers.
+
+config CONFIG_ASH_GETOPTS
+	bool "Builtin getopt to parse positional parameters"
+	default n
+	depends on CONFIG_ASH
+	help
+	  Enable getopts builtin in the ash shell.
+
+config CONFIG_ASH_BUILTIN_ECHO
+	bool "Builtin version of 'echo'"
+	default y
+	select CONFIG_ECHO
+	depends on CONFIG_ASH
+	help
+	  Enable support for echo, built in to ash.
+
+config CONFIG_ASH_BUILTIN_TEST
+	bool "Builtin version of 'test'"
+	default y
+	select CONFIG_TEST
+	depends on CONFIG_ASH
+	help
+	  Enable support for test, built in to ash.
+
+config CONFIG_ASH_CMDCMD
+	bool "'command' command to override shell builtins"
+	default n
+	depends on CONFIG_ASH
+	help
+	  Enable support for the ash 'command' builtin, which allows
+	  you to run the specified command with the specified arguments,
+	  even when there is an ash builtin command with the same name.
+
+config CONFIG_ASH_MAIL
+	bool "Check for new mail on interactive shells"
+	default y
+	depends on CONFIG_ASH
+	help
+	  Enable "check for new mail" in the ash shell.
+
+config CONFIG_ASH_OPTIMIZE_FOR_SIZE
+	bool "Optimize for size instead of speed"
+	default y
+	depends on CONFIG_ASH
+	help
+	  Compile ash for reduced size at the price of speed.
+
+config CONFIG_ASH_RANDOM_SUPPORT
+	bool "Pseudorandom generator and variable $RANDOM"
+	default n
+	depends on CONFIG_ASH
+	help
+	  Enable pseudorandom generator and dynamic variable "$RANDOM".
+	  Each read of "$RANDOM" will generate a new pseudorandom value.
+	  You can reset the generator by using a specified start value.
+	  After "unset RANDOM" then generator will switch off and this
+	  variable will no longer have special treatment.
+
+config CONFIG_ASH_EXPAND_PRMT
+	bool "Expand prompt string"
+	default n
+	depends on CONFIG_ASH
+	help
+	  "PS#" may be contain volatile content, such as backquote commands.
+	  This option recreates the prompt string from the environment
+	  variable each time it is displayed.
+
+config CONFIG_HUSH
+	bool "hush"
+	default n
+	select CONFIG_TRUE
+	select CONFIG_FALSE
+	select CONFIG_TEST
+	help
+	  hush is a very small shell (just 18k) and it has fairly complete
+	  Bourne shell grammar.  It even handles all the normal flow control
+	  options such as if/then/elif/else/fi, for/in/do/done, while loops,
+	  etc.
+
+	  It does not handle case/esac, select, function, here documents ( <<
+	  word ), arithmetic expansion, aliases, brace expansion, tilde
+	  expansion, &> and >& redirection of stdout+stderr, etc.
+
+
+config CONFIG_LASH
+	bool "lash"
+	default n
+	select CONFIG_TRUE
+	select CONFIG_FALSE
+	select CONFIG_TEST
+	help
+	  lash is the very smallest shell (adds just 10k) and it is quite
+	  usable as a command prompt, but it is not suitable for any but the
+	  most trivial scripting (such as an initrd that calls insmod a few
+	  times) since it does not understand any Bourne shell grammar.  It
+	  does handle pipes, redirects, and job control though.  Adding in
+	  command editing makes it a very nice lightweight command prompt.
+
+
+config CONFIG_MSH
+	bool "msh"
+	default n
+	select CONFIG_TRUE
+	select CONFIG_FALSE
+	select CONFIG_TEST
+	help
+	  The minix shell (adds just 30k) is quite complete and handles things
+	  like for/do/done, case/esac and all the things you expect a Bourne
+	  shell to do.  It is not always pedantically correct about Bourne
+	  shell grammar (try running the shell testscript "tests/sh.testcases"
+	  on it and compare vs bash) but for most things it works quite well.
+	  It also uses only vfork, so it can be used on uClinux systems.
+
+comment "Bourne Shell Options"
+	depends on CONFIG_MSH || CONFIG_LASH || CONFIG_HUSH || CONFIG_ASH
+
+config CONFIG_FEATURE_SH_EXTRA_QUIET
+	bool "Hide message on interactive shell startup"
+	default n
+	depends on CONFIG_MSH || CONFIG_LASH || CONFIG_HUSH || CONFIG_ASH
+	help
+	  Remove the busybox introduction when starting a shell.
+
+config CONFIG_FEATURE_SH_STANDALONE_SHELL
+	bool "Standalone shell"
+	default n
+	depends on CONFIG_MSH || CONFIG_LASH || CONFIG_HUSH || CONFIG_ASH
+	help
+	  This option causes the selected busybox shell to use busybox applets
+	  in preference to executables in the PATH whenever possible.  For
+	  example, entering the command 'ifconfig' into the shell would cause
+	  busybox to use the ifconfig busybox applet.  Specifying the fully
+	  qualified executable name, such as '/sbin/ifconfig' will still
+	  execute the /sbin/ifconfig executable on the filesystem.  This option
+	  is generally used when creating a statically linked version of busybox
+	  for use as a rescue shell, in the event that you screw up your system.
+
+	  Note that this will *also* cause applets to take precedence
+	  over shell builtins of the same name.  So turning this on will
+	  eliminate any performance gained by turning on the builtin "echo"
+	  and "test" commands in ash.
+
+	  Note that when using this option, the shell will attempt to directly
+	  run '/bin/busybox'.  If you do not have the busybox binary sitting in
+	  that exact location with that exact name, this option will not work at
+	  all.
+
+config CONFIG_FEATURE_COMMAND_EDITING
+	bool "Command line editing"
+	default n
+	depends on CONFIG_MSH || CONFIG_LASH || CONFIG_HUSH || CONFIG_ASH
+	help
+	  Enable command editing in shell.
+
+config CONFIG_FEATURE_COMMAND_EDITING_VI
+	bool "vi-style line editing commands"
+	default n
+	depends on CONFIG_FEATURE_COMMAND_EDITING
+	help
+	  Enable vi-style line editing in the shell.  This mode can be
+	  turned on and off with "set -o vi" and "set +o vi".
+
+config CONFIG_FEATURE_COMMAND_HISTORY
+	int "History size"
+	default 15
+	depends on CONFIG_FEATURE_COMMAND_EDITING
+	help
+	  Specify command history size in shell.
+
+config CONFIG_FEATURE_COMMAND_SAVEHISTORY
+	bool "History saving"
+	default n
+	depends on CONFIG_ASH && CONFIG_FEATURE_COMMAND_EDITING
+	help
+	  Enable history saving in ash shell.
+
+config CONFIG_FEATURE_COMMAND_TAB_COMPLETION
+	bool "Tab completion"
+	default n
+	depends on CONFIG_FEATURE_COMMAND_EDITING
+	help
+	  Enable tab completion in shell.
+
+config CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION
+	bool "Username completion"
+	default n
+	depends on CONFIG_FEATURE_COMMAND_TAB_COMPLETION
+	help
+	  Enable username completion in shell.
+
+config CONFIG_FEATURE_SH_FANCY_PROMPT
+	bool "Fancy shell prompts"
+	default n
+	depends on CONFIG_FEATURE_COMMAND_EDITING
+	help
+	  Setting this option allows for prompts to use things like \w and
+	  \$ and also using escape codes.
+
+endmenu

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/shell
+SHELL_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,33 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+SHELL_AR:=shell.a
+ifndef $(SHELL_DIR)
+SHELL_DIR:=$(top_builddir)/shell/
+endif
+srcdir=$(top_srcdir)/shell
+
+SHELLT-y:=
+SHELLT-$(CONFIG_ASH)				+= ash.o
+SHELLT-$(CONFIG_HUSH)				+= hush.o
+SHELLT-$(CONFIG_LASH)				+= lash.o
+SHELLT-$(CONFIG_MSH)				+= msh.o
+SHELLT-$(CONFIG_FEATURE_COMMAND_EDITING)	+= cmdedit.o
+
+ifneq ($(strip $(SHELLT-y)),)
+libraries-y+=$(SHELL_DIR)$(SHELL_AR)
+endif
+
+SHELLT_SRC-y:=$(patsubst %.o,$(srcdir)/%.c,$(SHELLT-y))
+SHELLT_SRC-a:=$(wildcard $(srcdir)/*.c)
+APPLET_SRC-y+=$(SHELLT_SRC-y)
+APPLET_SRC-a+=$(SHELLT_SRC-a)
+
+$(SHELL_DIR)$(SHELL_AR): $(patsubst %,$(SHELL_DIR)%, $(SHELLT-y))
+	$(do_ar)
+
+$(SHELL_DIR)%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/ash.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/ash.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/ash.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,13700 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * ash shell port for busybox
+ *
+ * Copyright (c) 1989, 1991, 1993, 1994
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Copyright (c) 1997-2005 Herbert Xu <herbert at gondor.apana.org.au>
+ * was re-ported from NetBSD and debianized.
+ *
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ * Original BSD copyright notice is retained at the end of this file.
+ */
+
+/*
+ * rewrite arith.y to micro stack based cryptic algorithm by
+ * Copyright (c) 2001 Aaron Lehmann <aaronl at vitelus.com>
+ *
+ * Modified by Paul Mundt <lethal at linux-sh.org> (c) 2004 to support
+ * dynamic variables.
+ *
+ * Modified by Vladimir Oleynik <dzo at simtreas.ru> (c) 2001-2005 to be
+ * used in busybox and size optimizations,
+ * rewrote arith (see notes to this), added locale support,
+ * rewrote dynamic variables.
+ *
+ */
+
+
+/*
+ * The follow should be set to reflect the type of system you have:
+ *      JOBS -> 1 if you have Berkeley job control, 0 otherwise.
+ *      define SYSV if you are running under System V.
+ *      define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
+ *      define DEBUG=2 to compile in and turn on debugging.
+ *
+ * When debugging is on, debugging info will be written to ./trace and
+ * a quit signal will generate a core dump.
+ */
+
+
+#define IFS_BROKEN
+
+#define PROFILE 0
+
+#include "busybox.h"
+
+#ifdef DEBUG
+#define _GNU_SOURCE
+#endif
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <assert.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <paths.h>
+#include <setjmp.h>
+#include <signal.h>
+/*#include <stdint.h>*/
+#include <time.h>
+#include <fnmatch.h>
+
+#include "pwd_.h"
+
+#ifdef CONFIG_ASH_JOB_CONTROL
+#define JOBS 1
+#else
+#undef JOBS
+#endif
+
+#if JOBS || defined(CONFIG_ASH_READ_NCHARS)
+#include <termios.h>
+#endif
+
+#include "cmdedit.h"
+
+#ifdef __GLIBC__
+/* glibc sucks */
+static int *dash_errno;
+#undef errno
+#define errno (*dash_errno)
+#endif
+
+#if defined(__uClinux__)
+#error "Do not even bother, ash will not run on uClinux"
+#endif
+
+#ifdef DEBUG
+#define _DIAGASSERT(assert_expr) assert(assert_expr)
+#else
+#define _DIAGASSERT(assert_expr)
+#endif
+
+
+#ifdef CONFIG_ASH_ALIAS
+/*      alias.h       */
+
+#define ALIASINUSE      1
+#define ALIASDEAD       2
+
+struct alias {
+	struct alias *next;
+	char *name;
+	char *val;
+	int flag;
+};
+
+static struct alias *lookupalias(const char *, int);
+static int aliascmd(int, char **);
+static int unaliascmd(int, char **);
+static void rmaliases(void);
+static int unalias(const char *);
+static void printalias(const struct alias *);
+#endif
+
+/*      cd.h  */
+
+
+static void    setpwd(const char *, int);
+
+/*      error.h      */
+
+
+/*
+ * Types of operations (passed to the errmsg routine).
+ */
+
+
+static const char not_found_msg[] = "%s: not found";
+
+
+#define E_OPEN  "No such file"          /* opening a file */
+#define E_CREAT "Directory nonexistent" /* creating a file */
+#define E_EXEC  not_found_msg+4         /* executing a program */
+
+/*
+ * We enclose jmp_buf in a structure so that we can declare pointers to
+ * jump locations.  The global variable handler contains the location to
+ * jump to when an exception occurs, and the global variable exception
+ * contains a code identifying the exception.  To implement nested
+ * exception handlers, the user should save the value of handler on entry
+ * to an inner scope, set handler to point to a jmploc structure for the
+ * inner scope, and restore handler on exit from the scope.
+ */
+
+struct jmploc {
+	jmp_buf loc;
+};
+
+static struct jmploc *handler;
+static int exception;
+static volatile int suppressint;
+static volatile sig_atomic_t intpending;
+
+/* exceptions */
+#define EXINT 0         /* SIGINT received */
+#define EXERROR 1       /* a generic error */
+#define EXSHELLPROC 2   /* execute a shell procedure */
+#define EXEXEC 3        /* command execution failed */
+#define EXEXIT 4        /* exit the shell */
+#define EXSIG 5         /* trapped signal in wait(1) */
+
+
+/* do we generate EXSIG events */
+static int exsig;
+/* last pending signal */
+static volatile sig_atomic_t pendingsigs;
+
+/*
+ * These macros allow the user to suspend the handling of interrupt signals
+ * over a period of time.  This is similar to SIGHOLD to or sigblock, but
+ * much more efficient and portable.  (But hacking the kernel is so much
+ * more fun than worrying about efficiency and portability. :-))
+ */
+
+#define xbarrier() ({ __asm__ __volatile__ ("": : :"memory"); })
+#define INTOFF \
+	({ \
+		suppressint++; \
+		xbarrier(); \
+		0; \
+	})
+#define SAVEINT(v) ((v) = suppressint)
+#define RESTOREINT(v) \
+	({ \
+		xbarrier(); \
+		if ((suppressint = (v)) == 0 && intpending) onint(); \
+		0; \
+	})
+#define EXSIGON() \
+	({ \
+		exsig++; \
+		xbarrier(); \
+		if (pendingsigs) \
+			exraise(EXSIG); \
+		0; \
+	})
+/* EXSIG is turned off by evalbltin(). */
+
+
+static void exraise(int) ATTRIBUTE_NORETURN;
+static void onint(void) ATTRIBUTE_NORETURN;
+
+static void sh_error(const char *, ...) ATTRIBUTE_NORETURN;
+static void exerror(int, const char *, ...) ATTRIBUTE_NORETURN;
+
+static void sh_warnx(const char *, ...);
+
+#ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
+static void
+inton(void) {
+	if (--suppressint == 0 && intpending) {
+		onint();
+	}
+}
+#define INTON inton()
+static void forceinton(void)
+{
+	suppressint = 0;
+	if (intpending)
+		onint();
+}
+#define FORCEINTON forceinton()
+#else
+#define INTON \
+	({ \
+		xbarrier(); \
+		if (--suppressint == 0 && intpending) onint(); \
+		0; \
+	})
+#define FORCEINTON \
+	({ \
+		xbarrier(); \
+		suppressint = 0; \
+		if (intpending) onint(); \
+		0; \
+	})
+#endif /* CONFIG_ASH_OPTIMIZE_FOR_SIZE */
+
+/*      expand.h     */
+
+struct strlist {
+	struct strlist *next;
+	char *text;
+};
+
+
+struct arglist {
+	struct strlist *list;
+	struct strlist **lastp;
+};
+
+/*
+ * expandarg() flags
+ */
+#define EXP_FULL        0x1     /* perform word splitting & file globbing */
+#define EXP_TILDE       0x2     /* do normal tilde expansion */
+#define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
+#define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
+#define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
+#define EXP_RECORD      0x20    /* need to record arguments for ifs breakup */
+#define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
+#define EXP_WORD        0x80    /* expand word in parameter expansion */
+#define EXP_QWORD       0x100   /* expand word in quoted parameter expansion */
+
+
+union node;
+static void expandarg(union node *, struct arglist *, int);
+#define rmescapes(p) _rmescapes((p), 0)
+static char *_rmescapes(char *, int);
+static int casematch(union node *, char *);
+
+#ifdef CONFIG_ASH_MATH_SUPPORT
+static void expari(int);
+#endif
+
+/*      eval.h       */
+
+static char *commandname;              /* currently executing command */
+static struct strlist *cmdenviron;     /* environment for builtin command */
+static int exitstatus;                 /* exit status of last command */
+static int back_exitstatus;            /* exit status of backquoted command */
+
+
+struct backcmd {                /* result of evalbackcmd */
+	int fd;                 /* file descriptor to read from */
+	char *buf;              /* buffer */
+	int nleft;              /* number of chars in buffer */
+	struct job *jp;         /* job structure for command */
+};
+
+/*
+ * This file was generated by the mknodes program.
+ */
+
+#define NCMD 0
+#define NPIPE 1
+#define NREDIR 2
+#define NBACKGND 3
+#define NSUBSHELL 4
+#define NAND 5
+#define NOR 6
+#define NSEMI 7
+#define NIF 8
+#define NWHILE 9
+#define NUNTIL 10
+#define NFOR 11
+#define NCASE 12
+#define NCLIST 13
+#define NDEFUN 14
+#define NARG 15
+#define NTO 16
+#define NCLOBBER 17
+#define NFROM 18
+#define NFROMTO 19
+#define NAPPEND 20
+#define NTOFD 21
+#define NFROMFD 22
+#define NHERE 23
+#define NXHERE 24
+#define NNOT 25
+
+
+
+struct ncmd {
+      int type;
+      union node *assign;
+      union node *args;
+      union node *redirect;
+};
+
+
+struct npipe {
+      int type;
+      int backgnd;
+      struct nodelist *cmdlist;
+};
+
+
+struct nredir {
+      int type;
+      union node *n;
+      union node *redirect;
+};
+
+
+struct nbinary {
+      int type;
+      union node *ch1;
+      union node *ch2;
+};
+
+
+struct nif {
+      int type;
+      union node *test;
+      union node *ifpart;
+      union node *elsepart;
+};
+
+
+struct nfor {
+      int type;
+      union node *args;
+      union node *body;
+      char *var;
+};
+
+
+struct ncase {
+      int type;
+      union node *expr;
+      union node *cases;
+};
+
+
+struct nclist {
+      int type;
+      union node *next;
+      union node *pattern;
+      union node *body;
+};
+
+
+struct narg {
+      int type;
+      union node *next;
+      char *text;
+      struct nodelist *backquote;
+};
+
+
+struct nfile {
+      int type;
+      union node *next;
+      int fd;
+      union node *fname;
+      char *expfname;
+};
+
+
+struct ndup {
+      int type;
+      union node *next;
+      int fd;
+      int dupfd;
+      union node *vname;
+};
+
+
+struct nhere {
+      int type;
+      union node *next;
+      int fd;
+      union node *doc;
+};
+
+
+struct nnot {
+      int type;
+      union node *com;
+};
+
+
+union node {
+      int type;
+      struct ncmd ncmd;
+      struct npipe npipe;
+      struct nredir nredir;
+      struct nbinary nbinary;
+      struct nif nif;
+      struct nfor nfor;
+      struct ncase ncase;
+      struct nclist nclist;
+      struct narg narg;
+      struct nfile nfile;
+      struct ndup ndup;
+      struct nhere nhere;
+      struct nnot nnot;
+};
+
+
+struct nodelist {
+	struct nodelist *next;
+	union node *n;
+};
+
+
+struct funcnode {
+	int count;
+	union node n;
+};
+
+
+static void freefunc(struct funcnode *);
+/*      parser.h     */
+
+/* control characters in argument strings */
+#define CTL_FIRST '\201'        /* first 'special' character */
+#define CTLESC '\201'           /* escape next character */
+#define CTLVAR '\202'           /* variable defn */
+#define CTLENDVAR '\203'
+#define CTLBACKQ '\204'
+#define CTLQUOTE 01             /* ored with CTLBACKQ code if in quotes */
+/*      CTLBACKQ | CTLQUOTE == '\205' */
+#define CTLARI  '\206'          /* arithmetic expression */
+#define CTLENDARI '\207'
+#define CTLQUOTEMARK '\210'
+#define CTL_LAST '\210'         /* last 'special' character */
+
+/* variable substitution byte (follows CTLVAR) */
+#define VSTYPE  0x0f            /* type of variable substitution */
+#define VSNUL   0x10            /* colon--treat the empty string as unset */
+#define VSQUOTE 0x80            /* inside double quotes--suppress splitting */
+
+/* values of VSTYPE field */
+#define VSNORMAL        0x1             /* normal variable:  $var or ${var} */
+#define VSMINUS         0x2             /* ${var-text} */
+#define VSPLUS          0x3             /* ${var+text} */
+#define VSQUESTION      0x4             /* ${var?message} */
+#define VSASSIGN        0x5             /* ${var=text} */
+#define VSTRIMRIGHT     0x6             /* ${var%pattern} */
+#define VSTRIMRIGHTMAX  0x7             /* ${var%%pattern} */
+#define VSTRIMLEFT      0x8             /* ${var#pattern} */
+#define VSTRIMLEFTMAX   0x9             /* ${var##pattern} */
+#define VSLENGTH        0xa             /* ${#var} */
+
+/* values of checkkwd variable */
+#define CHKALIAS        0x1
+#define CHKKWD          0x2
+#define CHKNL           0x4
+
+#define IBUFSIZ (BUFSIZ + 1)
+
+/*
+ * NEOF is returned by parsecmd when it encounters an end of file.  It
+ * must be distinct from NULL, so we use the address of a variable that
+ * happens to be handy.
+ */
+static int plinno = 1;                  /* input line number */
+
+/* number of characters left in input buffer */
+static int parsenleft;                  /* copy of parsefile->nleft */
+static int parselleft;                  /* copy of parsefile->lleft */
+
+/* next character in input buffer */
+static char *parsenextc;                /* copy of parsefile->nextc */
+
+struct strpush {
+	struct strpush *prev;   /* preceding string on stack */
+	char *prevstring;
+	int prevnleft;
+#ifdef CONFIG_ASH_ALIAS
+	struct alias *ap;       /* if push was associated with an alias */
+#endif
+	char *string;           /* remember the string since it may change */
+};
+
+struct parsefile {
+	struct parsefile *prev; /* preceding file on stack */
+	int linno;              /* current line */
+	int fd;                 /* file descriptor (or -1 if string) */
+	int nleft;              /* number of chars left in this line */
+	int lleft;              /* number of chars left in this buffer */
+	char *nextc;            /* next char in buffer */
+	char *buf;              /* input buffer */
+	struct strpush *strpush; /* for pushing strings at this level */
+	struct strpush basestrpush; /* so pushing one is fast */
+};
+
+static struct parsefile basepf;         /* top level input file */
+#define basebuf bb_common_bufsiz1       /* buffer for top level input file */
+static struct parsefile *parsefile = &basepf;  /* current input file */
+
+
+static int tokpushback;                 /* last token pushed back */
+#define NEOF ((union node *)&tokpushback)
+static int parsebackquote;             /* nonzero if we are inside backquotes */
+static int doprompt;                   /* if set, prompt the user */
+static int needprompt;                 /* true if interactive and at start of line */
+static int lasttoken;                  /* last token read */
+static char *wordtext;                 /* text of last word returned by readtoken */
+static int checkkwd;
+static struct nodelist *backquotelist;
+static union node *redirnode;
+static struct heredoc *heredoc;
+static int quoteflag;                  /* set if (part of) last token was quoted */
+static int startlinno;                 /* line # where last token started */
+
+static union node *parsecmd(int);
+static void fixredir(union node *, const char *, int);
+static const char *const *findkwd(const char *);
+static char *endofname(const char *);
+
+/*      shell.h   */
+
+typedef void *pointer;
+
+static char nullstr[1];                /* zero length string */
+static const char spcstr[] = " ";
+static const char snlfmt[] = "%s\n";
+static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
+static const char illnum[] = "Illegal number: %s";
+static const char homestr[] = "HOME";
+
+#ifdef DEBUG
+#define TRACE(param)    trace param
+#define TRACEV(param)   tracev param
+#else
+#define TRACE(param)
+#define TRACEV(param)
+#endif
+
+#if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
+#define __builtin_expect(x, expected_value) (x)
+#endif
+
+#define xlikely(x)       __builtin_expect((x),1)
+
+
+#define TEOF 0
+#define TNL 1
+#define TREDIR 2
+#define TWORD 3
+#define TSEMI 4
+#define TBACKGND 5
+#define TAND 6
+#define TOR 7
+#define TPIPE 8
+#define TLP 9
+#define TRP 10
+#define TENDCASE 11
+#define TENDBQUOTE 12
+#define TNOT 13
+#define TCASE 14
+#define TDO 15
+#define TDONE 16
+#define TELIF 17
+#define TELSE 18
+#define TESAC 19
+#define TFI 20
+#define TFOR 21
+#define TIF 22
+#define TIN 23
+#define TTHEN 24
+#define TUNTIL 25
+#define TWHILE 26
+#define TBEGIN 27
+#define TEND 28
+
+/* first char is indicating which tokens mark the end of a list */
+static const char *const tokname_array[] = {
+	"\1end of file",
+	"\0newline",
+	"\0redirection",
+	"\0word",
+	"\0;",
+	"\0&",
+	"\0&&",
+	"\0||",
+	"\0|",
+	"\0(",
+	"\1)",
+	"\1;;",
+	"\1`",
+#define KWDOFFSET 13
+	/* the following are keywords */
+	"\0!",
+	"\0case",
+	"\1do",
+	"\1done",
+	"\1elif",
+	"\1else",
+	"\1esac",
+	"\1fi",
+	"\0for",
+	"\0if",
+	"\0in",
+	"\1then",
+	"\0until",
+	"\0while",
+	"\0{",
+	"\1}",
+};
+
+static const char *tokname(int tok)
+{
+	static char buf[16];
+
+	if (tok >= TSEMI)
+		buf[0] = '"';
+	sprintf(buf + (tok >= TSEMI), "%s%c",
+			tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
+	return buf;
+}
+
+/*      machdep.h    */
+
+/*
+ * Most machines require the value returned from malloc to be aligned
+ * in some way.  The following macro will get this right on many machines.
+ */
+
+#define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
+/*
+ * It appears that grabstackstr() will barf with such alignments
+ * because stalloc() will return a string allocated in a new stackblock.
+ */
+#define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
+
+/*
+ * This file was generated by the mksyntax program.
+ */
+
+
+/* Syntax classes */
+#define CWORD 0                 /* character is nothing special */
+#define CNL 1                   /* newline character */
+#define CBACK 2                 /* a backslash character */
+#define CSQUOTE 3               /* single quote */
+#define CDQUOTE 4               /* double quote */
+#define CENDQUOTE 5             /* a terminating quote */
+#define CBQUOTE 6               /* backwards single quote */
+#define CVAR 7                  /* a dollar sign */
+#define CENDVAR 8               /* a '}' character */
+#define CLP 9                   /* a left paren in arithmetic */
+#define CRP 10                  /* a right paren in arithmetic */
+#define CENDFILE 11             /* end of file */
+#define CCTL 12                 /* like CWORD, except it must be escaped */
+#define CSPCL 13                /* these terminate a word */
+#define CIGN 14                 /* character should be ignored */
+
+#ifdef CONFIG_ASH_ALIAS
+#define SYNBASE 130
+#define PEOF -130
+#define PEOA -129
+#define PEOA_OR_PEOF PEOA
+#else
+#define SYNBASE 129
+#define PEOF -129
+#define PEOA_OR_PEOF PEOF
+#endif
+
+#define is_digit(c)     ((unsigned)((c) - '0') <= 9)
+#define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
+#define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
+
+/* C99 say: "char" declaration may be signed or unsigned default */
+#define SC2INT(chr2may_be_negative_int) (int)((signed char)chr2may_be_negative_int)
+
+/*
+ * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
+ * (assuming ascii char codes, as the original implementation did)
+ */
+#define is_special(c) \
+    ( (((unsigned int)c) - 33 < 32) \
+			 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
+
+#define digit_val(c)    ((c) - '0')
+
+/*
+ * This file was generated by the mksyntax program.
+ */
+
+#ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
+#define USE_SIT_FUNCTION
+#endif
+
+/* number syntax index */
+#define  BASESYNTAX  0  /* not in quotes */
+#define  DQSYNTAX    1  /* in double quotes */
+#define  SQSYNTAX    2  /* in single quotes */
+#define  ARISYNTAX   3  /* in arithmetic */
+
+#ifdef CONFIG_ASH_MATH_SUPPORT
+static const char S_I_T[][4] = {
+#ifdef CONFIG_ASH_ALIAS
+	{CSPCL, CIGN, CIGN, CIGN},              /* 0, PEOA */
+#endif
+	{CSPCL, CWORD, CWORD, CWORD},           /* 1, ' ' */
+	{CNL, CNL, CNL, CNL},                   /* 2, \n */
+	{CWORD, CCTL, CCTL, CWORD},             /* 3, !*-/:=?[]~ */
+	{CDQUOTE, CENDQUOTE, CWORD, CWORD},     /* 4, '"' */
+	{CVAR, CVAR, CWORD, CVAR},              /* 5, $ */
+	{CSQUOTE, CWORD, CENDQUOTE, CWORD},     /* 6, "'" */
+	{CSPCL, CWORD, CWORD, CLP},             /* 7, ( */
+	{CSPCL, CWORD, CWORD, CRP},             /* 8, ) */
+	{CBACK, CBACK, CCTL, CBACK},            /* 9, \ */
+	{CBQUOTE, CBQUOTE, CWORD, CBQUOTE},     /* 10, ` */
+	{CENDVAR, CENDVAR, CWORD, CENDVAR},     /* 11, } */
+#ifndef USE_SIT_FUNCTION
+	{CENDFILE, CENDFILE, CENDFILE, CENDFILE},       /* 12, PEOF */
+	{CWORD, CWORD, CWORD, CWORD},           /* 13, 0-9A-Za-z */
+	{CCTL, CCTL, CCTL, CCTL}                /* 14, CTLESC ... */
+#endif
+};
+#else
+static const char S_I_T[][3] = {
+#ifdef CONFIG_ASH_ALIAS
+	{CSPCL, CIGN, CIGN},                    /* 0, PEOA */
+#endif
+	{CSPCL, CWORD, CWORD},                  /* 1, ' ' */
+	{CNL, CNL, CNL},                        /* 2, \n */
+	{CWORD, CCTL, CCTL},                    /* 3, !*-/:=?[]~ */
+	{CDQUOTE, CENDQUOTE, CWORD},            /* 4, '"' */
+	{CVAR, CVAR, CWORD},                    /* 5, $ */
+	{CSQUOTE, CWORD, CENDQUOTE},            /* 6, "'" */
+	{CSPCL, CWORD, CWORD},                  /* 7, ( */
+	{CSPCL, CWORD, CWORD},                  /* 8, ) */
+	{CBACK, CBACK, CCTL},                   /* 9, \ */
+	{CBQUOTE, CBQUOTE, CWORD},              /* 10, ` */
+	{CENDVAR, CENDVAR, CWORD},              /* 11, } */
+#ifndef USE_SIT_FUNCTION
+	{CENDFILE, CENDFILE, CENDFILE},         /* 12, PEOF */
+	{CWORD, CWORD, CWORD},                  /* 13, 0-9A-Za-z */
+	{CCTL, CCTL, CCTL}                      /* 14, CTLESC ... */
+#endif
+};
+#endif /* CONFIG_ASH_MATH_SUPPORT */
+
+#ifdef USE_SIT_FUNCTION
+
+#define U_C(c) ((unsigned char)(c))
+
+static int SIT(int c, int syntax)
+{
+	static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
+#ifdef CONFIG_ASH_ALIAS
+	static const char syntax_index_table[] = {
+		1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
+		7, 8, 3, 3, 3, 3, 1, 1,         /* "()*-/:;<" */
+		3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
+		11, 3                           /* "}~" */
+	};
+#else
+	static const char syntax_index_table[] = {
+		0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
+		6, 7, 2, 2, 2, 2, 0, 0,         /* "()*-/:;<" */
+		2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
+		10, 2                           /* "}~" */
+	};
+#endif
+	const char *s;
+	int indx;
+
+	if (c == PEOF)          /* 2^8+2 */
+		return CENDFILE;
+#ifdef CONFIG_ASH_ALIAS
+	if (c == PEOA)          /* 2^8+1 */
+		indx = 0;
+	else
+#endif
+		if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
+			return CCTL;
+	else {
+		s = strchr(spec_symbls, c);
+		if (s == 0 || *s == 0)
+			return CWORD;
+		indx = syntax_index_table[(s - spec_symbls)];
+	}
+	return S_I_T[indx][syntax];
+}
+
+#else   /* USE_SIT_FUNCTION */
+
+#define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
+
+#ifdef CONFIG_ASH_ALIAS
+#define CSPCL_CIGN_CIGN_CIGN                           0
+#define CSPCL_CWORD_CWORD_CWORD                        1
+#define CNL_CNL_CNL_CNL                                2
+#define CWORD_CCTL_CCTL_CWORD                          3
+#define CDQUOTE_CENDQUOTE_CWORD_CWORD                  4
+#define CVAR_CVAR_CWORD_CVAR                           5
+#define CSQUOTE_CWORD_CENDQUOTE_CWORD                  6
+#define CSPCL_CWORD_CWORD_CLP                          7
+#define CSPCL_CWORD_CWORD_CRP                          8
+#define CBACK_CBACK_CCTL_CBACK                         9
+#define CBQUOTE_CBQUOTE_CWORD_CBQUOTE                 10
+#define CENDVAR_CENDVAR_CWORD_CENDVAR                 11
+#define CENDFILE_CENDFILE_CENDFILE_CENDFILE           12
+#define CWORD_CWORD_CWORD_CWORD                       13
+#define CCTL_CCTL_CCTL_CCTL                           14
+#else
+#define CSPCL_CWORD_CWORD_CWORD                        0
+#define CNL_CNL_CNL_CNL                                1
+#define CWORD_CCTL_CCTL_CWORD                          2
+#define CDQUOTE_CENDQUOTE_CWORD_CWORD                  3
+#define CVAR_CVAR_CWORD_CVAR                           4
+#define CSQUOTE_CWORD_CENDQUOTE_CWORD                  5
+#define CSPCL_CWORD_CWORD_CLP                          6
+#define CSPCL_CWORD_CWORD_CRP                          7
+#define CBACK_CBACK_CCTL_CBACK                         8
+#define CBQUOTE_CBQUOTE_CWORD_CBQUOTE                  9
+#define CENDVAR_CENDVAR_CWORD_CENDVAR                 10
+#define CENDFILE_CENDFILE_CENDFILE_CENDFILE           11
+#define CWORD_CWORD_CWORD_CWORD                       12
+#define CCTL_CCTL_CCTL_CCTL                           13
+#endif
+
+static const char syntax_index_table[258] = {
+	/* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
+	/*   0  PEOF */      CENDFILE_CENDFILE_CENDFILE_CENDFILE,
+#ifdef CONFIG_ASH_ALIAS
+	/*   1  PEOA */      CSPCL_CIGN_CIGN_CIGN,
+#endif
+	/*   2  -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
+	/*   3  -127 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
+	/*   4  -126 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
+	/*   5  -125 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
+	/*   6  -124 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
+	/*   7  -123 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
+	/*   8  -122 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
+	/*   9  -121 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
+	/*  10  -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
+	/*  11  -119      */ CWORD_CWORD_CWORD_CWORD,
+	/*  12  -118      */ CWORD_CWORD_CWORD_CWORD,
+	/*  13  -117      */ CWORD_CWORD_CWORD_CWORD,
+	/*  14  -116      */ CWORD_CWORD_CWORD_CWORD,
+	/*  15  -115      */ CWORD_CWORD_CWORD_CWORD,
+	/*  16  -114      */ CWORD_CWORD_CWORD_CWORD,
+	/*  17  -113      */ CWORD_CWORD_CWORD_CWORD,
+	/*  18  -112      */ CWORD_CWORD_CWORD_CWORD,
+	/*  19  -111      */ CWORD_CWORD_CWORD_CWORD,
+	/*  20  -110      */ CWORD_CWORD_CWORD_CWORD,
+	/*  21  -109      */ CWORD_CWORD_CWORD_CWORD,
+	/*  22  -108      */ CWORD_CWORD_CWORD_CWORD,
+	/*  23  -107      */ CWORD_CWORD_CWORD_CWORD,
+	/*  24  -106      */ CWORD_CWORD_CWORD_CWORD,
+	/*  25  -105      */ CWORD_CWORD_CWORD_CWORD,
+	/*  26  -104      */ CWORD_CWORD_CWORD_CWORD,
+	/*  27  -103      */ CWORD_CWORD_CWORD_CWORD,
+	/*  28  -102      */ CWORD_CWORD_CWORD_CWORD,
+	/*  29  -101      */ CWORD_CWORD_CWORD_CWORD,
+	/*  30  -100      */ CWORD_CWORD_CWORD_CWORD,
+	/*  31   -99      */ CWORD_CWORD_CWORD_CWORD,
+	/*  32   -98      */ CWORD_CWORD_CWORD_CWORD,
+	/*  33   -97      */ CWORD_CWORD_CWORD_CWORD,
+	/*  34   -96      */ CWORD_CWORD_CWORD_CWORD,
+	/*  35   -95      */ CWORD_CWORD_CWORD_CWORD,
+	/*  36   -94      */ CWORD_CWORD_CWORD_CWORD,
+	/*  37   -93      */ CWORD_CWORD_CWORD_CWORD,
+	/*  38   -92      */ CWORD_CWORD_CWORD_CWORD,
+	/*  39   -91      */ CWORD_CWORD_CWORD_CWORD,
+	/*  40   -90      */ CWORD_CWORD_CWORD_CWORD,
+	/*  41   -89      */ CWORD_CWORD_CWORD_CWORD,
+	/*  42   -88      */ CWORD_CWORD_CWORD_CWORD,
+	/*  43   -87      */ CWORD_CWORD_CWORD_CWORD,
+	/*  44   -86      */ CWORD_CWORD_CWORD_CWORD,
+	/*  45   -85      */ CWORD_CWORD_CWORD_CWORD,
+	/*  46   -84      */ CWORD_CWORD_CWORD_CWORD,
+	/*  47   -83      */ CWORD_CWORD_CWORD_CWORD,
+	/*  48   -82      */ CWORD_CWORD_CWORD_CWORD,
+	/*  49   -81      */ CWORD_CWORD_CWORD_CWORD,
+	/*  50   -80      */ CWORD_CWORD_CWORD_CWORD,
+	/*  51   -79      */ CWORD_CWORD_CWORD_CWORD,
+	/*  52   -78      */ CWORD_CWORD_CWORD_CWORD,
+	/*  53   -77      */ CWORD_CWORD_CWORD_CWORD,
+	/*  54   -76      */ CWORD_CWORD_CWORD_CWORD,
+	/*  55   -75      */ CWORD_CWORD_CWORD_CWORD,
+	/*  56   -74      */ CWORD_CWORD_CWORD_CWORD,
+	/*  57   -73      */ CWORD_CWORD_CWORD_CWORD,
+	/*  58   -72      */ CWORD_CWORD_CWORD_CWORD,
+	/*  59   -71      */ CWORD_CWORD_CWORD_CWORD,
+	/*  60   -70      */ CWORD_CWORD_CWORD_CWORD,
+	/*  61   -69      */ CWORD_CWORD_CWORD_CWORD,
+	/*  62   -68      */ CWORD_CWORD_CWORD_CWORD,
+	/*  63   -67      */ CWORD_CWORD_CWORD_CWORD,
+	/*  64   -66      */ CWORD_CWORD_CWORD_CWORD,
+	/*  65   -65      */ CWORD_CWORD_CWORD_CWORD,
+	/*  66   -64      */ CWORD_CWORD_CWORD_CWORD,
+	/*  67   -63      */ CWORD_CWORD_CWORD_CWORD,
+	/*  68   -62      */ CWORD_CWORD_CWORD_CWORD,
+	/*  69   -61      */ CWORD_CWORD_CWORD_CWORD,
+	/*  70   -60      */ CWORD_CWORD_CWORD_CWORD,
+	/*  71   -59      */ CWORD_CWORD_CWORD_CWORD,
+	/*  72   -58      */ CWORD_CWORD_CWORD_CWORD,
+	/*  73   -57      */ CWORD_CWORD_CWORD_CWORD,
+	/*  74   -56      */ CWORD_CWORD_CWORD_CWORD,
+	/*  75   -55      */ CWORD_CWORD_CWORD_CWORD,
+	/*  76   -54      */ CWORD_CWORD_CWORD_CWORD,
+	/*  77   -53      */ CWORD_CWORD_CWORD_CWORD,
+	/*  78   -52      */ CWORD_CWORD_CWORD_CWORD,
+	/*  79   -51      */ CWORD_CWORD_CWORD_CWORD,
+	/*  80   -50      */ CWORD_CWORD_CWORD_CWORD,
+	/*  81   -49      */ CWORD_CWORD_CWORD_CWORD,
+	/*  82   -48      */ CWORD_CWORD_CWORD_CWORD,
+	/*  83   -47      */ CWORD_CWORD_CWORD_CWORD,
+	/*  84   -46      */ CWORD_CWORD_CWORD_CWORD,
+	/*  85   -45      */ CWORD_CWORD_CWORD_CWORD,
+	/*  86   -44      */ CWORD_CWORD_CWORD_CWORD,
+	/*  87   -43      */ CWORD_CWORD_CWORD_CWORD,
+	/*  88   -42      */ CWORD_CWORD_CWORD_CWORD,
+	/*  89   -41      */ CWORD_CWORD_CWORD_CWORD,
+	/*  90   -40      */ CWORD_CWORD_CWORD_CWORD,
+	/*  91   -39      */ CWORD_CWORD_CWORD_CWORD,
+	/*  92   -38      */ CWORD_CWORD_CWORD_CWORD,
+	/*  93   -37      */ CWORD_CWORD_CWORD_CWORD,
+	/*  94   -36      */ CWORD_CWORD_CWORD_CWORD,
+	/*  95   -35      */ CWORD_CWORD_CWORD_CWORD,
+	/*  96   -34      */ CWORD_CWORD_CWORD_CWORD,
+	/*  97   -33      */ CWORD_CWORD_CWORD_CWORD,
+	/*  98   -32      */ CWORD_CWORD_CWORD_CWORD,
+	/*  99   -31      */ CWORD_CWORD_CWORD_CWORD,
+	/* 100   -30      */ CWORD_CWORD_CWORD_CWORD,
+	/* 101   -29      */ CWORD_CWORD_CWORD_CWORD,
+	/* 102   -28      */ CWORD_CWORD_CWORD_CWORD,
+	/* 103   -27      */ CWORD_CWORD_CWORD_CWORD,
+	/* 104   -26      */ CWORD_CWORD_CWORD_CWORD,
+	/* 105   -25      */ CWORD_CWORD_CWORD_CWORD,
+	/* 106   -24      */ CWORD_CWORD_CWORD_CWORD,
+	/* 107   -23      */ CWORD_CWORD_CWORD_CWORD,
+	/* 108   -22      */ CWORD_CWORD_CWORD_CWORD,
+	/* 109   -21      */ CWORD_CWORD_CWORD_CWORD,
+	/* 110   -20      */ CWORD_CWORD_CWORD_CWORD,
+	/* 111   -19      */ CWORD_CWORD_CWORD_CWORD,
+	/* 112   -18      */ CWORD_CWORD_CWORD_CWORD,
+	/* 113   -17      */ CWORD_CWORD_CWORD_CWORD,
+	/* 114   -16      */ CWORD_CWORD_CWORD_CWORD,
+	/* 115   -15      */ CWORD_CWORD_CWORD_CWORD,
+	/* 116   -14      */ CWORD_CWORD_CWORD_CWORD,
+	/* 117   -13      */ CWORD_CWORD_CWORD_CWORD,
+	/* 118   -12      */ CWORD_CWORD_CWORD_CWORD,
+	/* 119   -11      */ CWORD_CWORD_CWORD_CWORD,
+	/* 120   -10      */ CWORD_CWORD_CWORD_CWORD,
+	/* 121    -9      */ CWORD_CWORD_CWORD_CWORD,
+	/* 122    -8      */ CWORD_CWORD_CWORD_CWORD,
+	/* 123    -7      */ CWORD_CWORD_CWORD_CWORD,
+	/* 124    -6      */ CWORD_CWORD_CWORD_CWORD,
+	/* 125    -5      */ CWORD_CWORD_CWORD_CWORD,
+	/* 126    -4      */ CWORD_CWORD_CWORD_CWORD,
+	/* 127    -3      */ CWORD_CWORD_CWORD_CWORD,
+	/* 128    -2      */ CWORD_CWORD_CWORD_CWORD,
+	/* 129    -1      */ CWORD_CWORD_CWORD_CWORD,
+	/* 130     0      */ CWORD_CWORD_CWORD_CWORD,
+	/* 131     1      */ CWORD_CWORD_CWORD_CWORD,
+	/* 132     2      */ CWORD_CWORD_CWORD_CWORD,
+	/* 133     3      */ CWORD_CWORD_CWORD_CWORD,
+	/* 134     4      */ CWORD_CWORD_CWORD_CWORD,
+	/* 135     5      */ CWORD_CWORD_CWORD_CWORD,
+	/* 136     6      */ CWORD_CWORD_CWORD_CWORD,
+	/* 137     7      */ CWORD_CWORD_CWORD_CWORD,
+	/* 138     8      */ CWORD_CWORD_CWORD_CWORD,
+	/* 139     9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
+	/* 140    10 "\n" */ CNL_CNL_CNL_CNL,
+	/* 141    11      */ CWORD_CWORD_CWORD_CWORD,
+	/* 142    12      */ CWORD_CWORD_CWORD_CWORD,
+	/* 143    13      */ CWORD_CWORD_CWORD_CWORD,
+	/* 144    14      */ CWORD_CWORD_CWORD_CWORD,
+	/* 145    15      */ CWORD_CWORD_CWORD_CWORD,
+	/* 146    16      */ CWORD_CWORD_CWORD_CWORD,
+	/* 147    17      */ CWORD_CWORD_CWORD_CWORD,
+	/* 148    18      */ CWORD_CWORD_CWORD_CWORD,
+	/* 149    19      */ CWORD_CWORD_CWORD_CWORD,
+	/* 150    20      */ CWORD_CWORD_CWORD_CWORD,
+	/* 151    21      */ CWORD_CWORD_CWORD_CWORD,
+	/* 152    22      */ CWORD_CWORD_CWORD_CWORD,
+	/* 153    23      */ CWORD_CWORD_CWORD_CWORD,
+	/* 154    24      */ CWORD_CWORD_CWORD_CWORD,
+	/* 155    25      */ CWORD_CWORD_CWORD_CWORD,
+	/* 156    26      */ CWORD_CWORD_CWORD_CWORD,
+	/* 157    27      */ CWORD_CWORD_CWORD_CWORD,
+	/* 158    28      */ CWORD_CWORD_CWORD_CWORD,
+	/* 159    29      */ CWORD_CWORD_CWORD_CWORD,
+	/* 160    30      */ CWORD_CWORD_CWORD_CWORD,
+	/* 161    31      */ CWORD_CWORD_CWORD_CWORD,
+	/* 162    32  " " */ CSPCL_CWORD_CWORD_CWORD,
+	/* 163    33  "!" */ CWORD_CCTL_CCTL_CWORD,
+	/* 164    34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
+	/* 165    35  "#" */ CWORD_CWORD_CWORD_CWORD,
+	/* 166    36  "$" */ CVAR_CVAR_CWORD_CVAR,
+	/* 167    37  "%" */ CWORD_CWORD_CWORD_CWORD,
+	/* 168    38  "&" */ CSPCL_CWORD_CWORD_CWORD,
+	/* 169    39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
+	/* 170    40  "(" */ CSPCL_CWORD_CWORD_CLP,
+	/* 171    41  ")" */ CSPCL_CWORD_CWORD_CRP,
+	/* 172    42  "*" */ CWORD_CCTL_CCTL_CWORD,
+	/* 173    43  "+" */ CWORD_CWORD_CWORD_CWORD,
+	/* 174    44  "," */ CWORD_CWORD_CWORD_CWORD,
+	/* 175    45  "-" */ CWORD_CCTL_CCTL_CWORD,
+	/* 176    46  "." */ CWORD_CWORD_CWORD_CWORD,
+	/* 177    47  "/" */ CWORD_CCTL_CCTL_CWORD,
+	/* 178    48  "0" */ CWORD_CWORD_CWORD_CWORD,
+	/* 179    49  "1" */ CWORD_CWORD_CWORD_CWORD,
+	/* 180    50  "2" */ CWORD_CWORD_CWORD_CWORD,
+	/* 181    51  "3" */ CWORD_CWORD_CWORD_CWORD,
+	/* 182    52  "4" */ CWORD_CWORD_CWORD_CWORD,
+	/* 183    53  "5" */ CWORD_CWORD_CWORD_CWORD,
+	/* 184    54  "6" */ CWORD_CWORD_CWORD_CWORD,
+	/* 185    55  "7" */ CWORD_CWORD_CWORD_CWORD,
+	/* 186    56  "8" */ CWORD_CWORD_CWORD_CWORD,
+	/* 187    57  "9" */ CWORD_CWORD_CWORD_CWORD,
+	/* 188    58  ":" */ CWORD_CCTL_CCTL_CWORD,
+	/* 189    59  ";" */ CSPCL_CWORD_CWORD_CWORD,
+	/* 190    60  "<" */ CSPCL_CWORD_CWORD_CWORD,
+	/* 191    61  "=" */ CWORD_CCTL_CCTL_CWORD,
+	/* 192    62  ">" */ CSPCL_CWORD_CWORD_CWORD,
+	/* 193    63  "?" */ CWORD_CCTL_CCTL_CWORD,
+	/* 194    64  "@" */ CWORD_CWORD_CWORD_CWORD,
+	/* 195    65  "A" */ CWORD_CWORD_CWORD_CWORD,
+	/* 196    66  "B" */ CWORD_CWORD_CWORD_CWORD,
+	/* 197    67  "C" */ CWORD_CWORD_CWORD_CWORD,
+	/* 198    68  "D" */ CWORD_CWORD_CWORD_CWORD,
+	/* 199    69  "E" */ CWORD_CWORD_CWORD_CWORD,
+	/* 200    70  "F" */ CWORD_CWORD_CWORD_CWORD,
+	/* 201    71  "G" */ CWORD_CWORD_CWORD_CWORD,
+	/* 202    72  "H" */ CWORD_CWORD_CWORD_CWORD,
+	/* 203    73  "I" */ CWORD_CWORD_CWORD_CWORD,
+	/* 204    74  "J" */ CWORD_CWORD_CWORD_CWORD,
+	/* 205    75  "K" */ CWORD_CWORD_CWORD_CWORD,
+	/* 206    76  "L" */ CWORD_CWORD_CWORD_CWORD,
+	/* 207    77  "M" */ CWORD_CWORD_CWORD_CWORD,
+	/* 208    78  "N" */ CWORD_CWORD_CWORD_CWORD,
+	/* 209    79  "O" */ CWORD_CWORD_CWORD_CWORD,
+	/* 210    80  "P" */ CWORD_CWORD_CWORD_CWORD,
+	/* 211    81  "Q" */ CWORD_CWORD_CWORD_CWORD,
+	/* 212    82  "R" */ CWORD_CWORD_CWORD_CWORD,
+	/* 213    83  "S" */ CWORD_CWORD_CWORD_CWORD,
+	/* 214    84  "T" */ CWORD_CWORD_CWORD_CWORD,
+	/* 215    85  "U" */ CWORD_CWORD_CWORD_CWORD,
+	/* 216    86  "V" */ CWORD_CWORD_CWORD_CWORD,
+	/* 217    87  "W" */ CWORD_CWORD_CWORD_CWORD,
+	/* 218    88  "X" */ CWORD_CWORD_CWORD_CWORD,
+	/* 219    89  "Y" */ CWORD_CWORD_CWORD_CWORD,
+	/* 220    90  "Z" */ CWORD_CWORD_CWORD_CWORD,
+	/* 221    91  "[" */ CWORD_CCTL_CCTL_CWORD,
+	/* 222    92  "\" */ CBACK_CBACK_CCTL_CBACK,
+	/* 223    93  "]" */ CWORD_CCTL_CCTL_CWORD,
+	/* 224    94  "^" */ CWORD_CWORD_CWORD_CWORD,
+	/* 225    95  "_" */ CWORD_CWORD_CWORD_CWORD,
+	/* 226    96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
+	/* 227    97  "a" */ CWORD_CWORD_CWORD_CWORD,
+	/* 228    98  "b" */ CWORD_CWORD_CWORD_CWORD,
+	/* 229    99  "c" */ CWORD_CWORD_CWORD_CWORD,
+	/* 230   100  "d" */ CWORD_CWORD_CWORD_CWORD,
+	/* 231   101  "e" */ CWORD_CWORD_CWORD_CWORD,
+	/* 232   102  "f" */ CWORD_CWORD_CWORD_CWORD,
+	/* 233   103  "g" */ CWORD_CWORD_CWORD_CWORD,
+	/* 234   104  "h" */ CWORD_CWORD_CWORD_CWORD,
+	/* 235   105  "i" */ CWORD_CWORD_CWORD_CWORD,
+	/* 236   106  "j" */ CWORD_CWORD_CWORD_CWORD,
+	/* 237   107  "k" */ CWORD_CWORD_CWORD_CWORD,
+	/* 238   108  "l" */ CWORD_CWORD_CWORD_CWORD,
+	/* 239   109  "m" */ CWORD_CWORD_CWORD_CWORD,
+	/* 240   110  "n" */ CWORD_CWORD_CWORD_CWORD,
+	/* 241   111  "o" */ CWORD_CWORD_CWORD_CWORD,
+	/* 242   112  "p" */ CWORD_CWORD_CWORD_CWORD,
+	/* 243   113  "q" */ CWORD_CWORD_CWORD_CWORD,
+	/* 244   114  "r" */ CWORD_CWORD_CWORD_CWORD,
+	/* 245   115  "s" */ CWORD_CWORD_CWORD_CWORD,
+	/* 246   116  "t" */ CWORD_CWORD_CWORD_CWORD,
+	/* 247   117  "u" */ CWORD_CWORD_CWORD_CWORD,
+	/* 248   118  "v" */ CWORD_CWORD_CWORD_CWORD,
+	/* 249   119  "w" */ CWORD_CWORD_CWORD_CWORD,
+	/* 250   120  "x" */ CWORD_CWORD_CWORD_CWORD,
+	/* 251   121  "y" */ CWORD_CWORD_CWORD_CWORD,
+	/* 252   122  "z" */ CWORD_CWORD_CWORD_CWORD,
+	/* 253   123  "{" */ CWORD_CWORD_CWORD_CWORD,
+	/* 254   124  "|" */ CSPCL_CWORD_CWORD_CWORD,
+	/* 255   125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
+	/* 256   126  "~" */ CWORD_CCTL_CCTL_CWORD,
+	/* 257   127      */ CWORD_CWORD_CWORD_CWORD,
+};
+
+#endif  /* USE_SIT_FUNCTION */
+
+/*      alias.c      */
+
+
+#define ATABSIZE 39
+
+static int     funcblocksize;          /* size of structures in function */
+static int     funcstringsize;         /* size of strings in node */
+static pointer funcblock;              /* block to allocate function from */
+static char   *funcstring;             /* block to allocate strings from */
+
+static const short nodesize[26] = {
+      SHELL_ALIGN(sizeof (struct ncmd)),
+      SHELL_ALIGN(sizeof (struct npipe)),
+      SHELL_ALIGN(sizeof (struct nredir)),
+      SHELL_ALIGN(sizeof (struct nredir)),
+      SHELL_ALIGN(sizeof (struct nredir)),
+      SHELL_ALIGN(sizeof (struct nbinary)),
+      SHELL_ALIGN(sizeof (struct nbinary)),
+      SHELL_ALIGN(sizeof (struct nbinary)),
+      SHELL_ALIGN(sizeof (struct nif)),
+      SHELL_ALIGN(sizeof (struct nbinary)),
+      SHELL_ALIGN(sizeof (struct nbinary)),
+      SHELL_ALIGN(sizeof (struct nfor)),
+      SHELL_ALIGN(sizeof (struct ncase)),
+      SHELL_ALIGN(sizeof (struct nclist)),
+      SHELL_ALIGN(sizeof (struct narg)),
+      SHELL_ALIGN(sizeof (struct narg)),
+      SHELL_ALIGN(sizeof (struct nfile)),
+      SHELL_ALIGN(sizeof (struct nfile)),
+      SHELL_ALIGN(sizeof (struct nfile)),
+      SHELL_ALIGN(sizeof (struct nfile)),
+      SHELL_ALIGN(sizeof (struct nfile)),
+      SHELL_ALIGN(sizeof (struct ndup)),
+      SHELL_ALIGN(sizeof (struct ndup)),
+      SHELL_ALIGN(sizeof (struct nhere)),
+      SHELL_ALIGN(sizeof (struct nhere)),
+      SHELL_ALIGN(sizeof (struct nnot)),
+};
+
+
+static void calcsize(union node *);
+static void sizenodelist(struct nodelist *);
+static union node *copynode(union node *);
+static struct nodelist *copynodelist(struct nodelist *);
+static char *nodesavestr(char *);
+
+
+static int evalstring(char *, int mask);
+union node;     /* BLETCH for ansi C */
+static void evaltree(union node *, int);
+static void evalbackcmd(union node *, struct backcmd *);
+
+static int evalskip;                   /* set if we are skipping commands */
+static int skipcount;           /* number of levels to skip */
+static int funcnest;                   /* depth of function calls */
+
+/* reasons for skipping commands (see comment on breakcmd routine) */
+#define SKIPBREAK      (1 << 0)
+#define SKIPCONT       (1 << 1)
+#define SKIPFUNC       (1 << 2)
+#define SKIPFILE       (1 << 3)
+#define SKIPEVAL       (1 << 4)
+
+/*
+ * This file was generated by the mkbuiltins program.
+ */
+
+#if JOBS
+static int bgcmd(int, char **);
+#endif
+static int breakcmd(int, char **);
+static int cdcmd(int, char **);
+#ifdef CONFIG_ASH_CMDCMD
+static int commandcmd(int, char **);
+#endif
+static int dotcmd(int, char **);
+static int evalcmd(int, char **);
+#ifdef CONFIG_ASH_BUILTIN_ECHO
+static int echocmd(int, char **);
+#endif
+#ifdef CONFIG_ASH_BUILTIN_TEST
+static int testcmd(int, char **);
+#endif
+static int execcmd(int, char **);
+static int exitcmd(int, char **);
+static int exportcmd(int, char **);
+static int falsecmd(int, char **);
+#if JOBS
+static int fgcmd(int, char **);
+#endif
+#ifdef CONFIG_ASH_GETOPTS
+static int getoptscmd(int, char **);
+#endif
+static int hashcmd(int, char **);
+#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
+static int helpcmd(int argc, char **argv);
+#endif
+#if JOBS
+static int jobscmd(int, char **);
+#endif
+#ifdef CONFIG_ASH_MATH_SUPPORT
+static int letcmd(int, char **);
+#endif
+static int localcmd(int, char **);
+static int pwdcmd(int, char **);
+static int readcmd(int, char **);
+static int returncmd(int, char **);
+static int setcmd(int, char **);
+static int shiftcmd(int, char **);
+static int timescmd(int, char **);
+static int trapcmd(int, char **);
+static int truecmd(int, char **);
+static int typecmd(int, char **);
+static int umaskcmd(int, char **);
+static int unsetcmd(int, char **);
+static int waitcmd(int, char **);
+static int ulimitcmd(int, char **);
+#if JOBS
+static int killcmd(int, char **);
+#endif
+
+/*      mail.h        */
+
+#ifdef CONFIG_ASH_MAIL
+static void chkmail(void);
+static void changemail(const char *);
+#endif
+
+/*      exec.h    */
+
+/* values of cmdtype */
+#define CMDUNKNOWN      -1      /* no entry in table for command */
+#define CMDNORMAL       0       /* command is an executable program */
+#define CMDFUNCTION     1       /* command is a shell function */
+#define CMDBUILTIN      2       /* command is a shell builtin */
+
+struct builtincmd {
+	const char *name;
+	int (*builtin)(int, char **);
+	/* unsigned flags; */
+};
+
+
+#define COMMANDCMD (builtincmd + 5 + \
+	2 * ENABLE_ASH_BUILTIN_TEST + \
+	ENABLE_ASH_ALIAS + \
+	ENABLE_ASH_JOB_CONTROL)
+#define EXECCMD (builtincmd + 7 + \
+	2 * ENABLE_ASH_BUILTIN_TEST + \
+	ENABLE_ASH_ALIAS + \
+	ENABLE_ASH_JOB_CONTROL + \
+	ENABLE_ASH_CMDCMD + \
+	ENABLE_ASH_BUILTIN_ECHO)
+
+#define BUILTIN_NOSPEC  "0"
+#define BUILTIN_SPECIAL "1"
+#define BUILTIN_REGULAR "2"
+#define BUILTIN_SPEC_REG "3"
+#define BUILTIN_ASSIGN  "4"
+#define BUILTIN_SPEC_ASSG  "5"
+#define BUILTIN_REG_ASSG   "6"
+#define BUILTIN_SPEC_REG_ASSG   "7"
+
+#define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
+#define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
+#define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
+
+/* make sure to keep these in proper order since it is searched via bsearch() */
+static const struct builtincmd builtincmd[] = {
+	{ BUILTIN_SPEC_REG      ".", dotcmd },
+	{ BUILTIN_SPEC_REG      ":", truecmd },
+#ifdef CONFIG_ASH_BUILTIN_TEST
+	{ BUILTIN_REGULAR	"[", testcmd },
+	{ BUILTIN_REGULAR	"[[", testcmd },
+#endif
+#ifdef CONFIG_ASH_ALIAS
+	{ BUILTIN_REG_ASSG      "alias", aliascmd },
+#endif
+#if JOBS
+	{ BUILTIN_REGULAR       "bg", bgcmd },
+#endif
+	{ BUILTIN_SPEC_REG      "break", breakcmd },
+	{ BUILTIN_REGULAR       "cd", cdcmd },
+	{ BUILTIN_NOSPEC        "chdir", cdcmd },
+#ifdef CONFIG_ASH_CMDCMD
+	{ BUILTIN_REGULAR       "command", commandcmd },
+#endif
+	{ BUILTIN_SPEC_REG      "continue", breakcmd },
+#ifdef CONFIG_ASH_BUILTIN_ECHO
+	{ BUILTIN_REGULAR       "echo", echocmd },
+#endif
+	{ BUILTIN_SPEC_REG      "eval", evalcmd },
+	{ BUILTIN_SPEC_REG      "exec", execcmd },
+	{ BUILTIN_SPEC_REG      "exit", exitcmd },
+	{ BUILTIN_SPEC_REG_ASSG "export", exportcmd },
+	{ BUILTIN_REGULAR       "false", falsecmd },
+#if JOBS
+	{ BUILTIN_REGULAR       "fg", fgcmd },
+#endif
+#ifdef CONFIG_ASH_GETOPTS
+	{ BUILTIN_REGULAR       "getopts", getoptscmd },
+#endif
+	{ BUILTIN_NOSPEC        "hash", hashcmd },
+#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
+	{ BUILTIN_NOSPEC        "help", helpcmd },
+#endif
+#if JOBS
+	{ BUILTIN_REGULAR       "jobs", jobscmd },
+	{ BUILTIN_REGULAR       "kill", killcmd },
+#endif
+#ifdef CONFIG_ASH_MATH_SUPPORT
+	{ BUILTIN_NOSPEC        "let", letcmd },
+#endif
+	{ BUILTIN_ASSIGN        "local", localcmd },
+	{ BUILTIN_NOSPEC        "pwd", pwdcmd },
+	{ BUILTIN_REGULAR       "read", readcmd },
+	{ BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
+	{ BUILTIN_SPEC_REG      "return", returncmd },
+	{ BUILTIN_SPEC_REG      "set", setcmd },
+	{ BUILTIN_SPEC_REG      "shift", shiftcmd },
+	{ BUILTIN_SPEC_REG      "source", dotcmd },
+#ifdef CONFIG_ASH_BUILTIN_TEST
+	{ BUILTIN_REGULAR	"test", testcmd },
+#endif
+	{ BUILTIN_SPEC_REG      "times", timescmd },
+	{ BUILTIN_SPEC_REG      "trap", trapcmd },
+	{ BUILTIN_REGULAR       "true", truecmd },
+	{ BUILTIN_NOSPEC        "type", typecmd },
+	{ BUILTIN_NOSPEC        "ulimit", ulimitcmd },
+	{ BUILTIN_REGULAR       "umask", umaskcmd },
+#ifdef CONFIG_ASH_ALIAS
+	{ BUILTIN_REGULAR       "unalias", unaliascmd },
+#endif
+	{ BUILTIN_SPEC_REG      "unset", unsetcmd },
+	{ BUILTIN_REGULAR       "wait", waitcmd },
+};
+
+#define NUMBUILTINS  (sizeof (builtincmd) / sizeof (struct builtincmd) )
+
+
+
+struct cmdentry {
+	int cmdtype;
+	union param {
+		int index;
+		const struct builtincmd *cmd;
+		struct funcnode *func;
+	} u;
+};
+
+
+/* action to find_command() */
+#define DO_ERR          0x01    /* prints errors */
+#define DO_ABS          0x02    /* checks absolute paths */
+#define DO_NOFUNC       0x04    /* don't return shell functions, for command */
+#define DO_ALTPATH      0x08    /* using alternate path */
+#define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
+
+static const char *pathopt;     /* set by padvance */
+
+static void shellexec(char **, const char *, int)
+    ATTRIBUTE_NORETURN;
+static char *padvance(const char **, const char *);
+static void find_command(char *, struct cmdentry *, int, const char *);
+static struct builtincmd *find_builtin(const char *);
+static void hashcd(void);
+static void changepath(const char *);
+static void defun(char *, union node *);
+static void unsetfunc(const char *);
+
+#ifdef CONFIG_ASH_MATH_SUPPORT_64
+typedef int64_t arith_t;
+#define arith_t_type (long long)
+#else
+typedef long arith_t;
+#define arith_t_type (long)
+#endif
+
+#ifdef CONFIG_ASH_MATH_SUPPORT
+static arith_t dash_arith(const char *);
+static arith_t arith(const char *expr, int *perrcode);
+#endif
+
+#ifdef CONFIG_ASH_RANDOM_SUPPORT
+static unsigned long rseed;
+static void change_random(const char *);
+# ifndef DYNAMIC_VAR
+#  define DYNAMIC_VAR
+# endif
+#endif
+
+/*      init.h        */
+
+static void reset(void);
+
+/*      var.h     */
+
+/*
+ * Shell variables.
+ */
+
+/* flags */
+#define VEXPORT         0x01    /* variable is exported */
+#define VREADONLY       0x02    /* variable cannot be modified */
+#define VSTRFIXED       0x04    /* variable struct is statically allocated */
+#define VTEXTFIXED      0x08    /* text is statically allocated */
+#define VSTACK          0x10    /* text is allocated on the stack */
+#define VUNSET          0x20    /* the variable is not set */
+#define VNOFUNC         0x40    /* don't call the callback function */
+#define VNOSET          0x80    /* do not set variable - just readonly test */
+#define VNOSAVE         0x100   /* when text is on the heap before setvareq */
+#ifdef DYNAMIC_VAR
+# define VDYNAMIC        0x200   /* dynamic variable */
+# else
+# define VDYNAMIC        0
+#endif
+
+struct var {
+	struct var *next;               /* next entry in hash list */
+	int flags;                      /* flags are defined above */
+	const char *text;               /* name=value */
+	void (*func)(const char *);     /* function to be called when  */
+					/* the variable gets set/unset */
+};
+
+struct localvar {
+	struct localvar *next;          /* next local variable in list */
+	struct var *vp;                 /* the variable that was made local */
+	int flags;                      /* saved flags */
+	const char *text;               /* saved text */
+};
+
+
+static struct localvar *localvars;
+
+/*
+ * Shell variables.
+ */
+
+#ifdef CONFIG_ASH_GETOPTS
+static void getoptsreset(const char *);
+#endif
+
+#ifdef CONFIG_LOCALE_SUPPORT
+#include <locale.h>
+static void change_lc_all(const char *value);
+static void change_lc_ctype(const char *value);
+#endif
+
+
+#define VTABSIZE 39
+
+static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
+#ifdef IFS_BROKEN
+static const char defifsvar[] = "IFS= \t\n";
+#define defifs (defifsvar + 4)
+#else
+static const char defifs[] = " \t\n";
+#endif
+
+
+static struct var varinit[] = {
+#ifdef IFS_BROKEN
+	{ 0,    VSTRFIXED|VTEXTFIXED,           defifsvar,      0 },
+#else
+	{ 0,    VSTRFIXED|VTEXTFIXED|VUNSET,    "IFS\0",        0 },
+#endif
+
+#ifdef CONFIG_ASH_MAIL
+	{ 0,    VSTRFIXED|VTEXTFIXED|VUNSET,    "MAIL\0",       changemail },
+	{ 0,    VSTRFIXED|VTEXTFIXED|VUNSET,    "MAILPATH\0",   changemail },
+#endif
+
+	{ 0,    VSTRFIXED|VTEXTFIXED,           defpathvar,     changepath },
+	{ 0,    VSTRFIXED|VTEXTFIXED,           "PS1=$ ",       0          },
+	{ 0,    VSTRFIXED|VTEXTFIXED,           "PS2=> ",       0          },
+	{ 0,    VSTRFIXED|VTEXTFIXED,           "PS4=+ ",       0          },
+#ifdef CONFIG_ASH_GETOPTS
+	{ 0,    VSTRFIXED|VTEXTFIXED,           "OPTIND=1",     getoptsreset },
+#endif
+#ifdef CONFIG_ASH_RANDOM_SUPPORT
+	{0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
+#endif
+#ifdef CONFIG_LOCALE_SUPPORT
+	{0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
+	{0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
+#endif
+#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
+	{0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
+#endif
+};
+
+#define vifs varinit[0]
+#ifdef CONFIG_ASH_MAIL
+#define vmail (&vifs)[1]
+#define vmpath (&vmail)[1]
+#else
+#define vmpath vifs
+#endif
+#define vpath (&vmpath)[1]
+#define vps1 (&vpath)[1]
+#define vps2 (&vps1)[1]
+#define vps4 (&vps2)[1]
+#define voptind (&vps4)[1]
+#ifdef CONFIG_ASH_GETOPTS
+#define vrandom (&voptind)[1]
+#else
+#define vrandom (&vps4)[1]
+#endif
+#define defpath (defpathvar + 5)
+
+/*
+ * The following macros access the values of the above variables.
+ * They have to skip over the name.  They return the null string
+ * for unset variables.
+ */
+
+#define ifsval()        (vifs.text + 4)
+#define ifsset()        ((vifs.flags & VUNSET) == 0)
+#define mailval()       (vmail.text + 5)
+#define mpathval()      (vmpath.text + 9)
+#define pathval()       (vpath.text + 5)
+#define ps1val()        (vps1.text + 4)
+#define ps2val()        (vps2.text + 4)
+#define ps4val()        (vps4.text + 4)
+#define optindval()     (voptind.text + 7)
+
+#define mpathset()      ((vmpath.flags & VUNSET) == 0)
+
+static void setvar(const char *, const char *, int);
+static void setvareq(char *, int);
+static void listsetvar(struct strlist *, int);
+static char *lookupvar(const char *);
+static char *bltinlookup(const char *);
+static char **listvars(int, int, char ***);
+#define environment() listvars(VEXPORT, VUNSET, 0)
+static int showvars(const char *, int, int);
+static void poplocalvars(void);
+static int unsetvar(const char *);
+#ifdef CONFIG_ASH_GETOPTS
+static int setvarsafe(const char *, const char *, int);
+#endif
+static int varcmp(const char *, const char *);
+static struct var **hashvar(const char *);
+
+
+static inline int varequal(const char *a, const char *b) {
+	return !varcmp(a, b);
+}
+
+
+static int loopnest;            /* current loop nesting level */
+
+/*
+ * The parsefile structure pointed to by the global variable parsefile
+ * contains information about the current file being read.
+ */
+
+
+struct redirtab {
+	struct redirtab *next;
+	int renamed[10];
+	int nullredirs;
+};
+
+static struct redirtab *redirlist;
+static int nullredirs;
+
+extern char **environ;
+
+/*      output.h     */
+
+
+static void outstr(const char *, FILE *);
+static void outcslow(int, FILE *);
+static void flushall(void);
+static void flusherr(void);
+static int  out1fmt(const char *, ...)
+    __attribute__((__format__(__printf__,1,2)));
+static int fmtstr(char *, size_t, const char *, ...)
+    __attribute__((__format__(__printf__,3,4)));
+
+static int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
+
+
+static void out1str(const char *p)
+{
+	outstr(p, stdout);
+}
+
+static void out2str(const char *p)
+{
+	outstr(p, stderr);
+	flusherr();
+}
+
+/*
+ * Initialization code.
+ */
+
+/*
+ * This routine initializes the builtin variables.
+ */
+
+static inline void
+initvar(void)
+{
+	struct var *vp;
+	struct var *end;
+	struct var **vpp;
+
+	/*
+	 * PS1 depends on uid
+	 */
+#if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
+	vps1.text = "PS1=\\w \\$ ";
+#else
+	if (!geteuid())
+		vps1.text = "PS1=# ";
+#endif
+	vp = varinit;
+	end = vp + sizeof(varinit) / sizeof(varinit[0]);
+	do {
+		vpp = hashvar(vp->text);
+		vp->next = *vpp;
+		*vpp = vp;
+	} while (++vp < end);
+}
+
+static inline void
+init(void)
+{
+
+      /* from input.c: */
+      {
+	      basepf.nextc = basepf.buf = basebuf;
+      }
+
+      /* from trap.c: */
+      {
+	      signal(SIGCHLD, SIG_DFL);
+      }
+
+      /* from var.c: */
+      {
+	      char **envp;
+	      char ppid[32];
+	      const char *p;
+	      struct stat st1, st2;
+
+	      initvar();
+	      for (envp = environ ; envp && *envp ; envp++) {
+		      if (strchr(*envp, '=')) {
+			      setvareq(*envp, VEXPORT|VTEXTFIXED);
+		      }
+	      }
+
+	      snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
+	      setvar("PPID", ppid, 0);
+
+	      p = lookupvar("PWD");
+	      if (p)
+	      if (*p != '/' || stat(p, &st1) || stat(".", &st2) ||
+		  st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
+		      p = 0;
+	      setpwd(p, 0);
+      }
+}
+
+/* PEOF (the end of file marker) */
+
+enum {
+	INPUT_PUSH_FILE = 1,
+	INPUT_NOFILE_OK = 2,
+};
+
+/*
+ * The input line number.  Input.c just defines this variable, and saves
+ * and restores it when files are pushed and popped.  The user of this
+ * package must set its value.
+ */
+
+static int pgetc(void);
+static int pgetc2(void);
+static int preadbuffer(void);
+static void pungetc(void);
+static void pushstring(char *, void *);
+static void popstring(void);
+static void setinputfd(int, int);
+static void setinputstring(char *);
+static void popfile(void);
+static void popallfiles(void);
+static void closescript(void);
+
+
+/*      jobs.h    */
+
+
+/* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
+#define FORK_FG 0
+#define FORK_BG 1
+#define FORK_NOJOB 2
+
+/* mode flags for showjob(s) */
+#define SHOW_PGID       0x01    /* only show pgid - for jobs -p */
+#define SHOW_PID        0x04    /* include process pid */
+#define SHOW_CHANGED    0x08    /* only jobs whose state has changed */
+
+
+/*
+ * A job structure contains information about a job.  A job is either a
+ * single process or a set of processes contained in a pipeline.  In the
+ * latter case, pidlist will be non-NULL, and will point to a -1 terminated
+ * array of pids.
+ */
+
+struct procstat {
+	pid_t   pid;            /* process id */
+	int     status;         /* last process status from wait() */
+	char    *cmd;           /* text of command being run */
+};
+
+struct job {
+	struct procstat ps0;    /* status of process */
+	struct procstat *ps;    /* status or processes when more than one */
+#if JOBS
+	int stopstatus;         /* status of a stopped job */
+#endif
+	uint32_t
+		nprocs: 16,     /* number of processes */
+		state: 8,
+#define JOBRUNNING      0       /* at least one proc running */
+#define JOBSTOPPED      1       /* all procs are stopped */
+#define JOBDONE         2       /* all procs are completed */
+#if JOBS
+		sigint: 1,      /* job was killed by SIGINT */
+		jobctl: 1,      /* job running under job control */
+#endif
+		waited: 1,      /* true if this entry has been waited for */
+		used: 1,        /* true if this entry is in used */
+		changed: 1;     /* true if status has changed */
+	struct job *prev_job;   /* previous job */
+};
+
+static pid_t backgndpid;        /* pid of last background process */
+static int job_warning;         /* user was warned about stopped jobs */
+#if JOBS
+static int jobctl;              /* true if doing job control */
+#endif
+
+static struct job *makejob(union node *, int);
+static int forkshell(struct job *, union node *, int);
+static int waitforjob(struct job *);
+static int stoppedjobs(void);
+
+#if ! JOBS
+#define setjobctl(on)   /* do nothing */
+#else
+static void setjobctl(int);
+static void showjobs(FILE *, int);
+#endif
+
+/*      main.h        */
+
+
+/* pid of main shell */
+static int rootpid;
+/* shell level: 0 for the main shell, 1 for its children, and so on */
+static int shlvl;
+#define rootshell (!shlvl)
+
+static void readcmdfile(char *);
+static int cmdloop(int);
+
+/*      memalloc.h        */
+
+
+struct stackmark {
+	struct stack_block *stackp;
+	char *stacknxt;
+	size_t stacknleft;
+	struct stackmark *marknext;
+};
+
+/* minimum size of a block */
+#define MINSIZE SHELL_ALIGN(504)
+
+struct stack_block {
+	struct stack_block *prev;
+	char space[MINSIZE];
+};
+
+static struct stack_block stackbase;
+static struct stack_block *stackp = &stackbase;
+static struct stackmark *markp;
+static char *stacknxt = stackbase.space;
+static size_t stacknleft = MINSIZE;
+static char *sstrend = stackbase.space + MINSIZE;
+static int herefd = -1;
+
+
+static pointer ckmalloc(size_t);
+static pointer ckrealloc(pointer, size_t);
+static char *savestr(const char *);
+static pointer stalloc(size_t);
+static void stunalloc(pointer);
+static void setstackmark(struct stackmark *);
+static void popstackmark(struct stackmark *);
+static void growstackblock(void);
+static void *growstackstr(void);
+static char *makestrspace(size_t, char *);
+static char *stnputs(const char *, size_t, char *);
+static char *stputs(const char *, char *);
+
+
+static inline char *_STPUTC(int c, char *p) {
+	if (p == sstrend)
+		p = growstackstr();
+	*p++ = c;
+	return p;
+}
+
+#define stackblock() ((void *)stacknxt)
+#define stackblocksize() stacknleft
+#define STARTSTACKSTR(p) ((p) = stackblock())
+#define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
+#define CHECKSTRSPACE(n, p) \
+	({ \
+		char *q = (p); \
+		size_t l = (n); \
+		size_t m = sstrend - q; \
+		if (l > m) \
+			(p) = makestrspace(l, q); \
+		0; \
+	})
+#define USTPUTC(c, p)   (*p++ = (c))
+#define STACKSTRNUL(p)  ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
+#define STUNPUTC(p)     (--p)
+#define STTOPC(p)       p[-1]
+#define STADJUST(amount, p)     (p += (amount))
+
+#define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
+#define ungrabstackstr(s, p) stunalloc((s))
+#define stackstrend() ((void *)sstrend)
+
+#define ckfree(p)       free((pointer)(p))
+
+/*      mystring.h   */
+
+
+#define DOLATSTRLEN 4
+
+static char *prefix(const char *, const char *);
+static int number(const char *);
+static int is_number(const char *);
+static char *single_quote(const char *);
+static char *sstrdup(const char *);
+
+#define equal(s1, s2)   (strcmp(s1, s2) == 0)
+#define scopy(s1, s2)   ((void)strcpy(s2, s1))
+
+/*      options.h */
+
+struct shparam {
+	int nparam;             /* # of positional parameters (without $0) */
+	unsigned char malloc;   /* if parameter list dynamically allocated */
+	char **p;               /* parameter list */
+#ifdef CONFIG_ASH_GETOPTS
+	int optind;             /* next parameter to be processed by getopts */
+	int optoff;             /* used by getopts */
+#endif
+};
+
+
+#define eflag optlist[0]
+#define fflag optlist[1]
+#define Iflag optlist[2]
+#define iflag optlist[3]
+#define mflag optlist[4]
+#define nflag optlist[5]
+#define sflag optlist[6]
+#define xflag optlist[7]
+#define vflag optlist[8]
+#define Cflag optlist[9]
+#define aflag optlist[10]
+#define bflag optlist[11]
+#define uflag optlist[12]
+#define viflag optlist[13]
+
+#ifdef DEBUG
+#define nolog optlist[14]
+#define debug optlist[15]
+#endif
+
+#ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
+#define setvimode(on) viflag = 0   /* forcibly keep the option off */
+#endif
+
+/*      options.c */
+
+
+static const char *const optletters_optnames[] = {
+	"e"   "errexit",
+	"f"   "noglob",
+	"I"   "ignoreeof",
+	"i"   "interactive",
+	"m"   "monitor",
+	"n"   "noexec",
+	"s"   "stdin",
+	"x"   "xtrace",
+	"v"   "verbose",
+	"C"   "noclobber",
+	"a"   "allexport",
+	"b"   "notify",
+	"u"   "nounset",
+	"\0"  "vi",
+#ifdef DEBUG
+	"\0"  "nolog",
+	"\0"  "debug",
+#endif
+};
+
+#define optletters(n) optletters_optnames[(n)][0]
+#define optnames(n) (&optletters_optnames[(n)][1])
+
+#define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
+
+static char optlist[NOPTS];
+
+
+static char *arg0;                     /* value of $0 */
+static struct shparam shellparam;      /* $@ current positional parameters */
+static char **argptr;                  /* argument list for builtin commands */
+static char *optionarg;                /* set by nextopt (like getopt) */
+static char *optptr;                   /* used by nextopt */
+
+static char *minusc;                   /* argument to -c option */
+
+
+static void procargs(int, char **);
+static void optschanged(void);
+static void setparam(char **);
+static void freeparam(volatile struct shparam *);
+static int shiftcmd(int, char **);
+static int setcmd(int, char **);
+static int nextopt(const char *);
+
+/*      redir.h      */
+
+/* flags passed to redirect */
+#define REDIR_PUSH 01           /* save previous values of file descriptors */
+#define REDIR_SAVEFD2 03       /* set preverrout */
+
+union node;
+static void redirect(union node *, int);
+static void popredir(int);
+static void clearredir(int);
+static int copyfd(int, int);
+static int redirectsafe(union node *, int);
+
+/*      show.h     */
+
+
+#ifdef DEBUG
+static void showtree(union node *);
+static void trace(const char *, ...);
+static void tracev(const char *, va_list);
+static void trargs(char **);
+static void trputc(int);
+static void trputs(const char *);
+static void opentrace(void);
+#endif
+
+/*      trap.h       */
+
+
+/* trap handler commands */
+static char *trap[NSIG];
+/* current value of signal */
+static char sigmode[NSIG - 1];
+/* indicates specified signal received */
+static char gotsig[NSIG - 1];
+
+static void clear_traps(void);
+static void setsignal(int);
+static void ignoresig(int);
+static void onsig(int);
+static int dotrap(void);
+static void setinteractive(int);
+static void exitshell(void) ATTRIBUTE_NORETURN;
+static int decode_signal(const char *, int);
+
+/*
+ * This routine is called when an error or an interrupt occurs in an
+ * interactive shell and control is returned to the main command loop.
+ */
+
+static void
+reset(void)
+{
+      /* from eval.c: */
+      {
+	      evalskip = 0;
+	      loopnest = 0;
+      }
+
+      /* from input.c: */
+      {
+	      parselleft = parsenleft = 0;      /* clear input buffer */
+	      popallfiles();
+      }
+
+      /* from parser.c: */
+      {
+	      tokpushback = 0;
+	      checkkwd = 0;
+      }
+
+      /* from redir.c: */
+      {
+	      clearredir(0);
+      }
+
+}
+
+#ifdef CONFIG_ASH_ALIAS
+static struct alias *atab[ATABSIZE];
+
+static void setalias(const char *, const char *);
+static struct alias *freealias(struct alias *);
+static struct alias **__lookupalias(const char *);
+
+static void
+setalias(const char *name, const char *val)
+{
+	struct alias *ap, **app;
+
+	app = __lookupalias(name);
+	ap = *app;
+	INTOFF;
+	if (ap) {
+		if (!(ap->flag & ALIASINUSE)) {
+			ckfree(ap->val);
+		}
+		ap->val = savestr(val);
+		ap->flag &= ~ALIASDEAD;
+	} else {
+		/* not found */
+		ap = ckmalloc(sizeof (struct alias));
+		ap->name = savestr(name);
+		ap->val = savestr(val);
+		ap->flag = 0;
+		ap->next = 0;
+		*app = ap;
+	}
+	INTON;
+}
+
+static int
+unalias(const char *name)
+{
+	struct alias **app;
+
+	app = __lookupalias(name);
+
+	if (*app) {
+		INTOFF;
+		*app = freealias(*app);
+		INTON;
+		return (0);
+	}
+
+	return (1);
+}
+
+static void
+rmaliases(void)
+{
+	struct alias *ap, **app;
+	int i;
+
+	INTOFF;
+	for (i = 0; i < ATABSIZE; i++) {
+		app = &atab[i];
+		for (ap = *app; ap; ap = *app) {
+			*app = freealias(*app);
+			if (ap == *app) {
+				app = &ap->next;
+			}
+		}
+	}
+	INTON;
+}
+
+static struct alias *
+lookupalias(const char *name, int check)
+{
+	struct alias *ap = *__lookupalias(name);
+
+	if (check && ap && (ap->flag & ALIASINUSE))
+		return (NULL);
+	return (ap);
+}
+
+/*
+ * TODO - sort output
+ */
+static int
+aliascmd(int argc, char **argv)
+{
+	char *n, *v;
+	int ret = 0;
+	struct alias *ap;
+
+	if (argc == 1) {
+		int i;
+
+		for (i = 0; i < ATABSIZE; i++)
+			for (ap = atab[i]; ap; ap = ap->next) {
+				printalias(ap);
+			}
+		return (0);
+	}
+	while ((n = *++argv) != NULL) {
+		if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
+			if ((ap = *__lookupalias(n)) == NULL) {
+				fprintf(stderr, "%s: %s not found\n", "alias", n);
+				ret = 1;
+			} else
+				printalias(ap);
+		} else {
+			*v++ = '\0';
+			setalias(n, v);
+		}
+	}
+
+	return (ret);
+}
+
+static int
+unaliascmd(int argc, char **argv)
+{
+	int i;
+
+	while ((i = nextopt("a")) != '\0') {
+		if (i == 'a') {
+			rmaliases();
+			return (0);
+		}
+	}
+	for (i = 0; *argptr; argptr++) {
+		if (unalias(*argptr)) {
+			fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
+			i = 1;
+		}
+	}
+
+	return (i);
+}
+
+static struct alias *
+freealias(struct alias *ap) {
+	struct alias *next;
+
+	if (ap->flag & ALIASINUSE) {
+		ap->flag |= ALIASDEAD;
+		return ap;
+	}
+
+	next = ap->next;
+	ckfree(ap->name);
+	ckfree(ap->val);
+	ckfree(ap);
+	return next;
+}
+
+static void
+printalias(const struct alias *ap) {
+	out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
+}
+
+static struct alias **
+__lookupalias(const char *name) {
+	unsigned int hashval;
+	struct alias **app;
+	const char *p;
+	unsigned int ch;
+
+	p = name;
+
+	ch = (unsigned char)*p;
+	hashval = ch << 4;
+	while (ch) {
+		hashval += ch;
+		ch = (unsigned char)*++p;
+	}
+	app = &atab[hashval % ATABSIZE];
+
+	for (; *app; app = &(*app)->next) {
+		if (equal(name, (*app)->name)) {
+			break;
+		}
+	}
+
+	return app;
+}
+#endif /* CONFIG_ASH_ALIAS */
+
+
+/*      cd.c      */
+
+/*
+ * The cd and pwd commands.
+ */
+
+#define CD_PHYSICAL 1
+#define CD_PRINT 2
+
+static int docd(const char *, int);
+static int cdopt(void);
+
+static char *curdir = nullstr;          /* current working directory */
+static char *physdir = nullstr;         /* physical working directory */
+
+static int
+cdopt(void)
+{
+	int flags = 0;
+	int i, j;
+
+	j = 'L';
+	while ((i = nextopt("LP"))) {
+		if (i != j) {
+			flags ^= CD_PHYSICAL;
+			j = i;
+		}
+	}
+
+	return flags;
+}
+
+static int
+cdcmd(int argc, char **argv)
+{
+	const char *dest;
+	const char *path;
+	const char *p;
+	char c;
+	struct stat statb;
+	int flags;
+
+	flags = cdopt();
+	dest = *argptr;
+	if (!dest)
+		dest = bltinlookup(homestr);
+	else if (dest[0] == '-' && dest[1] == '\0') {
+		dest = bltinlookup("OLDPWD");
+		flags |= CD_PRINT;
+	}
+	if (!dest)
+		dest = nullstr;
+	if (*dest == '/')
+		goto step7;
+	if (*dest == '.') {
+		c = dest[1];
+dotdot:
+		switch (c) {
+		case '\0':
+		case '/':
+			goto step6;
+		case '.':
+			c = dest[2];
+			if (c != '.')
+				goto dotdot;
+		}
+	}
+	if (!*dest)
+		dest = ".";
+	if (!(path = bltinlookup("CDPATH"))) {
+step6:
+step7:
+		p = dest;
+		goto docd;
+	}
+	do {
+		c = *path;
+		p = padvance(&path, dest);
+		if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
+			if (c && c != ':')
+				flags |= CD_PRINT;
+docd:
+			if (!docd(p, flags))
+				goto out;
+			break;
+		}
+	} while (path);
+	sh_error("can't cd to %s", dest);
+	/* NOTREACHED */
+out:
+	if (flags & CD_PRINT)
+		out1fmt(snlfmt, curdir);
+	return 0;
+}
+
+
+/*
+ * Update curdir (the name of the current directory) in response to a
+ * cd command.
+ */
+
+static inline const char *
+updatepwd(const char *dir)
+{
+	char *new;
+	char *p;
+	char *cdcomppath;
+	const char *lim;
+
+	cdcomppath = sstrdup(dir);
+	STARTSTACKSTR(new);
+	if (*dir != '/') {
+		if (curdir == nullstr)
+			return 0;
+		new = stputs(curdir, new);
+	}
+	new = makestrspace(strlen(dir) + 2, new);
+	lim = stackblock() + 1;
+	if (*dir != '/') {
+		if (new[-1] != '/')
+			USTPUTC('/', new);
+		if (new > lim && *lim == '/')
+			lim++;
+	} else {
+		USTPUTC('/', new);
+		cdcomppath++;
+		if (dir[1] == '/' && dir[2] != '/') {
+			USTPUTC('/', new);
+			cdcomppath++;
+			lim++;
+		}
+	}
+	p = strtok(cdcomppath, "/");
+	while (p) {
+		switch(*p) {
+		case '.':
+			if (p[1] == '.' && p[2] == '\0') {
+				while (new > lim) {
+					STUNPUTC(new);
+					if (new[-1] == '/')
+						break;
+				}
+				break;
+			} else if (p[1] == '\0')
+				break;
+			/* fall through */
+		default:
+			new = stputs(p, new);
+			USTPUTC('/', new);
+		}
+		p = strtok(0, "/");
+	}
+	if (new > lim)
+		STUNPUTC(new);
+	*new = 0;
+	return stackblock();
+}
+
+/*
+ * Actually do the chdir.  We also call hashcd to let the routines in exec.c
+ * know that the current directory has changed.
+ */
+
+static int
+docd(const char *dest, int flags)
+{
+	const char *dir = 0;
+	int err;
+
+	TRACE(("docd(\"%s\", %d) called\n", dest, flags));
+
+	INTOFF;
+	if (!(flags & CD_PHYSICAL)) {
+		dir = updatepwd(dest);
+		if (dir)
+			dest = dir;
+	}
+	err = chdir(dest);
+	if (err)
+		goto out;
+	setpwd(dir, 1);
+	hashcd();
+out:
+	INTON;
+	return err;
+}
+
+/*
+ * Find out what the current directory is. If we already know the current
+ * directory, this routine returns immediately.
+ */
+static inline char *
+getpwd(void)
+{
+	char *dir = getcwd(0, 0);
+	return dir ? dir : nullstr;
+}
+
+static int
+pwdcmd(int argc, char **argv)
+{
+	int flags;
+	const char *dir = curdir;
+
+	flags = cdopt();
+	if (flags) {
+		if (physdir == nullstr)
+			setpwd(dir, 0);
+		dir = physdir;
+	}
+	out1fmt(snlfmt, dir);
+	return 0;
+}
+
+static void
+setpwd(const char *val, int setold)
+{
+	char *oldcur, *dir;
+
+	oldcur = dir = curdir;
+
+	if (setold) {
+		setvar("OLDPWD", oldcur, VEXPORT);
+	}
+	INTOFF;
+	if (physdir != nullstr) {
+		if (physdir != oldcur)
+			free(physdir);
+		physdir = nullstr;
+	}
+	if (oldcur == val || !val) {
+		char *s = getpwd();
+		physdir = s;
+		if (!val)
+			dir = s;
+	} else
+		dir = savestr(val);
+	if (oldcur != dir && oldcur != nullstr) {
+		free(oldcur);
+	}
+	curdir = dir;
+	INTON;
+	setvar("PWD", dir, VEXPORT);
+}
+
+/*      error.c   */
+
+/*
+ * Errors and exceptions.
+ */
+
+/*
+ * Code to handle exceptions in C.
+ */
+
+
+
+static void exverror(int, const char *, va_list)
+    ATTRIBUTE_NORETURN;
+
+/*
+ * Called to raise an exception.  Since C doesn't include exceptions, we
+ * just do a longjmp to the exception handler.  The type of exception is
+ * stored in the global variable "exception".
+ */
+
+static void
+exraise(int e)
+{
+#ifdef DEBUG
+	if (handler == NULL)
+		abort();
+#endif
+	INTOFF;
+
+	exception = e;
+	longjmp(handler->loc, 1);
+}
+
+
+/*
+ * Called from trap.c when a SIGINT is received.  (If the user specifies
+ * that SIGINT is to be trapped or ignored using the trap builtin, then
+ * this routine is not called.)  Suppressint is nonzero when interrupts
+ * are held using the INTOFF macro.  (The test for iflag is just
+ * defensive programming.)
+ */
+
+static void
+onint(void) {
+	int i;
+
+	intpending = 0;
+#if 0
+	/* comment by vodz: its strange for me, this programm don`t use other
+	   signal block */
+	sigsetmask(0);
+#endif
+	i = EXSIG;
+	if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
+		if (!(rootshell && iflag)) {
+			signal(SIGINT, SIG_DFL);
+			raise(SIGINT);
+		}
+		i = EXINT;
+	}
+	exraise(i);
+	/* NOTREACHED */
+}
+
+static void
+exvwarning(const char *msg, va_list ap)
+{
+	 FILE *errs;
+
+	 errs = stderr;
+	 fprintf(errs, "%s: ", arg0);
+	 if (commandname) {
+		 const char *fmt = (!iflag || parsefile->fd) ?
+					"%s: %d: " : "%s: ";
+		 fprintf(errs, fmt, commandname, startlinno);
+	 }
+	 vfprintf(errs, msg, ap);
+	 outcslow('\n', errs);
+}
+
+/*
+ * Exverror is called to raise the error exception.  If the second argument
+ * is not NULL then error prints an error message using printf style
+ * formatting.  It then raises the error exception.
+ */
+static void
+exverror(int cond, const char *msg, va_list ap)
+{
+#ifdef DEBUG
+	if (msg) {
+		TRACE(("exverror(%d, \"", cond));
+		TRACEV((msg, ap));
+		TRACE(("\") pid=%d\n", getpid()));
+	} else
+		TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
+	if (msg)
+#endif
+		exvwarning(msg, ap);
+
+	flushall();
+	exraise(cond);
+	/* NOTREACHED */
+}
+
+
+static void
+sh_error(const char *msg, ...)
+{
+	va_list ap;
+
+	va_start(ap, msg);
+	exverror(EXERROR, msg, ap);
+	/* NOTREACHED */
+	va_end(ap);
+}
+
+
+static void
+exerror(int cond, const char *msg, ...)
+{
+	va_list ap;
+
+	va_start(ap, msg);
+	exverror(cond, msg, ap);
+	/* NOTREACHED */
+	va_end(ap);
+}
+
+/*
+ * error/warning routines for external builtins
+ */
+
+static void
+sh_warnx(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	exvwarning(fmt, ap);
+	va_end(ap);
+}
+
+
+/*
+ * Return a string describing an error.  The returned string may be a
+ * pointer to a static buffer that will be overwritten on the next call.
+ * Action describes the operation that got the error.
+ */
+
+static const char *
+errmsg(int e, const char *em)
+{
+	if(e == ENOENT || e == ENOTDIR) {
+
+		return em;
+	}
+	return strerror(e);
+}
+
+
+/*      eval.c  */
+
+/*
+ * Evaluate a command.
+ */
+
+/* flags in argument to evaltree */
+#define EV_EXIT 01              /* exit after evaluating tree */
+#define EV_TESTED 02            /* exit status is checked; ignore -e flag */
+#define EV_BACKCMD 04           /* command executing within back quotes */
+
+
+static void evalloop(union node *, int);
+static void evalfor(union node *, int);
+static void evalcase(union node *, int);
+static void evalsubshell(union node *, int);
+static void expredir(union node *);
+static void evalpipe(union node *, int);
+static void evalcommand(union node *, int);
+static int evalbltin(const struct builtincmd *, int, char **);
+static int evalfun(struct funcnode *, int, char **, int);
+static void prehash(union node *);
+static int bltincmd(int, char **);
+
+
+static const struct builtincmd bltin = {
+	"\0\0", bltincmd
+};
+
+
+/*
+ * Called to reset things after an exception.
+ */
+
+/*
+ * The eval command.
+ */
+
+static int
+evalcmd(int argc, char **argv)
+{
+	char *p;
+	char *concat;
+	char **ap;
+
+	if (argc > 1) {
+		p = argv[1];
+		if (argc > 2) {
+			STARTSTACKSTR(concat);
+			ap = argv + 2;
+			for (;;) {
+				concat = stputs(p, concat);
+				if ((p = *ap++) == NULL)
+					break;
+				STPUTC(' ', concat);
+			}
+			STPUTC('\0', concat);
+			p = grabstackstr(concat);
+		}
+		evalstring(p, ~SKIPEVAL);
+
+	}
+	return exitstatus;
+}
+
+
+/*
+ * Execute a command or commands contained in a string.
+ */
+
+static int
+evalstring(char *s, int mask)
+{
+	union node *n;
+	struct stackmark smark;
+	int skip;
+
+	setinputstring(s);
+	setstackmark(&smark);
+
+	skip = 0;
+	while ((n = parsecmd(0)) != NEOF) {
+		evaltree(n, 0);
+		popstackmark(&smark);
+		skip = evalskip;
+		if (skip)
+			break;
+	}
+	popfile();
+
+	skip &= mask;
+	evalskip = skip;
+	return skip;
+}
+
+
+
+/*
+ * Evaluate a parse tree.  The value is left in the global variable
+ * exitstatus.
+ */
+
+static void
+evaltree(union node *n, int flags)
+{
+	int checkexit = 0;
+	void (*evalfn)(union node *, int);
+	unsigned isor;
+	int status;
+	if (n == NULL) {
+		TRACE(("evaltree(NULL) called\n"));
+		goto out;
+	}
+	TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
+	    getpid(), n, n->type, flags));
+	switch (n->type) {
+	default:
+#ifdef DEBUG
+		out1fmt("Node type = %d\n", n->type);
+		fflush(stdout);
+		break;
+#endif
+	case NNOT:
+		evaltree(n->nnot.com, EV_TESTED);
+		status = !exitstatus;
+		goto setstatus;
+	case NREDIR:
+		expredir(n->nredir.redirect);
+		status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
+		if (!status) {
+			evaltree(n->nredir.n, flags & EV_TESTED);
+			status = exitstatus;
+		}
+		popredir(0);
+		goto setstatus;
+	case NCMD:
+		evalfn = evalcommand;
+checkexit:
+		if (eflag && !(flags & EV_TESTED))
+			checkexit = ~0;
+		goto calleval;
+	case NFOR:
+		evalfn = evalfor;
+		goto calleval;
+	case NWHILE:
+	case NUNTIL:
+		evalfn = evalloop;
+		goto calleval;
+	case NSUBSHELL:
+	case NBACKGND:
+		evalfn = evalsubshell;
+		goto calleval;
+	case NPIPE:
+		evalfn = evalpipe;
+		goto checkexit;
+	case NCASE:
+		evalfn = evalcase;
+		goto calleval;
+	case NAND:
+	case NOR:
+	case NSEMI:
+#if NAND + 1 != NOR
+#error NAND + 1 != NOR
+#endif
+#if NOR + 1 != NSEMI
+#error NOR + 1 != NSEMI
+#endif
+		isor = n->type - NAND;
+		evaltree(
+			n->nbinary.ch1,
+			(flags | ((isor >> 1) - 1)) & EV_TESTED
+		);
+		if (!exitstatus == isor)
+			break;
+		if (!evalskip) {
+			n = n->nbinary.ch2;
+evaln:
+			evalfn = evaltree;
+calleval:
+			evalfn(n, flags);
+			break;
+		}
+		break;
+	case NIF:
+		evaltree(n->nif.test, EV_TESTED);
+		if (evalskip)
+			break;
+		if (exitstatus == 0) {
+			n = n->nif.ifpart;
+			goto evaln;
+		} else if (n->nif.elsepart) {
+			n = n->nif.elsepart;
+			goto evaln;
+		}
+		goto success;
+	case NDEFUN:
+		defun(n->narg.text, n->narg.next);
+success:
+		status = 0;
+setstatus:
+		exitstatus = status;
+		break;
+	}
+out:
+	if ((checkexit & exitstatus))
+		evalskip |= SKIPEVAL;
+	else if (pendingsigs && dotrap())
+		goto exexit;
+
+	if (flags & EV_EXIT) {
+exexit:
+		exraise(EXEXIT);
+	}
+}
+
+
+#if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
+static
+#endif
+void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
+
+
+static void
+evalloop(union node *n, int flags)
+{
+	int status;
+
+	loopnest++;
+	status = 0;
+	flags &= EV_TESTED;
+	for (;;) {
+		int i;
+
+		evaltree(n->nbinary.ch1, EV_TESTED);
+		if (evalskip) {
+skipping:         if (evalskip == SKIPCONT && --skipcount <= 0) {
+				evalskip = 0;
+				continue;
+			}
+			if (evalskip == SKIPBREAK && --skipcount <= 0)
+				evalskip = 0;
+			break;
+		}
+		i = exitstatus;
+		if (n->type != NWHILE)
+			i = !i;
+		if (i != 0)
+			break;
+		evaltree(n->nbinary.ch2, flags);
+		status = exitstatus;
+		if (evalskip)
+			goto skipping;
+	}
+	loopnest--;
+	exitstatus = status;
+}
+
+
+
+static void
+evalfor(union node *n, int flags)
+{
+	struct arglist arglist;
+	union node *argp;
+	struct strlist *sp;
+	struct stackmark smark;
+
+	setstackmark(&smark);
+	arglist.lastp = &arglist.list;
+	for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
+		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
+		/* XXX */
+		if (evalskip)
+			goto out;
+	}
+	*arglist.lastp = NULL;
+
+	exitstatus = 0;
+	loopnest++;
+	flags &= EV_TESTED;
+	for (sp = arglist.list ; sp ; sp = sp->next) {
+		setvar(n->nfor.var, sp->text, 0);
+		evaltree(n->nfor.body, flags);
+		if (evalskip) {
+			if (evalskip == SKIPCONT && --skipcount <= 0) {
+				evalskip = 0;
+				continue;
+			}
+			if (evalskip == SKIPBREAK && --skipcount <= 0)
+				evalskip = 0;
+			break;
+		}
+	}
+	loopnest--;
+out:
+	popstackmark(&smark);
+}
+
+
+
+static void
+evalcase(union node *n, int flags)
+{
+	union node *cp;
+	union node *patp;
+	struct arglist arglist;
+	struct stackmark smark;
+
+	setstackmark(&smark);
+	arglist.lastp = &arglist.list;
+	expandarg(n->ncase.expr, &arglist, EXP_TILDE);
+	exitstatus = 0;
+	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
+		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
+			if (casematch(patp, arglist.list->text)) {
+				if (evalskip == 0) {
+					evaltree(cp->nclist.body, flags);
+				}
+				goto out;
+			}
+		}
+	}
+out:
+	popstackmark(&smark);
+}
+
+
+
+/*
+ * Kick off a subshell to evaluate a tree.
+ */
+
+static void
+evalsubshell(union node *n, int flags)
+{
+	struct job *jp;
+	int backgnd = (n->type == NBACKGND);
+	int status;
+
+	expredir(n->nredir.redirect);
+	if (!backgnd && flags & EV_EXIT && !trap[0])
+		goto nofork;
+	INTOFF;
+	jp = makejob(n, 1);
+	if (forkshell(jp, n, backgnd) == 0) {
+		INTON;
+		flags |= EV_EXIT;
+		if (backgnd)
+			flags &=~ EV_TESTED;
+nofork:
+		redirect(n->nredir.redirect, 0);
+		evaltreenr(n->nredir.n, flags);
+		/* never returns */
+	}
+	status = 0;
+	if (! backgnd)
+		status = waitforjob(jp);
+	exitstatus = status;
+	INTON;
+}
+
+
+
+/*
+ * Compute the names of the files in a redirection list.
+ */
+
+static void
+expredir(union node *n)
+{
+	union node *redir;
+
+	for (redir = n ; redir ; redir = redir->nfile.next) {
+		struct arglist fn;
+		fn.lastp = &fn.list;
+		switch (redir->type) {
+		case NFROMTO:
+		case NFROM:
+		case NTO:
+		case NCLOBBER:
+		case NAPPEND:
+			expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
+			redir->nfile.expfname = fn.list->text;
+			break;
+		case NFROMFD:
+		case NTOFD:
+			if (redir->ndup.vname) {
+				expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
+				fixredir(redir, fn.list->text, 1);
+			}
+			break;
+		}
+	}
+}
+
+
+
+/*
+ * Evaluate a pipeline.  All the processes in the pipeline are children
+ * of the process creating the pipeline.  (This differs from some versions
+ * of the shell, which make the last process in a pipeline the parent
+ * of all the rest.)
+ */
+
+static void
+evalpipe(union node *n, int flags)
+{
+	struct job *jp;
+	struct nodelist *lp;
+	int pipelen;
+	int prevfd;
+	int pip[2];
+
+	TRACE(("evalpipe(0x%lx) called\n", (long)n));
+	pipelen = 0;
+	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
+		pipelen++;
+	flags |= EV_EXIT;
+	INTOFF;
+	jp = makejob(n, pipelen);
+	prevfd = -1;
+	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
+		prehash(lp->n);
+		pip[1] = -1;
+		if (lp->next) {
+			if (pipe(pip) < 0) {
+				close(prevfd);
+				sh_error("Pipe call failed");
+			}
+		}
+		if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
+			INTON;
+			if (pip[1] >= 0) {
+				close(pip[0]);
+			}
+			if (prevfd > 0) {
+				dup2(prevfd, 0);
+				close(prevfd);
+			}
+			if (pip[1] > 1) {
+				dup2(pip[1], 1);
+				close(pip[1]);
+			}
+			evaltreenr(lp->n, flags);
+			/* never returns */
+		}
+		if (prevfd >= 0)
+			close(prevfd);
+		prevfd = pip[0];
+		close(pip[1]);
+	}
+	if (n->npipe.backgnd == 0) {
+		exitstatus = waitforjob(jp);
+		TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
+	}
+	INTON;
+}
+
+
+
+/*
+ * Execute a command inside back quotes.  If it's a builtin command, we
+ * want to save its output in a block obtained from malloc.  Otherwise
+ * we fork off a subprocess and get the output of the command via a pipe.
+ * Should be called with interrupts off.
+ */
+
+static void
+evalbackcmd(union node *n, struct backcmd *result)
+{
+	int saveherefd;
+
+	result->fd = -1;
+	result->buf = NULL;
+	result->nleft = 0;
+	result->jp = NULL;
+	if (n == NULL) {
+		goto out;
+	}
+
+	saveherefd = herefd;
+	herefd = -1;
+
+	{
+		int pip[2];
+		struct job *jp;
+
+		if (pipe(pip) < 0)
+			sh_error("Pipe call failed");
+		jp = makejob(n, 1);
+		if (forkshell(jp, n, FORK_NOJOB) == 0) {
+			FORCEINTON;
+			close(pip[0]);
+			if (pip[1] != 1) {
+				close(1);
+				copyfd(pip[1], 1);
+				close(pip[1]);
+			}
+			eflag = 0;
+			evaltreenr(n, EV_EXIT);
+			/* NOTREACHED */
+		}
+		close(pip[1]);
+		result->fd = pip[0];
+		result->jp = jp;
+	}
+	herefd = saveherefd;
+out:
+	TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
+		result->fd, result->buf, result->nleft, result->jp));
+}
+
+#ifdef CONFIG_ASH_CMDCMD
+static inline char **
+parse_command_args(char **argv, const char **path)
+{
+	char *cp, c;
+
+	for (;;) {
+		cp = *++argv;
+		if (!cp)
+			return 0;
+		if (*cp++ != '-')
+			break;
+		if (!(c = *cp++))
+			break;
+		if (c == '-' && !*cp) {
+			argv++;
+			break;
+		}
+		do {
+			switch (c) {
+			case 'p':
+				*path = defpath;
+				break;
+			default:
+				/* run 'typecmd' for other options */
+				return 0;
+			}
+		} while ((c = *cp++));
+	}
+	return argv;
+}
+#endif
+
+static inline int
+isassignment(const char *p)
+{
+	const char *q = endofname(p);
+	if (p == q)
+		return 0;
+	return *q == '=';
+}
+
+#ifdef CONFIG_ASH_EXPAND_PRMT
+static const char *expandstr(const char *ps);
+#else
+#define expandstr(s) s
+#endif
+
+/*
+ * Execute a simple command.
+ */
+
+static void
+evalcommand(union node *cmd, int flags)
+{
+	struct stackmark smark;
+	union node *argp;
+	struct arglist arglist;
+	struct arglist varlist;
+	char **argv;
+	int argc;
+	const struct strlist *sp;
+	struct cmdentry cmdentry;
+	struct job *jp;
+	char *lastarg;
+	const char *path;
+	int spclbltin;
+	int cmd_is_exec;
+	int status;
+	char **nargv;
+	struct builtincmd *bcmd;
+	int pseudovarflag = 0;
+
+	/* First expand the arguments. */
+	TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
+	setstackmark(&smark);
+	back_exitstatus = 0;
+
+	cmdentry.cmdtype = CMDBUILTIN;
+	cmdentry.u.cmd = &bltin;
+	varlist.lastp = &varlist.list;
+	*varlist.lastp = NULL;
+	arglist.lastp = &arglist.list;
+	*arglist.lastp = NULL;
+
+	argc = 0;
+	if (cmd->ncmd.args)
+	{
+		bcmd = find_builtin(cmd->ncmd.args->narg.text);
+		pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
+	}
+
+	for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
+		struct strlist **spp;
+
+		spp = arglist.lastp;
+		if (pseudovarflag && isassignment(argp->narg.text))
+			expandarg(argp, &arglist, EXP_VARTILDE);
+		else
+			expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
+
+		for (sp = *spp; sp; sp = sp->next)
+			argc++;
+	}
+
+	argv = nargv = stalloc(sizeof (char *) * (argc + 1));
+	for (sp = arglist.list ; sp ; sp = sp->next) {
+		TRACE(("evalcommand arg: %s\n", sp->text));
+		*nargv++ = sp->text;
+	}
+	*nargv = NULL;
+
+	lastarg = NULL;
+	if (iflag && funcnest == 0 && argc > 0)
+		lastarg = nargv[-1];
+
+	preverrout_fd = 2;
+	expredir(cmd->ncmd.redirect);
+	status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
+
+	path = vpath.text;
+	for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
+		struct strlist **spp;
+		char *p;
+
+		spp = varlist.lastp;
+		expandarg(argp, &varlist, EXP_VARTILDE);
+
+		/*
+		 * Modify the command lookup path, if a PATH= assignment
+		 * is present
+		 */
+		p = (*spp)->text;
+		if (varequal(p, path))
+			path = p;
+	}
+
+	/* Print the command if xflag is set. */
+	if (xflag) {
+		int n;
+		const char *p = " %s";
+
+		p++;
+		dprintf(preverrout_fd, p, expandstr(ps4val()));
+
+		sp = varlist.list;
+		for(n = 0; n < 2; n++) {
+			while (sp) {
+				dprintf(preverrout_fd, p, sp->text);
+				sp = sp->next;
+				if(*p == '%') {
+					p--;
+				}
+			}
+			sp = arglist.list;
+		}
+		bb_full_write(preverrout_fd, "\n", 1);
+	}
+
+	cmd_is_exec = 0;
+	spclbltin = -1;
+
+	/* Now locate the command. */
+	if (argc) {
+		const char *oldpath;
+		int cmd_flag = DO_ERR;
+
+		path += 5;
+		oldpath = path;
+		for (;;) {
+			find_command(argv[0], &cmdentry, cmd_flag, path);
+			if (cmdentry.cmdtype == CMDUNKNOWN) {
+				status = 127;
+				flusherr();
+				goto bail;
+			}
+
+			/* implement bltin and command here */
+			if (cmdentry.cmdtype != CMDBUILTIN)
+				break;
+			if (spclbltin < 0)
+				spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
+			if (cmdentry.u.cmd == EXECCMD)
+				cmd_is_exec++;
+#ifdef CONFIG_ASH_CMDCMD
+			if (cmdentry.u.cmd == COMMANDCMD) {
+
+				path = oldpath;
+				nargv = parse_command_args(argv, &path);
+				if (!nargv)
+					break;
+				argc -= nargv - argv;
+				argv = nargv;
+				cmd_flag |= DO_NOFUNC;
+			} else
+#endif
+				break;
+		}
+	}
+
+	if (status) {
+		/* We have a redirection error. */
+		if (spclbltin > 0)
+			exraise(EXERROR);
+bail:
+		exitstatus = status;
+		goto out;
+	}
+
+	/* Execute the command. */
+	switch (cmdentry.cmdtype) {
+	default:
+		/* Fork off a child process if necessary. */
+		if (!(flags & EV_EXIT) || trap[0]) {
+			INTOFF;
+			jp = makejob(cmd, 1);
+			if (forkshell(jp, cmd, FORK_FG) != 0) {
+				exitstatus = waitforjob(jp);
+				INTON;
+				break;
+			}
+			FORCEINTON;
+		}
+		listsetvar(varlist.list, VEXPORT|VSTACK);
+		shellexec(argv, path, cmdentry.u.index);
+		/* NOTREACHED */
+
+	case CMDBUILTIN:
+		cmdenviron = varlist.list;
+		if (cmdenviron) {
+			struct strlist *list = cmdenviron;
+			int i = VNOSET;
+			if (spclbltin > 0 || argc == 0) {
+				i = 0;
+				if (cmd_is_exec && argc > 1)
+					i = VEXPORT;
+			}
+			listsetvar(list, i);
+		}
+		if (evalbltin(cmdentry.u.cmd, argc, argv)) {
+			int exit_status;
+			int i, j;
+
+			i = exception;
+			if (i == EXEXIT)
+				goto raise;
+
+			exit_status = 2;
+			j = 0;
+			if (i == EXINT)
+				j = SIGINT;
+			if (i == EXSIG)
+				j = pendingsigs;
+			if (j)
+				exit_status = j + 128;
+			exitstatus = exit_status;
+
+			if (i == EXINT || spclbltin > 0) {
+raise:
+				longjmp(handler->loc, 1);
+			}
+			FORCEINTON;
+		}
+		break;
+
+	case CMDFUNCTION:
+		listsetvar(varlist.list, 0);
+		if (evalfun(cmdentry.u.func, argc, argv, flags))
+			goto raise;
+		break;
+	}
+
+out:
+	popredir(cmd_is_exec);
+	if (lastarg)
+		/* dsl: I think this is intended to be used to support
+		 * '_' in 'vi' command mode during line editing...
+		 * However I implemented that within libedit itself.
+		 */
+		setvar("_", lastarg, 0);
+	popstackmark(&smark);
+}
+
+static int
+evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
+	char *volatile savecmdname;
+	struct jmploc *volatile savehandler;
+	struct jmploc jmploc;
+	int i;
+
+	savecmdname = commandname;
+	if ((i = setjmp(jmploc.loc)))
+		goto cmddone;
+	savehandler = handler;
+	handler = &jmploc;
+	commandname = argv[0];
+	argptr = argv + 1;
+	optptr = NULL;                  /* initialize nextopt */
+	exitstatus = (*cmd->builtin)(argc, argv);
+	flushall();
+cmddone:
+	exitstatus |= ferror(stdout);
+	clearerr(stdout);
+	commandname = savecmdname;
+	exsig = 0;
+	handler = savehandler;
+
+	return i;
+}
+
+static int
+evalfun(struct funcnode *func, int argc, char **argv, int flags)
+{
+	volatile struct shparam saveparam;
+	struct localvar *volatile savelocalvars;
+	struct jmploc *volatile savehandler;
+	struct jmploc jmploc;
+	int e;
+
+	saveparam = shellparam;
+	savelocalvars = localvars;
+	if ((e = setjmp(jmploc.loc))) {
+		goto funcdone;
+	}
+	INTOFF;
+	savehandler = handler;
+	handler = &jmploc;
+	localvars = NULL;
+	shellparam.malloc = 0;
+	func->count++;
+	funcnest++;
+	INTON;
+	shellparam.nparam = argc - 1;
+	shellparam.p = argv + 1;
+#ifdef CONFIG_ASH_GETOPTS
+	shellparam.optind = 1;
+	shellparam.optoff = -1;
+#endif
+	evaltree(&func->n, flags & EV_TESTED);
+funcdone:
+	INTOFF;
+	funcnest--;
+	freefunc(func);
+	poplocalvars();
+	localvars = savelocalvars;
+	freeparam(&shellparam);
+	shellparam = saveparam;
+	handler = savehandler;
+	INTON;
+	evalskip &= ~SKIPFUNC;
+	return e;
+}
+
+
+static inline int
+goodname(const char *p)
+{
+	return !*endofname(p);
+}
+
+/*
+ * Search for a command.  This is called before we fork so that the
+ * location of the command will be available in the parent as well as
+ * the child.  The check for "goodname" is an overly conservative
+ * check that the name will not be subject to expansion.
+ */
+
+static void
+prehash(union node *n)
+{
+	struct cmdentry entry;
+
+	if (n->type == NCMD && n->ncmd.args)
+		if (goodname(n->ncmd.args->narg.text))
+			find_command(n->ncmd.args->narg.text, &entry, 0,
+				     pathval());
+}
+
+
+
+/*
+ * Builtin commands.  Builtin commands whose functions are closely
+ * tied to evaluation are implemented here.
+ */
+
+/*
+ * No command given.
+ */
+
+static int
+bltincmd(int argc, char **argv)
+{
+	/*
+	 * Preserve exitstatus of a previous possible redirection
+	 * as POSIX mandates
+	 */
+	return back_exitstatus;
+}
+
+
+/*
+ * Handle break and continue commands.  Break, continue, and return are
+ * all handled by setting the evalskip flag.  The evaluation routines
+ * above all check this flag, and if it is set they start skipping
+ * commands rather than executing them.  The variable skipcount is
+ * the number of loops to break/continue, or the number of function
+ * levels to return.  (The latter is always 1.)  It should probably
+ * be an error to break out of more loops than exist, but it isn't
+ * in the standard shell so we don't make it one here.
+ */
+
+static int
+breakcmd(int argc, char **argv)
+{
+	int n = argc > 1 ? number(argv[1]) : 1;
+
+	if (n <= 0)
+		sh_error(illnum, argv[1]);
+	if (n > loopnest)
+		n = loopnest;
+	if (n > 0) {
+		evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
+		skipcount = n;
+	}
+	return 0;
+}
+
+
+/*
+ * The return command.
+ */
+
+static int
+returncmd(int argc, char **argv)
+{
+	/*
+	 * If called outside a function, do what ksh does;
+	 * skip the rest of the file.
+	 */
+	evalskip = funcnest ? SKIPFUNC : SKIPFILE;
+	return argv[1] ? number(argv[1]) : exitstatus;
+}
+
+
+static int
+falsecmd(int argc, char **argv)
+{
+	return 1;
+}
+
+
+static int
+truecmd(int argc, char **argv)
+{
+	return 0;
+}
+
+
+static int
+execcmd(int argc, char **argv)
+{
+	if (argc > 1) {
+		iflag = 0;              /* exit on error */
+		mflag = 0;
+		optschanged();
+		shellexec(argv + 1, pathval(), 0);
+	}
+	return 0;
+}
+
+
+/*      exec.c    */
+
+/*
+ * When commands are first encountered, they are entered in a hash table.
+ * This ensures that a full path search will not have to be done for them
+ * on each invocation.
+ *
+ * We should investigate converting to a linear search, even though that
+ * would make the command name "hash" a misnomer.
+ */
+
+#define CMDTABLESIZE 31         /* should be prime */
+#define ARB 1                   /* actual size determined at run time */
+
+
+
+struct tblentry {
+	struct tblentry *next;  /* next entry in hash chain */
+	union param param;      /* definition of builtin function */
+	short cmdtype;          /* index identifying command */
+	char rehash;            /* if set, cd done since entry created */
+	char cmdname[ARB];      /* name of command */
+};
+
+
+static struct tblentry *cmdtable[CMDTABLESIZE];
+static int builtinloc = -1;             /* index in path of %builtin, or -1 */
+
+
+static void tryexec(char *, char **, char **);
+static void clearcmdentry(int);
+static struct tblentry *cmdlookup(const char *, int);
+static void delete_cmd_entry(void);
+
+
+/*
+ * Exec a program.  Never returns.  If you change this routine, you may
+ * have to change the find_command routine as well.
+ */
+
+static void
+shellexec(char **argv, const char *path, int idx)
+{
+	char *cmdname;
+	int e;
+	char **envp;
+	int exerrno;
+
+	clearredir(1);
+	envp = environment();
+	if (strchr(argv[0], '/') != NULL
+#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
+		|| find_applet_by_name(argv[0])
+#endif
+						) {
+		tryexec(argv[0], argv, envp);
+		e = errno;
+	} else {
+		e = ENOENT;
+		while ((cmdname = padvance(&path, argv[0])) != NULL) {
+			if (--idx < 0 && pathopt == NULL) {
+				tryexec(cmdname, argv, envp);
+				if (errno != ENOENT && errno != ENOTDIR)
+					e = errno;
+			}
+			stunalloc(cmdname);
+		}
+	}
+
+	/* Map to POSIX errors */
+	switch (e) {
+	case EACCES:
+		exerrno = 126;
+		break;
+	case ENOENT:
+		exerrno = 127;
+		break;
+	default:
+		exerrno = 2;
+		break;
+	}
+	exitstatus = exerrno;
+	TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
+		argv[0], e, suppressint ));
+	exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
+	/* NOTREACHED */
+}
+
+
+static void
+tryexec(char *cmd, char **argv, char **envp)
+{
+	int repeated = 0;
+#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
+	if(find_applet_by_name(cmd) != NULL) {
+		/* re-exec ourselves with the new arguments */
+		execve(CONFIG_BUSYBOX_EXEC_PATH,argv,envp);
+		/* If they called chroot or otherwise made the binary no longer
+		 * executable, fall through */
+	}
+#endif
+
+repeat:
+#ifdef SYSV
+	do {
+		execve(cmd, argv, envp);
+	} while (errno == EINTR);
+#else
+	execve(cmd, argv, envp);
+#endif
+	if (repeated++) {
+		ckfree(argv);
+	} else if (errno == ENOEXEC) {
+		char **ap;
+		char **new;
+
+		for (ap = argv; *ap; ap++)
+			;
+		ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
+		ap[1] = cmd;
+		*ap = cmd = (char *)DEFAULT_SHELL;
+		ap += 2;
+		argv++;
+		while ((*ap++ = *argv++))
+			;
+		argv = new;
+		goto repeat;
+	}
+}
+
+
+
+/*
+ * Do a path search.  The variable path (passed by reference) should be
+ * set to the start of the path before the first call; padvance will update
+ * this value as it proceeds.  Successive calls to padvance will return
+ * the possible path expansions in sequence.  If an option (indicated by
+ * a percent sign) appears in the path entry then the global variable
+ * pathopt will be set to point to it; otherwise pathopt will be set to
+ * NULL.
+ */
+
+static char *
+padvance(const char **path, const char *name)
+{
+	const char *p;
+	char *q;
+	const char *start;
+	size_t len;
+
+	if (*path == NULL)
+		return NULL;
+	start = *path;
+	for (p = start ; *p && *p != ':' && *p != '%' ; p++);
+	len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
+	while (stackblocksize() < len)
+		growstackblock();
+	q = stackblock();
+	if (p != start) {
+		memcpy(q, start, p - start);
+		q += p - start;
+		*q++ = '/';
+	}
+	strcpy(q, name);
+	pathopt = NULL;
+	if (*p == '%') {
+		pathopt = ++p;
+		while (*p && *p != ':')  p++;
+	}
+	if (*p == ':')
+		*path = p + 1;
+	else
+		*path = NULL;
+	return stalloc(len);
+}
+
+
+/*** Command hashing code ***/
+
+static void
+printentry(struct tblentry *cmdp)
+{
+	int idx;
+	const char *path;
+	char *name;
+
+	idx = cmdp->param.index;
+	path = pathval();
+	do {
+		name = padvance(&path, cmdp->cmdname);
+		stunalloc(name);
+	} while (--idx >= 0);
+	out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
+}
+
+
+static int
+hashcmd(int argc, char **argv)
+{
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+	int c;
+	struct cmdentry entry;
+	char *name;
+
+	while ((c = nextopt("r")) != '\0') {
+		clearcmdentry(0);
+		return 0;
+	}
+	if (*argptr == NULL) {
+		for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
+			for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
+				if (cmdp->cmdtype == CMDNORMAL)
+					printentry(cmdp);
+			}
+		}
+		return 0;
+	}
+	c = 0;
+	while ((name = *argptr) != NULL) {
+		if ((cmdp = cmdlookup(name, 0)) != NULL
+		 && (cmdp->cmdtype == CMDNORMAL
+		     || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
+			delete_cmd_entry();
+		find_command(name, &entry, DO_ERR, pathval());
+		if (entry.cmdtype == CMDUNKNOWN)
+			c = 1;
+		argptr++;
+	}
+	return c;
+}
+
+
+/*
+ * Resolve a command name.  If you change this routine, you may have to
+ * change the shellexec routine as well.
+ */
+
+static void
+find_command(char *name, struct cmdentry *entry, int act, const char *path)
+{
+	struct tblentry *cmdp;
+	int idx;
+	int prev;
+	char *fullname;
+	struct stat statb;
+	int e;
+	int updatetbl;
+	struct builtincmd *bcmd;
+
+	/* If name contains a slash, don't use PATH or hash table */
+	if (strchr(name, '/') != NULL) {
+		entry->u.index = -1;
+		if (act & DO_ABS) {
+			while (stat(name, &statb) < 0) {
+#ifdef SYSV
+				if (errno == EINTR)
+					continue;
+#endif
+				entry->cmdtype = CMDUNKNOWN;
+				return;
+			}
+		}
+		entry->cmdtype = CMDNORMAL;
+		return;
+	}
+
+#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
+	if (find_applet_by_name(name)) {
+		entry->cmdtype = CMDNORMAL;
+		entry->u.index = -1;
+		return;
+	}
+#endif
+
+	updatetbl = (path == pathval());
+	if (!updatetbl) {
+		act |= DO_ALTPATH;
+		if (strstr(path, "%builtin") != NULL)
+			act |= DO_ALTBLTIN;
+	}
+
+	/* If name is in the table, check answer will be ok */
+	if ((cmdp = cmdlookup(name, 0)) != NULL) {
+		int bit;
+
+		switch (cmdp->cmdtype) {
+		default:
+#if DEBUG
+			abort();
+#endif
+		case CMDNORMAL:
+			bit = DO_ALTPATH;
+			break;
+		case CMDFUNCTION:
+			bit = DO_NOFUNC;
+			break;
+		case CMDBUILTIN:
+			bit = DO_ALTBLTIN;
+			break;
+		}
+		if (act & bit) {
+			updatetbl = 0;
+			cmdp = NULL;
+		} else if (cmdp->rehash == 0)
+			/* if not invalidated by cd, we're done */
+			goto success;
+	}
+
+	/* If %builtin not in path, check for builtin next */
+	bcmd = find_builtin(name);
+	if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
+		act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
+	)))
+		goto builtin_success;
+
+	/* We have to search path. */
+	prev = -1;              /* where to start */
+	if (cmdp && cmdp->rehash) {     /* doing a rehash */
+		if (cmdp->cmdtype == CMDBUILTIN)
+			prev = builtinloc;
+		else
+			prev = cmdp->param.index;
+	}
+
+	e = ENOENT;
+	idx = -1;
+loop:
+	while ((fullname = padvance(&path, name)) != NULL) {
+		stunalloc(fullname);
+		idx++;
+		if (pathopt) {
+			if (prefix(pathopt, "builtin")) {
+				if (bcmd)
+					goto builtin_success;
+				continue;
+			} else if (!(act & DO_NOFUNC) &&
+				   prefix(pathopt, "func")) {
+				/* handled below */
+			} else {
+				/* ignore unimplemented options */
+				continue;
+			}
+		}
+		/* if rehash, don't redo absolute path names */
+		if (fullname[0] == '/' && idx <= prev) {
+			if (idx < prev)
+				continue;
+			TRACE(("searchexec \"%s\": no change\n", name));
+			goto success;
+		}
+		while (stat(fullname, &statb) < 0) {
+#ifdef SYSV
+			if (errno == EINTR)
+				continue;
+#endif
+			if (errno != ENOENT && errno != ENOTDIR)
+				e = errno;
+			goto loop;
+		}
+		e = EACCES;     /* if we fail, this will be the error */
+		if (!S_ISREG(statb.st_mode))
+			continue;
+		if (pathopt) {          /* this is a %func directory */
+			stalloc(strlen(fullname) + 1);
+			readcmdfile(fullname);
+			if ((cmdp = cmdlookup(name, 0)) == NULL ||
+			    cmdp->cmdtype != CMDFUNCTION)
+				sh_error("%s not defined in %s", name, fullname);
+			stunalloc(fullname);
+			goto success;
+		}
+		TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
+		if (!updatetbl) {
+			entry->cmdtype = CMDNORMAL;
+			entry->u.index = idx;
+			return;
+		}
+		INTOFF;
+		cmdp = cmdlookup(name, 1);
+		cmdp->cmdtype = CMDNORMAL;
+		cmdp->param.index = idx;
+		INTON;
+		goto success;
+	}
+
+	/* We failed.  If there was an entry for this command, delete it */
+	if (cmdp && updatetbl)
+		delete_cmd_entry();
+	if (act & DO_ERR)
+		sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
+	entry->cmdtype = CMDUNKNOWN;
+	return;
+
+builtin_success:
+	if (!updatetbl) {
+		entry->cmdtype = CMDBUILTIN;
+		entry->u.cmd = bcmd;
+		return;
+	}
+	INTOFF;
+	cmdp = cmdlookup(name, 1);
+	cmdp->cmdtype = CMDBUILTIN;
+	cmdp->param.cmd = bcmd;
+	INTON;
+success:
+	cmdp->rehash = 0;
+	entry->cmdtype = cmdp->cmdtype;
+	entry->u = cmdp->param;
+}
+
+
+/*
+ * Wrapper around strcmp for qsort/bsearch/...
+ */
+static int pstrcmp(const void *a, const void *b)
+{
+	return strcmp((const char *) a, (*(const char *const *) b) + 1);
+}
+
+/*
+ * Search the table of builtin commands.
+ */
+
+static struct builtincmd *
+find_builtin(const char *name)
+{
+	struct builtincmd *bp;
+
+	bp = bsearch(
+		name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
+		pstrcmp
+	);
+	return bp;
+}
+
+
+
+/*
+ * Called when a cd is done.  Marks all commands so the next time they
+ * are executed they will be rehashed.
+ */
+
+static void
+hashcd(void)
+{
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+
+	for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
+		for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
+			if (cmdp->cmdtype == CMDNORMAL || (
+				cmdp->cmdtype == CMDBUILTIN &&
+				!(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
+				builtinloc > 0
+			))
+				cmdp->rehash = 1;
+		}
+	}
+}
+
+
+
+/*
+ * Fix command hash table when PATH changed.
+ * Called before PATH is changed.  The argument is the new value of PATH;
+ * pathval() still returns the old value at this point.
+ * Called with interrupts off.
+ */
+
+static void
+changepath(const char *newval)
+{
+	const char *old, *new;
+	int idx;
+	int firstchange;
+	int idx_bltin;
+
+	old = pathval();
+	new = newval;
+	firstchange = 9999;     /* assume no change */
+	idx = 0;
+	idx_bltin = -1;
+	for (;;) {
+		if (*old != *new) {
+			firstchange = idx;
+			if ((*old == '\0' && *new == ':')
+			 || (*old == ':' && *new == '\0'))
+				firstchange++;
+			old = new;      /* ignore subsequent differences */
+		}
+		if (*new == '\0')
+			break;
+		if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
+			idx_bltin = idx;
+		if (*new == ':') {
+			idx++;
+		}
+		new++, old++;
+	}
+	if (builtinloc < 0 && idx_bltin >= 0)
+		builtinloc = idx_bltin;             /* zap builtins */
+	if (builtinloc >= 0 && idx_bltin < 0)
+		firstchange = 0;
+	clearcmdentry(firstchange);
+	builtinloc = idx_bltin;
+}
+
+
+/*
+ * Clear out command entries.  The argument specifies the first entry in
+ * PATH which has changed.
+ */
+
+static void
+clearcmdentry(int firstchange)
+{
+	struct tblentry **tblp;
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+
+	INTOFF;
+	for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
+		pp = tblp;
+		while ((cmdp = *pp) != NULL) {
+			if ((cmdp->cmdtype == CMDNORMAL &&
+			     cmdp->param.index >= firstchange)
+			 || (cmdp->cmdtype == CMDBUILTIN &&
+			     builtinloc >= firstchange)) {
+				*pp = cmdp->next;
+				ckfree(cmdp);
+			} else {
+				pp = &cmdp->next;
+			}
+		}
+	}
+	INTON;
+}
+
+
+
+/*
+ * Locate a command in the command hash table.  If "add" is nonzero,
+ * add the command to the table if it is not already present.  The
+ * variable "lastcmdentry" is set to point to the address of the link
+ * pointing to the entry, so that delete_cmd_entry can delete the
+ * entry.
+ *
+ * Interrupts must be off if called with add != 0.
+ */
+
+static struct tblentry **lastcmdentry;
+
+
+static struct tblentry *
+cmdlookup(const char *name, int add)
+{
+	unsigned int hashval;
+	const char *p;
+	struct tblentry *cmdp;
+	struct tblentry **pp;
+
+	p = name;
+	hashval = (unsigned char)*p << 4;
+	while (*p)
+		hashval += (unsigned char)*p++;
+	hashval &= 0x7FFF;
+	pp = &cmdtable[hashval % CMDTABLESIZE];
+	for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
+		if (equal(cmdp->cmdname, name))
+			break;
+		pp = &cmdp->next;
+	}
+	if (add && cmdp == NULL) {
+		cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
+					+ strlen(name) + 1);
+		cmdp->next = NULL;
+		cmdp->cmdtype = CMDUNKNOWN;
+		strcpy(cmdp->cmdname, name);
+	}
+	lastcmdentry = pp;
+	return cmdp;
+}
+
+/*
+ * Delete the command entry returned on the last lookup.
+ */
+
+static void
+delete_cmd_entry(void)
+{
+	struct tblentry *cmdp;
+
+	INTOFF;
+	cmdp = *lastcmdentry;
+	*lastcmdentry = cmdp->next;
+	if (cmdp->cmdtype == CMDFUNCTION)
+		freefunc(cmdp->param.func);
+	ckfree(cmdp);
+	INTON;
+}
+
+
+/*
+ * Add a new command entry, replacing any existing command entry for
+ * the same name - except special builtins.
+ */
+
+static inline void
+addcmdentry(char *name, struct cmdentry *entry)
+{
+	struct tblentry *cmdp;
+
+	cmdp = cmdlookup(name, 1);
+	if (cmdp->cmdtype == CMDFUNCTION) {
+		freefunc(cmdp->param.func);
+	}
+	cmdp->cmdtype = entry->cmdtype;
+	cmdp->param = entry->u;
+	cmdp->rehash = 0;
+}
+
+/*
+ * Make a copy of a parse tree.
+ */
+
+static inline struct funcnode *
+copyfunc(union node *n)
+{
+	struct funcnode *f;
+	size_t blocksize;
+
+	funcblocksize = offsetof(struct funcnode, n);
+	funcstringsize = 0;
+	calcsize(n);
+	blocksize = funcblocksize;
+	f = ckmalloc(blocksize + funcstringsize);
+	funcblock = (char *) f + offsetof(struct funcnode, n);
+	funcstring = (char *) f + blocksize;
+	copynode(n);
+	f->count = 0;
+	return f;
+}
+
+/*
+ * Define a shell function.
+ */
+
+static void
+defun(char *name, union node *func)
+{
+	struct cmdentry entry;
+
+	INTOFF;
+	entry.cmdtype = CMDFUNCTION;
+	entry.u.func = copyfunc(func);
+	addcmdentry(name, &entry);
+	INTON;
+}
+
+
+/*
+ * Delete a function if it exists.
+ */
+
+static void
+unsetfunc(const char *name)
+{
+	struct tblentry *cmdp;
+
+	if ((cmdp = cmdlookup(name, 0)) != NULL &&
+	    cmdp->cmdtype == CMDFUNCTION)
+		delete_cmd_entry();
+}
+
+/*
+ * Locate and print what a word is...
+ */
+
+
+#ifdef CONFIG_ASH_CMDCMD
+static int
+describe_command(char *command, int describe_command_verbose)
+#else
+#define describe_command_verbose 1
+static int
+describe_command(char *command)
+#endif
+{
+	struct cmdentry entry;
+	struct tblentry *cmdp;
+#ifdef CONFIG_ASH_ALIAS
+	const struct alias *ap;
+#endif
+	const char *path = pathval();
+
+	if (describe_command_verbose) {
+		out1str(command);
+	}
+
+	/* First look at the keywords */
+	if (findkwd(command)) {
+		out1str(describe_command_verbose ? " is a shell keyword" : command);
+		goto out;
+	}
+
+#ifdef CONFIG_ASH_ALIAS
+	/* Then look at the aliases */
+	if ((ap = lookupalias(command, 0)) != NULL) {
+		if (describe_command_verbose) {
+			out1fmt(" is an alias for %s", ap->val);
+		} else {
+			out1str("alias ");
+			printalias(ap);
+			return 0;
+		}
+		goto out;
+	}
+#endif
+	/* Then check if it is a tracked alias */
+	if ((cmdp = cmdlookup(command, 0)) != NULL) {
+		entry.cmdtype = cmdp->cmdtype;
+		entry.u = cmdp->param;
+	} else {
+		/* Finally use brute force */
+		find_command(command, &entry, DO_ABS, path);
+	}
+
+	switch (entry.cmdtype) {
+	case CMDNORMAL: {
+		int j = entry.u.index;
+		char *p;
+		if (j == -1) {
+			p = command;
+		} else {
+			do {
+				p = padvance(&path, command);
+				stunalloc(p);
+			} while (--j >= 0);
+		}
+		if (describe_command_verbose) {
+			out1fmt(" is%s %s",
+				(cmdp ? " a tracked alias for" : nullstr), p
+			);
+		} else {
+			out1str(p);
+		}
+		break;
+	}
+
+	case CMDFUNCTION:
+		if (describe_command_verbose) {
+			out1str(" is a shell function");
+		} else {
+			out1str(command);
+		}
+		break;
+
+	case CMDBUILTIN:
+		if (describe_command_verbose) {
+			out1fmt(" is a %sshell builtin",
+				IS_BUILTIN_SPECIAL(entry.u.cmd) ?
+					"special " : nullstr
+			);
+		} else {
+			out1str(command);
+		}
+		break;
+
+	default:
+		if (describe_command_verbose) {
+			out1str(": not found\n");
+		}
+		return 127;
+	}
+
+out:
+	outstr("\n", stdout);
+	return 0;
+}
+
+static int
+typecmd(int argc, char **argv)
+{
+	int i;
+	int err = 0;
+
+	for (i = 1; i < argc; i++) {
+#ifdef CONFIG_ASH_CMDCMD
+		err |= describe_command(argv[i], 1);
+#else
+		err |= describe_command(argv[i]);
+#endif
+	}
+	return err;
+}
+
+#ifdef CONFIG_ASH_CMDCMD
+static int
+commandcmd(int argc, char **argv)
+{
+	int c;
+	enum {
+		VERIFY_BRIEF = 1,
+		VERIFY_VERBOSE = 2,
+	} verify = 0;
+
+	while ((c = nextopt("pvV")) != '\0')
+		if (c == 'V')
+			verify |= VERIFY_VERBOSE;
+		else if (c == 'v')
+			verify |= VERIFY_BRIEF;
+#ifdef DEBUG
+		else if (c != 'p')
+			abort();
+#endif
+	if (verify)
+		return describe_command(*argptr, verify - VERIFY_BRIEF);
+
+	return 0;
+}
+#endif
+
+/*      expand.c     */
+
+/*
+ * Routines to expand arguments to commands.  We have to deal with
+ * backquotes, shell variables, and file metacharacters.
+ */
+
+/*
+ * _rmescape() flags
+ */
+#define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
+#define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
+#define RMESCAPE_QUOTED 0x4     /* Remove CTLESC unless in quotes */
+#define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
+#define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
+
+/*
+ * Structure specifying which parts of the string should be searched
+ * for IFS characters.
+ */
+
+struct ifsregion {
+	struct ifsregion *next; /* next region in list */
+	int begoff;             /* offset of start of region */
+	int endoff;             /* offset of end of region */
+	int nulonly;            /* search for nul bytes only */
+};
+
+/* output of current string */
+static char *expdest;
+/* list of back quote expressions */
+static struct nodelist *argbackq;
+/* first struct in list of ifs regions */
+static struct ifsregion ifsfirst;
+/* last struct in list */
+static struct ifsregion *ifslastp;
+/* holds expanded arg list */
+static struct arglist exparg;
+
+static void argstr(char *, int);
+static char *exptilde(char *, char *, int);
+static void expbackq(union node *, int, int);
+static const char *subevalvar(char *, char *, int, int, int, int, int);
+static char *evalvar(char *, int);
+static void strtodest(const char *, int, int);
+static void memtodest(const char *p, size_t len, int syntax, int quotes);
+static ssize_t varvalue(char *, int, int);
+static void recordregion(int, int, int);
+static void removerecordregions(int);
+static void ifsbreakup(char *, struct arglist *);
+static void ifsfree(void);
+static void expandmeta(struct strlist *, int);
+static int patmatch(char *, const char *);
+
+static int cvtnum(arith_t);
+static size_t esclen(const char *, const char *);
+static char *scanleft(char *, char *, char *, char *, int, int);
+static char *scanright(char *, char *, char *, char *, int, int);
+static void varunset(const char *, const char *, const char *, int)
+	ATTRIBUTE_NORETURN;
+
+
+#define pmatch(a, b) !fnmatch((a), (b), 0)
+/*
+ * Prepare a pattern for a expmeta (internal glob(3)) call.
+ *
+ * Returns an stalloced string.
+ */
+
+static inline char *
+preglob(const char *pattern, int quoted, int flag) {
+	flag |= RMESCAPE_GLOB;
+	if (quoted) {
+		flag |= RMESCAPE_QUOTED;
+	}
+	return _rmescapes((char *)pattern, flag);
+}
+
+
+static size_t
+esclen(const char *start, const char *p) {
+	size_t esc = 0;
+
+	while (p > start && *--p == CTLESC) {
+		esc++;
+	}
+	return esc;
+}
+
+
+/*
+ * Expand shell variables and backquotes inside a here document.
+ */
+
+static inline void
+expandhere(union node *arg, int fd)
+{
+	herefd = fd;
+	expandarg(arg, (struct arglist *)NULL, 0);
+	bb_full_write(fd, stackblock(), expdest - (char *)stackblock());
+}
+
+
+/*
+ * Perform variable substitution and command substitution on an argument,
+ * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
+ * perform splitting and file name expansion.  When arglist is NULL, perform
+ * here document expansion.
+ */
+
+void
+expandarg(union node *arg, struct arglist *arglist, int flag)
+{
+	struct strlist *sp;
+	char *p;
+
+	argbackq = arg->narg.backquote;
+	STARTSTACKSTR(expdest);
+	ifsfirst.next = NULL;
+	ifslastp = NULL;
+	argstr(arg->narg.text, flag);
+	p = _STPUTC('\0', expdest);
+	expdest = p - 1;
+	if (arglist == NULL) {
+		return;                 /* here document expanded */
+	}
+	p = grabstackstr(p);
+	exparg.lastp = &exparg.list;
+	/*
+	 * TODO - EXP_REDIR
+	 */
+	if (flag & EXP_FULL) {
+		ifsbreakup(p, &exparg);
+		*exparg.lastp = NULL;
+		exparg.lastp = &exparg.list;
+		expandmeta(exparg.list, flag);
+	} else {
+		if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
+			rmescapes(p);
+		sp = (struct strlist *)stalloc(sizeof (struct strlist));
+		sp->text = p;
+		*exparg.lastp = sp;
+		exparg.lastp = &sp->next;
+	}
+	if (ifsfirst.next)
+		ifsfree();
+	*exparg.lastp = NULL;
+	if (exparg.list) {
+		*arglist->lastp = exparg.list;
+		arglist->lastp = exparg.lastp;
+	}
+}
+
+
+/*
+ * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
+ * characters to allow for further processing.  Otherwise treat
+ * $@ like $* since no splitting will be performed.
+ */
+
+static void
+argstr(char *p, int flag)
+{
+	static const char spclchars[] = {
+		'=',
+		':',
+		CTLQUOTEMARK,
+		CTLENDVAR,
+		CTLESC,
+		CTLVAR,
+		CTLBACKQ,
+		CTLBACKQ | CTLQUOTE,
+#ifdef CONFIG_ASH_MATH_SUPPORT
+		CTLENDARI,
+#endif
+		0
+	};
+	const char *reject = spclchars;
+	int c;
+	int quotes = flag & (EXP_FULL | EXP_CASE);      /* do CTLESC */
+	int breakall = flag & EXP_WORD;
+	int inquotes;
+	size_t length;
+	int startloc;
+
+	if (!(flag & EXP_VARTILDE)) {
+		reject += 2;
+	} else if (flag & EXP_VARTILDE2) {
+		reject++;
+	}
+	inquotes = 0;
+	length = 0;
+	if (flag & EXP_TILDE) {
+		char *q;
+
+		flag &= ~EXP_TILDE;
+tilde:
+		q = p;
+		if (*q == CTLESC && (flag & EXP_QWORD))
+			q++;
+		if (*q == '~')
+			p = exptilde(p, q, flag);
+	}
+start:
+	startloc = expdest - (char *)stackblock();
+	for (;;) {
+		length += strcspn(p + length, reject);
+		c = p[length];
+		if (c && (!(c & 0x80)
+#ifdef CONFIG_ASH_MATH_SUPPORT
+					|| c == CTLENDARI
+#endif
+		   )) {
+			/* c == '=' || c == ':' || c == CTLENDARI */
+			length++;
+		}
+		if (length > 0) {
+			int newloc;
+			expdest = stnputs(p, length, expdest);
+			newloc = expdest - (char *)stackblock();
+			if (breakall && !inquotes && newloc > startloc) {
+				recordregion(startloc, newloc, 0);
+			}
+			startloc = newloc;
+		}
+		p += length + 1;
+		length = 0;
+
+		switch (c) {
+		case '\0':
+			goto breakloop;
+		case '=':
+			if (flag & EXP_VARTILDE2) {
+				p--;
+				continue;
+			}
+			flag |= EXP_VARTILDE2;
+			reject++;
+			/* fall through */
+		case ':':
+			/*
+			 * sort of a hack - expand tildes in variable
+			 * assignments (after the first '=' and after ':'s).
+			 */
+			if (*--p == '~') {
+				goto tilde;
+			}
+			continue;
+		}
+
+		switch (c) {
+		case CTLENDVAR: /* ??? */
+			goto breakloop;
+		case CTLQUOTEMARK:
+			/* "$@" syntax adherence hack */
+			if (
+				!inquotes &&
+				!memcmp(p, dolatstr, DOLATSTRLEN) &&
+				(p[4] == CTLQUOTEMARK || (
+					p[4] == CTLENDVAR &&
+					p[5] == CTLQUOTEMARK
+				))
+			) {
+				p = evalvar(p + 1, flag) + 1;
+				goto start;
+			}
+			inquotes = !inquotes;
+addquote:
+			if (quotes) {
+				p--;
+				length++;
+				startloc++;
+			}
+			break;
+		case CTLESC:
+			startloc++;
+			length++;
+			goto addquote;
+		case CTLVAR:
+			p = evalvar(p, flag);
+			goto start;
+		case CTLBACKQ:
+			c = 0;
+		case CTLBACKQ|CTLQUOTE:
+			expbackq(argbackq->n, c, quotes);
+			argbackq = argbackq->next;
+			goto start;
+#ifdef CONFIG_ASH_MATH_SUPPORT
+		case CTLENDARI:
+			p--;
+			expari(quotes);
+			goto start;
+#endif
+		}
+	}
+breakloop:
+	;
+}
+
+static char *
+exptilde(char *startp, char *p, int flag)
+{
+	char c;
+	char *name;
+	struct passwd *pw;
+	const char *home;
+	int quotes = flag & (EXP_FULL | EXP_CASE);
+	int startloc;
+
+	name = p + 1;
+
+	while ((c = *++p) != '\0') {
+		switch(c) {
+		case CTLESC:
+			return (startp);
+		case CTLQUOTEMARK:
+			return (startp);
+		case ':':
+			if (flag & EXP_VARTILDE)
+				goto done;
+			break;
+		case '/':
+		case CTLENDVAR:
+			goto done;
+		}
+	}
+done:
+	*p = '\0';
+	if (*name == '\0') {
+		home = lookupvar(homestr);
+	} else {
+		if ((pw = getpwnam(name)) == NULL)
+			goto lose;
+		home = pw->pw_dir;
+	}
+	if (!home || !*home)
+		goto lose;
+	*p = c;
+	startloc = expdest - (char *)stackblock();
+	strtodest(home, SQSYNTAX, quotes);
+	recordregion(startloc, expdest - (char *)stackblock(), 0);
+	return (p);
+lose:
+	*p = c;
+	return (startp);
+}
+
+
+static void
+removerecordregions(int endoff)
+{
+	if (ifslastp == NULL)
+		return;
+
+	if (ifsfirst.endoff > endoff) {
+		while (ifsfirst.next != NULL) {
+			struct ifsregion *ifsp;
+			INTOFF;
+			ifsp = ifsfirst.next->next;
+			ckfree(ifsfirst.next);
+			ifsfirst.next = ifsp;
+			INTON;
+		}
+		if (ifsfirst.begoff > endoff)
+			ifslastp = NULL;
+		else {
+			ifslastp = &ifsfirst;
+			ifsfirst.endoff = endoff;
+		}
+		return;
+	}
+
+	ifslastp = &ifsfirst;
+	while (ifslastp->next && ifslastp->next->begoff < endoff)
+		ifslastp=ifslastp->next;
+	while (ifslastp->next != NULL) {
+		struct ifsregion *ifsp;
+		INTOFF;
+		ifsp = ifslastp->next->next;
+		ckfree(ifslastp->next);
+		ifslastp->next = ifsp;
+		INTON;
+	}
+	if (ifslastp->endoff > endoff)
+		ifslastp->endoff = endoff;
+}
+
+
+#ifdef CONFIG_ASH_MATH_SUPPORT
+/*
+ * Expand arithmetic expression.  Backup to start of expression,
+ * evaluate, place result in (backed up) result, adjust string position.
+ */
+void
+expari(int quotes)
+{
+	char *p, *start;
+	int begoff;
+	int flag;
+	int len;
+
+	/*      ifsfree(); */
+
+	/*
+	 * This routine is slightly over-complicated for
+	 * efficiency.  Next we scan backwards looking for the
+	 * start of arithmetic.
+	 */
+	start = stackblock();
+	p = expdest - 1;
+	*p = '\0';
+	p--;
+	do {
+		int esc;
+
+		while (*p != CTLARI) {
+			p--;
+#ifdef DEBUG
+			if (p < start) {
+				sh_error("missing CTLARI (shouldn't happen)");
+			}
+#endif
+		}
+
+		esc = esclen(start, p);
+		if (!(esc % 2)) {
+			break;
+		}
+
+		p -= esc + 1;
+	} while (1);
+
+	begoff = p - start;
+
+	removerecordregions(begoff);
+
+	flag = p[1];
+
+	expdest = p;
+
+	if (quotes)
+		rmescapes(p + 2);
+
+	len = cvtnum(dash_arith(p + 2));
+
+	if (flag != '"')
+		recordregion(begoff, begoff + len, 0);
+}
+#endif
+
+/*
+ * Expand stuff in backwards quotes.
+ */
+
+static void
+expbackq(union node *cmd, int quoted, int quotes)
+{
+	struct backcmd in;
+	int i;
+	char buf[128];
+	char *p;
+	char *dest;
+	int startloc;
+	int syntax = quoted? DQSYNTAX : BASESYNTAX;
+	struct stackmark smark;
+
+	INTOFF;
+	setstackmark(&smark);
+	dest = expdest;
+	startloc = dest - (char *)stackblock();
+	grabstackstr(dest);
+	evalbackcmd(cmd, (struct backcmd *) &in);
+	popstackmark(&smark);
+
+	p = in.buf;
+	i = in.nleft;
+	if (i == 0)
+		goto read;
+	for (;;) {
+		memtodest(p, i, syntax, quotes);
+read:
+		if (in.fd < 0)
+			break;
+		i = safe_read(in.fd, buf, sizeof buf);
+		TRACE(("expbackq: read returns %d\n", i));
+		if (i <= 0)
+			break;
+		p = buf;
+	}
+
+	if (in.buf)
+		ckfree(in.buf);
+	if (in.fd >= 0) {
+		close(in.fd);
+		back_exitstatus = waitforjob(in.jp);
+	}
+	INTON;
+
+	/* Eat all trailing newlines */
+	dest = expdest;
+	for (; dest > (char *)stackblock() && dest[-1] == '\n';)
+		STUNPUTC(dest);
+	expdest = dest;
+
+	if (quoted == 0)
+		recordregion(startloc, dest - (char *)stackblock(), 0);
+	TRACE(("evalbackq: size=%d: \"%.*s\"\n",
+		(dest - (char *)stackblock()) - startloc,
+		(dest - (char *)stackblock()) - startloc,
+		stackblock() + startloc));
+}
+
+
+static char *
+scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
+	int zero)
+{
+	char *loc;
+	char *loc2;
+	char c;
+
+	loc = startp;
+	loc2 = rmesc;
+	do {
+		int match;
+		const char *s = loc2;
+		c = *loc2;
+		if (zero) {
+			*loc2 = '\0';
+			s = rmesc;
+		}
+		match = pmatch(str, s);
+		*loc2 = c;
+		if (match)
+			return loc;
+		if (quotes && *loc == CTLESC)
+			loc++;
+		loc++;
+		loc2++;
+	} while (c);
+	return 0;
+}
+
+
+static char *
+scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
+	int zero)
+{
+	int esc = 0;
+	char *loc;
+	char *loc2;
+
+	for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
+		int match;
+		char c = *loc2;
+		const char *s = loc2;
+		if (zero) {
+			*loc2 = '\0';
+			s = rmesc;
+		}
+		match = pmatch(str, s);
+		*loc2 = c;
+		if (match)
+			return loc;
+		loc--;
+		if (quotes) {
+			if (--esc < 0) {
+				esc = esclen(startp, loc);
+			}
+			if (esc % 2) {
+				esc--;
+				loc--;
+			}
+		}
+	}
+	return 0;
+}
+
+static const char *
+subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
+{
+	char *startp;
+	char *loc;
+	int saveherefd = herefd;
+	struct nodelist *saveargbackq = argbackq;
+	int amount;
+	char *rmesc, *rmescend;
+	int zero;
+	char *(*scan)(char *, char *, char *, char *, int , int);
+
+	herefd = -1;
+	argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
+	STPUTC('\0', expdest);
+	herefd = saveherefd;
+	argbackq = saveargbackq;
+	startp = stackblock() + startloc;
+
+	switch (subtype) {
+	case VSASSIGN:
+		setvar(str, startp, 0);
+		amount = startp - expdest;
+		STADJUST(amount, expdest);
+		return startp;
+
+	case VSQUESTION:
+		varunset(p, str, startp, varflags);
+		/* NOTREACHED */
+	}
+
+	subtype -= VSTRIMRIGHT;
+#ifdef DEBUG
+	if (subtype < 0 || subtype > 3)
+		abort();
+#endif
+
+	rmesc = startp;
+	rmescend = stackblock() + strloc;
+	if (quotes) {
+		rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
+		if (rmesc != startp) {
+			rmescend = expdest;
+			startp = stackblock() + startloc;
+		}
+	}
+	rmescend--;
+	str = stackblock() + strloc;
+	preglob(str, varflags & VSQUOTE, 0);
+
+	/* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
+	zero = subtype >> 1;
+	/* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
+	scan = (subtype & 1) ^ zero ? scanleft : scanright;
+
+	loc = scan(startp, rmesc, rmescend, str, quotes, zero);
+	if (loc) {
+		if (zero) {
+			memmove(startp, loc, str - loc);
+			loc = startp + (str - loc) - 1;
+		}
+		*loc = '\0';
+		amount = loc - expdest;
+		STADJUST(amount, expdest);
+	}
+	return loc;
+}
+
+
+/*
+ * Expand a variable, and return a pointer to the next character in the
+ * input string.
+ */
+static char *
+evalvar(char *p, int flag)
+{
+	int subtype;
+	int varflags;
+	char *var;
+	int patloc;
+	int c;
+	int startloc;
+	ssize_t varlen;
+	int easy;
+	int quotes;
+	int quoted;
+
+	quotes = flag & (EXP_FULL | EXP_CASE);
+	varflags = *p++;
+	subtype = varflags & VSTYPE;
+	quoted = varflags & VSQUOTE;
+	var = p;
+	easy = (!quoted || (*var == '@' && shellparam.nparam));
+	startloc = expdest - (char *)stackblock();
+	p = strchr(p, '=') + 1;
+
+again:
+	varlen = varvalue(var, varflags, flag);
+	if (varflags & VSNUL)
+		varlen--;
+
+	if (subtype == VSPLUS) {
+		varlen = -1 - varlen;
+		goto vsplus;
+	}
+
+	if (subtype == VSMINUS) {
+vsplus:
+		if (varlen < 0) {
+			argstr(
+				p, flag | EXP_TILDE |
+					(quoted ?  EXP_QWORD : EXP_WORD)
+			);
+			goto end;
+		}
+		if (easy)
+			goto record;
+		goto end;
+	}
+
+	if (subtype == VSASSIGN || subtype == VSQUESTION) {
+		if (varlen < 0) {
+			if (subevalvar(p, var, 0, subtype, startloc,
+				       varflags, 0)) {
+				varflags &= ~VSNUL;
+				/*
+				 * Remove any recorded regions beyond
+				 * start of variable
+				 */
+				removerecordregions(startloc);
+				goto again;
+			}
+			goto end;
+		}
+		if (easy)
+			goto record;
+		goto end;
+	}
+
+	if (varlen < 0 && uflag)
+		varunset(p, var, 0, 0);
+
+	if (subtype == VSLENGTH) {
+		cvtnum(varlen > 0 ? varlen : 0);
+		goto record;
+	}
+
+	if (subtype == VSNORMAL) {
+		if (!easy)
+			goto end;
+record:
+		recordregion(startloc, expdest - (char *)stackblock(), quoted);
+		goto end;
+	}
+
+#ifdef DEBUG
+	switch (subtype) {
+	case VSTRIMLEFT:
+	case VSTRIMLEFTMAX:
+	case VSTRIMRIGHT:
+	case VSTRIMRIGHTMAX:
+		break;
+	default:
+		abort();
+	}
+#endif
+
+	if (varlen >= 0) {
+		/*
+		 * Terminate the string and start recording the pattern
+		 * right after it
+		 */
+		STPUTC('\0', expdest);
+		patloc = expdest - (char *)stackblock();
+		if (subevalvar(p, NULL, patloc, subtype,
+			       startloc, varflags, quotes) == 0) {
+			int amount = expdest - (
+				(char *)stackblock() + patloc - 1
+			);
+			STADJUST(-amount, expdest);
+		}
+		/* Remove any recorded regions beyond start of variable */
+		removerecordregions(startloc);
+		goto record;
+	}
+
+end:
+	if (subtype != VSNORMAL) {      /* skip to end of alternative */
+		int nesting = 1;
+		for (;;) {
+			if ((c = *p++) == CTLESC)
+				p++;
+			else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
+				if (varlen >= 0)
+					argbackq = argbackq->next;
+			} else if (c == CTLVAR) {
+				if ((*p++ & VSTYPE) != VSNORMAL)
+					nesting++;
+			} else if (c == CTLENDVAR) {
+				if (--nesting == 0)
+					break;
+			}
+		}
+	}
+	return p;
+}
+
+
+/*
+ * Put a string on the stack.
+ */
+
+static void
+memtodest(const char *p, size_t len, int syntax, int quotes) {
+	char *q = expdest;
+
+	q = makestrspace(len * 2, q);
+
+	while (len--) {
+		int c = SC2INT(*p++);
+		if (!c)
+			continue;
+		if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
+			USTPUTC(CTLESC, q);
+		USTPUTC(c, q);
+	}
+
+	expdest = q;
+}
+
+
+static void
+strtodest(const char *p, int syntax, int quotes)
+{
+	memtodest(p, strlen(p), syntax, quotes);
+}
+
+
+/*
+ * Add the value of a specialized variable to the stack string.
+ */
+
+static ssize_t
+varvalue(char *name, int varflags, int flags)
+{
+	int num;
+	char *p;
+	int i;
+	int sep = 0;
+	int sepq = 0;
+	ssize_t len = 0;
+	char **ap;
+	int syntax;
+	int quoted = varflags & VSQUOTE;
+	int subtype = varflags & VSTYPE;
+	int quotes = flags & (EXP_FULL | EXP_CASE);
+
+	if (quoted && (flags & EXP_FULL))
+		sep = 1 << CHAR_BIT;
+
+	syntax = quoted ? DQSYNTAX : BASESYNTAX;
+	switch (*name) {
+	case '$':
+		num = rootpid;
+		goto numvar;
+	case '?':
+		num = exitstatus;
+		goto numvar;
+	case '#':
+		num = shellparam.nparam;
+		goto numvar;
+	case '!':
+		num = backgndpid;
+		if (num == 0)
+			return -1;
+numvar:
+		len = cvtnum(num);
+		break;
+	case '-':
+		p = makestrspace(NOPTS, expdest);
+		for (i = NOPTS - 1; i >= 0; i--) {
+			if (optlist[i]) {
+				USTPUTC(optletters(i), p);
+				len++;
+			}
+		}
+		expdest = p;
+		break;
+	case '@':
+		if (sep)
+			goto param;
+		/* fall through */
+	case '*':
+		sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
+		if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
+			sepq = 1;
+param:
+		if (!(ap = shellparam.p))
+			return -1;
+		while ((p = *ap++)) {
+			size_t partlen;
+
+			partlen = strlen(p);
+			len += partlen;
+
+			if (!(subtype == VSPLUS || subtype == VSLENGTH))
+				memtodest(p, partlen, syntax, quotes);
+
+			if (*ap && sep) {
+				char *q;
+
+				len++;
+				if (subtype == VSPLUS || subtype == VSLENGTH) {
+					continue;
+				}
+				q = expdest;
+				if (sepq)
+					STPUTC(CTLESC, q);
+				STPUTC(sep, q);
+				expdest = q;
+			}
+		}
+		return len;
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+		num = atoi(name);
+		if (num < 0 || num > shellparam.nparam)
+			return -1;
+		p = num ? shellparam.p[num - 1] : arg0;
+		goto value;
+	default:
+		p = lookupvar(name);
+value:
+		if (!p)
+			return -1;
+
+		len = strlen(p);
+		if (!(subtype == VSPLUS || subtype == VSLENGTH))
+			memtodest(p, len, syntax, quotes);
+		return len;
+	}
+
+	if (subtype == VSPLUS || subtype == VSLENGTH)
+		STADJUST(-len, expdest);
+	return len;
+}
+
+
+/*
+ * Record the fact that we have to scan this region of the
+ * string for IFS characters.
+ */
+
+static void
+recordregion(int start, int end, int nulonly)
+{
+	struct ifsregion *ifsp;
+
+	if (ifslastp == NULL) {
+		ifsp = &ifsfirst;
+	} else {
+		INTOFF;
+		ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
+		ifsp->next = NULL;
+		ifslastp->next = ifsp;
+		INTON;
+	}
+	ifslastp = ifsp;
+	ifslastp->begoff = start;
+	ifslastp->endoff = end;
+	ifslastp->nulonly = nulonly;
+}
+
+
+/*
+ * Break the argument string into pieces based upon IFS and add the
+ * strings to the argument list.  The regions of the string to be
+ * searched for IFS characters have been stored by recordregion.
+ */
+static void
+ifsbreakup(char *string, struct arglist *arglist)
+{
+	struct ifsregion *ifsp;
+	struct strlist *sp;
+	char *start;
+	char *p;
+	char *q;
+	const char *ifs, *realifs;
+	int ifsspc;
+	int nulonly;
+
+
+	start = string;
+	if (ifslastp != NULL) {
+		ifsspc = 0;
+		nulonly = 0;
+		realifs = ifsset() ? ifsval() : defifs;
+		ifsp = &ifsfirst;
+		do {
+			p = string + ifsp->begoff;
+			nulonly = ifsp->nulonly;
+			ifs = nulonly ? nullstr : realifs;
+			ifsspc = 0;
+			while (p < string + ifsp->endoff) {
+				q = p;
+				if (*p == CTLESC)
+					p++;
+				if (strchr(ifs, *p)) {
+					if (!nulonly)
+						ifsspc = (strchr(defifs, *p) != NULL);
+					/* Ignore IFS whitespace at start */
+					if (q == start && ifsspc) {
+						p++;
+						start = p;
+						continue;
+					}
+					*q = '\0';
+					sp = (struct strlist *)stalloc(sizeof *sp);
+					sp->text = start;
+					*arglist->lastp = sp;
+					arglist->lastp = &sp->next;
+					p++;
+					if (!nulonly) {
+						for (;;) {
+							if (p >= string + ifsp->endoff) {
+								break;
+							}
+							q = p;
+							if (*p == CTLESC)
+								p++;
+							if (strchr(ifs, *p) == NULL ) {
+								p = q;
+								break;
+							} else if (strchr(defifs, *p) == NULL) {
+								if (ifsspc) {
+									p++;
+									ifsspc = 0;
+								} else {
+									p = q;
+									break;
+								}
+							} else
+								p++;
+						}
+					}
+					start = p;
+				} else
+					p++;
+			}
+		} while ((ifsp = ifsp->next) != NULL);
+		if (nulonly)
+			goto add;
+	}
+
+	if (!*start)
+		return;
+
+add:
+	sp = (struct strlist *)stalloc(sizeof *sp);
+	sp->text = start;
+	*arglist->lastp = sp;
+	arglist->lastp = &sp->next;
+}
+
+static void
+ifsfree(void)
+{
+	struct ifsregion *p;
+
+	INTOFF;
+	p = ifsfirst.next;
+	do {
+		struct ifsregion *ifsp;
+		ifsp = p->next;
+		ckfree(p);
+		p = ifsp;
+	} while (p);
+	ifslastp = NULL;
+	ifsfirst.next = NULL;
+	INTON;
+}
+
+static void expmeta(char *, char *);
+static struct strlist *expsort(struct strlist *);
+static struct strlist *msort(struct strlist *, int);
+
+static char *expdir;
+
+
+static void
+expandmeta(struct strlist *str, int flag)
+{
+	static const char metachars[] = {
+		'*', '?', '[', 0
+	};
+	/* TODO - EXP_REDIR */
+
+	while (str) {
+		struct strlist **savelastp;
+		struct strlist *sp;
+		char *p;
+
+		if (fflag)
+			goto nometa;
+		if (!strpbrk(str->text, metachars))
+			goto nometa;
+		savelastp = exparg.lastp;
+
+		INTOFF;
+		p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
+		{
+			int i = strlen(str->text);
+			expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
+		}
+
+		expmeta(expdir, p);
+		ckfree(expdir);
+		if (p != str->text)
+			ckfree(p);
+		INTON;
+		if (exparg.lastp == savelastp) {
+			/*
+			 * no matches
+			 */
+nometa:
+			*exparg.lastp = str;
+			rmescapes(str->text);
+			exparg.lastp = &str->next;
+		} else {
+			*exparg.lastp = NULL;
+			*savelastp = sp = expsort(*savelastp);
+			while (sp->next != NULL)
+				sp = sp->next;
+			exparg.lastp = &sp->next;
+		}
+		str = str->next;
+	}
+}
+
+/*
+ * Add a file name to the list.
+ */
+
+static void
+addfname(const char *name)
+{
+	struct strlist *sp;
+
+	sp = (struct strlist *)stalloc(sizeof *sp);
+	sp->text = sstrdup(name);
+	*exparg.lastp = sp;
+	exparg.lastp = &sp->next;
+}
+
+
+/*
+ * Do metacharacter (i.e. *, ?, [...]) expansion.
+ */
+
+static void
+expmeta(char *enddir, char *name)
+{
+	char *p;
+	const char *cp;
+	char *start;
+	char *endname;
+	int metaflag;
+	struct stat statb;
+	DIR *dirp;
+	struct dirent *dp;
+	int atend;
+	int matchdot;
+
+	metaflag = 0;
+	start = name;
+	for (p = name; *p; p++) {
+		if (*p == '*' || *p == '?')
+			metaflag = 1;
+		else if (*p == '[') {
+			char *q = p + 1;
+			if (*q == '!')
+				q++;
+			for (;;) {
+				if (*q == '\\')
+					q++;
+				if (*q == '/' || *q == '\0')
+					break;
+				if (*++q == ']') {
+					metaflag = 1;
+					break;
+				}
+			}
+		} else if (*p == '\\')
+			p++;
+		else if (*p == '/') {
+			if (metaflag)
+				goto out;
+			start = p + 1;
+		}
+	}
+out:
+	if (metaflag == 0) {    /* we've reached the end of the file name */
+		if (enddir != expdir)
+			metaflag++;
+		p = name;
+		do {
+			if (*p == '\\')
+				p++;
+			*enddir++ = *p;
+		} while (*p++);
+		if (metaflag == 0 || lstat(expdir, &statb) >= 0)
+			addfname(expdir);
+		return;
+	}
+	endname = p;
+	if (name < start) {
+		p = name;
+		do {
+			if (*p == '\\')
+				p++;
+			*enddir++ = *p++;
+		} while (p < start);
+	}
+	if (enddir == expdir) {
+		cp = ".";
+	} else if (enddir == expdir + 1 && *expdir == '/') {
+		cp = "/";
+	} else {
+		cp = expdir;
+		enddir[-1] = '\0';
+	}
+	if ((dirp = opendir(cp)) == NULL)
+		return;
+	if (enddir != expdir)
+		enddir[-1] = '/';
+	if (*endname == 0) {
+		atend = 1;
+	} else {
+		atend = 0;
+		*endname++ = '\0';
+	}
+	matchdot = 0;
+	p = start;
+	if (*p == '\\')
+		p++;
+	if (*p == '.')
+		matchdot++;
+	while (! intpending && (dp = readdir(dirp)) != NULL) {
+		if (dp->d_name[0] == '.' && ! matchdot)
+			continue;
+		if (pmatch(start, dp->d_name)) {
+			if (atend) {
+				scopy(dp->d_name, enddir);
+				addfname(expdir);
+			} else {
+				for (p = enddir, cp = dp->d_name;
+				     (*p++ = *cp++) != '\0';)
+					continue;
+				p[-1] = '/';
+				expmeta(p, endname);
+			}
+		}
+	}
+	closedir(dirp);
+	if (! atend)
+		endname[-1] = '/';
+}
+
+/*
+ * Sort the results of file name expansion.  It calculates the number of
+ * strings to sort and then calls msort (short for merge sort) to do the
+ * work.
+ */
+
+static struct strlist *
+expsort(struct strlist *str)
+{
+	int len;
+	struct strlist *sp;
+
+	len = 0;
+	for (sp = str ; sp ; sp = sp->next)
+		len++;
+	return msort(str, len);
+}
+
+
+static struct strlist *
+msort(struct strlist *list, int len)
+{
+	struct strlist *p, *q = NULL;
+	struct strlist **lpp;
+	int half;
+	int n;
+
+	if (len <= 1)
+		return list;
+	half = len >> 1;
+	p = list;
+	for (n = half ; --n >= 0 ; ) {
+		q = p;
+		p = p->next;
+	}
+	q->next = NULL;                 /* terminate first half of list */
+	q = msort(list, half);          /* sort first half of list */
+	p = msort(p, len - half);               /* sort second half */
+	lpp = &list;
+	for (;;) {
+#ifdef CONFIG_LOCALE_SUPPORT
+		if (strcoll(p->text, q->text) < 0)
+#else
+		if (strcmp(p->text, q->text) < 0)
+#endif
+						{
+			*lpp = p;
+			lpp = &p->next;
+			if ((p = *lpp) == NULL) {
+				*lpp = q;
+				break;
+			}
+		} else {
+			*lpp = q;
+			lpp = &q->next;
+			if ((q = *lpp) == NULL) {
+				*lpp = p;
+				break;
+			}
+		}
+	}
+	return list;
+}
+
+
+/*
+ * Returns true if the pattern matches the string.
+ */
+
+static inline int
+patmatch(char *pattern, const char *string)
+{
+	return pmatch(preglob(pattern, 0, 0), string);
+}
+
+
+/*
+ * Remove any CTLESC characters from a string.
+ */
+
+static char *
+_rmescapes(char *str, int flag)
+{
+	char *p, *q, *r;
+	static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
+	unsigned inquotes;
+	int notescaped;
+	int globbing;
+
+	p = strpbrk(str, qchars);
+	if (!p) {
+		return str;
+	}
+	q = p;
+	r = str;
+	if (flag & RMESCAPE_ALLOC) {
+		size_t len = p - str;
+		size_t fulllen = len + strlen(p) + 1;
+
+		if (flag & RMESCAPE_GROW) {
+			r = makestrspace(fulllen, expdest);
+		} else if (flag & RMESCAPE_HEAP) {
+			r = ckmalloc(fulllen);
+		} else {
+			r = stalloc(fulllen);
+		}
+		q = r;
+		if (len > 0) {
+			q = mempcpy(q, str, len);
+		}
+	}
+	inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
+	globbing = flag & RMESCAPE_GLOB;
+	notescaped = globbing;
+	while (*p) {
+		if (*p == CTLQUOTEMARK) {
+			inquotes = ~inquotes;
+			p++;
+			notescaped = globbing;
+			continue;
+		}
+		if (*p == '\\') {
+			/* naked back slash */
+			notescaped = 0;
+			goto copy;
+		}
+		if (*p == CTLESC) {
+			p++;
+			if (notescaped && inquotes && *p != '/') {
+				*q++ = '\\';
+			}
+		}
+		notescaped = globbing;
+copy:
+		*q++ = *p++;
+	}
+	*q = '\0';
+	if (flag & RMESCAPE_GROW) {
+		expdest = r;
+		STADJUST(q - r + 1, expdest);
+	}
+	return r;
+}
+
+
+/*
+ * See if a pattern matches in a case statement.
+ */
+
+int
+casematch(union node *pattern, char *val)
+{
+	struct stackmark smark;
+	int result;
+
+	setstackmark(&smark);
+	argbackq = pattern->narg.backquote;
+	STARTSTACKSTR(expdest);
+	ifslastp = NULL;
+	argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
+	STACKSTRNUL(expdest);
+	result = patmatch(stackblock(), val);
+	popstackmark(&smark);
+	return result;
+}
+
+/*
+ * Our own itoa().
+ */
+
+static int
+cvtnum(arith_t num)
+{
+	int len;
+
+	expdest = makestrspace(32, expdest);
+#ifdef CONFIG_ASH_MATH_SUPPORT_64
+	len = fmtstr(expdest, 32, "%lld", (long long) num);
+#else
+	len = fmtstr(expdest, 32, "%ld", num);
+#endif
+	STADJUST(len, expdest);
+	return len;
+}
+
+static void
+varunset(const char *end, const char *var, const char *umsg, int varflags)
+{
+	const char *msg;
+	const char *tail;
+
+	tail = nullstr;
+	msg = "parameter not set";
+	if (umsg) {
+		if (*end == CTLENDVAR) {
+			if (varflags & VSNUL)
+				tail = " or null";
+		} else
+			msg = umsg;
+	}
+	sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
+}
+
+
+/*      input.c      */
+
+/*
+ * This implements the input routines used by the parser.
+ */
+
+#define EOF_NLEFT -99           /* value of parsenleft when EOF pushed back */
+
+static void pushfile(void);
+
+/*
+ * Read a character from the script, returning PEOF on end of file.
+ * Nul characters in the input are silently discarded.
+ */
+
+
+#define pgetc_as_macro()   (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
+
+#ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
+#define pgetc_macro() pgetc()
+static int
+pgetc(void)
+{
+	return pgetc_as_macro();
+}
+#else
+#define pgetc_macro()   pgetc_as_macro()
+static int
+pgetc(void)
+{
+	return pgetc_macro();
+}
+#endif
+
+
+/*
+ * Same as pgetc(), but ignores PEOA.
+ */
+#ifdef CONFIG_ASH_ALIAS
+static int pgetc2(void)
+{
+	int c;
+
+	do {
+		c = pgetc_macro();
+	} while (c == PEOA);
+	return c;
+}
+#else
+static inline int pgetc2(void)
+{
+	return pgetc_macro();
+}
+#endif
+
+/*
+ * Read a line from the script.
+ */
+
+static inline char *
+pfgets(char *line, int len)
+{
+	char *p = line;
+	int nleft = len;
+	int c;
+
+	while (--nleft > 0) {
+		c = pgetc2();
+		if (c == PEOF) {
+			if (p == line)
+				return NULL;
+			break;
+		}
+		*p++ = c;
+		if (c == '\n')
+			break;
+	}
+	*p = '\0';
+	return line;
+}
+
+
+
+#ifdef CONFIG_FEATURE_COMMAND_EDITING
+#ifdef CONFIG_ASH_EXPAND_PRMT
+static char *cmdedit_prompt;
+#else
+static const char *cmdedit_prompt;
+#endif
+static inline void putprompt(const char *s)
+{
+#ifdef CONFIG_ASH_EXPAND_PRMT
+	free(cmdedit_prompt);
+	cmdedit_prompt = bb_xstrdup(s);
+#else
+	cmdedit_prompt = s;
+#endif
+}
+#else
+static inline void putprompt(const char *s)
+{
+	out2str(s);
+}
+#endif
+
+static inline int
+preadfd(void)
+{
+	int nr;
+	char *buf =  parsefile->buf;
+	parsenextc = buf;
+
+retry:
+#ifdef CONFIG_FEATURE_COMMAND_EDITING
+	if (!iflag || parsefile->fd)
+		nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
+	else {
+#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
+		cmdedit_path_lookup = pathval();
+#endif
+		nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
+		if(nr == 0) {
+			/* Ctrl+C presend */
+			if(trap[SIGINT]) {
+				buf[0] = '\n';
+				buf[1] = 0;
+				raise(SIGINT);
+				return 1;
+			}
+			goto retry;
+		}
+		if(nr < 0 && errno == 0) {
+			/* Ctrl+D presend */
+			nr = 0;
+		}
+	}
+#else
+	nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
+#endif
+
+	if (nr < 0) {
+		if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
+			int flags = fcntl(0, F_GETFL, 0);
+			if (flags >= 0 && flags & O_NONBLOCK) {
+				flags &=~ O_NONBLOCK;
+				if (fcntl(0, F_SETFL, flags) >= 0) {
+					out2str("sh: turning off NDELAY mode\n");
+					goto retry;
+				}
+			}
+		}
+	}
+	return nr;
+}
+
+/*
+ * Refill the input buffer and return the next input character:
+ *
+ * 1) If a string was pushed back on the input, pop it;
+ * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
+ *    from a string so we can't refill the buffer, return EOF.
+ * 3) If the is more stuff in this buffer, use it else call read to fill it.
+ * 4) Process input up to the next newline, deleting nul characters.
+ */
+
+int
+preadbuffer(void)
+{
+	char *q;
+	int more;
+	char savec;
+
+	while (parsefile->strpush) {
+#ifdef CONFIG_ASH_ALIAS
+		if (parsenleft == -1 && parsefile->strpush->ap &&
+			parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
+			return PEOA;
+		}
+#endif
+		popstring();
+		if (--parsenleft >= 0)
+			return SC2INT(*parsenextc++);
+	}
+	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
+		return PEOF;
+	flushall();
+
+	more = parselleft;
+	if (more <= 0) {
+again:
+		if ((more = preadfd()) <= 0) {
+			parselleft = parsenleft = EOF_NLEFT;
+			return PEOF;
+		}
+	}
+
+	q = parsenextc;
+
+	/* delete nul characters */
+	for (;;) {
+		int c;
+
+		more--;
+		c = *q;
+
+		if (!c)
+			memmove(q, q + 1, more);
+		else {
+			q++;
+			if (c == '\n') {
+				parsenleft = q - parsenextc - 1;
+				break;
+			}
+		}
+
+		if (more <= 0) {
+			parsenleft = q - parsenextc - 1;
+			if (parsenleft < 0)
+				goto again;
+			break;
+		}
+	}
+	parselleft = more;
+
+	savec = *q;
+	*q = '\0';
+
+	if (vflag) {
+		out2str(parsenextc);
+	}
+
+	*q = savec;
+
+	return SC2INT(*parsenextc++);
+}
+
+/*
+ * Undo the last call to pgetc.  Only one character may be pushed back.
+ * PEOF may be pushed back.
+ */
+
+void
+pungetc(void)
+{
+	parsenleft++;
+	parsenextc--;
+}
+
+/*
+ * Push a string back onto the input at this current parsefile level.
+ * We handle aliases this way.
+ */
+void
+pushstring(char *s, void *ap)
+{
+	struct strpush *sp;
+	size_t len;
+
+	len = strlen(s);
+	INTOFF;
+/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
+	if (parsefile->strpush) {
+		sp = ckmalloc(sizeof (struct strpush));
+		sp->prev = parsefile->strpush;
+		parsefile->strpush = sp;
+	} else
+		sp = parsefile->strpush = &(parsefile->basestrpush);
+	sp->prevstring = parsenextc;
+	sp->prevnleft = parsenleft;
+#ifdef CONFIG_ASH_ALIAS
+	sp->ap = (struct alias *)ap;
+	if (ap) {
+		((struct alias *)ap)->flag |= ALIASINUSE;
+		sp->string = s;
+	}
+#endif
+	parsenextc = s;
+	parsenleft = len;
+	INTON;
+}
+
+void
+popstring(void)
+{
+	struct strpush *sp = parsefile->strpush;
+
+	INTOFF;
+#ifdef CONFIG_ASH_ALIAS
+	if (sp->ap) {
+		if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
+			checkkwd |= CHKALIAS;
+		}
+		if (sp->string != sp->ap->val) {
+			ckfree(sp->string);
+		}
+		sp->ap->flag &= ~ALIASINUSE;
+		if (sp->ap->flag & ALIASDEAD) {
+			unalias(sp->ap->name);
+		}
+	}
+#endif
+	parsenextc = sp->prevstring;
+	parsenleft = sp->prevnleft;
+/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
+	parsefile->strpush = sp->prev;
+	if (sp != &(parsefile->basestrpush))
+		ckfree(sp);
+	INTON;
+}
+
+/*
+ * Set the input to take input from a file.  If push is set, push the
+ * old input onto the stack first.
+ */
+
+static int
+setinputfile(const char *fname, int flags)
+{
+	int fd;
+	int fd2;
+
+	INTOFF;
+	if ((fd = open(fname, O_RDONLY)) < 0) {
+		if (flags & INPUT_NOFILE_OK)
+			goto out;
+		sh_error("Can't open %s", fname);
+	}
+	if (fd < 10) {
+		fd2 = copyfd(fd, 10);
+		close(fd);
+		if (fd2 < 0)
+			sh_error("Out of file descriptors");
+		fd = fd2;
+	}
+	setinputfd(fd, flags & INPUT_PUSH_FILE);
+out:
+	INTON;
+	return fd;
+}
+
+
+/*
+ * Like setinputfile, but takes an open file descriptor.  Call this with
+ * interrupts off.
+ */
+
+static void
+setinputfd(int fd, int push)
+{
+	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
+	if (push) {
+		pushfile();
+		parsefile->buf = 0;
+	}
+	parsefile->fd = fd;
+	if (parsefile->buf == NULL)
+		parsefile->buf = ckmalloc(IBUFSIZ);
+	parselleft = parsenleft = 0;
+	plinno = 1;
+}
+
+
+/*
+ * Like setinputfile, but takes input from a string.
+ */
+
+static void
+setinputstring(char *string)
+{
+	INTOFF;
+	pushfile();
+	parsenextc = string;
+	parsenleft = strlen(string);
+	parsefile->buf = NULL;
+	plinno = 1;
+	INTON;
+}
+
+
+/*
+ * To handle the "." command, a stack of input files is used.  Pushfile
+ * adds a new entry to the stack and popfile restores the previous level.
+ */
+
+static void
+pushfile(void)
+{
+	struct parsefile *pf;
+
+	parsefile->nleft = parsenleft;
+	parsefile->lleft = parselleft;
+	parsefile->nextc = parsenextc;
+	parsefile->linno = plinno;
+	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
+	pf->prev = parsefile;
+	pf->fd = -1;
+	pf->strpush = NULL;
+	pf->basestrpush.prev = NULL;
+	parsefile = pf;
+}
+
+
+static void
+popfile(void)
+{
+	struct parsefile *pf = parsefile;
+
+	INTOFF;
+	if (pf->fd >= 0)
+		close(pf->fd);
+	if (pf->buf)
+		ckfree(pf->buf);
+	while (pf->strpush)
+		popstring();
+	parsefile = pf->prev;
+	ckfree(pf);
+	parsenleft = parsefile->nleft;
+	parselleft = parsefile->lleft;
+	parsenextc = parsefile->nextc;
+	plinno = parsefile->linno;
+	INTON;
+}
+
+
+/*
+ * Return to top level.
+ */
+
+static void
+popallfiles(void)
+{
+	while (parsefile != &basepf)
+		popfile();
+}
+
+
+/*
+ * Close the file(s) that the shell is reading commands from.  Called
+ * after a fork is done.
+ */
+
+static void
+closescript(void)
+{
+	popallfiles();
+	if (parsefile->fd > 0) {
+		close(parsefile->fd);
+		parsefile->fd = 0;
+	}
+}
+
+/*      jobs.c    */
+
+/* mode flags for set_curjob */
+#define CUR_DELETE 2
+#define CUR_RUNNING 1
+#define CUR_STOPPED 0
+
+/* mode flags for dowait */
+#define DOWAIT_NORMAL 0
+#define DOWAIT_BLOCK 1
+
+/* array of jobs */
+static struct job *jobtab;
+/* size of array */
+static unsigned njobs;
+#if JOBS
+/* pgrp of shell on invocation */
+static int initialpgrp;
+static int ttyfd = -1;
+#endif
+/* current job */
+static struct job *curjob;
+/* number of presumed living untracked jobs */
+static int jobless;
+
+static void set_curjob(struct job *, unsigned);
+#if JOBS
+static int restartjob(struct job *, int);
+static void xtcsetpgrp(int, pid_t);
+static char *commandtext(union node *);
+static void cmdlist(union node *, int);
+static void cmdtxt(union node *);
+static void cmdputs(const char *);
+static void showpipe(struct job *, FILE *);
+#endif
+static int sprint_status(char *, int, int);
+static void freejob(struct job *);
+static struct job *getjob(const char *, int);
+static struct job *growjobtab(void);
+static void forkchild(struct job *, union node *, int);
+static void forkparent(struct job *, union node *, int, pid_t);
+static int dowait(int, struct job *);
+static int getstatus(struct job *);
+
+static void
+set_curjob(struct job *jp, unsigned mode)
+{
+	struct job *jp1;
+	struct job **jpp, **curp;
+
+	/* first remove from list */
+	jpp = curp = &curjob;
+	do {
+		jp1 = *jpp;
+		if (jp1 == jp)
+			break;
+		jpp = &jp1->prev_job;
+	} while (1);
+	*jpp = jp1->prev_job;
+
+	/* Then re-insert in correct position */
+	jpp = curp;
+	switch (mode) {
+	default:
+#ifdef DEBUG
+		abort();
+#endif
+	case CUR_DELETE:
+		/* job being deleted */
+		break;
+	case CUR_RUNNING:
+		/* newly created job or backgrounded job,
+		   put after all stopped jobs. */
+		do {
+			jp1 = *jpp;
+#if JOBS
+			if (!jp1 || jp1->state != JOBSTOPPED)
+#endif
+				break;
+			jpp = &jp1->prev_job;
+		} while (1);
+		/* FALLTHROUGH */
+#if JOBS
+	case CUR_STOPPED:
+#endif
+		/* newly stopped job - becomes curjob */
+		jp->prev_job = *jpp;
+		*jpp = jp;
+		break;
+	}
+}
+
+#if JOBS
+/*
+ * Turn job control on and off.
+ *
+ * Note:  This code assumes that the third arg to ioctl is a character
+ * pointer, which is true on Berkeley systems but not System V.  Since
+ * System V doesn't have job control yet, this isn't a problem now.
+ *
+ * Called with interrupts off.
+ */
+
+void
+setjobctl(int on)
+{
+	int fd;
+	int pgrp;
+
+	if (on == jobctl || rootshell == 0)
+		return;
+	if (on) {
+		int ofd;
+		ofd = fd = open(_PATH_TTY, O_RDWR);
+		if (fd < 0) {
+			fd += 3;
+			while (!isatty(fd) && --fd >= 0)
+				;
+		}
+		fd = fcntl(fd, F_DUPFD, 10);
+		close(ofd);
+		if (fd < 0)
+			goto out;
+		fcntl(fd, F_SETFD, FD_CLOEXEC);
+		do { /* while we are in the background */
+			if ((pgrp = tcgetpgrp(fd)) < 0) {
+out:
+				sh_warnx("can't access tty; job control turned off");
+				mflag = on = 0;
+				goto close;
+			}
+			if (pgrp == getpgrp())
+				break;
+			killpg(0, SIGTTIN);
+		} while (1);
+		initialpgrp = pgrp;
+
+		setsignal(SIGTSTP);
+		setsignal(SIGTTOU);
+		setsignal(SIGTTIN);
+		pgrp = rootpid;
+		setpgid(0, pgrp);
+		xtcsetpgrp(fd, pgrp);
+	} else {
+		/* turning job control off */
+		fd = ttyfd;
+		pgrp = initialpgrp;
+		xtcsetpgrp(fd, pgrp);
+		setpgid(0, pgrp);
+		setsignal(SIGTSTP);
+		setsignal(SIGTTOU);
+		setsignal(SIGTTIN);
+close:
+		close(fd);
+		fd = -1;
+	}
+	ttyfd = fd;
+	jobctl = on;
+}
+
+static int
+killcmd(int argc, char **argv)
+{
+	int signo = -1;
+	int list = 0;
+	int i;
+	pid_t pid;
+	struct job *jp;
+
+	if (argc <= 1) {
+usage:
+		sh_error(
+"Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
+"kill -l [exitstatus]"
+		);
+	}
+
+	if (**++argv == '-') {
+		signo = decode_signal(*argv + 1, 1);
+		if (signo < 0) {
+			int c;
+
+			while ((c = nextopt("ls:")) != '\0')
+				switch (c) {
+				default:
+#ifdef DEBUG
+					abort();
+#endif
+				case 'l':
+					list = 1;
+					break;
+				case 's':
+					signo = decode_signal(optionarg, 1);
+					if (signo < 0) {
+						sh_error(
+							"invalid signal number or name: %s",
+							optionarg
+						);
+					}
+					break;
+				}
+			argv = argptr;
+		} else
+			argv++;
+	}
+
+	if (!list && signo < 0)
+		signo = SIGTERM;
+
+	if ((signo < 0 || !*argv) ^ list) {
+		goto usage;
+	}
+
+	if (list) {
+		const char *name;
+
+		if (!*argv) {
+			for (i = 1; i < NSIG; i++) {
+				name = u_signal_names(0, &i, 1);
+				if (name)
+					out1fmt(snlfmt, name);
+			}
+			return 0;
+		}
+		name = u_signal_names(*argptr, &signo, -1);
+		if (name)
+			out1fmt(snlfmt, name);
+		else
+			sh_error("invalid signal number or exit status: %s", *argptr);
+		return 0;
+	}
+
+	i = 0;
+	do {
+		if (**argv == '%') {
+			jp = getjob(*argv, 0);
+			pid = -jp->ps[0].pid;
+		} else {
+			pid = **argv == '-' ?
+				-number(*argv + 1) : number(*argv);
+		}
+		if (kill(pid, signo) != 0) {
+			sh_warnx("(%d) - %m", pid);
+			i = 1;
+		}
+	} while (*++argv);
+
+	return i;
+}
+#endif /* JOBS */
+
+#if defined(JOBS) || defined(DEBUG)
+static int
+jobno(const struct job *jp)
+{
+	return jp - jobtab + 1;
+}
+#endif
+
+#if JOBS
+static int
+fgcmd(int argc, char **argv)
+{
+	struct job *jp;
+	FILE *out;
+	int mode;
+	int retval;
+
+	mode = (**argv == 'f') ? FORK_FG : FORK_BG;
+	nextopt(nullstr);
+	argv = argptr;
+	out = stdout;
+	do {
+		jp = getjob(*argv, 1);
+		if (mode == FORK_BG) {
+			set_curjob(jp, CUR_RUNNING);
+			fprintf(out, "[%d] ", jobno(jp));
+		}
+		outstr(jp->ps->cmd, out);
+		showpipe(jp, out);
+		retval = restartjob(jp, mode);
+	} while (*argv && *++argv);
+	return retval;
+}
+
+static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
+
+
+static int
+restartjob(struct job *jp, int mode)
+{
+	struct procstat *ps;
+	int i;
+	int status;
+	pid_t pgid;
+
+	INTOFF;
+	if (jp->state == JOBDONE)
+		goto out;
+	jp->state = JOBRUNNING;
+	pgid = jp->ps->pid;
+	if (mode == FORK_FG)
+		xtcsetpgrp(ttyfd, pgid);
+	killpg(pgid, SIGCONT);
+	ps = jp->ps;
+	i = jp->nprocs;
+	do {
+		if (WIFSTOPPED(ps->status)) {
+			ps->status = -1;
+		}
+	} while (ps++, --i);
+out:
+	status = (mode == FORK_FG) ? waitforjob(jp) : 0;
+	INTON;
+	return status;
+}
+#endif
+
+static int
+sprint_status(char *s, int status, int sigonly)
+{
+	int col;
+	int st;
+
+	col = 0;
+	if (!WIFEXITED(status)) {
+#if JOBS
+		if (WIFSTOPPED(status))
+			st = WSTOPSIG(status);
+		else
+#endif
+			st = WTERMSIG(status);
+		if (sigonly) {
+			if (st == SIGINT || st == SIGPIPE)
+				goto out;
+#if JOBS
+			if (WIFSTOPPED(status))
+				goto out;
+#endif
+		}
+		st &= 0x7f;
+		col = fmtstr(s, 32, strsignal(st));
+		if (WCOREDUMP(status)) {
+			col += fmtstr(s + col, 16, " (core dumped)");
+		}
+	} else if (!sigonly) {
+		st = WEXITSTATUS(status);
+		if (st)
+			col = fmtstr(s, 16, "Done(%d)", st);
+		else
+			col = fmtstr(s, 16, "Done");
+	}
+
+out:
+	return col;
+}
+
+#if JOBS
+static void
+showjob(FILE *out, struct job *jp, int mode)
+{
+	struct procstat *ps;
+	struct procstat *psend;
+	int col;
+	int indent;
+	char s[80];
+
+	ps = jp->ps;
+
+	if (mode & SHOW_PGID) {
+		/* just output process (group) id of pipeline */
+		fprintf(out, "%d\n", ps->pid);
+		return;
+	}
+
+	col = fmtstr(s, 16, "[%d]   ", jobno(jp));
+	indent = col;
+
+	if (jp == curjob)
+		s[col - 2] = '+';
+	else if (curjob && jp == curjob->prev_job)
+		s[col - 2] = '-';
+
+	if (mode & SHOW_PID)
+		col += fmtstr(s + col, 16, "%d ", ps->pid);
+
+	psend = ps + jp->nprocs;
+
+	if (jp->state == JOBRUNNING) {
+		scopy("Running", s + col);
+		col += strlen("Running");
+	} else {
+		int status = psend[-1].status;
+#if JOBS
+		if (jp->state == JOBSTOPPED)
+			status = jp->stopstatus;
+#endif
+		col += sprint_status(s + col, status, 0);
+	}
+
+	goto start;
+
+	do {
+		/* for each process */
+		col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
+
+start:
+		fprintf(out, "%s%*c%s",
+			s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
+		);
+		if (!(mode & SHOW_PID)) {
+			showpipe(jp, out);
+			break;
+		}
+		if (++ps == psend) {
+			outcslow('\n', out);
+			break;
+		}
+	} while (1);
+
+	jp->changed = 0;
+
+	if (jp->state == JOBDONE) {
+		TRACE(("showjob: freeing job %d\n", jobno(jp)));
+		freejob(jp);
+	}
+}
+
+
+static int
+jobscmd(int argc, char **argv)
+{
+	int mode, m;
+	FILE *out;
+
+	mode = 0;
+	while ((m = nextopt("lp")))
+		if (m == 'l')
+			mode = SHOW_PID;
+		else
+			mode = SHOW_PGID;
+
+	out = stdout;
+	argv = argptr;
+	if (*argv)
+		do
+			showjob(out, getjob(*argv,0), mode);
+		while (*++argv);
+	else
+		showjobs(out, mode);
+
+	return 0;
+}
+
+
+/*
+ * Print a list of jobs.  If "change" is nonzero, only print jobs whose
+ * statuses have changed since the last call to showjobs.
+ */
+
+static void
+showjobs(FILE *out, int mode)
+{
+	struct job *jp;
+
+	TRACE(("showjobs(%x) called\n", mode));
+
+	/* If not even one one job changed, there is nothing to do */
+	while (dowait(DOWAIT_NORMAL, NULL) > 0)
+		continue;
+
+	for (jp = curjob; jp; jp = jp->prev_job) {
+		if (!(mode & SHOW_CHANGED) || jp->changed)
+			showjob(out, jp, mode);
+	}
+}
+#endif /* JOBS */
+
+/*
+ * Mark a job structure as unused.
+ */
+
+static void
+freejob(struct job *jp)
+{
+	struct procstat *ps;
+	int i;
+
+	INTOFF;
+	for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
+		if (ps->cmd != nullstr)
+			ckfree(ps->cmd);
+	}
+	if (jp->ps != &jp->ps0)
+		ckfree(jp->ps);
+	jp->used = 0;
+	set_curjob(jp, CUR_DELETE);
+	INTON;
+}
+
+
+static int
+waitcmd(int argc, char **argv)
+{
+	struct job *job;
+	int retval;
+	struct job *jp;
+
+	EXSIGON();
+
+	nextopt(nullstr);
+	retval = 0;
+
+	argv = argptr;
+	if (!*argv) {
+		/* wait for all jobs */
+		for (;;) {
+			jp = curjob;
+			while (1) {
+				if (!jp) {
+					/* no running procs */
+					goto out;
+				}
+				if (jp->state == JOBRUNNING)
+					break;
+				jp->waited = 1;
+				jp = jp->prev_job;
+			}
+			dowait(DOWAIT_BLOCK, 0);
+		}
+	}
+
+	retval = 127;
+	do {
+		if (**argv != '%') {
+			pid_t pid = number(*argv);
+			job = curjob;
+			goto start;
+			do {
+				if (job->ps[job->nprocs - 1].pid == pid)
+					break;
+				job = job->prev_job;
+start:
+				if (!job)
+					goto repeat;
+			} while (1);
+		} else
+			job = getjob(*argv, 0);
+		/* loop until process terminated or stopped */
+		while (job->state == JOBRUNNING)
+			dowait(DOWAIT_BLOCK, 0);
+		job->waited = 1;
+		retval = getstatus(job);
+repeat:
+		;
+	} while (*++argv);
+
+out:
+	return retval;
+}
+
+
+/*
+ * Convert a job name to a job structure.
+ */
+
+static struct job *
+getjob(const char *name, int getctl)
+{
+	struct job *jp;
+	struct job *found;
+	const char *err_msg = "No such job: %s";
+	unsigned num;
+	int c;
+	const char *p;
+	char *(*match)(const char *, const char *);
+
+	jp = curjob;
+	p = name;
+	if (!p)
+		goto currentjob;
+
+	if (*p != '%')
+		goto err;
+
+	c = *++p;
+	if (!c)
+		goto currentjob;
+
+	if (!p[1]) {
+		if (c == '+' || c == '%') {
+currentjob:
+			err_msg = "No current job";
+			goto check;
+		} else if (c == '-') {
+			if (jp)
+				jp = jp->prev_job;
+			err_msg = "No previous job";
+check:
+			if (!jp)
+				goto err;
+			goto gotit;
+		}
+	}
+
+	if (is_number(p)) {
+		num = atoi(p);
+		if (num < njobs) {
+			jp = jobtab + num - 1;
+			if (jp->used)
+				goto gotit;
+			goto err;
+		}
+	}
+
+	match = prefix;
+	if (*p == '?') {
+		match = strstr;
+		p++;
+	}
+
+	found = 0;
+	while (1) {
+		if (!jp)
+			goto err;
+		if (match(jp->ps[0].cmd, p)) {
+			if (found)
+				goto err;
+			found = jp;
+			err_msg = "%s: ambiguous";
+		}
+		jp = jp->prev_job;
+	}
+
+gotit:
+#if JOBS
+	err_msg = "job %s not created under job control";
+	if (getctl && jp->jobctl == 0)
+		goto err;
+#endif
+	return jp;
+err:
+	sh_error(err_msg, name);
+}
+
+
+/*
+ * Return a new job structure.
+ * Called with interrupts off.
+ */
+
+static struct job *
+makejob(union node *node, int nprocs)
+{
+	int i;
+	struct job *jp;
+
+	for (i = njobs, jp = jobtab ; ; jp++) {
+		if (--i < 0) {
+			jp = growjobtab();
+			break;
+		}
+		if (jp->used == 0)
+			break;
+		if (jp->state != JOBDONE || !jp->waited)
+			continue;
+#if JOBS
+		if (jobctl)
+			continue;
+#endif
+		freejob(jp);
+		break;
+	}
+	memset(jp, 0, sizeof(*jp));
+#if JOBS
+	if (jobctl)
+		jp->jobctl = 1;
+#endif
+	jp->prev_job = curjob;
+	curjob = jp;
+	jp->used = 1;
+	jp->ps = &jp->ps0;
+	if (nprocs > 1) {
+		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
+	}
+	TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
+	    jobno(jp)));
+	return jp;
+}
+
+static struct job *
+growjobtab(void)
+{
+	size_t len;
+	ptrdiff_t offset;
+	struct job *jp, *jq;
+
+	len = njobs * sizeof(*jp);
+	jq = jobtab;
+	jp = ckrealloc(jq, len + 4 * sizeof(*jp));
+
+	offset = (char *)jp - (char *)jq;
+	if (offset) {
+		/* Relocate pointers */
+		size_t l = len;
+
+		jq = (struct job *)((char *)jq + l);
+		while (l) {
+			l -= sizeof(*jp);
+			jq--;
+#define joff(p) ((struct job *)((char *)(p) + l))
+#define jmove(p) (p) = (void *)((char *)(p) + offset)
+			if (xlikely(joff(jp)->ps == &jq->ps0))
+				jmove(joff(jp)->ps);
+			if (joff(jp)->prev_job)
+				jmove(joff(jp)->prev_job);
+		}
+		if (curjob)
+			jmove(curjob);
+#undef joff
+#undef jmove
+	}
+
+	njobs += 4;
+	jobtab = jp;
+	jp = (struct job *)((char *)jp + len);
+	jq = jp + 3;
+	do {
+		jq->used = 0;
+	} while (--jq >= jp);
+	return jp;
+}
+
+
+/*
+ * Fork off a subshell.  If we are doing job control, give the subshell its
+ * own process group.  Jp is a job structure that the job is to be added to.
+ * N is the command that will be evaluated by the child.  Both jp and n may
+ * be NULL.  The mode parameter can be one of the following:
+ *      FORK_FG - Fork off a foreground process.
+ *      FORK_BG - Fork off a background process.
+ *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
+ *                   process group even if job control is on.
+ *
+ * When job control is turned off, background processes have their standard
+ * input redirected to /dev/null (except for the second and later processes
+ * in a pipeline).
+ *
+ * Called with interrupts off.
+ */
+
+static inline void
+forkchild(struct job *jp, union node *n, int mode)
+{
+	int oldlvl;
+
+	TRACE(("Child shell %d\n", getpid()));
+	oldlvl = shlvl;
+	shlvl++;
+
+	closescript();
+	clear_traps();
+#if JOBS
+	/* do job control only in root shell */
+	jobctl = 0;
+	if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
+		pid_t pgrp;
+
+		if (jp->nprocs == 0)
+			pgrp = getpid();
+		else
+			pgrp = jp->ps[0].pid;
+		/* This can fail because we are doing it in the parent also */
+		(void)setpgid(0, pgrp);
+		if (mode == FORK_FG)
+			xtcsetpgrp(ttyfd, pgrp);
+		setsignal(SIGTSTP);
+		setsignal(SIGTTOU);
+	} else
+#endif
+	if (mode == FORK_BG) {
+		ignoresig(SIGINT);
+		ignoresig(SIGQUIT);
+		if (jp->nprocs == 0) {
+			close(0);
+			if (open(bb_dev_null, O_RDONLY) != 0)
+				sh_error("Can't open %s", bb_dev_null);
+		}
+	}
+	if (!oldlvl && iflag) {
+		setsignal(SIGINT);
+		setsignal(SIGQUIT);
+		setsignal(SIGTERM);
+	}
+	for (jp = curjob; jp; jp = jp->prev_job)
+		freejob(jp);
+	jobless = 0;
+}
+
+static inline void
+forkparent(struct job *jp, union node *n, int mode, pid_t pid)
+{
+	TRACE(("In parent shell:  child = %d\n", pid));
+	if (!jp) {
+		while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
+		jobless++;
+		return;
+	}
+#if JOBS
+	if (mode != FORK_NOJOB && jp->jobctl) {
+		int pgrp;
+
+		if (jp->nprocs == 0)
+			pgrp = pid;
+		else
+			pgrp = jp->ps[0].pid;
+		/* This can fail because we are doing it in the child also */
+		(void)setpgid(pid, pgrp);
+	}
+#endif
+	if (mode == FORK_BG) {
+		backgndpid = pid;               /* set $! */
+		set_curjob(jp, CUR_RUNNING);
+	}
+	if (jp) {
+		struct procstat *ps = &jp->ps[jp->nprocs++];
+		ps->pid = pid;
+		ps->status = -1;
+		ps->cmd = nullstr;
+#if JOBS
+		if (jobctl && n)
+			ps->cmd = commandtext(n);
+#endif
+	}
+}
+
+static int
+forkshell(struct job *jp, union node *n, int mode)
+{
+	int pid;
+
+	TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
+	pid = fork();
+	if (pid < 0) {
+		TRACE(("Fork failed, errno=%d", errno));
+		if (jp)
+			freejob(jp);
+		sh_error("Cannot fork");
+	}
+	if (pid == 0)
+		forkchild(jp, n, mode);
+	else
+		forkparent(jp, n, mode, pid);
+	return pid;
+}
+
+/*
+ * Wait for job to finish.
+ *
+ * Under job control we have the problem that while a child process is
+ * running interrupts generated by the user are sent to the child but not
+ * to the shell.  This means that an infinite loop started by an inter-
+ * active user may be hard to kill.  With job control turned off, an
+ * interactive user may place an interactive program inside a loop.  If
+ * the interactive program catches interrupts, the user doesn't want
+ * these interrupts to also abort the loop.  The approach we take here
+ * is to have the shell ignore interrupt signals while waiting for a
+ * foreground process to terminate, and then send itself an interrupt
+ * signal if the child process was terminated by an interrupt signal.
+ * Unfortunately, some programs want to do a bit of cleanup and then
+ * exit on interrupt; unless these processes terminate themselves by
+ * sending a signal to themselves (instead of calling exit) they will
+ * confuse this approach.
+ *
+ * Called with interrupts off.
+ */
+
+int
+waitforjob(struct job *jp)
+{
+	int st;
+
+	TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
+	while (jp->state == JOBRUNNING) {
+		dowait(DOWAIT_BLOCK, jp);
+	}
+	st = getstatus(jp);
+#if JOBS
+	if (jp->jobctl) {
+		xtcsetpgrp(ttyfd, rootpid);
+		/*
+		 * This is truly gross.
+		 * If we're doing job control, then we did a TIOCSPGRP which
+		 * caused us (the shell) to no longer be in the controlling
+		 * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
+		 * intuit from the subprocess exit status whether a SIGINT
+		 * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
+		 */
+		if (jp->sigint)
+			raise(SIGINT);
+	}
+	if (jp->state == JOBDONE)
+#endif
+		freejob(jp);
+	return st;
+}
+
+
+/*
+ * Do a wait system call.  If job control is compiled in, we accept
+ * stopped processes.  If block is zero, we return a value of zero
+ * rather than blocking.
+ *
+ * System V doesn't have a non-blocking wait system call.  It does
+ * have a SIGCLD signal that is sent to a process when one of it's
+ * children dies.  The obvious way to use SIGCLD would be to install
+ * a handler for SIGCLD which simply bumped a counter when a SIGCLD
+ * was received, and have waitproc bump another counter when it got
+ * the status of a process.  Waitproc would then know that a wait
+ * system call would not block if the two counters were different.
+ * This approach doesn't work because if a process has children that
+ * have not been waited for, System V will send it a SIGCLD when it
+ * installs a signal handler for SIGCLD.  What this means is that when
+ * a child exits, the shell will be sent SIGCLD signals continuously
+ * until is runs out of stack space, unless it does a wait call before
+ * restoring the signal handler.  The code below takes advantage of
+ * this (mis)feature by installing a signal handler for SIGCLD and
+ * then checking to see whether it was called.  If there are any
+ * children to be waited for, it will be.
+ *
+ * If neither SYSV nor BSD is defined, we don't implement nonblocking
+ * waits at all.  In this case, the user will not be informed when
+ * a background process until the next time she runs a real program
+ * (as opposed to running a builtin command or just typing return),
+ * and the jobs command may give out of date information.
+ */
+
+static inline int
+waitproc(int block, int *status)
+{
+	int flags = 0;
+
+#if JOBS
+	if (jobctl)
+		flags |= WUNTRACED;
+#endif
+	if (block == 0)
+		flags |= WNOHANG;
+	return wait3(status, flags, (struct rusage *)NULL);
+}
+
+/*
+ * Wait for a process to terminate.
+ */
+
+static int
+dowait(int block, struct job *job)
+{
+	int pid;
+	int status;
+	struct job *jp;
+	struct job *thisjob;
+	int state;
+
+	TRACE(("dowait(%d) called\n", block));
+	pid = waitproc(block, &status);
+	TRACE(("wait returns pid %d, status=%d\n", pid, status));
+	if (pid <= 0)
+		return pid;
+	INTOFF;
+	thisjob = NULL;
+	for (jp = curjob; jp; jp = jp->prev_job) {
+		struct procstat *sp;
+		struct procstat *spend;
+		if (jp->state == JOBDONE)
+			continue;
+		state = JOBDONE;
+		spend = jp->ps + jp->nprocs;
+		sp = jp->ps;
+		do {
+			if (sp->pid == pid) {
+				TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
+				sp->status = status;
+				thisjob = jp;
+			}
+			if (sp->status == -1)
+				state = JOBRUNNING;
+#if JOBS
+			if (state == JOBRUNNING)
+				continue;
+			if (WIFSTOPPED(sp->status)) {
+				jp->stopstatus = sp->status;
+				state = JOBSTOPPED;
+			}
+#endif
+		} while (++sp < spend);
+		if (thisjob)
+			goto gotjob;
+	}
+#if JOBS
+	if (!WIFSTOPPED(status))
+#endif
+
+		jobless--;
+	goto out;
+
+gotjob:
+	if (state != JOBRUNNING) {
+		thisjob->changed = 1;
+
+		if (thisjob->state != state) {
+			TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
+			thisjob->state = state;
+#if JOBS
+			if (state == JOBSTOPPED) {
+				set_curjob(thisjob, CUR_STOPPED);
+			}
+#endif
+		}
+	}
+
+out:
+	INTON;
+
+	if (thisjob && thisjob == job) {
+		char s[48 + 1];
+		int len;
+
+		len = sprint_status(s, status, 1);
+		if (len) {
+			s[len] = '\n';
+			s[len + 1] = 0;
+			out2str(s);
+		}
+	}
+	return pid;
+}
+
+
+/*
+ * return 1 if there are stopped jobs, otherwise 0
+ */
+
+int
+stoppedjobs(void)
+{
+	struct job *jp;
+	int retval;
+
+	retval = 0;
+	if (job_warning)
+		goto out;
+	jp = curjob;
+	if (jp && jp->state == JOBSTOPPED) {
+		out2str("You have stopped jobs.\n");
+		job_warning = 2;
+		retval++;
+	}
+
+out:
+	return retval;
+}
+
+/*
+ * Return a string identifying a command (to be printed by the
+ * jobs command).
+ */
+
+#if JOBS
+static char *cmdnextc;
+
+static char *
+commandtext(union node *n)
+{
+	char *name;
+
+	STARTSTACKSTR(cmdnextc);
+	cmdtxt(n);
+	name = stackblock();
+	TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
+		name, cmdnextc, cmdnextc));
+	return savestr(name);
+}
+
+static void
+cmdtxt(union node *n)
+{
+	union node *np;
+	struct nodelist *lp;
+	const char *p;
+	char s[2];
+
+	if (!n)
+		return;
+	switch (n->type) {
+	default:
+#if DEBUG
+		abort();
+#endif
+	case NPIPE:
+		lp = n->npipe.cmdlist;
+		for (;;) {
+			cmdtxt(lp->n);
+			lp = lp->next;
+			if (!lp)
+				break;
+			cmdputs(" | ");
+		}
+		break;
+	case NSEMI:
+		p = "; ";
+		goto binop;
+	case NAND:
+		p = " && ";
+		goto binop;
+	case NOR:
+		p = " || ";
+binop:
+		cmdtxt(n->nbinary.ch1);
+		cmdputs(p);
+		n = n->nbinary.ch2;
+		goto donode;
+	case NREDIR:
+	case NBACKGND:
+		n = n->nredir.n;
+		goto donode;
+	case NNOT:
+		cmdputs("!");
+		n = n->nnot.com;
+donode:
+		cmdtxt(n);
+		break;
+	case NIF:
+		cmdputs("if ");
+		cmdtxt(n->nif.test);
+		cmdputs("; then ");
+		n = n->nif.ifpart;
+		if (n->nif.elsepart) {
+			cmdtxt(n);
+			cmdputs("; else ");
+			n = n->nif.elsepart;
+		}
+		p = "; fi";
+		goto dotail;
+	case NSUBSHELL:
+		cmdputs("(");
+		n = n->nredir.n;
+		p = ")";
+		goto dotail;
+	case NWHILE:
+		p = "while ";
+		goto until;
+	case NUNTIL:
+		p = "until ";
+until:
+		cmdputs(p);
+		cmdtxt(n->nbinary.ch1);
+		n = n->nbinary.ch2;
+		p = "; done";
+dodo:
+		cmdputs("; do ");
+dotail:
+		cmdtxt(n);
+		goto dotail2;
+	case NFOR:
+		cmdputs("for ");
+		cmdputs(n->nfor.var);
+		cmdputs(" in ");
+		cmdlist(n->nfor.args, 1);
+		n = n->nfor.body;
+		p = "; done";
+		goto dodo;
+	case NDEFUN:
+		cmdputs(n->narg.text);
+		p = "() { ... }";
+		goto dotail2;
+	case NCMD:
+		cmdlist(n->ncmd.args, 1);
+		cmdlist(n->ncmd.redirect, 0);
+		break;
+	case NARG:
+		p = n->narg.text;
+dotail2:
+		cmdputs(p);
+		break;
+	case NHERE:
+	case NXHERE:
+		p = "<<...";
+		goto dotail2;
+	case NCASE:
+		cmdputs("case ");
+		cmdputs(n->ncase.expr->narg.text);
+		cmdputs(" in ");
+		for (np = n->ncase.cases; np; np = np->nclist.next) {
+			cmdtxt(np->nclist.pattern);
+			cmdputs(") ");
+			cmdtxt(np->nclist.body);
+			cmdputs(";; ");
+		}
+		p = "esac";
+		goto dotail2;
+	case NTO:
+		p = ">";
+		goto redir;
+	case NCLOBBER:
+		p = ">|";
+		goto redir;
+	case NAPPEND:
+		p = ">>";
+		goto redir;
+	case NTOFD:
+		p = ">&";
+		goto redir;
+	case NFROM:
+		p = "<";
+		goto redir;
+	case NFROMFD:
+		p = "<&";
+		goto redir;
+	case NFROMTO:
+		p = "<>";
+redir:
+		s[0] = n->nfile.fd + '0';
+		s[1] = '\0';
+		cmdputs(s);
+		cmdputs(p);
+		if (n->type == NTOFD || n->type == NFROMFD) {
+			s[0] = n->ndup.dupfd + '0';
+			p = s;
+			goto dotail2;
+		} else {
+			n = n->nfile.fname;
+			goto donode;
+		}
+	}
+}
+
+static void
+cmdlist(union node *np, int sep)
+{
+	for (; np; np = np->narg.next) {
+		if (!sep)
+			cmdputs(spcstr);
+		cmdtxt(np);
+		if (sep && np->narg.next)
+			cmdputs(spcstr);
+	}
+}
+
+static void
+cmdputs(const char *s)
+{
+	const char *p, *str;
+	char c, cc[2] = " ";
+	char *nextc;
+	int subtype = 0;
+	int quoted = 0;
+	static const char vstype[VSTYPE + 1][4] = {
+		"", "}", "-", "+", "?", "=",
+		"%", "%%", "#", "##"
+	};
+	nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
+	p = s;
+	while ((c = *p++) != 0) {
+		str = 0;
+		switch (c) {
+		case CTLESC:
+			c = *p++;
+			break;
+		case CTLVAR:
+			subtype = *p++;
+			if ((subtype & VSTYPE) == VSLENGTH)
+				str = "${#";
+			else
+				str = "${";
+			if (!(subtype & VSQUOTE) != !(quoted & 1)) {
+				quoted ^= 1;
+				c = '"';
+			} else
+				goto dostr;
+			break;
+		case CTLENDVAR:
+			str = "\"}" + !(quoted & 1);
+			quoted >>= 1;
+			subtype = 0;
+			goto dostr;
+		case CTLBACKQ:
+			str = "$(...)";
+			goto dostr;
+		case CTLBACKQ+CTLQUOTE:
+			str = "\"$(...)\"";
+			goto dostr;
+#ifdef CONFIG_ASH_MATH_SUPPORT
+		case CTLARI:
+			str = "$((";
+			goto dostr;
+		case CTLENDARI:
+			str = "))";
+			goto dostr;
+#endif
+		case CTLQUOTEMARK:
+			quoted ^= 1;
+			c = '"';
+			break;
+		case '=':
+			if (subtype == 0)
+				break;
+			if ((subtype & VSTYPE) != VSNORMAL)
+				quoted <<= 1;
+			str = vstype[subtype & VSTYPE];
+			if (subtype & VSNUL)
+				c = ':';
+			else
+				goto checkstr;
+			break;
+		case '\'':
+		case '\\':
+		case '"':
+		case '$':
+			/* These can only happen inside quotes */
+			cc[0] = c;
+			str = cc;
+			c = '\\';
+			break;
+		default:
+			break;
+		}
+		USTPUTC(c, nextc);
+checkstr:
+		if (!str)
+			continue;
+dostr:
+		while ((c = *str++)) {
+			USTPUTC(c, nextc);
+		}
+	}
+	if (quoted & 1) {
+		USTPUTC('"', nextc);
+	}
+	*nextc = 0;
+	cmdnextc = nextc;
+}
+
+
+static void
+showpipe(struct job *jp, FILE *out)
+{
+	struct procstat *sp;
+	struct procstat *spend;
+
+	spend = jp->ps + jp->nprocs;
+	for (sp = jp->ps + 1; sp < spend; sp++)
+		fprintf(out, " | %s", sp->cmd);
+	outcslow('\n', out);
+	flushall();
+}
+
+static void
+xtcsetpgrp(int fd, pid_t pgrp)
+{
+	if (tcsetpgrp(fd, pgrp))
+		sh_error("Cannot set tty process group (%m)");
+}
+#endif /* JOBS */
+
+static int
+getstatus(struct job *job) {
+	int status;
+	int retval;
+
+	status = job->ps[job->nprocs - 1].status;
+	retval = WEXITSTATUS(status);
+	if (!WIFEXITED(status)) {
+#if JOBS
+		retval = WSTOPSIG(status);
+		if (!WIFSTOPPED(status))
+#endif
+		{
+			/* XXX: limits number of signals */
+			retval = WTERMSIG(status);
+#if JOBS
+			if (retval == SIGINT)
+				job->sigint = 1;
+#endif
+		}
+		retval += 128;
+	}
+	TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
+		jobno(job), job->nprocs, status, retval));
+	return retval;
+}
+
+#ifdef CONFIG_ASH_MAIL
+/*      mail.c       */
+
+/*
+ * Routines to check for mail.  (Perhaps make part of main.c?)
+ */
+
+#define MAXMBOXES 10
+
+/* times of mailboxes */
+static time_t mailtime[MAXMBOXES];
+/* Set if MAIL or MAILPATH is changed. */
+static int mail_var_path_changed;
+
+
+
+/*
+ * Print appropriate message(s) if mail has arrived.
+ * If mail_var_path_changed is set,
+ * then the value of MAIL has mail_var_path_changed,
+ * so we just update the values.
+ */
+
+static void
+chkmail(void)
+{
+	const char *mpath;
+	char *p;
+	char *q;
+	time_t *mtp;
+	struct stackmark smark;
+	struct stat statb;
+
+	setstackmark(&smark);
+	mpath = mpathset() ? mpathval() : mailval();
+	for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
+		p = padvance(&mpath, nullstr);
+		if (p == NULL)
+			break;
+		if (*p == '\0')
+			continue;
+		for (q = p ; *q ; q++);
+#ifdef DEBUG
+		if (q[-1] != '/')
+			abort();
+#endif
+		q[-1] = '\0';                   /* delete trailing '/' */
+		if (stat(p, &statb) < 0) {
+			*mtp = 0;
+			continue;
+		}
+		if (!mail_var_path_changed && statb.st_mtime != *mtp) {
+			fprintf(
+				stderr, snlfmt,
+				pathopt ? pathopt : "you have mail"
+			);
+		}
+		*mtp = statb.st_mtime;
+	}
+	mail_var_path_changed = 0;
+	popstackmark(&smark);
+}
+
+
+static void
+changemail(const char *val)
+{
+	mail_var_path_changed++;
+}
+
+#endif /* CONFIG_ASH_MAIL */
+
+/*      main.c       */
+
+
+#if PROFILE
+static short profile_buf[16384];
+extern int etext();
+#endif
+
+static int isloginsh;
+
+static void read_profile(const char *);
+
+/*
+ * Main routine.  We initialize things, parse the arguments, execute
+ * profiles if we're a login shell, and then call cmdloop to execute
+ * commands.  The setjmp call sets up the location to jump to when an
+ * exception occurs.  When an exception occurs the variable "state"
+ * is used to figure out how far we had gotten.
+ */
+
+int
+ash_main(int argc, char **argv)
+{
+	char *shinit;
+	volatile int state;
+	struct jmploc jmploc;
+	struct stackmark smark;
+
+#ifdef __GLIBC__
+	dash_errno = __errno_location();
+#endif
+
+#if PROFILE
+	monitor(4, etext, profile_buf, sizeof profile_buf, 50);
+#endif
+	state = 0;
+	if (setjmp(jmploc.loc)) {
+		int e;
+		int s;
+
+		reset();
+
+		e = exception;
+		if (e == EXERROR)
+			exitstatus = 2;
+		s = state;
+		if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
+			exitshell();
+
+		if (e == EXINT) {
+			outcslow('\n', stderr);
+		}
+		popstackmark(&smark);
+		FORCEINTON;                             /* enable interrupts */
+		if (s == 1)
+			goto state1;
+		else if (s == 2)
+			goto state2;
+		else if (s == 3)
+			goto state3;
+		else
+			goto state4;
+	}
+	handler = &jmploc;
+#ifdef DEBUG
+	opentrace();
+	trputs("Shell args:  ");  trargs(argv);
+#endif
+	rootpid = getpid();
+
+#ifdef CONFIG_ASH_RANDOM_SUPPORT
+	rseed = rootpid + ((time_t)time((time_t *)0));
+#endif
+	init();
+	setstackmark(&smark);
+	procargs(argc, argv);
+#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
+	if ( iflag ) {
+		const char *hp = lookupvar("HISTFILE");
+
+		if(hp == NULL ) {
+			hp = lookupvar("HOME");
+			if(hp != NULL) {
+				char *defhp = concat_path_file(hp, ".ash_history");
+				setvar("HISTFILE", defhp, 0);
+				free(defhp);
+			}
+		}
+	}
+#endif
+	if (argv[0] && argv[0][0] == '-')
+		isloginsh = 1;
+	if (isloginsh) {
+		state = 1;
+		read_profile("/etc/profile");
+state1:
+		state = 2;
+		read_profile(".profile");
+	}
+state2:
+	state = 3;
+	if (
+#ifndef linux
+		getuid() == geteuid() && getgid() == getegid() &&
+#endif
+		iflag
+	) {
+		if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
+			read_profile(shinit);
+		}
+	}
+state3:
+	state = 4;
+	if (minusc)
+		evalstring(minusc, 0);
+
+	if (sflag || minusc == NULL) {
+#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
+	    if ( iflag ) {
+		const char *hp = lookupvar("HISTFILE");
+
+		if(hp != NULL )
+			load_history ( hp );
+	    }
+#endif
+state4: /* XXX ??? - why isn't this before the "if" statement */
+		cmdloop(1);
+	}
+#if PROFILE
+	monitor(0);
+#endif
+#if GPROF
+	{
+		extern void _mcleanup(void);
+		_mcleanup();
+	}
+#endif
+	exitshell();
+	/* NOTREACHED */
+}
+
+
+/*
+ * Read and execute commands.  "Top" is nonzero for the top level command
+ * loop; it turns on prompting if the shell is interactive.
+ */
+
+static int
+cmdloop(int top)
+{
+	union node *n;
+	struct stackmark smark;
+	int inter;
+	int numeof = 0;
+
+	TRACE(("cmdloop(%d) called\n", top));
+	for (;;) {
+		int skip;
+
+		setstackmark(&smark);
+#if JOBS
+		if (jobctl)
+			showjobs(stderr, SHOW_CHANGED);
+#endif
+		inter = 0;
+		if (iflag && top) {
+			inter++;
+#ifdef CONFIG_ASH_MAIL
+			chkmail();
+#endif
+		}
+		n = parsecmd(inter);
+		/* showtree(n); DEBUG */
+		if (n == NEOF) {
+			if (!top || numeof >= 50)
+				break;
+			if (!stoppedjobs()) {
+				if (!Iflag)
+					break;
+				out2str("\nUse \"exit\" to leave shell.\n");
+			}
+			numeof++;
+		} else if (nflag == 0) {
+			job_warning = (job_warning == 2) ? 1 : 0;
+			numeof = 0;
+			evaltree(n, 0);
+		}
+		popstackmark(&smark);
+		skip = evalskip;
+
+		if (skip) {
+			evalskip = 0;
+			return skip & SKIPEVAL;
+		}
+	}
+
+	return 0;
+}
+
+
+/*
+ * Read /etc/profile or .profile.  Return on error.
+ */
+
+static void
+read_profile(const char *name)
+{
+	int skip;
+
+	if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
+		return;
+
+	skip = cmdloop(0);
+	popfile();
+
+	if (skip)
+		exitshell();
+}
+
+
+/*
+ * Read a file containing shell functions.
+ */
+
+static void
+readcmdfile(char *name)
+{
+	setinputfile(name, INPUT_PUSH_FILE);
+	cmdloop(0);
+	popfile();
+}
+
+
+/*
+ * Take commands from a file.  To be compatible we should do a path
+ * search for the file, which is necessary to find sub-commands.
+ */
+
+static inline char *
+find_dot_file(char *name)
+{
+	char *fullname;
+	const char *path = pathval();
+	struct stat statb;
+
+	/* don't try this for absolute or relative paths */
+	if (strchr(name, '/'))
+		return name;
+
+	while ((fullname = padvance(&path, name)) != NULL) {
+		if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
+			/*
+			 * Don't bother freeing here, since it will
+			 * be freed by the caller.
+			 */
+			return fullname;
+		}
+		stunalloc(fullname);
+	}
+
+	/* not found in the PATH */
+	sh_error(not_found_msg, name);
+	/* NOTREACHED */
+}
+
+static int dotcmd(int argc, char **argv)
+{
+	struct strlist *sp;
+	volatile struct shparam saveparam;
+	int status = 0;
+
+	for (sp = cmdenviron; sp; sp = sp->next)
+		setvareq(bb_xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
+
+	if (argc >= 2) {        /* That's what SVR2 does */
+		char *fullname;
+
+		fullname = find_dot_file(argv[1]);
+
+		if (argc > 2) {
+			saveparam = shellparam;
+			shellparam.malloc = 0;
+			shellparam.nparam = argc - 2;
+			shellparam.p = argv + 2;
+		};
+
+		setinputfile(fullname, INPUT_PUSH_FILE);
+		commandname = fullname;
+		cmdloop(0);
+		popfile();
+
+		if (argc > 2) {
+			freeparam(&shellparam);
+			shellparam = saveparam;
+		};
+		status = exitstatus;
+	}
+	return status;
+}
+
+
+static int
+exitcmd(int argc, char **argv)
+{
+	if (stoppedjobs())
+		return 0;
+	if (argc > 1)
+		exitstatus = number(argv[1]);
+	exraise(EXEXIT);
+	/* NOTREACHED */
+}
+
+#ifdef CONFIG_ASH_BUILTIN_ECHO
+static int
+echocmd(int argc, char **argv)
+{
+	return bb_echo(argc, argv);
+}
+#endif
+
+#ifdef CONFIG_ASH_BUILTIN_TEST
+static int
+testcmd(int argc, char **argv)
+{
+	return bb_test(argc, argv);
+}
+#endif
+
+/*      memalloc.c        */
+
+/*
+ * Same for malloc, realloc, but returns an error when out of space.
+ */
+
+static pointer
+ckrealloc(pointer p, size_t nbytes)
+{
+	p = realloc(p, nbytes);
+	if (p == NULL)
+		sh_error(bb_msg_memory_exhausted);
+	return p;
+}
+
+static pointer
+ckmalloc(size_t nbytes)
+{
+	return ckrealloc(NULL, nbytes);
+}
+
+/*
+ * Make a copy of a string in safe storage.
+ */
+
+static char *
+savestr(const char *s)
+{
+	char *p = strdup(s);
+	if (!p)
+		sh_error(bb_msg_memory_exhausted);
+	return p;
+}
+
+
+/*
+ * Parse trees for commands are allocated in lifo order, so we use a stack
+ * to make this more efficient, and also to avoid all sorts of exception
+ * handling code to handle interrupts in the middle of a parse.
+ *
+ * The size 504 was chosen because the Ultrix malloc handles that size
+ * well.
+ */
+
+
+static pointer
+stalloc(size_t nbytes)
+{
+	char *p;
+	size_t aligned;
+
+	aligned = SHELL_ALIGN(nbytes);
+	if (aligned > stacknleft) {
+		size_t len;
+		size_t blocksize;
+		struct stack_block *sp;
+
+		blocksize = aligned;
+		if (blocksize < MINSIZE)
+			blocksize = MINSIZE;
+		len = sizeof(struct stack_block) - MINSIZE + blocksize;
+		if (len < blocksize)
+			sh_error(bb_msg_memory_exhausted);
+		INTOFF;
+		sp = ckmalloc(len);
+		sp->prev = stackp;
+		stacknxt = sp->space;
+		stacknleft = blocksize;
+		sstrend = stacknxt + blocksize;
+		stackp = sp;
+		INTON;
+	}
+	p = stacknxt;
+	stacknxt += aligned;
+	stacknleft -= aligned;
+	return p;
+}
+
+
+void
+stunalloc(pointer p)
+{
+#ifdef DEBUG
+	if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
+		write(2, "stunalloc\n", 10);
+		abort();
+	}
+#endif
+	stacknleft += stacknxt - (char *)p;
+	stacknxt = p;
+}
+
+
+void
+setstackmark(struct stackmark *mark)
+{
+	mark->stackp = stackp;
+	mark->stacknxt = stacknxt;
+	mark->stacknleft = stacknleft;
+	mark->marknext = markp;
+	markp = mark;
+}
+
+
+void
+popstackmark(struct stackmark *mark)
+{
+	struct stack_block *sp;
+
+	INTOFF;
+	markp = mark->marknext;
+	while (stackp != mark->stackp) {
+		sp = stackp;
+		stackp = sp->prev;
+		ckfree(sp);
+	}
+	stacknxt = mark->stacknxt;
+	stacknleft = mark->stacknleft;
+	sstrend = mark->stacknxt + mark->stacknleft;
+	INTON;
+}
+
+
+/*
+ * When the parser reads in a string, it wants to stick the string on the
+ * stack and only adjust the stack pointer when it knows how big the
+ * string is.  Stackblock (defined in stack.h) returns a pointer to a block
+ * of space on top of the stack and stackblocklen returns the length of
+ * this block.  Growstackblock will grow this space by at least one byte,
+ * possibly moving it (like realloc).  Grabstackblock actually allocates the
+ * part of the block that has been used.
+ */
+
+void
+growstackblock(void)
+{
+	size_t newlen;
+
+	newlen = stacknleft * 2;
+	if (newlen < stacknleft)
+		sh_error(bb_msg_memory_exhausted);
+	if (newlen < 128)
+		newlen += 128;
+
+	if (stacknxt == stackp->space && stackp != &stackbase) {
+		struct stack_block *oldstackp;
+		struct stackmark *xmark;
+		struct stack_block *sp;
+		struct stack_block *prevstackp;
+		size_t grosslen;
+
+		INTOFF;
+		oldstackp = stackp;
+		sp = stackp;
+		prevstackp = sp->prev;
+		grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
+		sp = ckrealloc((pointer)sp, grosslen);
+		sp->prev = prevstackp;
+		stackp = sp;
+		stacknxt = sp->space;
+		stacknleft = newlen;
+		sstrend = sp->space + newlen;
+
+		/*
+		 * Stack marks pointing to the start of the old block
+		 * must be relocated to point to the new block
+		 */
+		xmark = markp;
+		while (xmark != NULL && xmark->stackp == oldstackp) {
+			xmark->stackp = stackp;
+			xmark->stacknxt = stacknxt;
+			xmark->stacknleft = stacknleft;
+			xmark = xmark->marknext;
+		}
+		INTON;
+	} else {
+		char *oldspace = stacknxt;
+		int oldlen = stacknleft;
+		char *p = stalloc(newlen);
+
+		/* free the space we just allocated */
+		stacknxt = memcpy(p, oldspace, oldlen);
+		stacknleft += newlen;
+	}
+}
+
+static inline void
+grabstackblock(size_t len)
+{
+	len = SHELL_ALIGN(len);
+	stacknxt += len;
+	stacknleft -= len;
+}
+
+/*
+ * The following routines are somewhat easier to use than the above.
+ * The user declares a variable of type STACKSTR, which may be declared
+ * to be a register.  The macro STARTSTACKSTR initializes things.  Then
+ * the user uses the macro STPUTC to add characters to the string.  In
+ * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
+ * grown as necessary.  When the user is done, she can just leave the
+ * string there and refer to it using stackblock().  Or she can allocate
+ * the space for it using grabstackstr().  If it is necessary to allow
+ * someone else to use the stack temporarily and then continue to grow
+ * the string, the user should use grabstack to allocate the space, and
+ * then call ungrabstr(p) to return to the previous mode of operation.
+ *
+ * USTPUTC is like STPUTC except that it doesn't check for overflow.
+ * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
+ * is space for at least one character.
+ */
+
+void *
+growstackstr(void)
+{
+	size_t len = stackblocksize();
+	if (herefd >= 0 && len >= 1024) {
+		bb_full_write(herefd, stackblock(), len);
+		return stackblock();
+	}
+	growstackblock();
+	return stackblock() + len;
+}
+
+/*
+ * Called from CHECKSTRSPACE.
+ */
+
+char *
+makestrspace(size_t newlen, char *p)
+{
+	size_t len = p - stacknxt;
+	size_t size = stackblocksize();
+
+	for (;;) {
+		size_t nleft;
+
+		size = stackblocksize();
+		nleft = size - len;
+		if (nleft >= newlen)
+			break;
+		growstackblock();
+	}
+	return stackblock() + len;
+}
+
+char *
+stnputs(const char *s, size_t n, char *p)
+{
+	p = makestrspace(n, p);
+	p = mempcpy(p, s, n);
+	return p;
+}
+
+char *
+stputs(const char *s, char *p)
+{
+	return stnputs(s, strlen(s), p);
+}
+
+/*      mystring.c   */
+
+/*
+ * String functions.
+ *
+ *      number(s)               Convert a string of digits to an integer.
+ *      is_number(s)            Return true if s is a string of digits.
+ */
+
+/*
+ * prefix -- see if pfx is a prefix of string.
+ */
+
+char *
+prefix(const char *string, const char *pfx)
+{
+	while (*pfx) {
+		if (*pfx++ != *string++)
+			return 0;
+	}
+	return (char *) string;
+}
+
+
+/*
+ * Convert a string of digits to an integer, printing an error message on
+ * failure.
+ */
+
+int
+number(const char *s)
+{
+
+	if (! is_number(s))
+		sh_error(illnum, s);
+	return atoi(s);
+}
+
+
+/*
+ * Check for a valid number.  This should be elsewhere.
+ */
+
+int
+is_number(const char *p)
+{
+	do {
+		if (! is_digit(*p))
+			return 0;
+	} while (*++p != '\0');
+	return 1;
+}
+
+
+/*
+ * Produce a possibly single quoted string suitable as input to the shell.
+ * The return string is allocated on the stack.
+ */
+
+char *
+single_quote(const char *s) {
+	char *p;
+
+	STARTSTACKSTR(p);
+
+	do {
+		char *q;
+		size_t len;
+
+		len = strchrnul(s, '\'') - s;
+
+		q = p = makestrspace(len + 3, p);
+
+		*q++ = '\'';
+		q = mempcpy(q, s, len);
+		*q++ = '\'';
+		s += len;
+
+		STADJUST(q - p, p);
+
+		len = strspn(s, "'");
+		if (!len)
+			break;
+
+		q = p = makestrspace(len + 3, p);
+
+		*q++ = '"';
+		q = mempcpy(q, s, len);
+		*q++ = '"';
+		s += len;
+
+		STADJUST(q - p, p);
+	} while (*s);
+
+	USTPUTC(0, p);
+
+	return stackblock();
+}
+
+/*
+ * Like strdup but works with the ash stack.
+ */
+
+char *
+sstrdup(const char *p)
+{
+	size_t len = strlen(p) + 1;
+	return memcpy(stalloc(len), p, len);
+}
+
+
+static void
+calcsize(union node *n)
+{
+      if (n == NULL)
+	    return;
+      funcblocksize += nodesize[n->type];
+      switch (n->type) {
+      case NCMD:
+	    calcsize(n->ncmd.redirect);
+	    calcsize(n->ncmd.args);
+	    calcsize(n->ncmd.assign);
+	    break;
+      case NPIPE:
+	    sizenodelist(n->npipe.cmdlist);
+	    break;
+      case NREDIR:
+      case NBACKGND:
+      case NSUBSHELL:
+	    calcsize(n->nredir.redirect);
+	    calcsize(n->nredir.n);
+	    break;
+      case NAND:
+      case NOR:
+      case NSEMI:
+      case NWHILE:
+      case NUNTIL:
+	    calcsize(n->nbinary.ch2);
+	    calcsize(n->nbinary.ch1);
+	    break;
+      case NIF:
+	    calcsize(n->nif.elsepart);
+	    calcsize(n->nif.ifpart);
+	    calcsize(n->nif.test);
+	    break;
+      case NFOR:
+	    funcstringsize += strlen(n->nfor.var) + 1;
+	    calcsize(n->nfor.body);
+	    calcsize(n->nfor.args);
+	    break;
+      case NCASE:
+	    calcsize(n->ncase.cases);
+	    calcsize(n->ncase.expr);
+	    break;
+      case NCLIST:
+	    calcsize(n->nclist.body);
+	    calcsize(n->nclist.pattern);
+	    calcsize(n->nclist.next);
+	    break;
+      case NDEFUN:
+      case NARG:
+	    sizenodelist(n->narg.backquote);
+	    funcstringsize += strlen(n->narg.text) + 1;
+	    calcsize(n->narg.next);
+	    break;
+      case NTO:
+      case NCLOBBER:
+      case NFROM:
+      case NFROMTO:
+      case NAPPEND:
+	    calcsize(n->nfile.fname);
+	    calcsize(n->nfile.next);
+	    break;
+      case NTOFD:
+      case NFROMFD:
+	    calcsize(n->ndup.vname);
+	    calcsize(n->ndup.next);
+	    break;
+      case NHERE:
+      case NXHERE:
+	    calcsize(n->nhere.doc);
+	    calcsize(n->nhere.next);
+	    break;
+      case NNOT:
+	    calcsize(n->nnot.com);
+	    break;
+      };
+}
+
+
+static void
+sizenodelist(struct nodelist *lp)
+{
+	while (lp) {
+		funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
+		calcsize(lp->n);
+		lp = lp->next;
+	}
+}
+
+
+static union node *
+copynode(union node *n)
+{
+      union node *new;
+
+      if (n == NULL)
+	    return NULL;
+      new = funcblock;
+      funcblock = (char *) funcblock + nodesize[n->type];
+      switch (n->type) {
+      case NCMD:
+	    new->ncmd.redirect = copynode(n->ncmd.redirect);
+	    new->ncmd.args = copynode(n->ncmd.args);
+	    new->ncmd.assign = copynode(n->ncmd.assign);
+	    break;
+      case NPIPE:
+	    new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
+	    new->npipe.backgnd = n->npipe.backgnd;
+	    break;
+      case NREDIR:
+      case NBACKGND:
+      case NSUBSHELL:
+	    new->nredir.redirect = copynode(n->nredir.redirect);
+	    new->nredir.n = copynode(n->nredir.n);
+	    break;
+      case NAND:
+      case NOR:
+      case NSEMI:
+      case NWHILE:
+      case NUNTIL:
+	    new->nbinary.ch2 = copynode(n->nbinary.ch2);
+	    new->nbinary.ch1 = copynode(n->nbinary.ch1);
+	    break;
+      case NIF:
+	    new->nif.elsepart = copynode(n->nif.elsepart);
+	    new->nif.ifpart = copynode(n->nif.ifpart);
+	    new->nif.test = copynode(n->nif.test);
+	    break;
+      case NFOR:
+	    new->nfor.var = nodesavestr(n->nfor.var);
+	    new->nfor.body = copynode(n->nfor.body);
+	    new->nfor.args = copynode(n->nfor.args);
+	    break;
+      case NCASE:
+	    new->ncase.cases = copynode(n->ncase.cases);
+	    new->ncase.expr = copynode(n->ncase.expr);
+	    break;
+      case NCLIST:
+	    new->nclist.body = copynode(n->nclist.body);
+	    new->nclist.pattern = copynode(n->nclist.pattern);
+	    new->nclist.next = copynode(n->nclist.next);
+	    break;
+      case NDEFUN:
+      case NARG:
+	    new->narg.backquote = copynodelist(n->narg.backquote);
+	    new->narg.text = nodesavestr(n->narg.text);
+	    new->narg.next = copynode(n->narg.next);
+	    break;
+      case NTO:
+      case NCLOBBER:
+      case NFROM:
+      case NFROMTO:
+      case NAPPEND:
+	    new->nfile.fname = copynode(n->nfile.fname);
+	    new->nfile.fd = n->nfile.fd;
+	    new->nfile.next = copynode(n->nfile.next);
+	    break;
+      case NTOFD:
+      case NFROMFD:
+	    new->ndup.vname = copynode(n->ndup.vname);
+	    new->ndup.dupfd = n->ndup.dupfd;
+	    new->ndup.fd = n->ndup.fd;
+	    new->ndup.next = copynode(n->ndup.next);
+	    break;
+      case NHERE:
+      case NXHERE:
+	    new->nhere.doc = copynode(n->nhere.doc);
+	    new->nhere.fd = n->nhere.fd;
+	    new->nhere.next = copynode(n->nhere.next);
+	    break;
+      case NNOT:
+	    new->nnot.com = copynode(n->nnot.com);
+	    break;
+      };
+      new->type = n->type;
+	return new;
+}
+
+
+static struct nodelist *
+copynodelist(struct nodelist *lp)
+{
+	struct nodelist *start;
+	struct nodelist **lpp;
+
+	lpp = &start;
+	while (lp) {
+		*lpp = funcblock;
+		funcblock = (char *) funcblock +
+		    SHELL_ALIGN(sizeof(struct nodelist));
+		(*lpp)->n = copynode(lp->n);
+		lp = lp->next;
+		lpp = &(*lpp)->next;
+	}
+	*lpp = NULL;
+	return start;
+}
+
+
+static char *
+nodesavestr(char   *s)
+{
+	char   *rtn = funcstring;
+
+	funcstring = stpcpy(funcstring, s) + 1;
+	return rtn;
+}
+
+
+/*
+ * Free a parse tree.
+ */
+
+static void
+freefunc(struct funcnode *f)
+{
+	if (f && --f->count < 0)
+		ckfree(f);
+}
+
+
+static void options(int);
+static void setoption(int, int);
+
+
+/*
+ * Process the shell command line arguments.
+ */
+
+void
+procargs(int argc, char **argv)
+{
+	int i;
+	const char *xminusc;
+	char **xargv;
+
+	xargv = argv;
+	arg0 = xargv[0];
+	if (argc > 0)
+		xargv++;
+	for (i = 0; i < NOPTS; i++)
+		optlist[i] = 2;
+	argptr = xargv;
+	options(1);
+	xargv = argptr;
+	xminusc = minusc;
+	if (*xargv == NULL) {
+		if (xminusc)
+			sh_error(bb_msg_requires_arg, "-c");
+		sflag = 1;
+	}
+	if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
+		iflag = 1;
+	if (mflag == 2)
+		mflag = iflag;
+	for (i = 0; i < NOPTS; i++)
+		if (optlist[i] == 2)
+			optlist[i] = 0;
+#if DEBUG == 2
+	debug = 1;
+#endif
+	/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
+	if (xminusc) {
+		minusc = *xargv++;
+		if (*xargv)
+			goto setarg0;
+	} else if (!sflag) {
+		setinputfile(*xargv, 0);
+setarg0:
+		arg0 = *xargv++;
+		commandname = arg0;
+	}
+
+	shellparam.p = xargv;
+#ifdef CONFIG_ASH_GETOPTS
+	shellparam.optind = 1;
+	shellparam.optoff = -1;
+#endif
+	/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
+	while (*xargv) {
+		shellparam.nparam++;
+		xargv++;
+	}
+	optschanged();
+}
+
+
+void
+optschanged(void)
+{
+#ifdef DEBUG
+	opentrace();
+#endif
+	setinteractive(iflag);
+	setjobctl(mflag);
+	setvimode(viflag);
+}
+
+static inline void
+minus_o(char *name, int val)
+{
+	int i;
+
+	if (name == NULL) {
+		out1str("Current option settings\n");
+		for (i = 0; i < NOPTS; i++)
+			out1fmt("%-16s%s\n", optnames(i),
+				optlist[i] ? "on" : "off");
+	} else {
+		for (i = 0; i < NOPTS; i++)
+			if (equal(name, optnames(i))) {
+				optlist[i] = val;
+				return;
+			}
+		sh_error("Illegal option -o %s", name);
+	}
+}
+
+/*
+ * Process shell options.  The global variable argptr contains a pointer
+ * to the argument list; we advance it past the options.
+ */
+
+static void
+options(int cmdline)
+{
+	char *p;
+	int val;
+	int c;
+
+	if (cmdline)
+		minusc = NULL;
+	while ((p = *argptr) != NULL) {
+		argptr++;
+		if ((c = *p++) == '-') {
+			val = 1;
+			if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
+				if (!cmdline) {
+					/* "-" means turn off -x and -v */
+					if (p[0] == '\0')
+						xflag = vflag = 0;
+					/* "--" means reset params */
+					else if (*argptr == NULL)
+						setparam(argptr);
+				}
+				break;    /* "-" or  "--" terminates options */
+			}
+		} else if (c == '+') {
+			val = 0;
+		} else {
+			argptr--;
+			break;
+		}
+		while ((c = *p++) != '\0') {
+			if (c == 'c' && cmdline) {
+				minusc = p;     /* command is after shell args*/
+			} else if (c == 'o') {
+				minus_o(*argptr, val);
+				if (*argptr)
+					argptr++;
+			} else if (cmdline && (c == '-')) {     // long options
+				if (strcmp(p, "login") == 0)
+					isloginsh = 1;
+				break;
+			} else {
+				setoption(c, val);
+			}
+		}
+	}
+}
+
+
+static void
+setoption(int flag, int val)
+{
+	int i;
+
+	for (i = 0; i < NOPTS; i++)
+		if (optletters(i) == flag) {
+			optlist[i] = val;
+			return;
+		}
+	sh_error("Illegal option -%c", flag);
+	/* NOTREACHED */
+}
+
+
+
+/*
+ * Set the shell parameters.
+ */
+
+void
+setparam(char **argv)
+{
+	char **newparam;
+	char **ap;
+	int nparam;
+
+	for (nparam = 0 ; argv[nparam] ; nparam++);
+	ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
+	while (*argv) {
+		*ap++ = savestr(*argv++);
+	}
+	*ap = NULL;
+	freeparam(&shellparam);
+	shellparam.malloc = 1;
+	shellparam.nparam = nparam;
+	shellparam.p = newparam;
+#ifdef CONFIG_ASH_GETOPTS
+	shellparam.optind = 1;
+	shellparam.optoff = -1;
+#endif
+}
+
+
+/*
+ * Free the list of positional parameters.
+ */
+
+void
+freeparam(volatile struct shparam *param)
+{
+	char **ap;
+
+	if (param->malloc) {
+		for (ap = param->p ; *ap ; ap++)
+			ckfree(*ap);
+		ckfree(param->p);
+	}
+}
+
+
+
+/*
+ * The shift builtin command.
+ */
+
+int
+shiftcmd(int argc, char **argv)
+{
+	int n;
+	char **ap1, **ap2;
+
+	n = 1;
+	if (argc > 1)
+		n = number(argv[1]);
+	if (n > shellparam.nparam)
+		sh_error("can't shift that many");
+	INTOFF;
+	shellparam.nparam -= n;
+	for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
+		if (shellparam.malloc)
+			ckfree(*ap1);
+	}
+	ap2 = shellparam.p;
+	while ((*ap2++ = *ap1++) != NULL);
+#ifdef CONFIG_ASH_GETOPTS
+	shellparam.optind = 1;
+	shellparam.optoff = -1;
+#endif
+	INTON;
+	return 0;
+}
+
+
+
+/*
+ * The set command builtin.
+ */
+
+int
+setcmd(int argc, char **argv)
+{
+	if (argc == 1)
+		return showvars(nullstr, 0, VUNSET);
+	INTOFF;
+	options(0);
+	optschanged();
+	if (*argptr != NULL) {
+		setparam(argptr);
+	}
+	INTON;
+	return 0;
+}
+
+
+#ifdef CONFIG_ASH_GETOPTS
+static void
+getoptsreset(const char *value)
+{
+	shellparam.optind = number(value);
+	shellparam.optoff = -1;
+}
+#endif
+
+#ifdef CONFIG_LOCALE_SUPPORT
+static void change_lc_all(const char *value)
+{
+	if (value != 0 && *value != 0)
+		setlocale(LC_ALL, value);
+}
+
+static void change_lc_ctype(const char *value)
+{
+	if (value != 0 && *value != 0)
+		setlocale(LC_CTYPE, value);
+}
+
+#endif
+
+#ifdef CONFIG_ASH_RANDOM_SUPPORT
+/* Roughly copied from bash.. */
+static void change_random(const char *value)
+{
+	if(value == NULL) {
+		/* "get", generate */
+		char buf[16];
+
+		rseed = rseed * 1103515245 + 12345;
+		sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
+		/* set without recursion */
+		setvar(vrandom.text, buf, VNOFUNC);
+		vrandom.flags &= ~VNOFUNC;
+	} else {
+		/* set/reset */
+		rseed = strtoul(value, (char **)NULL, 10);
+	}
+}
+#endif
+
+
+#ifdef CONFIG_ASH_GETOPTS
+static int
+getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
+{
+	char *p, *q;
+	char c = '?';
+	int done = 0;
+	int err = 0;
+	char s[12];
+	char **optnext;
+
+	if(*param_optind < 1)
+		return 1;
+	optnext = optfirst + *param_optind - 1;
+
+	if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
+		p = NULL;
+	else
+		p = optnext[-1] + *optoff;
+	if (p == NULL || *p == '\0') {
+		/* Current word is done, advance */
+		p = *optnext;
+		if (p == NULL || *p != '-' || *++p == '\0') {
+atend:
+			p = NULL;
+			done = 1;
+			goto out;
+		}
+		optnext++;
+		if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
+			goto atend;
+	}
+
+	c = *p++;
+	for (q = optstr; *q != c; ) {
+		if (*q == '\0') {
+			if (optstr[0] == ':') {
+				s[0] = c;
+				s[1] = '\0';
+				err |= setvarsafe("OPTARG", s, 0);
+			} else {
+				fprintf(stderr, "Illegal option -%c\n", c);
+				(void) unsetvar("OPTARG");
+			}
+			c = '?';
+			goto out;
+		}
+		if (*++q == ':')
+			q++;
+	}
+
+	if (*++q == ':') {
+		if (*p == '\0' && (p = *optnext) == NULL) {
+			if (optstr[0] == ':') {
+				s[0] = c;
+				s[1] = '\0';
+				err |= setvarsafe("OPTARG", s, 0);
+				c = ':';
+			} else {
+				fprintf(stderr, "No arg for -%c option\n", c);
+				(void) unsetvar("OPTARG");
+				c = '?';
+			}
+			goto out;
+		}
+
+		if (p == *optnext)
+			optnext++;
+		err |= setvarsafe("OPTARG", p, 0);
+		p = NULL;
+	} else
+		err |= setvarsafe("OPTARG", nullstr, 0);
+
+out:
+	*optoff = p ? p - *(optnext - 1) : -1;
+	*param_optind = optnext - optfirst + 1;
+	fmtstr(s, sizeof(s), "%d", *param_optind);
+	err |= setvarsafe("OPTIND", s, VNOFUNC);
+	s[0] = c;
+	s[1] = '\0';
+	err |= setvarsafe(optvar, s, 0);
+	if (err) {
+		*param_optind = 1;
+		*optoff = -1;
+		flushall();
+		exraise(EXERROR);
+	}
+	return done;
+}
+
+/*
+ * The getopts builtin.  Shellparam.optnext points to the next argument
+ * to be processed.  Shellparam.optptr points to the next character to
+ * be processed in the current argument.  If shellparam.optnext is NULL,
+ * then it's the first time getopts has been called.
+ */
+
+int
+getoptscmd(int argc, char **argv)
+{
+	char **optbase;
+
+	if (argc < 3)
+		sh_error("Usage: getopts optstring var [arg]");
+	else if (argc == 3) {
+		optbase = shellparam.p;
+		if (shellparam.optind > shellparam.nparam + 1) {
+			shellparam.optind = 1;
+			shellparam.optoff = -1;
+		}
+	}
+	else {
+		optbase = &argv[3];
+		if (shellparam.optind > argc - 2) {
+			shellparam.optind = 1;
+			shellparam.optoff = -1;
+		}
+	}
+
+	return getopts(argv[1], argv[2], optbase, &shellparam.optind,
+		       &shellparam.optoff);
+}
+#endif /* CONFIG_ASH_GETOPTS */
+
+/*
+ * XXX - should get rid of.  have all builtins use getopt(3).  the
+ * library getopt must have the BSD extension static variable "optreset"
+ * otherwise it can't be used within the shell safely.
+ *
+ * Standard option processing (a la getopt) for builtin routines.  The
+ * only argument that is passed to nextopt is the option string; the
+ * other arguments are unnecessary.  It return the character, or '\0' on
+ * end of input.
+ */
+
+static int
+nextopt(const char *optstring)
+{
+	char *p;
+	const char *q;
+	char c;
+
+	if ((p = optptr) == NULL || *p == '\0') {
+		p = *argptr;
+		if (p == NULL || *p != '-' || *++p == '\0')
+			return '\0';
+		argptr++;
+		if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
+			return '\0';
+	}
+	c = *p++;
+	for (q = optstring ; *q != c ; ) {
+		if (*q == '\0')
+			sh_error("Illegal option -%c", c);
+		if (*++q == ':')
+			q++;
+	}
+	if (*++q == ':') {
+		if (*p == '\0' && (p = *argptr++) == NULL)
+			sh_error("No arg for -%c option", c);
+		optionarg = p;
+		p = NULL;
+	}
+	optptr = p;
+	return c;
+}
+
+
+/*      output.c     */
+
+void
+outstr(const char *p, FILE *file)
+{
+	INTOFF;
+	fputs(p, file);
+	INTON;
+}
+
+void
+flushall(void)
+{
+	INTOFF;
+	fflush(stdout);
+	fflush(stderr);
+	INTON;
+}
+
+void
+flusherr(void)
+{
+	INTOFF;
+	fflush(stderr);
+	INTON;
+}
+
+static void
+outcslow(int c, FILE *dest)
+{
+	INTOFF;
+	putc(c, dest);
+	fflush(dest);
+	INTON;
+}
+
+
+static int
+out1fmt(const char *fmt, ...)
+{
+	va_list ap;
+	int r;
+
+	INTOFF;
+	va_start(ap, fmt);
+	r = vprintf(fmt, ap);
+	va_end(ap);
+	INTON;
+	return r;
+}
+
+
+int
+fmtstr(char *outbuf, size_t length, const char *fmt, ...)
+{
+	va_list ap;
+	int ret;
+
+	va_start(ap, fmt);
+	INTOFF;
+	ret = vsnprintf(outbuf, length, fmt, ap);
+	va_end(ap);
+	INTON;
+	return ret;
+}
+
+
+
+/*      parser.c     */
+
+
+/*
+ * Shell command parser.
+ */
+
+#define EOFMARKLEN 79
+
+
+struct heredoc {
+	struct heredoc *next;   /* next here document in list */
+	union node *here;               /* redirection node */
+	char *eofmark;          /* string indicating end of input */
+	int striptabs;          /* if set, strip leading tabs */
+};
+
+
+
+static struct heredoc *heredoclist;    /* list of here documents to read */
+
+
+static union node *list(int);
+static union node *andor(void);
+static union node *pipeline(void);
+static union node *command(void);
+static union node *simplecmd(void);
+static union node *makename(void);
+static void parsefname(void);
+static void parseheredoc(void);
+static char peektoken(void);
+static int readtoken(void);
+static int xxreadtoken(void);
+static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
+static int noexpand(char *);
+static void synexpect(int) ATTRIBUTE_NORETURN;
+static void synerror(const char *) ATTRIBUTE_NORETURN;
+static void setprompt(int);
+
+
+
+
+/*
+ * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
+ * valid parse tree indicating a blank line.)
+ */
+
+union node *
+parsecmd(int interact)
+{
+	int t;
+
+	tokpushback = 0;
+	doprompt = interact;
+	if (doprompt)
+		setprompt(doprompt);
+	needprompt = 0;
+	t = readtoken();
+	if (t == TEOF)
+		return NEOF;
+	if (t == TNL)
+		return NULL;
+	tokpushback++;
+	return list(1);
+}
+
+
+static union node *
+list(int nlflag)
+{
+	union node *n1, *n2, *n3;
+	int tok;
+
+	checkkwd = CHKNL | CHKKWD | CHKALIAS;
+	if (nlflag == 2 && peektoken())
+		return NULL;
+	n1 = NULL;
+	for (;;) {
+		n2 = andor();
+		tok = readtoken();
+		if (tok == TBACKGND) {
+			if (n2->type == NPIPE) {
+				n2->npipe.backgnd = 1;
+			} else {
+				if (n2->type != NREDIR) {
+					n3 = stalloc(sizeof(struct nredir));
+					n3->nredir.n = n2;
+					n3->nredir.redirect = NULL;
+					n2 = n3;
+				}
+				n2->type = NBACKGND;
+			}
+		}
+		if (n1 == NULL) {
+			n1 = n2;
+		}
+		else {
+			n3 = (union node *)stalloc(sizeof (struct nbinary));
+			n3->type = NSEMI;
+			n3->nbinary.ch1 = n1;
+			n3->nbinary.ch2 = n2;
+			n1 = n3;
+		}
+		switch (tok) {
+		case TBACKGND:
+		case TSEMI:
+			tok = readtoken();
+			/* fall through */
+		case TNL:
+			if (tok == TNL) {
+				parseheredoc();
+				if (nlflag == 1)
+					return n1;
+			} else {
+				tokpushback++;
+			}
+			checkkwd = CHKNL | CHKKWD | CHKALIAS;
+			if (peektoken())
+				return n1;
+			break;
+		case TEOF:
+			if (heredoclist)
+				parseheredoc();
+			else
+				pungetc();              /* push back EOF on input */
+			return n1;
+		default:
+			if (nlflag == 1)
+				synexpect(-1);
+			tokpushback++;
+			return n1;
+		}
+	}
+}
+
+
+
+static union node *
+andor(void)
+{
+	union node *n1, *n2, *n3;
+	int t;
+
+	n1 = pipeline();
+	for (;;) {
+		if ((t = readtoken()) == TAND) {
+			t = NAND;
+		} else if (t == TOR) {
+			t = NOR;
+		} else {
+			tokpushback++;
+			return n1;
+		}
+		checkkwd = CHKNL | CHKKWD | CHKALIAS;
+		n2 = pipeline();
+		n3 = (union node *)stalloc(sizeof (struct nbinary));
+		n3->type = t;
+		n3->nbinary.ch1 = n1;
+		n3->nbinary.ch2 = n2;
+		n1 = n3;
+	}
+}
+
+
+
+static union node *
+pipeline(void)
+{
+	union node *n1, *n2, *pipenode;
+	struct nodelist *lp, *prev;
+	int negate;
+
+	negate = 0;
+	TRACE(("pipeline: entered\n"));
+	if (readtoken() == TNOT) {
+		negate = !negate;
+		checkkwd = CHKKWD | CHKALIAS;
+	} else
+		tokpushback++;
+	n1 = command();
+	if (readtoken() == TPIPE) {
+		pipenode = (union node *)stalloc(sizeof (struct npipe));
+		pipenode->type = NPIPE;
+		pipenode->npipe.backgnd = 0;
+		lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+		pipenode->npipe.cmdlist = lp;
+		lp->n = n1;
+		do {
+			prev = lp;
+			lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+			checkkwd = CHKNL | CHKKWD | CHKALIAS;
+			lp->n = command();
+			prev->next = lp;
+		} while (readtoken() == TPIPE);
+		lp->next = NULL;
+		n1 = pipenode;
+	}
+	tokpushback++;
+	if (negate) {
+		n2 = (union node *)stalloc(sizeof (struct nnot));
+		n2->type = NNOT;
+		n2->nnot.com = n1;
+		return n2;
+	} else
+		return n1;
+}
+
+
+
+static union node *
+command(void)
+{
+	union node *n1, *n2;
+	union node *ap, **app;
+	union node *cp, **cpp;
+	union node *redir, **rpp;
+	union node **rpp2;
+	int t;
+
+	redir = NULL;
+	rpp2 = &redir;
+
+	switch (readtoken()) {
+	default:
+		synexpect(-1);
+		/* NOTREACHED */
+	case TIF:
+		n1 = (union node *)stalloc(sizeof (struct nif));
+		n1->type = NIF;
+		n1->nif.test = list(0);
+		if (readtoken() != TTHEN)
+			synexpect(TTHEN);
+		n1->nif.ifpart = list(0);
+		n2 = n1;
+		while (readtoken() == TELIF) {
+			n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
+			n2 = n2->nif.elsepart;
+			n2->type = NIF;
+			n2->nif.test = list(0);
+			if (readtoken() != TTHEN)
+				synexpect(TTHEN);
+			n2->nif.ifpart = list(0);
+		}
+		if (lasttoken == TELSE)
+			n2->nif.elsepart = list(0);
+		else {
+			n2->nif.elsepart = NULL;
+			tokpushback++;
+		}
+		t = TFI;
+		break;
+	case TWHILE:
+	case TUNTIL: {
+		int got;
+		n1 = (union node *)stalloc(sizeof (struct nbinary));
+		n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
+		n1->nbinary.ch1 = list(0);
+		if ((got=readtoken()) != TDO) {
+TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
+			synexpect(TDO);
+		}
+		n1->nbinary.ch2 = list(0);
+		t = TDONE;
+		break;
+	}
+	case TFOR:
+		if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
+			synerror("Bad for loop variable");
+		n1 = (union node *)stalloc(sizeof (struct nfor));
+		n1->type = NFOR;
+		n1->nfor.var = wordtext;
+		checkkwd = CHKKWD | CHKALIAS;
+		if (readtoken() == TIN) {
+			app = ≈
+			while (readtoken() == TWORD) {
+				n2 = (union node *)stalloc(sizeof (struct narg));
+				n2->type = NARG;
+				n2->narg.text = wordtext;
+				n2->narg.backquote = backquotelist;
+				*app = n2;
+				app = &n2->narg.next;
+			}
+			*app = NULL;
+			n1->nfor.args = ap;
+			if (lasttoken != TNL && lasttoken != TSEMI)
+				synexpect(-1);
+		} else {
+			n2 = (union node *)stalloc(sizeof (struct narg));
+			n2->type = NARG;
+			n2->narg.text = (char *)dolatstr;
+			n2->narg.backquote = NULL;
+			n2->narg.next = NULL;
+			n1->nfor.args = n2;
+			/*
+			 * Newline or semicolon here is optional (but note
+			 * that the original Bourne shell only allowed NL).
+			 */
+			if (lasttoken != TNL && lasttoken != TSEMI)
+				tokpushback++;
+		}
+		checkkwd = CHKNL | CHKKWD | CHKALIAS;
+		if (readtoken() != TDO)
+			synexpect(TDO);
+		n1->nfor.body = list(0);
+		t = TDONE;
+		break;
+	case TCASE:
+		n1 = (union node *)stalloc(sizeof (struct ncase));
+		n1->type = NCASE;
+		if (readtoken() != TWORD)
+			synexpect(TWORD);
+		n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
+		n2->type = NARG;
+		n2->narg.text = wordtext;
+		n2->narg.backquote = backquotelist;
+		n2->narg.next = NULL;
+		do {
+			checkkwd = CHKKWD | CHKALIAS;
+		} while (readtoken() == TNL);
+		if (lasttoken != TIN)
+			synexpect(TIN);
+		cpp = &n1->ncase.cases;
+next_case:
+		checkkwd = CHKNL | CHKKWD;
+		t = readtoken();
+		while(t != TESAC) {
+			if (lasttoken == TLP)
+				readtoken();
+			*cpp = cp = (union node *)stalloc(sizeof (struct nclist));
+			cp->type = NCLIST;
+			app = &cp->nclist.pattern;
+			for (;;) {
+				*app = ap = (union node *)stalloc(sizeof (struct narg));
+				ap->type = NARG;
+				ap->narg.text = wordtext;
+				ap->narg.backquote = backquotelist;
+				if (readtoken() != TPIPE)
+					break;
+				app = &ap->narg.next;
+				readtoken();
+			}
+			ap->narg.next = NULL;
+			if (lasttoken != TRP)
+				synexpect(TRP);
+			cp->nclist.body = list(2);
+
+			cpp = &cp->nclist.next;
+
+			checkkwd = CHKNL | CHKKWD;
+			if ((t = readtoken()) != TESAC) {
+				if (t != TENDCASE)
+					synexpect(TENDCASE);
+				else
+					goto next_case;
+			}
+		}
+		*cpp = NULL;
+		goto redir;
+	case TLP:
+		n1 = (union node *)stalloc(sizeof (struct nredir));
+		n1->type = NSUBSHELL;
+		n1->nredir.n = list(0);
+		n1->nredir.redirect = NULL;
+		t = TRP;
+		break;
+	case TBEGIN:
+		n1 = list(0);
+		t = TEND;
+		break;
+	case TWORD:
+	case TREDIR:
+		tokpushback++;
+		return simplecmd();
+	}
+
+	if (readtoken() != t)
+		synexpect(t);
+
+redir:
+	/* Now check for redirection which may follow command */
+	checkkwd = CHKKWD | CHKALIAS;
+	rpp = rpp2;
+	while (readtoken() == TREDIR) {
+		*rpp = n2 = redirnode;
+		rpp = &n2->nfile.next;
+		parsefname();
+	}
+	tokpushback++;
+	*rpp = NULL;
+	if (redir) {
+		if (n1->type != NSUBSHELL) {
+			n2 = (union node *)stalloc(sizeof (struct nredir));
+			n2->type = NREDIR;
+			n2->nredir.n = n1;
+			n1 = n2;
+		}
+		n1->nredir.redirect = redir;
+	}
+
+	return n1;
+}
+
+
+static union node *
+simplecmd(void) {
+	union node *args, **app;
+	union node *n = NULL;
+	union node *vars, **vpp;
+	union node **rpp, *redir;
+	int savecheckkwd;
+
+	args = NULL;
+	app = &args;
+	vars = NULL;
+	vpp = &vars;
+	redir = NULL;
+	rpp = &redir;
+
+	savecheckkwd = CHKALIAS;
+	for (;;) {
+		checkkwd = savecheckkwd;
+		switch (readtoken()) {
+		case TWORD:
+			n = (union node *)stalloc(sizeof (struct narg));
+			n->type = NARG;
+			n->narg.text = wordtext;
+			n->narg.backquote = backquotelist;
+			if (savecheckkwd && isassignment(wordtext)) {
+				*vpp = n;
+				vpp = &n->narg.next;
+			} else {
+				*app = n;
+				app = &n->narg.next;
+				savecheckkwd = 0;
+			}
+			break;
+		case TREDIR:
+			*rpp = n = redirnode;
+			rpp = &n->nfile.next;
+			parsefname();   /* read name of redirection file */
+			break;
+		case TLP:
+			if (
+				args && app == &args->narg.next &&
+				!vars && !redir
+			) {
+				struct builtincmd *bcmd;
+				const char *name;
+
+				/* We have a function */
+				if (readtoken() != TRP)
+					synexpect(TRP);
+				name = n->narg.text;
+				if (
+					!goodname(name) || (
+						(bcmd = find_builtin(name)) &&
+						IS_BUILTIN_SPECIAL(bcmd)
+					)
+				)
+					synerror("Bad function name");
+				n->type = NDEFUN;
+				checkkwd = CHKNL | CHKKWD | CHKALIAS;
+				n->narg.next = command();
+				return n;
+			}
+			/* fall through */
+		default:
+			tokpushback++;
+			goto out;
+		}
+	}
+out:
+	*app = NULL;
+	*vpp = NULL;
+	*rpp = NULL;
+	n = (union node *)stalloc(sizeof (struct ncmd));
+	n->type = NCMD;
+	n->ncmd.args = args;
+	n->ncmd.assign = vars;
+	n->ncmd.redirect = redir;
+	return n;
+}
+
+static union node *
+makename(void)
+{
+	union node *n;
+
+	n = (union node *)stalloc(sizeof (struct narg));
+	n->type = NARG;
+	n->narg.next = NULL;
+	n->narg.text = wordtext;
+	n->narg.backquote = backquotelist;
+	return n;
+}
+
+void fixredir(union node *n, const char *text, int err)
+{
+	TRACE(("Fix redir %s %d\n", text, err));
+	if (!err)
+		n->ndup.vname = NULL;
+
+	if (is_digit(text[0]) && text[1] == '\0')
+		n->ndup.dupfd = digit_val(text[0]);
+	else if (text[0] == '-' && text[1] == '\0')
+		n->ndup.dupfd = -1;
+	else {
+
+		if (err)
+			synerror("Bad fd number");
+		else
+			n->ndup.vname = makename();
+	}
+}
+
+
+static void
+parsefname(void)
+{
+	union node *n = redirnode;
+
+	if (readtoken() != TWORD)
+		synexpect(-1);
+	if (n->type == NHERE) {
+		struct heredoc *here = heredoc;
+		struct heredoc *p;
+		int i;
+
+		if (quoteflag == 0)
+			n->type = NXHERE;
+		TRACE(("Here document %d\n", n->type));
+		if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
+			synerror("Illegal eof marker for << redirection");
+		rmescapes(wordtext);
+		here->eofmark = wordtext;
+		here->next = NULL;
+		if (heredoclist == NULL)
+			heredoclist = here;
+		else {
+			for (p = heredoclist ; p->next ; p = p->next);
+			p->next = here;
+		}
+	} else if (n->type == NTOFD || n->type == NFROMFD) {
+		fixredir(n, wordtext, 0);
+	} else {
+		n->nfile.fname = makename();
+	}
+}
+
+
+/*
+ * Input any here documents.
+ */
+
+static void
+parseheredoc(void)
+{
+	struct heredoc *here;
+	union node *n;
+
+	here = heredoclist;
+	heredoclist = 0;
+
+	while (here) {
+		if (needprompt) {
+			setprompt(2);
+		}
+		readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
+				here->eofmark, here->striptabs);
+		n = (union node *)stalloc(sizeof (struct narg));
+		n->narg.type = NARG;
+		n->narg.next = NULL;
+		n->narg.text = wordtext;
+		n->narg.backquote = backquotelist;
+		here->here->nhere.doc = n;
+		here = here->next;
+	}
+}
+
+static char peektoken(void)
+{
+	int t;
+
+	t = readtoken();
+	tokpushback++;
+	return tokname_array[t][0];
+}
+
+static int
+readtoken(void)
+{
+	int t;
+#ifdef DEBUG
+	int alreadyseen = tokpushback;
+#endif
+
+#ifdef CONFIG_ASH_ALIAS
+top:
+#endif
+
+	t = xxreadtoken();
+
+	/*
+	 * eat newlines
+	 */
+	if (checkkwd & CHKNL) {
+		while (t == TNL) {
+			parseheredoc();
+			t = xxreadtoken();
+		}
+	}
+
+	if (t != TWORD || quoteflag) {
+		goto out;
+	}
+
+	/*
+	 * check for keywords
+	 */
+	if (checkkwd & CHKKWD) {
+		const char *const *pp;
+
+		if ((pp = findkwd(wordtext))) {
+			lasttoken = t = pp - tokname_array;
+			TRACE(("keyword %s recognized\n", tokname(t)));
+			goto out;
+		}
+	}
+
+	if (checkkwd & CHKALIAS) {
+#ifdef CONFIG_ASH_ALIAS
+		struct alias *ap;
+		if ((ap = lookupalias(wordtext, 1)) != NULL) {
+			if (*ap->val) {
+				pushstring(ap->val, ap);
+			}
+			goto top;
+		}
+#endif
+	}
+out:
+	checkkwd = 0;
+#ifdef DEBUG
+	if (!alreadyseen)
+	    TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
+	else
+	    TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
+#endif
+	return (t);
+}
+
+
+/*
+ * Read the next input token.
+ * If the token is a word, we set backquotelist to the list of cmds in
+ *      backquotes.  We set quoteflag to true if any part of the word was
+ *      quoted.
+ * If the token is TREDIR, then we set redirnode to a structure containing
+ *      the redirection.
+ * In all cases, the variable startlinno is set to the number of the line
+ *      on which the token starts.
+ *
+ * [Change comment:  here documents and internal procedures]
+ * [Readtoken shouldn't have any arguments.  Perhaps we should make the
+ *  word parsing code into a separate routine.  In this case, readtoken
+ *  doesn't need to have any internal procedures, but parseword does.
+ *  We could also make parseoperator in essence the main routine, and
+ *  have parseword (readtoken1?) handle both words and redirection.]
+ */
+
+#define NEW_xxreadtoken
+#ifdef NEW_xxreadtoken
+
+/* singles must be first! */
+static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
+
+static const char xxreadtoken_tokens[] = {
+	TNL, TLP, TRP,          /* only single occurrence allowed */
+	TBACKGND, TPIPE, TSEMI, /* if single occurrence */
+	TEOF,                   /* corresponds to trailing nul */
+	TAND, TOR, TENDCASE,    /* if double occurrence */
+};
+
+#define xxreadtoken_doubles \
+	(sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
+#define xxreadtoken_singles \
+	(sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
+
+static int xxreadtoken(void)
+{
+	int c;
+
+	if (tokpushback) {
+		tokpushback = 0;
+		return lasttoken;
+	}
+	if (needprompt) {
+		setprompt(2);
+	}
+	startlinno = plinno;
+	for (;;) {                      /* until token or start of word found */
+		c = pgetc_macro();
+
+		if ((c != ' ') && (c != '\t')
+#ifdef CONFIG_ASH_ALIAS
+			&& (c != PEOA)
+#endif
+			) {
+			if (c == '#') {
+				while ((c = pgetc()) != '\n' && c != PEOF);
+				pungetc();
+			} else if (c == '\\') {
+				if (pgetc() != '\n') {
+					pungetc();
+					goto READTOKEN1;
+				}
+				startlinno = ++plinno;
+				if (doprompt)
+					setprompt(2);
+			} else {
+				const char *p
+					= xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
+
+				if (c != PEOF) {
+					if (c == '\n') {
+						plinno++;
+						needprompt = doprompt;
+					}
+
+					p = strchr(xxreadtoken_chars, c);
+					if (p == NULL) {
+					  READTOKEN1:
+						return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
+					}
+
+					if (p - xxreadtoken_chars >= xxreadtoken_singles) {
+						if (pgetc() == *p) {    /* double occurrence? */
+							p += xxreadtoken_doubles + 1;
+						} else {
+							pungetc();
+						}
+					}
+				}
+
+				return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
+			}
+		}
+	}
+}
+
+
+#else
+#define RETURN(token)   return lasttoken = token
+
+static int
+xxreadtoken(void)
+{
+	int c;
+
+	if (tokpushback) {
+		tokpushback = 0;
+		return lasttoken;
+	}
+	if (needprompt) {
+		setprompt(2);
+	}
+	startlinno = plinno;
+	for (;;) {      /* until token or start of word found */
+		c = pgetc_macro();
+		switch (c) {
+		case ' ': case '\t':
+#ifdef CONFIG_ASH_ALIAS
+		case PEOA:
+#endif
+			continue;
+		case '#':
+			while ((c = pgetc()) != '\n' && c != PEOF);
+			pungetc();
+			continue;
+		case '\\':
+			if (pgetc() == '\n') {
+				startlinno = ++plinno;
+				if (doprompt)
+					setprompt(2);
+				continue;
+			}
+			pungetc();
+			goto breakloop;
+		case '\n':
+			plinno++;
+			needprompt = doprompt;
+			RETURN(TNL);
+		case PEOF:
+			RETURN(TEOF);
+		case '&':
+			if (pgetc() == '&')
+				RETURN(TAND);
+			pungetc();
+			RETURN(TBACKGND);
+		case '|':
+			if (pgetc() == '|')
+				RETURN(TOR);
+			pungetc();
+			RETURN(TPIPE);
+		case ';':
+			if (pgetc() == ';')
+				RETURN(TENDCASE);
+			pungetc();
+			RETURN(TSEMI);
+		case '(':
+			RETURN(TLP);
+		case ')':
+			RETURN(TRP);
+		default:
+			goto breakloop;
+		}
+	}
+breakloop:
+	return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
+#undef RETURN
+}
+#endif /* NEW_xxreadtoken */
+
+
+/*
+ * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
+ * is not NULL, read a here document.  In the latter case, eofmark is the
+ * word which marks the end of the document and striptabs is true if
+ * leading tabs should be stripped from the document.  The argument firstc
+ * is the first character of the input token or document.
+ *
+ * Because C does not have internal subroutines, I have simulated them
+ * using goto's to implement the subroutine linkage.  The following macros
+ * will run code that appears at the end of readtoken1.
+ */
+
+#define CHECKEND()      {goto checkend; checkend_return:;}
+#define PARSEREDIR()    {goto parseredir; parseredir_return:;}
+#define PARSESUB()      {goto parsesub; parsesub_return:;}
+#define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
+#define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
+#define PARSEARITH()    {goto parsearith; parsearith_return:;}
+
+static int
+readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
+{
+	int c = firstc;
+	char *out;
+	int len;
+	char line[EOFMARKLEN + 1];
+	struct nodelist *bqlist = 0;
+	int quotef = 0;
+	int dblquote = 0;
+	int varnest = 0;    /* levels of variables expansion */
+	int arinest = 0;    /* levels of arithmetic expansion */
+	int parenlevel = 0; /* levels of parens in arithmetic */
+	int dqvarnest = 0;  /* levels of variables expansion within double quotes */
+	int oldstyle = 0;
+	int prevsyntax = 0; /* syntax before arithmetic */
+#if __GNUC__
+	/* Avoid longjmp clobbering */
+	(void) &out;
+	(void) "ef;
+	(void) &dblquote;
+	(void) &varnest;
+	(void) &arinest;
+	(void) &parenlevel;
+	(void) &dqvarnest;
+	(void) &oldstyle;
+	(void) &prevsyntax;
+	(void) &syntax;
+#endif
+
+	startlinno = plinno;
+	dblquote = 0;
+	if (syntax == DQSYNTAX)
+		dblquote = 1;
+	quotef = 0;
+	bqlist = NULL;
+	varnest = 0;
+	arinest = 0;
+	parenlevel = 0;
+	dqvarnest = 0;
+
+	STARTSTACKSTR(out);
+	loop: { /* for each line, until end of word */
+		CHECKEND();     /* set c to PEOF if at end of here document */
+		for (;;) {      /* until end of line or end of word */
+			CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
+			switch(SIT(c, syntax)) {
+			case CNL:       /* '\n' */
+				if (syntax == BASESYNTAX)
+					goto endword;   /* exit outer loop */
+				USTPUTC(c, out);
+				plinno++;
+				if (doprompt)
+					setprompt(2);
+				c = pgetc();
+				goto loop;              /* continue outer loop */
+			case CWORD:
+				USTPUTC(c, out);
+				break;
+			case CCTL:
+				if (eofmark == NULL || dblquote)
+					USTPUTC(CTLESC, out);
+				USTPUTC(c, out);
+				break;
+			case CBACK:     /* backslash */
+				c = pgetc2();
+				if (c == PEOF) {
+					USTPUTC(CTLESC, out);
+					USTPUTC('\\', out);
+					pungetc();
+				} else if (c == '\n') {
+					if (doprompt)
+						setprompt(2);
+				} else {
+					if (dblquote &&
+						c != '\\' && c != '`' &&
+						c != '$' && (
+							c != '"' ||
+							eofmark != NULL)
+					) {
+						USTPUTC(CTLESC, out);
+						USTPUTC('\\', out);
+					}
+					if (SIT(c, SQSYNTAX) == CCTL)
+						USTPUTC(CTLESC, out);
+					USTPUTC(c, out);
+					quotef++;
+				}
+				break;
+			case CSQUOTE:
+				syntax = SQSYNTAX;
+quotemark:
+				if (eofmark == NULL) {
+					USTPUTC(CTLQUOTEMARK, out);
+				}
+				break;
+			case CDQUOTE:
+				syntax = DQSYNTAX;
+				dblquote = 1;
+				goto quotemark;
+			case CENDQUOTE:
+				if (eofmark != NULL && arinest == 0 &&
+				    varnest == 0) {
+					USTPUTC(c, out);
+				} else {
+					if (dqvarnest == 0) {
+						syntax = BASESYNTAX;
+						dblquote = 0;
+					}
+					quotef++;
+					goto quotemark;
+				}
+				break;
+			case CVAR:      /* '$' */
+				PARSESUB();             /* parse substitution */
+				break;
+			case CENDVAR:   /* '}' */
+				if (varnest > 0) {
+					varnest--;
+					if (dqvarnest > 0) {
+						dqvarnest--;
+					}
+					USTPUTC(CTLENDVAR, out);
+				} else {
+					USTPUTC(c, out);
+				}
+				break;
+#ifdef CONFIG_ASH_MATH_SUPPORT
+			case CLP:       /* '(' in arithmetic */
+				parenlevel++;
+				USTPUTC(c, out);
+				break;
+			case CRP:       /* ')' in arithmetic */
+				if (parenlevel > 0) {
+					USTPUTC(c, out);
+					--parenlevel;
+				} else {
+					if (pgetc() == ')') {
+						if (--arinest == 0) {
+							USTPUTC(CTLENDARI, out);
+							syntax = prevsyntax;
+							if (syntax == DQSYNTAX)
+								dblquote = 1;
+							else
+								dblquote = 0;
+						} else
+							USTPUTC(')', out);
+					} else {
+						/*
+						 * unbalanced parens
+						 *  (don't 2nd guess - no error)
+						 */
+						pungetc();
+						USTPUTC(')', out);
+					}
+				}
+				break;
+#endif
+			case CBQUOTE:   /* '`' */
+				PARSEBACKQOLD();
+				break;
+			case CENDFILE:
+				goto endword;           /* exit outer loop */
+			case CIGN:
+				break;
+			default:
+				if (varnest == 0)
+					goto endword;   /* exit outer loop */
+#ifdef CONFIG_ASH_ALIAS
+				if (c != PEOA)
+#endif
+					USTPUTC(c, out);
+
+			}
+			c = pgetc_macro();
+		}
+	}
+endword:
+#ifdef CONFIG_ASH_MATH_SUPPORT
+	if (syntax == ARISYNTAX)
+		synerror("Missing '))'");
+#endif
+	if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
+		synerror("Unterminated quoted string");
+	if (varnest != 0) {
+		startlinno = plinno;
+		/* { */
+		synerror("Missing '}'");
+	}
+	USTPUTC('\0', out);
+	len = out - (char *)stackblock();
+	out = stackblock();
+	if (eofmark == NULL) {
+		if ((c == '>' || c == '<')
+		 && quotef == 0
+		 && len <= 2
+		 && (*out == '\0' || is_digit(*out))) {
+			PARSEREDIR();
+			return lasttoken = TREDIR;
+		} else {
+			pungetc();
+		}
+	}
+	quoteflag = quotef;
+	backquotelist = bqlist;
+	grabstackblock(len);
+	wordtext = out;
+	return lasttoken = TWORD;
+/* end of readtoken routine */
+
+
+
+/*
+ * Check to see whether we are at the end of the here document.  When this
+ * is called, c is set to the first character of the next input line.  If
+ * we are at the end of the here document, this routine sets the c to PEOF.
+ */
+
+checkend: {
+	if (eofmark) {
+#ifdef CONFIG_ASH_ALIAS
+		if (c == PEOA) {
+			c = pgetc2();
+		}
+#endif
+		if (striptabs) {
+			while (c == '\t') {
+				c = pgetc2();
+			}
+		}
+		if (c == *eofmark) {
+			if (pfgets(line, sizeof line) != NULL) {
+				char *p, *q;
+
+				p = line;
+				for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
+				if (*p == '\n' && *q == '\0') {
+					c = PEOF;
+					plinno++;
+					needprompt = doprompt;
+				} else {
+					pushstring(line, NULL);
+				}
+			}
+		}
+	}
+	goto checkend_return;
+}
+
+
+/*
+ * Parse a redirection operator.  The variable "out" points to a string
+ * specifying the fd to be redirected.  The variable "c" contains the
+ * first character of the redirection operator.
+ */
+
+parseredir: {
+	char fd = *out;
+	union node *np;
+
+	np = (union node *)stalloc(sizeof (struct nfile));
+	if (c == '>') {
+		np->nfile.fd = 1;
+		c = pgetc();
+		if (c == '>')
+			np->type = NAPPEND;
+		else if (c == '|')
+			np->type = NCLOBBER;
+		else if (c == '&')
+			np->type = NTOFD;
+		else {
+			np->type = NTO;
+			pungetc();
+		}
+	} else {        /* c == '<' */
+		np->nfile.fd = 0;
+		switch (c = pgetc()) {
+		case '<':
+			if (sizeof (struct nfile) != sizeof (struct nhere)) {
+				np = (union node *)stalloc(sizeof (struct nhere));
+				np->nfile.fd = 0;
+			}
+			np->type = NHERE;
+			heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
+			heredoc->here = np;
+			if ((c = pgetc()) == '-') {
+				heredoc->striptabs = 1;
+			} else {
+				heredoc->striptabs = 0;
+				pungetc();
+			}
+			break;
+
+		case '&':
+			np->type = NFROMFD;
+			break;
+
+		case '>':
+			np->type = NFROMTO;
+			break;
+
+		default:
+			np->type = NFROM;
+			pungetc();
+			break;
+		}
+	}
+	if (fd != '\0')
+		np->nfile.fd = digit_val(fd);
+	redirnode = np;
+	goto parseredir_return;
+}
+
+
+/*
+ * Parse a substitution.  At this point, we have read the dollar sign
+ * and nothing else.
+ */
+
+parsesub: {
+	int subtype;
+	int typeloc;
+	int flags;
+	char *p;
+	static const char types[] = "}-+?=";
+
+	c = pgetc();
+	if (
+		c <= PEOA_OR_PEOF  ||
+		(c != '(' && c != '{' && !is_name(c) && !is_special(c))
+	) {
+		USTPUTC('$', out);
+		pungetc();
+	} else if (c == '(') {  /* $(command) or $((arith)) */
+		if (pgetc() == '(') {
+#ifdef CONFIG_ASH_MATH_SUPPORT
+			PARSEARITH();
+#else
+			synerror("We unsupport $((arith))");
+#endif
+		} else {
+			pungetc();
+			PARSEBACKQNEW();
+		}
+	} else {
+		USTPUTC(CTLVAR, out);
+		typeloc = out - (char *)stackblock();
+		USTPUTC(VSNORMAL, out);
+		subtype = VSNORMAL;
+		if (c == '{') {
+			c = pgetc();
+			if (c == '#') {
+				if ((c = pgetc()) == '}')
+					c = '#';
+				else
+					subtype = VSLENGTH;
+			}
+			else
+				subtype = 0;
+		}
+		if (c > PEOA_OR_PEOF && is_name(c)) {
+			do {
+				STPUTC(c, out);
+				c = pgetc();
+			} while (c > PEOA_OR_PEOF && is_in_name(c));
+		} else if (is_digit(c)) {
+			do {
+				STPUTC(c, out);
+				c = pgetc();
+			} while (is_digit(c));
+		}
+		else if (is_special(c)) {
+			USTPUTC(c, out);
+			c = pgetc();
+		}
+		else
+badsub:                 synerror("Bad substitution");
+
+		STPUTC('=', out);
+		flags = 0;
+		if (subtype == 0) {
+			switch (c) {
+			case ':':
+				flags = VSNUL;
+				c = pgetc();
+				/*FALLTHROUGH*/
+			default:
+				p = strchr(types, c);
+				if (p == NULL)
+					goto badsub;
+				subtype = p - types + VSNORMAL;
+				break;
+			case '%':
+			case '#':
+				{
+					int cc = c;
+					subtype = c == '#' ? VSTRIMLEFT :
+							     VSTRIMRIGHT;
+					c = pgetc();
+					if (c == cc)
+						subtype++;
+					else
+						pungetc();
+					break;
+				}
+			}
+		} else {
+			pungetc();
+		}
+		if (dblquote || arinest)
+			flags |= VSQUOTE;
+		*((char *)stackblock() + typeloc) = subtype | flags;
+		if (subtype != VSNORMAL) {
+			varnest++;
+			if (dblquote || arinest) {
+				dqvarnest++;
+			}
+		}
+	}
+	goto parsesub_return;
+}
+
+
+/*
+ * Called to parse command substitutions.  Newstyle is set if the command
+ * is enclosed inside $(...); nlpp is a pointer to the head of the linked
+ * list of commands (passed by reference), and savelen is the number of
+ * characters on the top of the stack which must be preserved.
+ */
+
+parsebackq: {
+	struct nodelist **nlpp;
+	int savepbq;
+	union node *n;
+	char *volatile str;
+	struct jmploc jmploc;
+	struct jmploc *volatile savehandler;
+	size_t savelen;
+	int saveprompt = 0;
+#ifdef __GNUC__
+	(void) &saveprompt;
+#endif
+
+	savepbq = parsebackquote;
+	if (setjmp(jmploc.loc)) {
+		if (str)
+			ckfree(str);
+		parsebackquote = 0;
+		handler = savehandler;
+		longjmp(handler->loc, 1);
+	}
+	INTOFF;
+	str = NULL;
+	savelen = out - (char *)stackblock();
+	if (savelen > 0) {
+		str = ckmalloc(savelen);
+		memcpy(str, stackblock(), savelen);
+	}
+	savehandler = handler;
+	handler = &jmploc;
+	INTON;
+	if (oldstyle) {
+		/* We must read until the closing backquote, giving special
+		   treatment to some slashes, and then push the string and
+		   reread it as input, interpreting it normally.  */
+		char *pout;
+		int pc;
+		size_t psavelen;
+		char *pstr;
+
+
+		STARTSTACKSTR(pout);
+		for (;;) {
+			if (needprompt) {
+				setprompt(2);
+			}
+			switch (pc = pgetc()) {
+			case '`':
+				goto done;
+
+			case '\\':
+				if ((pc = pgetc()) == '\n') {
+					plinno++;
+					if (doprompt)
+						setprompt(2);
+					/*
+					 * If eating a newline, avoid putting
+					 * the newline into the new character
+					 * stream (via the STPUTC after the
+					 * switch).
+					 */
+					continue;
+				}
+				if (pc != '\\' && pc != '`' && pc != '$'
+				    && (!dblquote || pc != '"'))
+					STPUTC('\\', pout);
+				if (pc > PEOA_OR_PEOF) {
+					break;
+				}
+				/* fall through */
+
+			case PEOF:
+#ifdef CONFIG_ASH_ALIAS
+			case PEOA:
+#endif
+				startlinno = plinno;
+				synerror("EOF in backquote substitution");
+
+			case '\n':
+				plinno++;
+				needprompt = doprompt;
+				break;
+
+			default:
+				break;
+			}
+			STPUTC(pc, pout);
+		}
+done:
+		STPUTC('\0', pout);
+		psavelen = pout - (char *)stackblock();
+		if (psavelen > 0) {
+			pstr = grabstackstr(pout);
+			setinputstring(pstr);
+		}
+	}
+	nlpp = &bqlist;
+	while (*nlpp)
+		nlpp = &(*nlpp)->next;
+	*nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+	(*nlpp)->next = NULL;
+	parsebackquote = oldstyle;
+
+	if (oldstyle) {
+		saveprompt = doprompt;
+		doprompt = 0;
+	}
+
+	n = list(2);
+
+	if (oldstyle)
+		doprompt = saveprompt;
+	else {
+		if (readtoken() != TRP)
+			synexpect(TRP);
+	}
+
+	(*nlpp)->n = n;
+	if (oldstyle) {
+		/*
+		 * Start reading from old file again, ignoring any pushed back
+		 * tokens left from the backquote parsing
+		 */
+		popfile();
+		tokpushback = 0;
+	}
+	while (stackblocksize() <= savelen)
+		growstackblock();
+	STARTSTACKSTR(out);
+	if (str) {
+		memcpy(out, str, savelen);
+		STADJUST(savelen, out);
+		INTOFF;
+		ckfree(str);
+		str = NULL;
+		INTON;
+	}
+	parsebackquote = savepbq;
+	handler = savehandler;
+	if (arinest || dblquote)
+		USTPUTC(CTLBACKQ | CTLQUOTE, out);
+	else
+		USTPUTC(CTLBACKQ, out);
+	if (oldstyle)
+		goto parsebackq_oldreturn;
+	else
+		goto parsebackq_newreturn;
+}
+
+#ifdef CONFIG_ASH_MATH_SUPPORT
+/*
+ * Parse an arithmetic expansion (indicate start of one and set state)
+ */
+parsearith: {
+
+	if (++arinest == 1) {
+		prevsyntax = syntax;
+		syntax = ARISYNTAX;
+		USTPUTC(CTLARI, out);
+		if (dblquote)
+			USTPUTC('"',out);
+		else
+			USTPUTC(' ',out);
+	} else {
+		/*
+		 * we collapse embedded arithmetic expansion to
+		 * parenthesis, which should be equivalent
+		 */
+		USTPUTC('(', out);
+	}
+	goto parsearith_return;
+}
+#endif
+
+} /* end of readtoken */
+
+
+
+/*
+ * Returns true if the text contains nothing to expand (no dollar signs
+ * or backquotes).
+ */
+
+static int
+noexpand(char *text)
+{
+	char *p;
+	char c;
+
+	p = text;
+	while ((c = *p++) != '\0') {
+		if (c == CTLQUOTEMARK)
+			continue;
+		if (c == CTLESC)
+			p++;
+		else if (SIT(c, BASESYNTAX) == CCTL)
+			return 0;
+	}
+	return 1;
+}
+
+
+/*
+ * Return of a legal variable name (a letter or underscore followed by zero or
+ * more letters, underscores, and digits).
+ */
+
+static char *
+endofname(const char *name)
+{
+	char *p;
+
+	p = (char *) name;
+	if (! is_name(*p))
+		return p;
+	while (*++p) {
+		if (! is_in_name(*p))
+			break;
+	}
+	return p;
+}
+
+
+/*
+ * Called when an unexpected token is read during the parse.  The argument
+ * is the token that is expected, or -1 if more than one type of token can
+ * occur at this point.
+ */
+
+static void synexpect(int token)
+{
+	char msg[64];
+	int l;
+
+	l = sprintf(msg, "%s unexpected", tokname(lasttoken));
+	if (token >= 0)
+		sprintf(msg + l, " (expecting %s)", tokname(token));
+	synerror(msg);
+	/* NOTREACHED */
+}
+
+static void
+synerror(const char *msg)
+{
+	sh_error("Syntax error: %s", msg);
+	/* NOTREACHED */
+}
+
+
+/*
+ * called by editline -- any expansions to the prompt
+ *    should be added here.
+ */
+
+#ifdef CONFIG_ASH_EXPAND_PRMT
+static const char *
+expandstr(const char *ps)
+{
+	union node n;
+
+	/* XXX Fix (char *) cast. */
+	setinputstring((char *)ps);
+	readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
+	popfile();
+
+	n.narg.type = NARG;
+	n.narg.next = NULL;
+	n.narg.text = wordtext;
+	n.narg.backquote = backquotelist;
+
+	expandarg(&n, NULL, 0);
+	return stackblock();
+}
+#endif
+
+static void setprompt(int whichprompt)
+{
+	const char *prompt;
+#ifdef CONFIG_ASH_EXPAND_PRMT
+	struct stackmark smark;
+#endif
+
+	needprompt = 0;
+
+	switch (whichprompt) {
+	case 1:
+		prompt = ps1val();
+		break;
+	case 2:
+		prompt = ps2val();
+		break;
+	default:                        /* 0 */
+		prompt = nullstr;
+	}
+#ifdef CONFIG_ASH_EXPAND_PRMT
+	setstackmark(&smark);
+	stalloc(stackblocksize());
+#endif
+	putprompt(expandstr(prompt));
+#ifdef CONFIG_ASH_EXPAND_PRMT
+	popstackmark(&smark);
+#endif
+}
+
+
+static const char *const *findkwd(const char *s)
+{
+	return bsearch(s, tokname_array + KWDOFFSET,
+		       (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
+				   sizeof(const char *), pstrcmp);
+}
+
+/*      redir.c      */
+
+/*
+ * Code for dealing with input/output redirection.
+ */
+
+#define EMPTY -2                /* marks an unused slot in redirtab */
+#ifndef PIPE_BUF
+# define PIPESIZE 4096          /* amount of buffering in a pipe */
+#else
+# define PIPESIZE PIPE_BUF
+#endif
+
+/*
+ * Open a file in noclobber mode.
+ * The code was copied from bash.
+ */
+static inline int
+noclobberopen(const char *fname)
+{
+	int r, fd;
+	struct stat finfo, finfo2;
+
+	/*
+	 * If the file exists and is a regular file, return an error
+	 * immediately.
+	 */
+	r = stat(fname, &finfo);
+	if (r == 0 && S_ISREG(finfo.st_mode)) {
+		errno = EEXIST;
+		return -1;
+	}
+
+	/*
+	 * If the file was not present (r != 0), make sure we open it
+	 * exclusively so that if it is created before we open it, our open
+	 * will fail.  Make sure that we do not truncate an existing file.
+	 * Note that we don't turn on O_EXCL unless the stat failed -- if the
+	 * file was not a regular file, we leave O_EXCL off.
+	 */
+	if (r != 0)
+		return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
+	fd = open(fname, O_WRONLY|O_CREAT, 0666);
+
+	/* If the open failed, return the file descriptor right away. */
+	if (fd < 0)
+		return fd;
+
+	/*
+	 * OK, the open succeeded, but the file may have been changed from a
+	 * non-regular file to a regular file between the stat and the open.
+	 * We are assuming that the O_EXCL open handles the case where FILENAME
+	 * did not exist and is symlinked to an existing file between the stat
+	 * and open.
+	 */
+
+	/*
+	 * If we can open it and fstat the file descriptor, and neither check
+	 * revealed that it was a regular file, and the file has not been
+	 * replaced, return the file descriptor.
+	 */
+	 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
+	     finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
+		return fd;
+
+	/* The file has been replaced.  badness. */
+	close(fd);
+	errno = EEXIST;
+	return -1;
+}
+
+/*
+ * Handle here documents.  Normally we fork off a process to write the
+ * data to a pipe.  If the document is short, we can stuff the data in
+ * the pipe without forking.
+ */
+
+static inline int
+openhere(union node *redir)
+{
+	int pip[2];
+	size_t len = 0;
+
+	if (pipe(pip) < 0)
+		sh_error("Pipe call failed");
+	if (redir->type == NHERE) {
+		len = strlen(redir->nhere.doc->narg.text);
+		if (len <= PIPESIZE) {
+			bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
+			goto out;
+		}
+	}
+	if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
+		close(pip[0]);
+		signal(SIGINT, SIG_IGN);
+		signal(SIGQUIT, SIG_IGN);
+		signal(SIGHUP, SIG_IGN);
+#ifdef SIGTSTP
+		signal(SIGTSTP, SIG_IGN);
+#endif
+		signal(SIGPIPE, SIG_DFL);
+		if (redir->type == NHERE)
+			bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
+		else
+			expandhere(redir->nhere.doc, pip[1]);
+		_exit(0);
+	}
+out:
+	close(pip[1]);
+	return pip[0];
+}
+
+static int
+openredirect(union node *redir)
+{
+	char *fname;
+	int f;
+
+	switch (redir->nfile.type) {
+	case NFROM:
+		fname = redir->nfile.expfname;
+		if ((f = open(fname, O_RDONLY)) < 0)
+			goto eopen;
+		break;
+	case NFROMTO:
+		fname = redir->nfile.expfname;
+		if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
+			goto ecreate;
+		break;
+	case NTO:
+		/* Take care of noclobber mode. */
+		if (Cflag) {
+			fname = redir->nfile.expfname;
+			if ((f = noclobberopen(fname)) < 0)
+				goto ecreate;
+			break;
+		}
+		/* FALLTHROUGH */
+	case NCLOBBER:
+		fname = redir->nfile.expfname;
+		if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
+			goto ecreate;
+		break;
+	case NAPPEND:
+		fname = redir->nfile.expfname;
+		if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
+			goto ecreate;
+		break;
+	default:
+#ifdef DEBUG
+		abort();
+#endif
+		/* Fall through to eliminate warning. */
+	case NTOFD:
+	case NFROMFD:
+		f = -1;
+		break;
+	case NHERE:
+	case NXHERE:
+		f = openhere(redir);
+		break;
+	}
+
+	return f;
+ecreate:
+	sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
+eopen:
+	sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
+}
+
+static inline void
+dupredirect(union node *redir, int f)
+{
+	int fd = redir->nfile.fd;
+
+	if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
+		if (redir->ndup.dupfd >= 0) {   /* if not ">&-" */
+				copyfd(redir->ndup.dupfd, fd);
+		}
+		return;
+	}
+
+	if (f != fd) {
+		copyfd(f, fd);
+		close(f);
+	}
+	return;
+}
+
+/*
+ * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
+ * old file descriptors are stashed away so that the redirection can be
+ * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
+ * standard output, and the standard error if it becomes a duplicate of
+ * stdout, is saved in memory.
+ */
+
+static void
+redirect(union node *redir, int flags)
+{
+	union node *n;
+	struct redirtab *sv;
+	int i;
+	int fd;
+	int newfd;
+	int *p;
+	nullredirs++;
+	if (!redir) {
+		return;
+	}
+	sv = NULL;
+	INTOFF;
+	if (flags & REDIR_PUSH) {
+		struct redirtab *q;
+		q = ckmalloc(sizeof (struct redirtab));
+		q->next = redirlist;
+		redirlist = q;
+		q->nullredirs = nullredirs - 1;
+		for (i = 0 ; i < 10 ; i++)
+			q->renamed[i] = EMPTY;
+		nullredirs = 0;
+		sv = q;
+	}
+	n = redir;
+	do {
+		fd = n->nfile.fd;
+		if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
+		    n->ndup.dupfd == fd)
+			continue; /* redirect from/to same file descriptor */
+
+		newfd = openredirect(n);
+		if (fd == newfd)
+			continue;
+		if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
+			i = fcntl(fd, F_DUPFD, 10);
+
+			if (i == -1) {
+				i = errno;
+				if (i != EBADF) {
+					close(newfd);
+					errno = i;
+					sh_error("%d: %m", fd);
+					/* NOTREACHED */
+				}
+			} else {
+				*p = i;
+				close(fd);
+			}
+		} else {
+			close(fd);
+		}
+		dupredirect(n, newfd);
+	} while ((n = n->nfile.next));
+	INTON;
+	if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
+		preverrout_fd = sv->renamed[2];
+}
+
+
+/*
+ * Undo the effects of the last redirection.
+ */
+
+void
+popredir(int drop)
+{
+	struct redirtab *rp;
+	int i;
+
+	if (--nullredirs >= 0)
+		return;
+	INTOFF;
+	rp = redirlist;
+	for (i = 0 ; i < 10 ; i++) {
+		if (rp->renamed[i] != EMPTY) {
+			if (!drop) {
+				close(i);
+				copyfd(rp->renamed[i], i);
+			}
+			close(rp->renamed[i]);
+		}
+	}
+	redirlist = rp->next;
+	nullredirs = rp->nullredirs;
+	ckfree(rp);
+	INTON;
+}
+
+/*
+ * Undo all redirections.  Called on error or interrupt.
+ */
+
+/*
+ * Discard all saved file descriptors.
+ */
+
+void
+clearredir(int drop)
+{
+	for (;;) {
+		nullredirs = 0;
+		if (!redirlist)
+			break;
+		popredir(drop);
+	}
+}
+
+
+/*
+ * Copy a file descriptor to be >= to.  Returns -1
+ * if the source file descriptor is closed, EMPTY if there are no unused
+ * file descriptors left.
+ */
+
+int
+copyfd(int from, int to)
+{
+	int newfd;
+
+	newfd = fcntl(from, F_DUPFD, to);
+	if (newfd < 0) {
+		if (errno == EMFILE)
+			return EMPTY;
+		else
+			sh_error("%d: %m", from);
+	}
+	return newfd;
+}
+
+
+int
+redirectsafe(union node *redir, int flags)
+{
+	int err;
+	volatile int saveint;
+	struct jmploc *volatile savehandler = handler;
+	struct jmploc jmploc;
+
+	SAVEINT(saveint);
+	if (!(err = setjmp(jmploc.loc) * 2)) {
+		handler = &jmploc;
+		redirect(redir, flags);
+	}
+	handler = savehandler;
+	if (err && exception != EXERROR)
+		longjmp(handler->loc, 1);
+	RESTOREINT(saveint);
+	return err;
+}
+
+/*      show.c    */
+
+#ifdef DEBUG
+static void shtree(union node *, int, char *, FILE*);
+static void shcmd(union node *, FILE *);
+static void sharg(union node *, FILE *);
+static void indent(int, char *, FILE *);
+static void trstring(char *);
+
+
+void
+showtree(union node *n)
+{
+	trputs("showtree called\n");
+	shtree(n, 1, NULL, stdout);
+}
+
+
+static void
+shtree(union node *n, int ind, char *pfx, FILE *fp)
+{
+	struct nodelist *lp;
+	const char *s;
+
+	if (n == NULL)
+		return;
+
+	indent(ind, pfx, fp);
+	switch(n->type) {
+	case NSEMI:
+		s = "; ";
+		goto binop;
+	case NAND:
+		s = " && ";
+		goto binop;
+	case NOR:
+		s = " || ";
+binop:
+		shtree(n->nbinary.ch1, ind, NULL, fp);
+	   /*    if (ind < 0) */
+			fputs(s, fp);
+		shtree(n->nbinary.ch2, ind, NULL, fp);
+		break;
+	case NCMD:
+		shcmd(n, fp);
+		if (ind >= 0)
+			putc('\n', fp);
+		break;
+	case NPIPE:
+		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
+			shcmd(lp->n, fp);
+			if (lp->next)
+				fputs(" | ", fp);
+		}
+		if (n->npipe.backgnd)
+			fputs(" &", fp);
+		if (ind >= 0)
+			putc('\n', fp);
+		break;
+	default:
+		fprintf(fp, "<node type %d>", n->type);
+		if (ind >= 0)
+			putc('\n', fp);
+		break;
+	}
+}
+
+
+static void
+shcmd(union node *cmd, FILE *fp)
+{
+	union node *np;
+	int first;
+	const char *s;
+	int dftfd;
+
+	first = 1;
+	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
+		if (! first)
+			putchar(' ');
+		sharg(np, fp);
+		first = 0;
+	}
+	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
+		if (! first)
+			putchar(' ');
+		switch (np->nfile.type) {
+			case NTO:       s = ">";  dftfd = 1; break;
+			case NCLOBBER:  s = ">|"; dftfd = 1; break;
+			case NAPPEND:   s = ">>"; dftfd = 1; break;
+			case NTOFD:     s = ">&"; dftfd = 1; break;
+			case NFROM:     s = "<";  dftfd = 0; break;
+			case NFROMFD:   s = "<&"; dftfd = 0; break;
+			case NFROMTO:   s = "<>"; dftfd = 0; break;
+			default:        s = "*error*"; dftfd = 0; break;
+		}
+		if (np->nfile.fd != dftfd)
+			fprintf(fp, "%d", np->nfile.fd);
+		fputs(s, fp);
+		if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
+			fprintf(fp, "%d", np->ndup.dupfd);
+		} else {
+			sharg(np->nfile.fname, fp);
+		}
+		first = 0;
+	}
+}
+
+
+
+static void
+sharg(union node *arg, FILE *fp)
+{
+	char *p;
+	struct nodelist *bqlist;
+	int subtype;
+
+	if (arg->type != NARG) {
+		out1fmt("<node type %d>\n", arg->type);
+		abort();
+	}
+	bqlist = arg->narg.backquote;
+	for (p = arg->narg.text ; *p ; p++) {
+		switch (*p) {
+		case CTLESC:
+			putc(*++p, fp);
+			break;
+		case CTLVAR:
+			putc('$', fp);
+			putc('{', fp);
+			subtype = *++p;
+			if (subtype == VSLENGTH)
+				putc('#', fp);
+
+			while (*p != '=')
+				putc(*p++, fp);
+
+			if (subtype & VSNUL)
+				putc(':', fp);
+
+			switch (subtype & VSTYPE) {
+			case VSNORMAL:
+				putc('}', fp);
+				break;
+			case VSMINUS:
+				putc('-', fp);
+				break;
+			case VSPLUS:
+				putc('+', fp);
+				break;
+			case VSQUESTION:
+				putc('?', fp);
+				break;
+			case VSASSIGN:
+				putc('=', fp);
+				break;
+			case VSTRIMLEFT:
+				putc('#', fp);
+				break;
+			case VSTRIMLEFTMAX:
+				putc('#', fp);
+				putc('#', fp);
+				break;
+			case VSTRIMRIGHT:
+				putc('%', fp);
+				break;
+			case VSTRIMRIGHTMAX:
+				putc('%', fp);
+				putc('%', fp);
+				break;
+			case VSLENGTH:
+				break;
+			default:
+				out1fmt("<subtype %d>", subtype);
+			}
+			break;
+		case CTLENDVAR:
+		     putc('}', fp);
+		     break;
+		case CTLBACKQ:
+		case CTLBACKQ|CTLQUOTE:
+			putc('$', fp);
+			putc('(', fp);
+			shtree(bqlist->n, -1, NULL, fp);
+			putc(')', fp);
+			break;
+		default:
+			putc(*p, fp);
+			break;
+		}
+	}
+}
+
+
+static void
+indent(int amount, char *pfx, FILE *fp)
+{
+	int i;
+
+	for (i = 0 ; i < amount ; i++) {
+		if (pfx && i == amount - 1)
+			fputs(pfx, fp);
+		putc('\t', fp);
+	}
+}
+
+
+
+/*
+ * Debugging stuff.
+ */
+
+
+FILE *tracefile;
+
+
+void
+trputc(int c)
+{
+	if (debug != 1)
+		return;
+	putc(c, tracefile);
+}
+
+void
+trace(const char *fmt, ...)
+{
+	va_list va;
+
+	if (debug != 1)
+		return;
+	va_start(va, fmt);
+	(void) vfprintf(tracefile, fmt, va);
+	va_end(va);
+}
+
+void
+tracev(const char *fmt, va_list va)
+{
+	if (debug != 1)
+		return;
+	(void) vfprintf(tracefile, fmt, va);
+}
+
+
+void
+trputs(const char *s)
+{
+	if (debug != 1)
+		return;
+	fputs(s, tracefile);
+}
+
+
+static void
+trstring(char *s)
+{
+	char *p;
+	char c;
+
+	if (debug != 1)
+		return;
+	putc('"', tracefile);
+	for (p = s ; *p ; p++) {
+		switch (*p) {
+		case '\n':  c = 'n';  goto backslash;
+		case '\t':  c = 't';  goto backslash;
+		case '\r':  c = 'r';  goto backslash;
+		case '"':  c = '"';  goto backslash;
+		case '\\':  c = '\\';  goto backslash;
+		case CTLESC:  c = 'e';  goto backslash;
+		case CTLVAR:  c = 'v';  goto backslash;
+		case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
+		case CTLBACKQ:  c = 'q';  goto backslash;
+		case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
+backslash:        putc('\\', tracefile);
+			putc(c, tracefile);
+			break;
+		default:
+			if (*p >= ' ' && *p <= '~')
+				putc(*p, tracefile);
+			else {
+				putc('\\', tracefile);
+				putc(*p >> 6 & 03, tracefile);
+				putc(*p >> 3 & 07, tracefile);
+				putc(*p & 07, tracefile);
+			}
+			break;
+		}
+	}
+	putc('"', tracefile);
+}
+
+
+void
+trargs(char **ap)
+{
+	if (debug != 1)
+		return;
+	while (*ap) {
+		trstring(*ap++);
+		if (*ap)
+			putc(' ', tracefile);
+		else
+			putc('\n', tracefile);
+	}
+}
+
+
+void
+opentrace(void)
+{
+	char s[100];
+#ifdef O_APPEND
+	int flags;
+#endif
+
+	if (debug != 1) {
+		if (tracefile)
+			fflush(tracefile);
+		/* leave open because libedit might be using it */
+		return;
+	}
+	scopy("./trace", s);
+	if (tracefile) {
+		if (!freopen(s, "a", tracefile)) {
+			fprintf(stderr, "Can't re-open %s\n", s);
+			debug = 0;
+			return;
+		}
+	} else {
+		if ((tracefile = fopen(s, "a")) == NULL) {
+			fprintf(stderr, "Can't open %s\n", s);
+			debug = 0;
+			return;
+		}
+	}
+#ifdef O_APPEND
+	if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
+		fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
+#endif
+	setlinebuf(tracefile);
+	fputs("\nTracing started.\n", tracefile);
+}
+#endif /* DEBUG */
+
+
+/*      trap.c       */
+
+/*
+ * Sigmode records the current value of the signal handlers for the various
+ * modes.  A value of zero means that the current handler is not known.
+ * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
+ */
+
+#define S_DFL 1                 /* default signal handling (SIG_DFL) */
+#define S_CATCH 2               /* signal is caught */
+#define S_IGN 3                 /* signal is ignored (SIG_IGN) */
+#define S_HARD_IGN 4            /* signal is ignored permenantly */
+#define S_RESET 5               /* temporary - to reset a hard ignored sig */
+
+
+
+/*
+ * The trap builtin.
+ */
+
+int
+trapcmd(int argc, char **argv)
+{
+	char *action;
+	char **ap;
+	int signo;
+
+	nextopt(nullstr);
+	ap = argptr;
+	if (!*ap) {
+		for (signo = 0 ; signo < NSIG ; signo++) {
+			if (trap[signo] != NULL) {
+				const char *sn;
+
+				sn = u_signal_names(0, &signo, 0);
+				if (sn == NULL)
+					sn = "???";
+				out1fmt("trap -- %s %s\n",
+					single_quote(trap[signo]), sn);
+			}
+		}
+		return 0;
+	}
+	if (!ap[1])
+		action = NULL;
+	else
+		action = *ap++;
+	while (*ap) {
+		if ((signo = decode_signal(*ap, 0)) < 0)
+			sh_error("%s: bad trap", *ap);
+		INTOFF;
+		if (action) {
+			if (action[0] == '-' && action[1] == '\0')
+				action = NULL;
+			else
+				action = savestr(action);
+		}
+		if (trap[signo])
+			ckfree(trap[signo]);
+		trap[signo] = action;
+		if (signo != 0)
+			setsignal(signo);
+		INTON;
+		ap++;
+	}
+	return 0;
+}
+
+
+/*
+ * Clear traps on a fork.
+ */
+
+void
+clear_traps(void)
+{
+	char **tp;
+
+	for (tp = trap ; tp < &trap[NSIG] ; tp++) {
+		if (*tp && **tp) {      /* trap not NULL or SIG_IGN */
+			INTOFF;
+			ckfree(*tp);
+			*tp = NULL;
+			if (tp != &trap[0])
+				setsignal(tp - trap);
+			INTON;
+		}
+	}
+}
+
+
+/*
+ * Set the signal handler for the specified signal.  The routine figures
+ * out what it should be set to.
+ */
+
+void
+setsignal(int signo)
+{
+	int action;
+	char *t, tsig;
+	struct sigaction act;
+
+	if ((t = trap[signo]) == NULL)
+		action = S_DFL;
+	else if (*t != '\0')
+		action = S_CATCH;
+	else
+		action = S_IGN;
+	if (rootshell && action == S_DFL) {
+		switch (signo) {
+		case SIGINT:
+			if (iflag || minusc || sflag == 0)
+				action = S_CATCH;
+			break;
+		case SIGQUIT:
+#ifdef DEBUG
+			if (debug)
+				break;
+#endif
+			/* FALLTHROUGH */
+		case SIGTERM:
+			if (iflag)
+				action = S_IGN;
+			break;
+#if JOBS
+		case SIGTSTP:
+		case SIGTTOU:
+			if (mflag)
+				action = S_IGN;
+			break;
+#endif
+		}
+	}
+
+	t = &sigmode[signo - 1];
+	tsig = *t;
+	if (tsig == 0) {
+		/*
+		 * current setting unknown
+		 */
+		if (sigaction(signo, 0, &act) == -1) {
+			/*
+			 * Pretend it worked; maybe we should give a warning
+			 * here, but other shells don't. We don't alter
+			 * sigmode, so that we retry every time.
+			 */
+			return;
+		}
+		if (act.sa_handler == SIG_IGN) {
+			if (mflag && (signo == SIGTSTP ||
+			     signo == SIGTTIN || signo == SIGTTOU)) {
+				tsig = S_IGN;   /* don't hard ignore these */
+			} else
+				tsig = S_HARD_IGN;
+		} else {
+			tsig = S_RESET; /* force to be set */
+		}
+	}
+	if (tsig == S_HARD_IGN || tsig == action)
+		return;
+	switch (action) {
+	case S_CATCH:
+		act.sa_handler = onsig;
+		break;
+	case S_IGN:
+		act.sa_handler = SIG_IGN;
+		break;
+	default:
+		act.sa_handler = SIG_DFL;
+	}
+	*t = action;
+	act.sa_flags = 0;
+	sigfillset(&act.sa_mask);
+	sigaction(signo, &act, 0);
+}
+
+/*
+ * Ignore a signal.
+ */
+
+void
+ignoresig(int signo)
+{
+	if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
+		signal(signo, SIG_IGN);
+	}
+	sigmode[signo - 1] = S_HARD_IGN;
+}
+
+
+/*
+ * Signal handler.
+ */
+
+void
+onsig(int signo)
+{
+	gotsig[signo - 1] = 1;
+	pendingsigs = signo;
+
+	if (exsig || (signo == SIGINT && !trap[SIGINT])) {
+		if (!suppressint)
+			onint();
+		intpending = 1;
+	}
+}
+
+
+/*
+ * Called to execute a trap.  Perhaps we should avoid entering new trap
+ * handlers while we are executing a trap handler.
+ */
+
+int
+dotrap(void)
+{
+	char *p;
+	char *q;
+	int i;
+	int savestatus;
+	int skip = 0;
+
+	savestatus = exitstatus;
+	pendingsigs = 0;
+	xbarrier();
+
+	for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
+		if (!*q)
+			continue;
+		*q = 0;
+
+		p = trap[i + 1];
+		if (!p)
+			continue;
+		skip = evalstring(p, SKIPEVAL);
+		exitstatus = savestatus;
+		if (skip)
+			break;
+	}
+
+	return skip;
+}
+
+
+/*
+ * Controls whether the shell is interactive or not.
+ */
+
+void
+setinteractive(int on)
+{
+	static int is_interactive;
+
+	if (++on == is_interactive)
+		return;
+	is_interactive = on;
+	setsignal(SIGINT);
+	setsignal(SIGQUIT);
+	setsignal(SIGTERM);
+#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
+		if(is_interactive > 1) {
+			/* Looks like they want an interactive shell */
+			static int do_banner;
+
+				if(!do_banner) {
+					out1fmt(
+			"\n\n%s Built-in shell (ash)\n"
+			"Enter 'help' for a list of built-in commands.\n\n",
+					BB_BANNER);
+					do_banner++;
+				}
+		}
+#endif
+}
+
+
+#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
+/*** List the available builtins ***/
+
+static int helpcmd(int argc, char **argv)
+{
+	int col, i;
+
+	out1fmt("\nBuilt-in commands:\n-------------------\n");
+	for (col = 0, i = 0; i < NUMBUILTINS; i++) {
+		col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
+					  builtincmd[i].name + 1);
+		if (col > 60) {
+			out1fmt("\n");
+			col = 0;
+		}
+	}
+#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
+	{
+		extern const struct BB_applet applets[];
+		extern const size_t NUM_APPLETS;
+
+		for (i = 0; i < NUM_APPLETS; i++) {
+
+			col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
+			if (col > 60) {
+				out1fmt("\n");
+				col = 0;
+			}
+		}
+	}
+#endif
+	out1fmt("\n\n");
+	return EXIT_SUCCESS;
+}
+#endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
+
+/*
+ * Called to exit the shell.
+ */
+
+void
+exitshell(void)
+{
+	struct jmploc loc;
+	char *p;
+	int status;
+
+	status = exitstatus;
+	TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
+	if (setjmp(loc.loc)) {
+		if (exception == EXEXIT)
+			_exit(exitstatus);
+		goto out;
+	}
+	handler = &loc;
+	if ((p = trap[0])) {
+		trap[0] = NULL;
+		evalstring(p, 0);
+	}
+	flushall();
+	setjobctl(0);
+#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
+	if (iflag && rootshell) {
+		const char *hp = lookupvar("HISTFILE");
+
+		if(hp != NULL )
+			save_history ( hp );
+	}
+#endif
+out:
+	_exit(status);
+	/* NOTREACHED */
+}
+
+static int decode_signal(const char *string, int minsig)
+{
+	int signo;
+	const char *name = u_signal_names(string, &signo, minsig);
+
+	return name ? signo : -1;
+}
+
+/*      var.c     */
+
+static struct var *vartab[VTABSIZE];
+
+static int vpcmp(const void *, const void *);
+static struct var **findvar(struct var **, const char *);
+
+/*
+ * Initialize the variable symbol tables and import the environment
+ */
+
+
+#ifdef CONFIG_ASH_GETOPTS
+/*
+ * Safe version of setvar, returns 1 on success 0 on failure.
+ */
+
+int
+setvarsafe(const char *name, const char *val, int flags)
+{
+	int err;
+	volatile int saveint;
+	struct jmploc *volatile savehandler = handler;
+	struct jmploc jmploc;
+
+	SAVEINT(saveint);
+	if (setjmp(jmploc.loc))
+		err = 1;
+	else {
+		handler = &jmploc;
+		setvar(name, val, flags);
+		err = 0;
+	}
+	handler = savehandler;
+	RESTOREINT(saveint);
+	return err;
+}
+#endif
+
+/*
+ * Set the value of a variable.  The flags argument is ored with the
+ * flags of the variable.  If val is NULL, the variable is unset.
+ */
+
+static void
+setvar(const char *name, const char *val, int flags)
+{
+	char *p, *q;
+	size_t namelen;
+	char *nameeq;
+	size_t vallen;
+
+	q = endofname(name);
+	p = strchrnul(q, '=');
+	namelen = p - name;
+	if (!namelen || p != q)
+		sh_error("%.*s: bad variable name", namelen, name);
+	vallen = 0;
+	if (val == NULL) {
+		flags |= VUNSET;
+	} else {
+		vallen = strlen(val);
+	}
+	INTOFF;
+	p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
+	if (val) {
+		*p++ = '=';
+		p = mempcpy(p, val, vallen);
+	}
+	*p = '\0';
+	setvareq(nameeq, flags | VNOSAVE);
+	INTON;
+}
+
+
+/*
+ * Same as setvar except that the variable and value are passed in
+ * the first argument as name=value.  Since the first argument will
+ * be actually stored in the table, it should not be a string that
+ * will go away.
+ * Called with interrupts off.
+ */
+
+void
+setvareq(char *s, int flags)
+{
+	struct var *vp, **vpp;
+
+	vpp = hashvar(s);
+	flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
+	vp = *findvar(vpp, s);
+	if (vp) {
+		if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
+			const char *n;
+
+			if (flags & VNOSAVE)
+				free(s);
+			n = vp->text;
+			sh_error("%.*s: is read only", strchrnul(n, '=') - n, n);
+		}
+
+		if (flags & VNOSET)
+			return;
+
+		if (vp->func && (flags & VNOFUNC) == 0)
+			(*vp->func)(strchrnul(s, '=') + 1);
+
+		if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
+			ckfree(vp->text);
+
+		flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
+	} else {
+		if (flags & VNOSET)
+			return;
+		/* not found */
+		vp = ckmalloc(sizeof (*vp));
+		vp->next = *vpp;
+		vp->func = NULL;
+		*vpp = vp;
+	}
+	if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
+		s = savestr(s);
+	vp->text = s;
+	vp->flags = flags;
+}
+
+
+/*
+ * Process a linked list of variable assignments.
+ */
+
+static void
+listsetvar(struct strlist *list_set_var, int flags)
+{
+	struct strlist *lp = list_set_var;
+
+	if (!lp)
+		return;
+	INTOFF;
+	do {
+		setvareq(lp->text, flags);
+	} while ((lp = lp->next));
+	INTON;
+}
+
+
+/*
+ * Find the value of a variable.  Returns NULL if not set.
+ */
+
+static char *
+lookupvar(const char *name)
+{
+	struct var *v;
+
+	if ((v = *findvar(hashvar(name), name))) {
+#ifdef DYNAMIC_VAR
+	/*
+	 * Dynamic variables are implemented roughly the same way they are
+	 * in bash. Namely, they're "special" so long as they aren't unset.
+	 * As soon as they're unset, they're no longer dynamic, and dynamic
+	 * lookup will no longer happen at that point. -- PFM.
+	 */
+		if((v->flags & VDYNAMIC))
+			(*v->func)(NULL);
+#endif
+		if(!(v->flags & VUNSET))
+			return strchrnul(v->text, '=') + 1;
+	}
+
+	return NULL;
+}
+
+
+/*
+ * Search the environment of a builtin command.
+ */
+
+static char *
+bltinlookup(const char *name)
+{
+	struct strlist *sp;
+
+	for (sp = cmdenviron ; sp ; sp = sp->next) {
+		if (varequal(sp->text, name))
+			return strchrnul(sp->text, '=') + 1;
+	}
+	return lookupvar(name);
+}
+
+
+/*
+ * Generate a list of variables satisfying the given conditions.
+ */
+
+static char **
+listvars(int on, int off, char ***end)
+{
+	struct var **vpp;
+	struct var *vp;
+	char **ep;
+	int mask;
+
+	STARTSTACKSTR(ep);
+	vpp = vartab;
+	mask = on | off;
+	do {
+		for (vp = *vpp ; vp ; vp = vp->next)
+			if ((vp->flags & mask) == on) {
+				if (ep == stackstrend())
+					ep = growstackstr();
+				*ep++ = (char *) vp->text;
+			}
+	} while (++vpp < vartab + VTABSIZE);
+	if (ep == stackstrend())
+		ep = growstackstr();
+	if (end)
+		*end = ep;
+	*ep++ = NULL;
+	return grabstackstr(ep);
+}
+
+
+/*
+ * POSIX requires that 'set' (but not export or readonly) output the
+ * variables in lexicographic order - by the locale's collating order (sigh).
+ * Maybe we could keep them in an ordered balanced binary tree
+ * instead of hashed lists.
+ * For now just roll 'em through qsort for printing...
+ */
+
+static int
+showvars(const char *sep_prefix, int on, int off)
+{
+	const char *sep;
+	char **ep, **epend;
+
+	ep = listvars(on, off, &epend);
+	qsort(ep, epend - ep, sizeof(char *), vpcmp);
+
+	sep = *sep_prefix ? spcstr : sep_prefix;
+
+	for (; ep < epend; ep++) {
+		const char *p;
+		const char *q;
+
+		p = strchrnul(*ep, '=');
+		q = nullstr;
+		if (*p)
+			q = single_quote(++p);
+
+		out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
+	}
+
+	return 0;
+}
+
+
+
+/*
+ * The export and readonly commands.
+ */
+
+static int
+exportcmd(int argc, char **argv)
+{
+	struct var *vp;
+	char *name;
+	const char *p;
+	char **aptr;
+	int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
+	int notp;
+
+	notp = nextopt("p") - 'p';
+	if (notp && ((name = *(aptr = argptr)))) {
+		do {
+			if ((p = strchr(name, '=')) != NULL) {
+				p++;
+			} else {
+				if ((vp = *findvar(hashvar(name), name))) {
+					vp->flags |= flag;
+					continue;
+				}
+			}
+			setvar(name, p, flag);
+		} while ((name = *++aptr) != NULL);
+	} else {
+		showvars(argv[0], flag, 0);
+	}
+	return 0;
+}
+
+
+/*
+ * Make a variable a local variable.  When a variable is made local, it's
+ * value and flags are saved in a localvar structure.  The saved values
+ * will be restored when the shell function returns.  We handle the name
+ * "-" as a special case.
+ */
+
+static inline void
+mklocal(char *name)
+{
+	struct localvar *lvp;
+	struct var **vpp;
+	struct var *vp;
+
+	INTOFF;
+	lvp = ckmalloc(sizeof (struct localvar));
+	if (name[0] == '-' && name[1] == '\0') {
+		char *p;
+		p = ckmalloc(sizeof(optlist));
+		lvp->text = memcpy(p, optlist, sizeof(optlist));
+		vp = NULL;
+	} else {
+		char *eq;
+
+		vpp = hashvar(name);
+		vp = *findvar(vpp, name);
+		eq = strchr(name, '=');
+		if (vp == NULL) {
+			if (eq)
+				setvareq(name, VSTRFIXED);
+			else
+				setvar(name, NULL, VSTRFIXED);
+			vp = *vpp;      /* the new variable */
+			lvp->flags = VUNSET;
+		} else {
+			lvp->text = vp->text;
+			lvp->flags = vp->flags;
+			vp->flags |= VSTRFIXED|VTEXTFIXED;
+			if (eq)
+				setvareq(name, 0);
+		}
+	}
+	lvp->vp = vp;
+	lvp->next = localvars;
+	localvars = lvp;
+	INTON;
+}
+
+/*
+ * The "local" command.
+ */
+
+static int
+localcmd(int argc, char **argv)
+{
+	char *name;
+
+	argv = argptr;
+	while ((name = *argv++) != NULL) {
+		mklocal(name);
+	}
+	return 0;
+}
+
+
+/*
+ * Called after a function returns.
+ * Interrupts must be off.
+ */
+
+static void
+poplocalvars(void)
+{
+	struct localvar *lvp;
+	struct var *vp;
+
+	while ((lvp = localvars) != NULL) {
+		localvars = lvp->next;
+		vp = lvp->vp;
+		TRACE(("poplocalvar %s", vp ? vp->text : "-"));
+		if (vp == NULL) {       /* $- saved */
+			memcpy(optlist, lvp->text, sizeof(optlist));
+			ckfree(lvp->text);
+			optschanged();
+		} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
+			unsetvar(vp->text);
+		} else {
+			if (vp->func)
+				(*vp->func)(strchrnul(lvp->text, '=') + 1);
+			if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
+				ckfree(vp->text);
+			vp->flags = lvp->flags;
+			vp->text = lvp->text;
+		}
+		ckfree(lvp);
+	}
+}
+
+
+/*
+ * The unset builtin command.  We unset the function before we unset the
+ * variable to allow a function to be unset when there is a readonly variable
+ * with the same name.
+ */
+
+int
+unsetcmd(int argc, char **argv)
+{
+	char **ap;
+	int i;
+	int flag = 0;
+	int ret = 0;
+
+	while ((i = nextopt("vf")) != '\0') {
+		flag = i;
+	}
+
+	for (ap = argptr; *ap ; ap++) {
+		if (flag != 'f') {
+			i = unsetvar(*ap);
+			ret |= i;
+			if (!(i & 2))
+				continue;
+		}
+		if (flag != 'v')
+			unsetfunc(*ap);
+	}
+	return ret & 1;
+}
+
+
+/*
+ * Unset the specified variable.
+ */
+
+int
+unsetvar(const char *s)
+{
+	struct var **vpp;
+	struct var *vp;
+	int retval;
+
+	vpp = findvar(hashvar(s), s);
+	vp = *vpp;
+	retval = 2;
+	if (vp) {
+		int flags = vp->flags;
+
+		retval = 1;
+		if (flags & VREADONLY)
+			goto out;
+#ifdef DYNAMIC_VAR
+		vp->flags &= ~VDYNAMIC;
+#endif
+		if (flags & VUNSET)
+			goto ok;
+		if ((flags & VSTRFIXED) == 0) {
+			INTOFF;
+			if ((flags & (VTEXTFIXED|VSTACK)) == 0)
+				ckfree(vp->text);
+			*vpp = vp->next;
+			ckfree(vp);
+			INTON;
+		} else {
+			setvar(s, 0, 0);
+			vp->flags &= ~VEXPORT;
+		}
+ok:
+		retval = 0;
+	}
+
+out:
+	return retval;
+}
+
+
+
+/*
+ * Find the appropriate entry in the hash table from the name.
+ */
+
+static struct var **
+hashvar(const char *p)
+{
+	unsigned int hashval;
+
+	hashval = ((unsigned char) *p) << 4;
+	while (*p && *p != '=')
+		hashval += (unsigned char) *p++;
+	return &vartab[hashval % VTABSIZE];
+}
+
+
+
+/*
+ * Compares two strings up to the first = or '\0'.  The first
+ * string must be terminated by '='; the second may be terminated by
+ * either '=' or '\0'.
+ */
+
+int
+varcmp(const char *p, const char *q)
+{
+	int c, d;
+
+	while ((c = *p) == (d = *q)) {
+		if (!c || c == '=')
+			goto out;
+		p++;
+		q++;
+	}
+	if (c == '=')
+		c = 0;
+	if (d == '=')
+		d = 0;
+out:
+	return c - d;
+}
+
+static int
+vpcmp(const void *a, const void *b)
+{
+	return varcmp(*(const char **)a, *(const char **)b);
+}
+
+static struct var **
+findvar(struct var **vpp, const char *name)
+{
+	for (; *vpp; vpp = &(*vpp)->next) {
+		if (varequal((*vpp)->text, name)) {
+			break;
+		}
+	}
+	return vpp;
+}
+/*      setmode.c      */
+
+#include <sys/times.h>
+
+static const unsigned char timescmd_str[] = {
+	' ',  offsetof(struct tms, tms_utime),
+	'\n', offsetof(struct tms, tms_stime),
+	' ',  offsetof(struct tms, tms_cutime),
+	'\n', offsetof(struct tms, tms_cstime),
+	0
+};
+
+static int timescmd(int ac, char **av)
+{
+	long int clk_tck, s, t;
+	const unsigned char *p;
+	struct tms buf;
+
+	clk_tck = sysconf(_SC_CLK_TCK);
+	times(&buf);
+
+	p = timescmd_str;
+	do {
+		t = *(clock_t *)(((char *) &buf) + p[1]);
+		s = t / clk_tck;
+		out1fmt("%ldm%ld.%.3lds%c",
+			s/60, s%60,
+			((t - s * clk_tck) * 1000) / clk_tck,
+			p[0]);
+	} while (*(p += 2));
+
+	return 0;
+}
+
+#ifdef CONFIG_ASH_MATH_SUPPORT
+static arith_t
+dash_arith(const char *s)
+{
+	arith_t result;
+	int errcode = 0;
+
+	INTOFF;
+	result = arith(s, &errcode);
+	if (errcode < 0) {
+		if (errcode == -3)
+			sh_error("exponent less than 0");
+		else if (errcode == -2)
+			sh_error("divide by zero");
+		else if (errcode == -5)
+			sh_error("expression recursion loop detected");
+		else
+			synerror(s);
+	}
+	INTON;
+
+	return (result);
+}
+
+
+/*
+ *  The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
+ *  Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+ *
+ *  Copyright (C) 2003 Vladimir Oleynik <dzo at simtreas.ru>
+ */
+
+static int
+letcmd(int argc, char **argv)
+{
+	char **ap;
+	arith_t i;
+
+	ap = argv + 1;
+	if(!*ap)
+		sh_error("expression expected");
+	for (ap = argv + 1; *ap; ap++) {
+		i = dash_arith(*ap);
+	}
+
+	return (!i);
+}
+#endif /* CONFIG_ASH_MATH_SUPPORT */
+
+/*      miscbltin.c  */
+
+/*
+ * Miscellaneous builtins.
+ */
+
+#undef rflag
+
+#ifdef __GLIBC__
+#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
+typedef enum __rlimit_resource rlim_t;
+#endif
+#endif
+
+
+/*
+ * The read builtin.  The -e option causes backslashes to escape the
+ * following character.
+ *
+ * This uses unbuffered input, which may be avoidable in some cases.
+ */
+
+static int
+readcmd(int argc, char **argv)
+{
+	char **ap;
+	int backslash;
+	char c;
+	int rflag;
+	char *prompt;
+	const char *ifs;
+	char *p;
+	int startword;
+	int status;
+	int i;
+#if defined(CONFIG_ASH_READ_NCHARS)
+	int nch_flag = 0;
+	int nchars = 0;
+	int silent = 0;
+	struct termios tty, old_tty;
+#endif
+#if defined(CONFIG_ASH_READ_TIMEOUT)
+	fd_set set;
+	struct timeval ts;
+
+	ts.tv_sec = ts.tv_usec = 0;
+#endif
+
+	rflag = 0;
+	prompt = NULL;
+#if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
+	while ((i = nextopt("p:rt:n:s")) != '\0')
+#elif defined(CONFIG_ASH_READ_NCHARS)
+	while ((i = nextopt("p:rn:s")) != '\0')
+#elif defined(CONFIG_ASH_READ_TIMEOUT)
+	while ((i = nextopt("p:rt:")) != '\0')
+#else
+	while ((i = nextopt("p:r")) != '\0')
+#endif
+	{
+		switch(i) {
+		case 'p':
+			prompt = optionarg;
+			break;
+#if defined(CONFIG_ASH_READ_NCHARS)
+		case 'n':
+			nchars = strtol(optionarg, &p, 10);
+			if (*p)
+				sh_error("invalid count");
+			nch_flag = (nchars > 0);
+			break;
+		case 's':
+			silent = 1;
+			break;
+#endif
+#if defined(CONFIG_ASH_READ_TIMEOUT)
+		case 't':
+			ts.tv_sec = strtol(optionarg, &p, 10);
+			ts.tv_usec = 0;
+			if (*p == '.') {
+				char *p2;
+				if (*++p) {
+					int scale;
+					ts.tv_usec = strtol(p, &p2, 10);
+					if (*p2)
+						sh_error("invalid timeout");
+					scale = p2 - p;
+					/* normalize to usec */
+					if (scale > 6)
+						sh_error("invalid timeout");
+					while (scale++ < 6)
+						ts.tv_usec *= 10;
+				}
+			} else if (*p) {
+				sh_error("invalid timeout");
+			}
+			if ( ! ts.tv_sec && ! ts.tv_usec)
+				sh_error("invalid timeout");
+			break;
+#endif
+		case 'r':
+			rflag = 1;
+			break;
+		default:
+			break;
+		}
+	}
+	if (prompt && isatty(0)) {
+		out2str(prompt);
+	}
+	if (*(ap = argptr) == NULL)
+		sh_error("arg count");
+	if ((ifs = bltinlookup("IFS")) == NULL)
+		ifs = defifs;
+#if defined(CONFIG_ASH_READ_NCHARS)
+	if (nch_flag || silent) {
+		tcgetattr(0, &tty);
+		old_tty = tty;
+		if (nch_flag) {
+		    tty.c_lflag &= ~ICANON;
+		    tty.c_cc[VMIN] = nchars;
+		}
+		if (silent) {
+		    tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
+
+		}
+		tcsetattr(0, TCSANOW, &tty);
+	}
+#endif
+#if defined(CONFIG_ASH_READ_TIMEOUT)
+	if (ts.tv_sec || ts.tv_usec) {
+		FD_ZERO (&set);
+		FD_SET (0, &set);
+
+		i = select (FD_SETSIZE, &set, NULL, NULL, &ts);
+		if (!i) {
+#if defined(CONFIG_ASH_READ_NCHARS)
+			if (nch_flag)
+				tcsetattr(0, TCSANOW, &old_tty);
+#endif
+			return 1;
+		}
+	}
+#endif
+	status = 0;
+	startword = 1;
+	backslash = 0;
+	STARTSTACKSTR(p);
+#if defined(CONFIG_ASH_READ_NCHARS)
+	while (!nch_flag || nchars--)
+#else
+	for (;;)
+#endif
+	{
+		if (read(0, &c, 1) != 1) {
+			status = 1;
+			break;
+		}
+		if (c == '\0')
+			continue;
+		if (backslash) {
+			backslash = 0;
+			if (c != '\n')
+				goto put;
+			continue;
+		}
+		if (!rflag && c == '\\') {
+			backslash++;
+			continue;
+		}
+		if (c == '\n')
+			break;
+		if (startword && *ifs == ' ' && strchr(ifs, c)) {
+			continue;
+		}
+		startword = 0;
+		if (ap[1] != NULL && strchr(ifs, c) != NULL) {
+			STACKSTRNUL(p);
+			setvar(*ap, stackblock(), 0);
+			ap++;
+			startword = 1;
+			STARTSTACKSTR(p);
+		} else {
+put:
+			STPUTC(c, p);
+		}
+	}
+#if defined(CONFIG_ASH_READ_NCHARS)
+	if (nch_flag || silent)
+		tcsetattr(0, TCSANOW, &old_tty);
+#endif
+
+	STACKSTRNUL(p);
+	/* Remove trailing blanks */
+	while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
+		*p = '\0';
+	setvar(*ap, stackblock(), 0);
+	while (*++ap != NULL)
+		setvar(*ap, nullstr, 0);
+	return status;
+}
+
+
+static int umaskcmd(int argc, char **argv)
+{
+	static const char permuser[3] = "ugo";
+	static const char permmode[3] = "rwx";
+	static const short int permmask[] = {
+		S_IRUSR, S_IWUSR, S_IXUSR,
+		S_IRGRP, S_IWGRP, S_IXGRP,
+		S_IROTH, S_IWOTH, S_IXOTH
+	};
+
+	char *ap;
+	mode_t mask;
+	int i;
+	int symbolic_mode = 0;
+
+	while (nextopt("S") != '\0') {
+		symbolic_mode = 1;
+	}
+
+	INTOFF;
+	mask = umask(0);
+	umask(mask);
+	INTON;
+
+	if ((ap = *argptr) == NULL) {
+		if (symbolic_mode) {
+			char buf[18];
+			char *p = buf;
+
+			for (i = 0; i < 3; i++) {
+				int j;
+
+				*p++ = permuser[i];
+				*p++ = '=';
+				for (j = 0; j < 3; j++) {
+					if ((mask & permmask[3 * i + j]) == 0) {
+						*p++ = permmode[j];
+					}
+				}
+				*p++ = ',';
+			}
+			*--p = 0;
+			puts(buf);
+		} else {
+			out1fmt("%.4o\n", mask);
+		}
+	} else {
+		if (is_digit((unsigned char) *ap)) {
+			mask = 0;
+			do {
+				if (*ap >= '8' || *ap < '0')
+					sh_error(illnum, argv[1]);
+				mask = (mask << 3) + (*ap - '0');
+			} while (*++ap != '\0');
+			umask(mask);
+		} else {
+			mask = ~mask & 0777;
+			if (!bb_parse_mode(ap, &mask)) {
+				sh_error("Illegal mode: %s", ap);
+			}
+			umask(~mask & 0777);
+		}
+	}
+	return 0;
+}
+
+/*
+ * ulimit builtin
+ *
+ * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
+ * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
+ * ash by J.T. Conklin.
+ *
+ * Public domain.
+ */
+
+struct limits {
+	const char *name;
+	int     cmd;
+	int     factor; /* multiply by to get rlim_{cur,max} values */
+	char    option;
+};
+
+static const struct limits limits[] = {
+#ifdef RLIMIT_CPU
+	{ "time(seconds)",              RLIMIT_CPU,        1, 't' },
+#endif
+#ifdef RLIMIT_FSIZE
+	{ "file(blocks)",               RLIMIT_FSIZE,    512, 'f' },
+#endif
+#ifdef RLIMIT_DATA
+	{ "data(kbytes)",               RLIMIT_DATA,    1024, 'd' },
+#endif
+#ifdef RLIMIT_STACK
+	{ "stack(kbytes)",              RLIMIT_STACK,   1024, 's' },
+#endif
+#ifdef  RLIMIT_CORE
+	{ "coredump(blocks)",           RLIMIT_CORE,     512, 'c' },
+#endif
+#ifdef RLIMIT_RSS
+	{ "memory(kbytes)",             RLIMIT_RSS,     1024, 'm' },
+#endif
+#ifdef RLIMIT_MEMLOCK
+	{ "locked memory(kbytes)",      RLIMIT_MEMLOCK, 1024, 'l' },
+#endif
+#ifdef RLIMIT_NPROC
+	{ "process",                    RLIMIT_NPROC,      1, 'p' },
+#endif
+#ifdef RLIMIT_NOFILE
+	{ "nofiles",                    RLIMIT_NOFILE,     1, 'n' },
+#endif
+#ifdef RLIMIT_AS
+	{ "vmemory(kbytes)",            RLIMIT_AS,      1024, 'v' },
+#endif
+#ifdef RLIMIT_LOCKS
+	{ "locks",                      RLIMIT_LOCKS,      1, 'w' },
+#endif
+	{ (char *) 0,                   0,                 0,  '\0' }
+};
+
+enum limtype { SOFT = 0x1, HARD = 0x2 };
+
+static void printlim(enum limtype how, const struct rlimit *limit,
+			const struct limits *l)
+{
+	rlim_t val;
+
+	val = limit->rlim_max;
+	if (how & SOFT)
+		val = limit->rlim_cur;
+
+	if (val == RLIM_INFINITY)
+		out1fmt("unlimited\n");
+	else {
+		val /= l->factor;
+		out1fmt("%lld\n", (long long) val);
+	}
+}
+
+int
+ulimitcmd(int argc, char **argv)
+{
+	int     c;
+	rlim_t val = 0;
+	enum limtype how = SOFT | HARD;
+	const struct limits     *l;
+	int             set, all = 0;
+	int             optc, what;
+	struct rlimit   limit;
+
+	what = 'f';
+	while ((optc = nextopt("HSa"
+#ifdef RLIMIT_CPU
+				"t"
+#endif
+#ifdef RLIMIT_FSIZE
+				"f"
+#endif
+#ifdef RLIMIT_DATA
+				"d"
+#endif
+#ifdef RLIMIT_STACK
+				"s"
+#endif
+#ifdef RLIMIT_CORE
+				"c"
+#endif
+#ifdef RLIMIT_RSS
+				"m"
+#endif
+#ifdef RLIMIT_MEMLOCK
+				"l"
+#endif
+#ifdef RLIMIT_NPROC
+				"p"
+#endif
+#ifdef RLIMIT_NOFILE
+				"n"
+#endif
+#ifdef RLIMIT_AS
+				"v"
+#endif
+#ifdef RLIMIT_LOCKS
+				"w"
+#endif
+						)) != '\0')
+		switch (optc) {
+		case 'H':
+			how = HARD;
+			break;
+		case 'S':
+			how = SOFT;
+			break;
+		case 'a':
+			all = 1;
+			break;
+		default:
+			what = optc;
+		}
+
+	for (l = limits; l->option != what; l++)
+		;
+
+	set = *argptr ? 1 : 0;
+	if (set) {
+		char *p = *argptr;
+
+		if (all || argptr[1])
+			sh_error("too many arguments");
+		if (strncmp(p, "unlimited\n", 9) == 0)
+			val = RLIM_INFINITY;
+		else {
+			val = (rlim_t) 0;
+
+			while ((c = *p++) >= '0' && c <= '9')
+			{
+				val = (val * 10) + (long)(c - '0');
+				if (val < (rlim_t) 0)
+					break;
+			}
+			if (c)
+				sh_error("bad number");
+			val *= l->factor;
+		}
+	}
+	if (all) {
+		for (l = limits; l->name; l++) {
+			getrlimit(l->cmd, &limit);
+			out1fmt("%-20s ", l->name);
+			printlim(how, &limit, l);
+		}
+		return 0;
+	}
+
+	getrlimit(l->cmd, &limit);
+	if (set) {
+		if (how & HARD)
+			limit.rlim_max = val;
+		if (how & SOFT)
+			limit.rlim_cur = val;
+		if (setrlimit(l->cmd, &limit) < 0)
+			sh_error("error setting limit (%m)");
+	} else {
+		printlim(how, &limit, l);
+	}
+	return 0;
+}
+
+
+#ifdef CONFIG_ASH_MATH_SUPPORT
+
+/* Copyright (c) 2001 Aaron Lehmann <aaronl at vitelus.com>
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   "Software"), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be
+   included in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+   CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+   TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/* This is my infix parser/evaluator. It is optimized for size, intended
+ * as a replacement for yacc-based parsers. However, it may well be faster
+ * than a comparable parser written in yacc. The supported operators are
+ * listed in #defines below. Parens, order of operations, and error handling
+ * are supported. This code is thread safe. The exact expression format should
+ * be that which POSIX specifies for shells. */
+
+/* The code uses a simple two-stack algorithm. See
+ * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
+ * for a detailed explanation of the infix-to-postfix algorithm on which
+ * this is based (this code differs in that it applies operators immediately
+ * to the stack instead of adding them to a queue to end up with an
+ * expression). */
+
+/* To use the routine, call it with an expression string and error return
+ * pointer */
+
+/*
+ * Aug 24, 2001              Manuel Novoa III
+ *
+ * Reduced the generated code size by about 30% (i386) and fixed several bugs.
+ *
+ * 1) In arith_apply():
+ *    a) Cached values of *numptr and &(numptr[-1]).
+ *    b) Removed redundant test for zero denominator.
+ *
+ * 2) In arith():
+ *    a) Eliminated redundant code for processing operator tokens by moving
+ *       to a table-based implementation.  Also folded handling of parens
+ *       into the table.
+ *    b) Combined all 3 loops which called arith_apply to reduce generated
+ *       code size at the cost of speed.
+ *
+ * 3) The following expressions were treated as valid by the original code:
+ *       1()  ,    0!  ,    1 ( *3 )   .
+ *    These bugs have been fixed by internally enclosing the expression in
+ *    parens and then checking that all binary ops and right parens are
+ *    preceded by a valid expression (NUM_TOKEN).
+ *
+ * Note: It may be desirable to replace Aaron's test for whitespace with
+ * ctype's isspace() if it is used by another busybox applet or if additional
+ * whitespace chars should be considered.  Look below the "#include"s for a
+ * precompiler test.
+ */
+
+/*
+ * Aug 26, 2001              Manuel Novoa III
+ *
+ * Return 0 for null expressions.  Pointed out by Vladimir Oleynik.
+ *
+ * Merge in Aaron's comments previously posted to the busybox list,
+ * modified slightly to take account of my changes to the code.
+ *
+ */
+
+/*
+ *  (C) 2003 Vladimir Oleynik <dzo at simtreas.ru>
+ *
+ * - allow access to variable,
+ *   used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
+ * - realize assign syntax (VAR=expr, +=, *= etc)
+ * - realize exponentiation (** operator)
+ * - realize comma separated - expr, expr
+ * - realise ++expr --expr expr++ expr--
+ * - realise expr ? expr : expr (but, second expr calculate always)
+ * - allow hexadecimal and octal numbers
+ * - was restored loses XOR operator
+ * - remove one goto label, added three ;-)
+ * - protect $((num num)) as true zero expr (Manuel`s error)
+ * - always use special isspace(), see comment from bash ;-)
+ */
+
+
+#define arith_isspace(arithval) \
+	(arithval == ' ' || arithval == '\n' || arithval == '\t')
+
+
+typedef unsigned char operator;
+
+/* An operator's token id is a bit of a bitfield. The lower 5 bits are the
+ * precedence, and 3 high bits are an ID unique across operators of that
+ * precedence. The ID portion is so that multiple operators can have the
+ * same precedence, ensuring that the leftmost one is evaluated first.
+ * Consider * and /. */
+
+#define tok_decl(prec,id) (((id)<<5)|(prec))
+#define PREC(op) ((op) & 0x1F)
+
+#define TOK_LPAREN tok_decl(0,0)
+
+#define TOK_COMMA tok_decl(1,0)
+
+#define TOK_ASSIGN tok_decl(2,0)
+#define TOK_AND_ASSIGN tok_decl(2,1)
+#define TOK_OR_ASSIGN tok_decl(2,2)
+#define TOK_XOR_ASSIGN tok_decl(2,3)
+#define TOK_PLUS_ASSIGN tok_decl(2,4)
+#define TOK_MINUS_ASSIGN tok_decl(2,5)
+#define TOK_LSHIFT_ASSIGN tok_decl(2,6)
+#define TOK_RSHIFT_ASSIGN tok_decl(2,7)
+
+#define TOK_MUL_ASSIGN tok_decl(3,0)
+#define TOK_DIV_ASSIGN tok_decl(3,1)
+#define TOK_REM_ASSIGN tok_decl(3,2)
+
+/* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
+#define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
+
+/* conditional is right associativity too */
+#define TOK_CONDITIONAL tok_decl(4,0)
+#define TOK_CONDITIONAL_SEP tok_decl(4,1)
+
+#define TOK_OR tok_decl(5,0)
+
+#define TOK_AND tok_decl(6,0)
+
+#define TOK_BOR tok_decl(7,0)
+
+#define TOK_BXOR tok_decl(8,0)
+
+#define TOK_BAND tok_decl(9,0)
+
+#define TOK_EQ tok_decl(10,0)
+#define TOK_NE tok_decl(10,1)
+
+#define TOK_LT tok_decl(11,0)
+#define TOK_GT tok_decl(11,1)
+#define TOK_GE tok_decl(11,2)
+#define TOK_LE tok_decl(11,3)
+
+#define TOK_LSHIFT tok_decl(12,0)
+#define TOK_RSHIFT tok_decl(12,1)
+
+#define TOK_ADD tok_decl(13,0)
+#define TOK_SUB tok_decl(13,1)
+
+#define TOK_MUL tok_decl(14,0)
+#define TOK_DIV tok_decl(14,1)
+#define TOK_REM tok_decl(14,2)
+
+/* exponent is right associativity */
+#define TOK_EXPONENT tok_decl(15,1)
+
+/* For now unary operators. */
+#define UNARYPREC 16
+#define TOK_BNOT tok_decl(UNARYPREC,0)
+#define TOK_NOT tok_decl(UNARYPREC,1)
+
+#define TOK_UMINUS tok_decl(UNARYPREC+1,0)
+#define TOK_UPLUS tok_decl(UNARYPREC+1,1)
+
+#define PREC_PRE (UNARYPREC+2)
+
+#define TOK_PRE_INC tok_decl(PREC_PRE, 0)
+#define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
+
+#define PREC_POST (UNARYPREC+3)
+
+#define TOK_POST_INC tok_decl(PREC_POST, 0)
+#define TOK_POST_DEC tok_decl(PREC_POST, 1)
+
+#define SPEC_PREC (UNARYPREC+4)
+
+#define TOK_NUM tok_decl(SPEC_PREC, 0)
+#define TOK_RPAREN tok_decl(SPEC_PREC, 1)
+
+#define NUMPTR (*numstackptr)
+
+static inline int tok_have_assign(operator op)
+{
+	operator prec = PREC(op);
+
+	convert_prec_is_assing(prec);
+	return (prec == PREC(TOK_ASSIGN) ||
+			prec == PREC_PRE || prec == PREC_POST);
+}
+
+static inline int is_right_associativity(operator prec)
+{
+    return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
+	    prec == PREC(TOK_CONDITIONAL));
+}
+
+
+typedef struct ARITCH_VAR_NUM {
+	arith_t val;
+	arith_t contidional_second_val;
+	char contidional_second_val_initialized;
+	char *var;      /* if NULL then is regular number,
+			   else is variable name */
+} v_n_t;
+
+
+typedef struct CHK_VAR_RECURSIVE_LOOPED {
+	const char *var;
+	struct CHK_VAR_RECURSIVE_LOOPED *next;
+} chk_var_recursive_looped_t;
+
+static chk_var_recursive_looped_t *prev_chk_var_recursive;
+
+
+static int arith_lookup_val(v_n_t *t)
+{
+    if(t->var) {
+	const char * p = lookupvar(t->var);
+
+	if(p) {
+	    int errcode;
+
+	    /* recursive try as expression */
+	    chk_var_recursive_looped_t *cur;
+	    chk_var_recursive_looped_t cur_save;
+
+	    for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
+		if(strcmp(cur->var, t->var) == 0) {
+		    /* expression recursion loop detected */
+		    return -5;
+		}
+	    }
+	    /* save current lookuped var name */
+	    cur = prev_chk_var_recursive;
+	    cur_save.var = t->var;
+	    cur_save.next = cur;
+	    prev_chk_var_recursive = &cur_save;
+
+	    t->val = arith (p, &errcode);
+	    /* restore previous ptr after recursiving */
+	    prev_chk_var_recursive = cur;
+	    return errcode;
+	} else {
+	    /* allow undefined var as 0 */
+	    t->val = 0;
+	}
+    }
+    return 0;
+}
+
+/* "applying" a token means performing it on the top elements on the integer
+ * stack. For a unary operator it will only change the top element, but a
+ * binary operator will pop two arguments and push a result */
+static inline int
+arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
+{
+	v_n_t *numptr_m1;
+	arith_t numptr_val, rez;
+	int ret_arith_lookup_val;
+
+	if (NUMPTR == numstack) goto err; /* There is no operator that can work
+										 without arguments */
+	numptr_m1 = NUMPTR - 1;
+
+	/* check operand is var with noninteger value */
+	ret_arith_lookup_val = arith_lookup_val(numptr_m1);
+	if(ret_arith_lookup_val)
+		return ret_arith_lookup_val;
+
+	rez = numptr_m1->val;
+	if (op == TOK_UMINUS)
+		rez *= -1;
+	else if (op == TOK_NOT)
+		rez = !rez;
+	else if (op == TOK_BNOT)
+		rez = ~rez;
+	else if (op == TOK_POST_INC || op == TOK_PRE_INC)
+		rez++;
+	else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
+		rez--;
+	else if (op != TOK_UPLUS) {
+		/* Binary operators */
+
+	    /* check and binary operators need two arguments */
+	    if (numptr_m1 == numstack) goto err;
+
+	    /* ... and they pop one */
+	    --NUMPTR;
+	    numptr_val = rez;
+	    if (op == TOK_CONDITIONAL) {
+		if(! numptr_m1->contidional_second_val_initialized) {
+		    /* protect $((expr1 ? expr2)) without ": expr" */
+		    goto err;
+		}
+		rez = numptr_m1->contidional_second_val;
+	    } else if(numptr_m1->contidional_second_val_initialized) {
+		    /* protect $((expr1 : expr2)) without "expr ? " */
+		    goto err;
+	    }
+	    numptr_m1 = NUMPTR - 1;
+	    if(op != TOK_ASSIGN) {
+		/* check operand is var with noninteger value for not '=' */
+		ret_arith_lookup_val = arith_lookup_val(numptr_m1);
+		if(ret_arith_lookup_val)
+		    return ret_arith_lookup_val;
+	    }
+	    if (op == TOK_CONDITIONAL) {
+		    numptr_m1->contidional_second_val = rez;
+	    }
+	    rez = numptr_m1->val;
+	    if (op == TOK_BOR || op == TOK_OR_ASSIGN)
+			rez |= numptr_val;
+	    else if (op == TOK_OR)
+			rez = numptr_val || rez;
+	    else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
+			rez &= numptr_val;
+	    else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
+			rez ^= numptr_val;
+	    else if (op == TOK_AND)
+			rez = rez && numptr_val;
+	    else if (op == TOK_EQ)
+			rez = (rez == numptr_val);
+	    else if (op == TOK_NE)
+			rez = (rez != numptr_val);
+	    else if (op == TOK_GE)
+			rez = (rez >= numptr_val);
+	    else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
+			rez >>= numptr_val;
+	    else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
+			rez <<= numptr_val;
+	    else if (op == TOK_GT)
+			rez = (rez > numptr_val);
+	    else if (op == TOK_LT)
+			rez = (rez < numptr_val);
+	    else if (op == TOK_LE)
+			rez = (rez <= numptr_val);
+	    else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
+			rez *= numptr_val;
+	    else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
+			rez += numptr_val;
+	    else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
+			rez -= numptr_val;
+	    else if (op == TOK_ASSIGN || op == TOK_COMMA)
+			rez = numptr_val;
+	    else if (op == TOK_CONDITIONAL_SEP) {
+			if (numptr_m1 == numstack) {
+			    /* protect $((expr : expr)) without "expr ? " */
+			    goto err;
+			}
+			numptr_m1->contidional_second_val_initialized = op;
+			numptr_m1->contidional_second_val = numptr_val;
+	    }
+	    else if (op == TOK_CONDITIONAL) {
+			rez = rez ?
+			      numptr_val : numptr_m1->contidional_second_val;
+	    }
+	    else if(op == TOK_EXPONENT) {
+			if(numptr_val < 0)
+				return -3;      /* exponent less than 0 */
+			else {
+				arith_t c = 1;
+
+				if(numptr_val)
+					while(numptr_val--)
+						c *= rez;
+				rez = c;
+			}
+	    }
+	    else if(numptr_val==0)          /* zero divisor check */
+			return -2;
+	    else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
+			rez /= numptr_val;
+	    else if (op == TOK_REM || op == TOK_REM_ASSIGN)
+			rez %= numptr_val;
+	}
+	if(tok_have_assign(op)) {
+		char buf[32];
+
+		if(numptr_m1->var == NULL) {
+			/* Hmm, 1=2 ? */
+			goto err;
+		}
+		/* save to shell variable */
+#ifdef CONFIG_ASH_MATH_SUPPORT_64
+		snprintf(buf, sizeof(buf), "%lld", arith_t_type rez);
+#else
+		snprintf(buf, sizeof(buf), "%ld", arith_t_type rez);
+#endif
+		setvar(numptr_m1->var, buf, 0);
+		/* after saving, make previous value for v++ or v-- */
+		if(op == TOK_POST_INC)
+			rez--;
+		else if(op == TOK_POST_DEC)
+			rez++;
+	}
+	numptr_m1->val = rez;
+	/* protect geting var value, is number now */
+	numptr_m1->var = NULL;
+	return 0;
+err: return(-1);
+}
+
+/* longest must first */
+static const char op_tokens[] = {
+	'<','<','=',0, TOK_LSHIFT_ASSIGN,
+	'>','>','=',0, TOK_RSHIFT_ASSIGN,
+	'<','<',    0, TOK_LSHIFT,
+	'>','>',    0, TOK_RSHIFT,
+	'|','|',    0, TOK_OR,
+	'&','&',    0, TOK_AND,
+	'!','=',    0, TOK_NE,
+	'<','=',    0, TOK_LE,
+	'>','=',    0, TOK_GE,
+	'=','=',    0, TOK_EQ,
+	'|','=',    0, TOK_OR_ASSIGN,
+	'&','=',    0, TOK_AND_ASSIGN,
+	'*','=',    0, TOK_MUL_ASSIGN,
+	'/','=',    0, TOK_DIV_ASSIGN,
+	'%','=',    0, TOK_REM_ASSIGN,
+	'+','=',    0, TOK_PLUS_ASSIGN,
+	'-','=',    0, TOK_MINUS_ASSIGN,
+	'-','-',    0, TOK_POST_DEC,
+	'^','=',    0, TOK_XOR_ASSIGN,
+	'+','+',    0, TOK_POST_INC,
+	'*','*',    0, TOK_EXPONENT,
+	'!',        0, TOK_NOT,
+	'<',        0, TOK_LT,
+	'>',        0, TOK_GT,
+	'=',        0, TOK_ASSIGN,
+	'|',        0, TOK_BOR,
+	'&',        0, TOK_BAND,
+	'*',        0, TOK_MUL,
+	'/',        0, TOK_DIV,
+	'%',        0, TOK_REM,
+	'+',        0, TOK_ADD,
+	'-',        0, TOK_SUB,
+	'^',        0, TOK_BXOR,
+	/* uniq */
+	'~',        0, TOK_BNOT,
+	',',        0, TOK_COMMA,
+	'?',        0, TOK_CONDITIONAL,
+	':',        0, TOK_CONDITIONAL_SEP,
+	')',        0, TOK_RPAREN,
+	'(',        0, TOK_LPAREN,
+	0
+};
+/* ptr to ")" */
+#define endexpression &op_tokens[sizeof(op_tokens)-7]
+
+
+static arith_t arith (const char *expr, int *perrcode)
+{
+    register char arithval; /* Current character under analysis */
+    operator lasttok, op;
+    operator prec;
+
+    const char *p = endexpression;
+    int errcode;
+
+    size_t datasizes = strlen(expr) + 2;
+
+    /* Stack of integers */
+    /* The proof that there can be no more than strlen(startbuf)/2+1 integers
+     * in any given correct or incorrect expression is left as an exercise to
+     * the reader. */
+    v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
+	    *numstackptr = numstack;
+    /* Stack of operator tokens */
+    operator *stack = alloca((datasizes) * sizeof(operator)),
+	    *stackptr = stack;
+
+    *stackptr++ = lasttok = TOK_LPAREN;     /* start off with a left paren */
+    *perrcode = errcode = 0;
+
+    while(1) {
+	if ((arithval = *expr) == 0) {
+		if (p == endexpression) {
+			/* Null expression. */
+			return 0;
+		}
+
+		/* This is only reached after all tokens have been extracted from the
+		 * input stream. If there are still tokens on the operator stack, they
+		 * are to be applied in order. At the end, there should be a final
+		 * result on the integer stack */
+
+		if (expr != endexpression + 1) {
+			/* If we haven't done so already, */
+			/* append a closing right paren */
+			expr = endexpression;
+			/* and let the loop process it. */
+			continue;
+		}
+		/* At this point, we're done with the expression. */
+		if (numstackptr != numstack+1) {
+			/* ... but if there isn't, it's bad */
+		  err:
+			return (*perrcode = -1);
+		}
+		if(numstack->var) {
+		    /* expression is $((var)) only, lookup now */
+		    errcode = arith_lookup_val(numstack);
+		}
+	ret:
+		*perrcode = errcode;
+		return numstack->val;
+	} else {
+		/* Continue processing the expression. */
+		if (arith_isspace(arithval)) {
+			/* Skip whitespace */
+			goto prologue;
+		}
+		if((p = endofname(expr)) != expr) {
+			size_t var_name_size = (p-expr) + 1;  /* trailing zero */
+
+			numstackptr->var = alloca(var_name_size);
+			safe_strncpy(numstackptr->var, expr, var_name_size);
+			expr = p;
+		num:
+			numstackptr->contidional_second_val_initialized = 0;
+			numstackptr++;
+			lasttok = TOK_NUM;
+			continue;
+		} else if (is_digit(arithval)) {
+			numstackptr->var = NULL;
+#ifdef CONFIG_ASH_MATH_SUPPORT_64
+			numstackptr->val = strtoll(expr, (char **) &expr, 0);
+#else
+			numstackptr->val = strtol(expr, (char **) &expr, 0);
+#endif
+			goto num;
+		}
+		for(p = op_tokens; ; p++) {
+			const char *o;
+
+			if(*p == 0) {
+				/* strange operator not found */
+				goto err;
+			}
+			for(o = expr; *p && *o == *p; p++)
+				o++;
+			if(! *p) {
+				/* found */
+				expr = o - 1;
+				break;
+			}
+			/* skip tail uncompared token */
+			while(*p)
+				p++;
+			/* skip zero delim */
+			p++;
+		}
+		op = p[1];
+
+		/* post grammar: a++ reduce to num */
+		if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
+		    lasttok = TOK_NUM;
+
+		/* Plus and minus are binary (not unary) _only_ if the last
+		 * token was as number, or a right paren (which pretends to be
+		 * a number, since it evaluates to one). Think about it.
+		 * It makes sense. */
+		if (lasttok != TOK_NUM) {
+			switch(op) {
+				case TOK_ADD:
+				    op = TOK_UPLUS;
+				    break;
+				case TOK_SUB:
+				    op = TOK_UMINUS;
+				    break;
+				case TOK_POST_INC:
+				    op = TOK_PRE_INC;
+				    break;
+				case TOK_POST_DEC:
+				    op = TOK_PRE_DEC;
+				    break;
+			}
+		}
+		/* We don't want a unary operator to cause recursive descent on the
+		 * stack, because there can be many in a row and it could cause an
+		 * operator to be evaluated before its argument is pushed onto the
+		 * integer stack. */
+		/* But for binary operators, "apply" everything on the operator
+		 * stack until we find an operator with a lesser priority than the
+		 * one we have just extracted. */
+		/* Left paren is given the lowest priority so it will never be
+		 * "applied" in this way.
+		 * if associativity is right and priority eq, applied also skip
+		 */
+		prec = PREC(op);
+		if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
+			/* not left paren or unary */
+			if (lasttok != TOK_NUM) {
+				/* binary op must be preceded by a num */
+				goto err;
+			}
+			while (stackptr != stack) {
+			    if (op == TOK_RPAREN) {
+				/* The algorithm employed here is simple: while we don't
+				 * hit an open paren nor the bottom of the stack, pop
+				 * tokens and apply them */
+				if (stackptr[-1] == TOK_LPAREN) {
+				    --stackptr;
+				    /* Any operator directly after a */
+				    lasttok = TOK_NUM;
+				    /* close paren should consider itself binary */
+				    goto prologue;
+				}
+			    } else {
+				operator prev_prec = PREC(stackptr[-1]);
+
+				convert_prec_is_assing(prec);
+				convert_prec_is_assing(prev_prec);
+				if (prev_prec < prec)
+					break;
+				/* check right assoc */
+				if(prev_prec == prec && is_right_associativity(prec))
+					break;
+			    }
+			    errcode = arith_apply(*--stackptr, numstack, &numstackptr);
+			    if(errcode) goto ret;
+			}
+			if (op == TOK_RPAREN) {
+				goto err;
+			}
+		}
+
+		/* Push this operator to the stack and remember it. */
+		*stackptr++ = lasttok = op;
+
+	  prologue:
+		++expr;
+	}
+    }
+}
+#endif /* CONFIG_ASH_MATH_SUPPORT */
+
+
+#ifdef DEBUG
+const char *bb_applet_name = "debug stuff usage";
+int main(int argc, char **argv)
+{
+	return ash_main(argc, argv);
+}
+#endif
+
+/*-
+ * Copyright (c) 1989, 1991, 1993, 1994
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/cmdedit.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/cmdedit.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/cmdedit.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1929 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Termios command line History and Editing.
+ *
+ * Copyright (c) 1986-2003 may safely be consumed by a BSD or GPL license.
+ * Written by:   Vladimir Oleynik <dzo at simtreas.ru>
+ *
+ * Used ideas:
+ *      Adam Rogoyski    <rogoyski at cs.utexas.edu>
+ *      Dave Cinege      <dcinege at psychosis.com>
+ *      Jakub Jelinek (c) 1995
+ *      Erik Andersen    <andersen at codepoet.org> (Majorly adjusted for busybox)
+ *
+ * This code is 'as is' with no warranty.
+ *
+ *
+ */
+
+/*
+   Usage and Known bugs:
+   Terminal key codes are not extensive, and more will probably
+   need to be added. This version was created on Debian GNU/Linux 2.x.
+   Delete, Backspace, Home, End, and the arrow keys were tested
+   to work in an Xterm and console. Ctrl-A also works as Home.
+   Ctrl-E also works as End.
+
+   Small bugs (simple effect):
+   - not true viewing if terminal size (x*y symbols) less
+     size (prompt + editor`s line + 2 symbols)
+   - not true viewing if length prompt less terminal width
+ */
+
+
+#include "busybox.h"
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <ctype.h>
+#include <signal.h>
+#include <limits.h>
+
+#include "../shell/cmdedit.h"
+
+
+#ifdef CONFIG_LOCALE_SUPPORT
+#define Isprint(c) isprint((c))
+#else
+#define Isprint(c) ( (c) >= ' ' && (c) != ((unsigned char)'\233') )
+#endif
+
+#ifdef TEST
+
+/* pretect redefined for test */
+#undef CONFIG_FEATURE_COMMAND_EDITING
+#undef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
+#undef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION
+#undef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
+#undef CONFIG_FEATURE_CLEAN_UP
+
+#define CONFIG_FEATURE_COMMAND_EDITING
+#define CONFIG_FEATURE_COMMAND_TAB_COMPLETION
+#define CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION
+#define CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
+#define CONFIG_FEATURE_CLEAN_UP
+
+#endif  /* TEST */
+
+#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
+#include <dirent.h>
+#include <sys/stat.h>
+#endif
+
+#ifdef CONFIG_FEATURE_COMMAND_EDITING
+
+#if defined(CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION) || defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
+#define CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR
+#endif
+
+#ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR
+#include "pwd_.h"
+#endif  /* advanced FEATURES */
+
+
+/* Maximum length of the linked list for the command line history */
+#ifndef CONFIG_FEATURE_COMMAND_HISTORY
+#define MAX_HISTORY   15
+#else
+#define MAX_HISTORY   CONFIG_FEATURE_COMMAND_HISTORY
+#endif
+
+#if MAX_HISTORY < 1
+#warning cmdedit: You set MAX_HISTORY < 1. The history algorithm switched off.
+#else
+static char *history[MAX_HISTORY+1]; /* history + current */
+/* saved history lines */
+static int n_history;
+/* current pointer to history line */
+static int cur_history;
+#endif
+
+#include <termios.h>
+#define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp)
+#define getTermSettings(fd,argp) tcgetattr(fd, argp);
+
+/* Current termio and the previous termio before starting sh */
+static struct termios initial_settings, new_settings;
+
+
+static
+volatile int cmdedit_termw = 80;        /* actual terminal width */
+static
+volatile int handlers_sets = 0; /* Set next bites: */
+
+enum {
+	SET_ATEXIT = 1,         /* when atexit() has been called
+				   and get euid,uid,gid to fast compare */
+	SET_WCHG_HANDLERS = 2,  /* winchg signal handler */
+	SET_RESET_TERM = 4,     /* if the terminal needs to be reset upon exit */
+};
+
+
+static int cmdedit_x;           /* real x terminal position */
+static int cmdedit_y;           /* pseudoreal y terminal position */
+static int cmdedit_prmt_len;    /* lenght prompt without colores string */
+
+static int cursor;              /* required global for signal handler */
+static int len;                 /* --- "" - - "" - -"- --""-- --""--- */
+static char *command_ps;        /* --- "" - - "" - -"- --""-- --""--- */
+static
+#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
+	const
+#endif
+char *cmdedit_prompt;           /* --- "" - - "" - -"- --""-- --""--- */
+
+#ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR
+static char *user_buf = "";
+static char *home_pwd_buf = "";
+static int my_euid;
+#endif
+
+#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
+static char *hostname_buf;
+static int num_ok_lines = 1;
+#endif
+
+
+#ifdef  CONFIG_FEATURE_COMMAND_TAB_COMPLETION
+
+#ifndef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR
+static int my_euid;
+#endif
+
+static int my_uid;
+static int my_gid;
+
+#endif  /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */
+
+static void cmdedit_setwidth(int w, int redraw_flg);
+
+static void win_changed(int nsig)
+{
+	static sighandler_t previous_SIGWINCH_handler;  /* for reset */
+
+	/*   emulate      || signal call */
+	if (nsig == -SIGWINCH || nsig == SIGWINCH) {
+		int width = 0;
+		get_terminal_width_height(0, &width, NULL);
+		cmdedit_setwidth(width, nsig == SIGWINCH);
+	}
+	/* Unix not all standart in recall signal */
+
+	if (nsig == -SIGWINCH)          /* save previous handler   */
+		previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
+	else if (nsig == SIGWINCH)      /* signaled called handler */
+		signal(SIGWINCH, win_changed);  /* set for next call       */
+	else                                            /* nsig == 0 */
+		/* set previous handler    */
+		signal(SIGWINCH, previous_SIGWINCH_handler);    /* reset    */
+}
+
+static void cmdedit_reset_term(void)
+{
+	if ((handlers_sets & SET_RESET_TERM) != 0) {
+/* sparc and other have broken termios support: use old termio handling. */
+		setTermSettings(STDIN_FILENO, (void *) &initial_settings);
+		handlers_sets &= ~SET_RESET_TERM;
+	}
+	if ((handlers_sets & SET_WCHG_HANDLERS) != 0) {
+		/* reset SIGWINCH handler to previous (default) */
+		win_changed(0);
+		handlers_sets &= ~SET_WCHG_HANDLERS;
+	}
+	fflush(stdout);
+}
+
+
+/* special for recount position for scroll and remove terminal margin effect */
+static void cmdedit_set_out_char(int next_char)
+{
+
+	int c = (int)((unsigned char) command_ps[cursor]);
+
+	if (c == 0)
+		c = ' ';        /* destroy end char? */
+#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
+	if (!Isprint(c)) {      /* Inverse put non-printable characters */
+		if (c >= 128)
+			c -= 128;
+		if (c < ' ')
+			c += '@';
+		if (c == 127)
+			c = '?';
+		printf("\033[7m%c\033[0m", c);
+	} else
+#endif
+		putchar(c);
+	if (++cmdedit_x >= cmdedit_termw) {
+		/* terminal is scrolled down */
+		cmdedit_y++;
+		cmdedit_x = 0;
+
+		if (!next_char)
+			next_char = ' ';
+		/* destroy "(auto)margin" */
+		putchar(next_char);
+		putchar('\b');
+	}
+	cursor++;
+}
+
+/* Move to end line. Bonus: rewrite line from cursor */
+static void input_end(void)
+{
+	while (cursor < len)
+		cmdedit_set_out_char(0);
+}
+
+/* Go to the next line */
+static void goto_new_line(void)
+{
+	input_end();
+	if (cmdedit_x)
+		putchar('\n');
+}
+
+
+static inline void out1str(const char *s)
+{
+	if ( s )
+		fputs(s, stdout);
+}
+
+static inline void beep(void)
+{
+	putchar('\007');
+}
+
+/* Move back one character */
+/* special for slow terminal */
+static void input_backward(int num)
+{
+	if (num > cursor)
+		num = cursor;
+	cursor -= num;          /* new cursor (in command, not terminal) */
+
+	if (cmdedit_x >= num) {         /* no to up line */
+		cmdedit_x -= num;
+		if (num < 4)
+			while (num-- > 0)
+				putchar('\b');
+
+		else
+			printf("\033[%dD", num);
+	} else {
+		int count_y;
+
+		if (cmdedit_x) {
+			putchar('\r');          /* back to first terminal pos.  */
+			num -= cmdedit_x;       /* set previous backward        */
+		}
+		count_y = 1 + num / cmdedit_termw;
+		printf("\033[%dA", count_y);
+		cmdedit_y -= count_y;
+		/*  require  forward  after  uping   */
+		cmdedit_x = cmdedit_termw * count_y - num;
+		printf("\033[%dC", cmdedit_x);  /* set term cursor   */
+	}
+}
+
+static void put_prompt(void)
+{
+	out1str(cmdedit_prompt);
+	cmdedit_x = cmdedit_prmt_len;   /* count real x terminal position */
+	cursor = 0;
+	cmdedit_y = 0;                  /* new quasireal y */
+}
+
+#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
+static void parse_prompt(const char *prmt_ptr)
+{
+	cmdedit_prompt = prmt_ptr;
+	cmdedit_prmt_len = strlen(prmt_ptr);
+	put_prompt();
+}
+#else
+static void parse_prompt(const char *prmt_ptr)
+{
+	int prmt_len = 0;
+	size_t cur_prmt_len = 0;
+	char  flg_not_length = '[';
+	char *prmt_mem_ptr = xcalloc(1, 1);
+	char *pwd_buf = xgetcwd(0);
+	char  buf2[PATH_MAX + 1];
+	char  buf[2];
+	char  c;
+	char *pbuf;
+
+	if (!pwd_buf) {
+		pwd_buf=(char *)bb_msg_unknown;
+	}
+
+	while (*prmt_ptr) {
+		pbuf    = buf;
+		pbuf[1] = 0;
+		c = *prmt_ptr++;
+		if (c == '\\') {
+			const char *cp = prmt_ptr;
+			int l;
+
+			c = bb_process_escape_sequence(&prmt_ptr);
+			if(prmt_ptr==cp) {
+			  if (*cp == 0)
+				break;
+			  c = *prmt_ptr++;
+			  switch (c) {
+#ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR
+			  case 'u':
+				pbuf = user_buf;
+				break;
+#endif
+			  case 'h':
+				pbuf = hostname_buf;
+				if (pbuf == 0) {
+					pbuf = xcalloc(256, 1);
+					if (gethostname(pbuf, 255) < 0) {
+						strcpy(pbuf, "?");
+					} else {
+						char *s = strchr(pbuf, '.');
+
+						if (s)
+							*s = 0;
+					}
+					hostname_buf = pbuf;
+				}
+				break;
+			  case '$':
+				c = my_euid == 0 ? '#' : '$';
+				break;
+#ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR
+			  case 'w':
+				pbuf = pwd_buf;
+				l = strlen(home_pwd_buf);
+				if (home_pwd_buf[0] != 0 &&
+				    strncmp(home_pwd_buf, pbuf, l) == 0 &&
+				    (pbuf[l]=='/' || pbuf[l]=='\0') &&
+				    strlen(pwd_buf+l)<PATH_MAX) {
+					pbuf = buf2;
+					*pbuf = '~';
+					strcpy(pbuf+1, pwd_buf+l);
+					}
+				break;
+#endif
+			  case 'W':
+				pbuf = pwd_buf;
+				cp = strrchr(pbuf,'/');
+				if ( (cp != NULL) && (cp != pbuf) )
+					pbuf += (cp-pbuf)+1;
+				break;
+			  case '!':
+				snprintf(pbuf = buf2, sizeof(buf2), "%d", num_ok_lines);
+				break;
+			  case 'e': case 'E':     /* \e \E = \033 */
+				c = '\033';
+				break;
+			  case 'x': case 'X':
+				for (l = 0; l < 3;) {
+					int h;
+					buf2[l++] = *prmt_ptr;
+					buf2[l] = 0;
+					h = strtol(buf2, &pbuf, 16);
+					if (h > UCHAR_MAX || (pbuf - buf2) < l) {
+						l--;
+						break;
+					}
+					prmt_ptr++;
+				}
+				buf2[l] = 0;
+				c = (char)strtol(buf2, 0, 16);
+				if(c==0)
+					c = '?';
+				pbuf = buf;
+				break;
+			  case '[': case ']':
+				if (c == flg_not_length) {
+					flg_not_length = flg_not_length == '[' ? ']' : '[';
+					continue;
+				}
+				break;
+			  }
+			}
+		}
+		if(pbuf == buf)
+			*pbuf = c;
+		cur_prmt_len = strlen(pbuf);
+		prmt_len += cur_prmt_len;
+		if (flg_not_length != ']')
+			cmdedit_prmt_len += cur_prmt_len;
+		prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf);
+	}
+	if(pwd_buf!=(char *)bb_msg_unknown)
+		free(pwd_buf);
+	cmdedit_prompt = prmt_mem_ptr;
+	put_prompt();
+}
+#endif
+
+
+/* draw prompt, editor line, and clear tail */
+static void redraw(int y, int back_cursor)
+{
+	if (y > 0)                              /* up to start y */
+		printf("\033[%dA", y);
+	putchar('\r');
+	put_prompt();
+	input_end();                            /* rewrite */
+	printf("\033[J");                       /* destroy tail after cursor */
+	input_backward(back_cursor);
+}
+
+#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
+#define DELBUFSIZ 128
+static char *delbuf;  /* a (malloced) place to store deleted characters */
+static char *delp;
+static char newdelflag;      /* whether delbuf should be reused yet */
+#endif
+
+/* Delete the char in front of the cursor, optionally saving it
+ * for later putback */
+static void input_delete(int save)
+{
+	int j = cursor;
+
+	if (j == len)
+		return;
+
+#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
+	if (save) {
+		if (newdelflag) {
+			if (!delbuf)
+				delbuf = malloc(DELBUFSIZ);
+			/* safe if malloc fails */
+			delp = delbuf;
+			newdelflag = 0;
+		}
+		if (delbuf && (delp - delbuf < DELBUFSIZ))
+			*delp++ = command_ps[j];
+	}
+#endif
+
+	strcpy(command_ps + j, command_ps + j + 1);
+	len--;
+	input_end();                    /* rewrite new line */
+	cmdedit_set_out_char(0);        /* destroy end char */
+	input_backward(cursor - j);     /* back to old pos cursor */
+}
+
+#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
+static void put(void)
+{
+	int ocursor, j = delp - delbuf;
+	if (j == 0)
+		return;
+	ocursor = cursor;
+	/* open hole and then fill it */
+	memmove(command_ps + cursor + j, command_ps + cursor, len - cursor + 1);
+	strncpy(command_ps + cursor, delbuf, j);
+	len += j;
+	input_end();                    /* rewrite new line */
+	input_backward(cursor-ocursor-j+1); /* at end of new text */
+}
+#endif
+
+/* Delete the char in back of the cursor */
+static void input_backspace(void)
+{
+	if (cursor > 0) {
+		input_backward(1);
+		input_delete(0);
+	}
+}
+
+
+/* Move forward one character */
+static void input_forward(void)
+{
+	if (cursor < len)
+		cmdedit_set_out_char(command_ps[cursor + 1]);
+}
+
+static void cmdedit_setwidth(int w, int redraw_flg)
+{
+	cmdedit_termw = cmdedit_prmt_len + 2;
+	if (w <= cmdedit_termw) {
+		cmdedit_termw = cmdedit_termw % w;
+	}
+	if (w > cmdedit_termw) {
+		cmdedit_termw = w;
+
+		if (redraw_flg) {
+			/* new y for current cursor */
+			int new_y = (cursor + cmdedit_prmt_len) / w;
+
+			/* redraw */
+			redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), len - cursor);
+			fflush(stdout);
+		}
+	}
+}
+
+static void cmdedit_init(void)
+{
+	cmdedit_prmt_len = 0;
+	if ((handlers_sets & SET_WCHG_HANDLERS) == 0) {
+		/* emulate usage handler to set handler and call yours work */
+		win_changed(-SIGWINCH);
+		handlers_sets |= SET_WCHG_HANDLERS;
+	}
+
+	if ((handlers_sets & SET_ATEXIT) == 0) {
+#ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR
+		struct passwd *entry;
+
+		my_euid = geteuid();
+		entry = getpwuid(my_euid);
+		if (entry) {
+			user_buf = bb_xstrdup(entry->pw_name);
+			home_pwd_buf = bb_xstrdup(entry->pw_dir);
+		}
+#endif
+
+#ifdef  CONFIG_FEATURE_COMMAND_TAB_COMPLETION
+
+#ifndef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR
+		my_euid = geteuid();
+#endif
+		my_uid = getuid();
+		my_gid = getgid();
+#endif  /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */
+		handlers_sets |= SET_ATEXIT;
+		atexit(cmdedit_reset_term);     /* be sure to do this only once */
+	}
+}
+
+#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
+
+static char **matches;
+static int num_matches;
+static char *add_char_to_match;
+
+static void add_match(char *matched, int add_char)
+{
+	int nm = num_matches;
+	int nm1 = nm + 1;
+
+	matches = xrealloc(matches, nm1 * sizeof(char *));
+	add_char_to_match = xrealloc(add_char_to_match, nm1);
+	matches[nm] = matched;
+	add_char_to_match[nm] = (char)add_char;
+	num_matches++;
+}
+
+static int is_execute(const struct stat *st)
+{
+	if ((!my_euid && (st->st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) ||
+		(my_uid == st->st_uid && (st->st_mode & S_IXUSR)) ||
+		(my_gid == st->st_gid && (st->st_mode & S_IXGRP)) ||
+		(st->st_mode & S_IXOTH)) return TRUE;
+	return FALSE;
+}
+
+#ifdef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION
+
+static void username_tab_completion(char *ud, char *with_shash_flg)
+{
+	struct passwd *entry;
+	int userlen;
+
+	ud++;                           /* ~user/... to user/... */
+	userlen = strlen(ud);
+
+	if (with_shash_flg) {           /* "~/..." or "~user/..." */
+		char *sav_ud = ud - 1;
+		char *home = 0;
+		char *temp;
+
+		if (*ud == '/') {       /* "~/..."     */
+			home = home_pwd_buf;
+		} else {
+			/* "~user/..." */
+			temp = strchr(ud, '/');
+			*temp = 0;              /* ~user\0 */
+			entry = getpwnam(ud);
+			*temp = '/';            /* restore ~user/... */
+			ud = temp;
+			if (entry)
+				home = entry->pw_dir;
+		}
+		if (home) {
+			if ((userlen + strlen(home) + 1) < BUFSIZ) {
+				char temp2[BUFSIZ];     /* argument size */
+
+				/* /home/user/... */
+				sprintf(temp2, "%s%s", home, ud);
+				strcpy(sav_ud, temp2);
+			}
+		}
+	} else {
+		/* "~[^/]*" */
+		setpwent();
+
+		while ((entry = getpwent()) != NULL) {
+			/* Null usernames should result in all users as possible completions. */
+			if ( /*!userlen || */ !strncmp(ud, entry->pw_name, userlen)) {
+				add_match(bb_xasprintf("~%s", entry->pw_name), '/');
+			}
+		}
+
+		endpwent();
+	}
+}
+#endif  /* CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION */
+
+enum {
+	FIND_EXE_ONLY = 0,
+	FIND_DIR_ONLY = 1,
+	FIND_FILE_ONLY = 2,
+};
+
+#ifdef CONFIG_ASH
+const char *cmdedit_path_lookup;
+#else
+#define cmdedit_path_lookup getenv("PATH")
+#endif
+
+static int path_parse(char ***p, int flags)
+{
+	int npth;
+	const char *tmp;
+	const char *pth;
+
+	/* if not setenv PATH variable, to search cur dir "." */
+	if (flags != FIND_EXE_ONLY || (pth = cmdedit_path_lookup) == 0 ||
+		/* PATH=<empty> or PATH=:<empty> */
+		*pth == 0 || (*pth == ':' && *(pth + 1) == 0)) {
+		return 1;
+	}
+
+	tmp = pth;
+	npth = 0;
+
+	for (;;) {
+		npth++;                 /* count words is + 1 count ':' */
+		tmp = strchr(tmp, ':');
+		if (tmp) {
+			if (*++tmp == 0)
+				break;  /* :<empty> */
+		} else
+			break;
+	}
+
+	*p = xmalloc(npth * sizeof(char *));
+
+	tmp = pth;
+	(*p)[0] = bb_xstrdup(tmp);
+	npth = 1;                       /* count words is + 1 count ':' */
+
+	for (;;) {
+		tmp = strchr(tmp, ':');
+		if (tmp) {
+			(*p)[0][(tmp - pth)] = 0;       /* ':' -> '\0' */
+			if (*++tmp == 0)
+				break;                  /* :<empty> */
+		} else
+			break;
+		(*p)[npth++] = &(*p)[0][(tmp - pth)];   /* p[next]=p[0][&'\0'+1] */
+	}
+
+	return npth;
+}
+
+static char *add_quote_for_spec_chars(char *found, int add)
+{
+	int l = 0;
+	char *s = xmalloc((strlen(found) + 1) * 2);
+
+	while (*found) {
+		if (strchr(" `\"#$%^&*()=+{}[]:;\'|\\<>", *found))
+			s[l++] = '\\';
+		s[l++] = *found++;
+	}
+	if(add)
+	    s[l++] = (char)add;
+	s[l] = 0;
+	return s;
+}
+
+static void exe_n_cwd_tab_completion(char *command, int type)
+{
+	DIR *dir;
+	struct dirent *next;
+	char dirbuf[BUFSIZ];
+	struct stat st;
+	char *path1[1];
+	char **paths = path1;
+	int npaths;
+	int i;
+	char *found;
+	char *pfind = strrchr(command, '/');
+
+	path1[0] = ".";
+
+	if (pfind == NULL) {
+		/* no dir, if flags==EXE_ONLY - get paths, else "." */
+		npaths = path_parse(&paths, type);
+		pfind = command;
+	} else {
+		/* with dir */
+		/* save for change */
+		strcpy(dirbuf, command);
+		/* set dir only */
+		dirbuf[(pfind - command) + 1] = 0;
+#ifdef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION
+		if (dirbuf[0] == '~')   /* ~/... or ~user/... */
+			username_tab_completion(dirbuf, dirbuf);
+#endif
+		/* "strip" dirname in command */
+		pfind++;
+
+		paths[0] = dirbuf;
+		npaths = 1;                             /* only 1 dir */
+	}
+
+	for (i = 0; i < npaths; i++) {
+
+		dir = opendir(paths[i]);
+		if (!dir)                       /* Don't print an error */
+			continue;
+
+		while ((next = readdir(dir)) != NULL) {
+			char *str_found = next->d_name;
+			int add_chr = 0;
+
+			/* matched ? */
+			if (strncmp(str_found, pfind, strlen(pfind)))
+				continue;
+			/* not see .name without .match */
+			if (*str_found == '.' && *pfind == 0) {
+				if (*paths[i] == '/' && paths[i][1] == 0
+					&& str_found[1] == 0) str_found = "";   /* only "/" */
+				else
+					continue;
+			}
+			found = concat_path_file(paths[i], str_found);
+			/* hmm, remover in progress? */
+			if (stat(found, &st) < 0)
+				goto cont;
+			/* find with dirs ? */
+			if (paths[i] != dirbuf)
+				strcpy(found, next->d_name);    /* only name */
+			if (S_ISDIR(st.st_mode)) {
+				/* name is directory      */
+				char *e = found + strlen(found) - 1;
+
+				add_chr = '/';
+				if(*e == '/')
+					*e = '\0';
+			} else {
+				/* not put found file if search only dirs for cd */
+				if (type == FIND_DIR_ONLY)
+					goto cont;
+				if (type == FIND_FILE_ONLY ||
+					(type == FIND_EXE_ONLY && is_execute(&st)))
+					add_chr = ' ';
+			}
+			/* Add it to the list */
+			add_match(found, add_chr);
+			continue;
+cont:
+			free(found);
+		}
+		closedir(dir);
+	}
+	if (paths != path1) {
+		free(paths[0]);                 /* allocated memory only in first member */
+		free(paths);
+	}
+}
+
+
+#define QUOT    (UCHAR_MAX+1)
+
+#define collapse_pos(is, in) { \
+	memmove(int_buf+(is), int_buf+(in), (BUFSIZ+1-(is)-(in))*sizeof(int)); \
+	memmove(pos_buf+(is), pos_buf+(in), (BUFSIZ+1-(is)-(in))*sizeof(int)); }
+
+static int find_match(char *matchBuf, int *len_with_quotes)
+{
+	int i, j;
+	int command_mode;
+	int c, c2;
+	int int_buf[BUFSIZ + 1];
+	int pos_buf[BUFSIZ + 1];
+
+	/* set to integer dimension characters and own positions */
+	for (i = 0;; i++) {
+		int_buf[i] = (int) ((unsigned char) matchBuf[i]);
+		if (int_buf[i] == 0) {
+			pos_buf[i] = -1;        /* indicator end line */
+			break;
+		} else
+			pos_buf[i] = i;
+	}
+
+	/* mask \+symbol and convert '\t' to ' ' */
+	for (i = j = 0; matchBuf[i]; i++, j++)
+		if (matchBuf[i] == '\\') {
+			collapse_pos(j, j + 1);
+			int_buf[j] |= QUOT;
+			i++;
+#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
+			if (matchBuf[i] == '\t')        /* algorithm equivalent */
+				int_buf[j] = ' ' | QUOT;
+#endif
+		}
+#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
+		else if (matchBuf[i] == '\t')
+			int_buf[j] = ' ';
+#endif
+
+	/* mask "symbols" or 'symbols' */
+	c2 = 0;
+	for (i = 0; int_buf[i]; i++) {
+		c = int_buf[i];
+		if (c == '\'' || c == '"') {
+			if (c2 == 0)
+				c2 = c;
+			else {
+				if (c == c2)
+					c2 = 0;
+				else
+					int_buf[i] |= QUOT;
+			}
+		} else if (c2 != 0 && c != '$')
+			int_buf[i] |= QUOT;
+	}
+
+	/* skip commands with arguments if line have commands delimiters */
+	/* ';' ';;' '&' '|' '&&' '||' but `>&' `<&' `>|' */
+	for (i = 0; int_buf[i]; i++) {
+		c = int_buf[i];
+		c2 = int_buf[i + 1];
+		j = i ? int_buf[i - 1] : -1;
+		command_mode = 0;
+		if (c == ';' || c == '&' || c == '|') {
+			command_mode = 1 + (c == c2);
+			if (c == '&') {
+				if (j == '>' || j == '<')
+					command_mode = 0;
+			} else if (c == '|' && j == '>')
+				command_mode = 0;
+		}
+		if (command_mode) {
+			collapse_pos(0, i + command_mode);
+			i = -1;                         /* hack incremet */
+		}
+	}
+	/* collapse `command...` */
+	for (i = 0; int_buf[i]; i++)
+		if (int_buf[i] == '`') {
+			for (j = i + 1; int_buf[j]; j++)
+				if (int_buf[j] == '`') {
+					collapse_pos(i, j + 1);
+					j = 0;
+					break;
+				}
+			if (j) {
+				/* not found close ` - command mode, collapse all previous */
+				collapse_pos(0, i + 1);
+				break;
+			} else
+				i--;                    /* hack incremet */
+		}
+
+	/* collapse (command...(command...)...) or {command...{command...}...} */
+	c = 0;                                          /* "recursive" level */
+	c2 = 0;
+	for (i = 0; int_buf[i]; i++)
+		if (int_buf[i] == '(' || int_buf[i] == '{') {
+			if (int_buf[i] == '(')
+				c++;
+			else
+				c2++;
+			collapse_pos(0, i + 1);
+			i = -1;                         /* hack incremet */
+		}
+	for (i = 0; pos_buf[i] >= 0 && (c > 0 || c2 > 0); i++)
+		if ((int_buf[i] == ')' && c > 0) || (int_buf[i] == '}' && c2 > 0)) {
+			if (int_buf[i] == ')')
+				c--;
+			else
+				c2--;
+			collapse_pos(0, i + 1);
+			i = -1;                         /* hack incremet */
+		}
+
+	/* skip first not quote space */
+	for (i = 0; int_buf[i]; i++)
+		if (int_buf[i] != ' ')
+			break;
+	if (i)
+		collapse_pos(0, i);
+
+	/* set find mode for completion */
+	command_mode = FIND_EXE_ONLY;
+	for (i = 0; int_buf[i]; i++)
+		if (int_buf[i] == ' ' || int_buf[i] == '<' || int_buf[i] == '>') {
+			if (int_buf[i] == ' ' && command_mode == FIND_EXE_ONLY
+				&& matchBuf[pos_buf[0]]=='c'
+				&& matchBuf[pos_buf[1]]=='d' )
+				command_mode = FIND_DIR_ONLY;
+			else {
+				command_mode = FIND_FILE_ONLY;
+				break;
+			}
+		}
+	/* "strlen" */
+	for (i = 0; int_buf[i]; i++);
+	/* find last word */
+	for (--i; i >= 0; i--) {
+		c = int_buf[i];
+		if (c == ' ' || c == '<' || c == '>' || c == '|' || c == '&') {
+			collapse_pos(0, i + 1);
+			break;
+		}
+	}
+	/* skip first not quoted '\'' or '"' */
+	for (i = 0; int_buf[i] == '\'' || int_buf[i] == '"'; i++);
+	/* collapse quote or unquote // or /~ */
+	while ((int_buf[i] & ~QUOT) == '/' &&
+			((int_buf[i + 1] & ~QUOT) == '/'
+			 || (int_buf[i + 1] & ~QUOT) == '~')) {
+		i++;
+	}
+
+	/* set only match and destroy quotes */
+	j = 0;
+	for (c = 0; pos_buf[i] >= 0; i++) {
+		matchBuf[c++] = matchBuf[pos_buf[i]];
+		j = pos_buf[i] + 1;
+	}
+	matchBuf[c] = 0;
+	/* old lenght matchBuf with quotes symbols */
+	*len_with_quotes = j ? j - pos_buf[0] : 0;
+
+	return command_mode;
+}
+
+/*
+   display by column original ideas from ls applet,
+   very optimize by my :)
+*/
+static void showfiles(void)
+{
+	int ncols, row;
+	int column_width = 0;
+	int nfiles = num_matches;
+	int nrows = nfiles;
+	char str_add_chr[2];
+	int l;
+
+	/* find the longest file name-  use that as the column width */
+	for (row = 0; row < nrows; row++) {
+		l = strlen(matches[row]);
+		if(add_char_to_match[row])
+		    l++;
+		if (column_width < l)
+			column_width = l;
+	}
+	column_width += 2;              /* min space for columns */
+	ncols = cmdedit_termw / column_width;
+
+	if (ncols > 1) {
+		nrows /= ncols;
+		if(nfiles % ncols)
+			nrows++;        /* round up fractionals */
+	} else {
+		ncols = 1;
+	}
+	str_add_chr[1] = 0;
+	for (row = 0; row < nrows; row++) {
+		int n = row;
+		int nc;
+		int acol;
+
+		for(nc = 1; nc < ncols && n+nrows < nfiles; n += nrows, nc++) {
+			str_add_chr[0] = add_char_to_match[n];
+			acol = str_add_chr[0] ? column_width - 1 : column_width;
+			printf("%s%s", matches[n], str_add_chr);
+			l = strlen(matches[n]);
+			while(l < acol) {
+			    putchar(' ');
+			    l++;
+			}
+		}
+		str_add_chr[0] = add_char_to_match[n];
+		printf("%s%s\n", matches[n], str_add_chr);
+	}
+}
+
+
+static void input_tab(int *lastWasTab)
+{
+	/* Do TAB completion */
+	if (lastWasTab == 0) {          /* free all memory */
+		if (matches) {
+			while (num_matches > 0)
+				free(matches[--num_matches]);
+			free(matches);
+			matches = (char **) NULL;
+			free(add_char_to_match);
+			add_char_to_match = NULL;
+		}
+		return;
+	}
+	if (! *lastWasTab) {
+
+		char *tmp, *tmp1;
+		int len_found;
+		char matchBuf[BUFSIZ];
+		int find_type;
+		int recalc_pos;
+
+		*lastWasTab = TRUE;             /* flop trigger */
+
+		/* Make a local copy of the string -- up
+		 * to the position of the cursor */
+		tmp = strncpy(matchBuf, command_ps, cursor);
+		tmp[cursor] = 0;
+
+		find_type = find_match(matchBuf, &recalc_pos);
+
+		/* Free up any memory already allocated */
+		input_tab(0);
+
+#ifdef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION
+		/* If the word starts with `~' and there is no slash in the word,
+		 * then try completing this word as a username. */
+
+		if (matchBuf[0] == '~' && strchr(matchBuf, '/') == 0)
+			username_tab_completion(matchBuf, NULL);
+		if (!matches)
+#endif
+		/* Try to match any executable in our path and everything
+		 * in the current working directory that matches.  */
+			exe_n_cwd_tab_completion(matchBuf, find_type);
+		/* Remove duplicate found and sort */
+		if(matches) {
+			int i, j, n, srt;
+			/* bubble */
+			n = num_matches;
+			for(i=0; i<(n-1); i++)
+			    for(j=i+1; j<n; j++)
+				if(matches[i]!=NULL && matches[j]!=NULL) {
+				    srt = strcmp(matches[i], matches[j]);
+				    if(srt == 0) {
+					free(matches[j]);
+					matches[j]=0;
+				    } else if(srt > 0) {
+					tmp1 = matches[i];
+					matches[i] = matches[j];
+					matches[j] = tmp1;
+					srt = add_char_to_match[i];
+					add_char_to_match[i] = add_char_to_match[j];
+					add_char_to_match[j] = srt;
+				    }
+				}
+			j = n;
+			n = 0;
+			for(i=0; i<j; i++)
+			    if(matches[i]) {
+				matches[n]=matches[i];
+				add_char_to_match[n]=add_char_to_match[i];
+				n++;
+			    }
+			num_matches = n;
+		}
+		/* Did we find exactly one match? */
+		if (!matches || num_matches > 1) {
+
+			beep();
+			if (!matches)
+				return;         /* not found */
+			/* find minimal match */
+			tmp1 = bb_xstrdup(matches[0]);
+			for (tmp = tmp1; *tmp; tmp++)
+				for (len_found = 1; len_found < num_matches; len_found++)
+					if (matches[len_found][(tmp - tmp1)] != *tmp) {
+						*tmp = 0;
+						break;
+					}
+			if (*tmp1 == 0) {        /* have unique */
+				free(tmp1);
+				return;
+			}
+			tmp = add_quote_for_spec_chars(tmp1, 0);
+			free(tmp1);
+		} else {                        /* one match */
+			tmp = add_quote_for_spec_chars(matches[0], add_char_to_match[0]);
+			/* for next completion current found */
+			*lastWasTab = FALSE;
+		}
+		len_found = strlen(tmp);
+		/* have space to placed match? */
+		if ((len_found - strlen(matchBuf) + len) < BUFSIZ) {
+
+			/* before word for match   */
+			command_ps[cursor - recalc_pos] = 0;
+			/* save   tail line        */
+			strcpy(matchBuf, command_ps + cursor);
+			/* add    match            */
+			strcat(command_ps, tmp);
+			/* add    tail             */
+			strcat(command_ps, matchBuf);
+			/* back to begin word for match    */
+			input_backward(recalc_pos);
+			/* new pos                         */
+			recalc_pos = cursor + len_found;
+			/* new len                         */
+			len = strlen(command_ps);
+			/* write out the matched command   */
+			redraw(cmdedit_y, len - recalc_pos);
+		}
+		free(tmp);
+	} else {
+		/* Ok -- the last char was a TAB.  Since they
+		 * just hit TAB again, print a list of all the
+		 * available choices... */
+		if (matches && num_matches > 0) {
+			int sav_cursor = cursor;        /* change goto_new_line() */
+
+			/* Go to the next line */
+			goto_new_line();
+			showfiles();
+			redraw(0, len - sav_cursor);
+		}
+	}
+}
+#endif  /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */
+
+#if MAX_HISTORY >= 1
+static void get_previous_history(void)
+{
+	if(command_ps[0] != 0 || history[cur_history] == 0) {
+		free(history[cur_history]);
+		history[cur_history] = bb_xstrdup(command_ps);
+	}
+	cur_history--;
+}
+
+static int get_next_history(void)
+{
+	int ch = cur_history;
+
+	if (ch < n_history) {
+		get_previous_history(); /* save the current history line */
+		return (cur_history = ch+1);
+	} else {
+		beep();
+		return 0;
+	}
+}
+
+#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
+void load_history ( const char *fromfile )
+{
+	FILE *fp;
+	int hi;
+
+	/* cleanup old */
+
+	for(hi = n_history; hi > 0; ) {
+		hi--;
+		free ( history [hi] );
+	}
+
+	if (( fp = fopen ( fromfile, "r" ))) {
+
+		for ( hi = 0; hi < MAX_HISTORY; ) {
+			char * hl = bb_get_chomped_line_from_file(fp);
+			int l;
+
+			if(!hl)
+				break;
+			l = strlen(hl);
+			if(l >= BUFSIZ)
+				hl[BUFSIZ-1] = 0;
+			if(l == 0 || hl[0] == ' ') {
+				free(hl);
+				continue;
+			}
+			history [hi++] = hl;
+		}
+		fclose ( fp );
+	}
+	cur_history = n_history = hi;
+}
+
+void save_history ( const char *tofile )
+{
+	FILE *fp = fopen ( tofile, "w" );
+
+	if ( fp ) {
+		int i;
+
+		for ( i = 0; i < n_history; i++ ) {
+			fprintf(fp, "%s\n", history [i]);
+		}
+		fclose ( fp );
+	}
+}
+#endif
+
+#endif
+
+enum {
+	ESC = 27,
+	DEL = 127,
+};
+
+
+/*
+ * This function is used to grab a character buffer
+ * from the input file descriptor and allows you to
+ * a string with full command editing (sort of like
+ * a mini readline).
+ *
+ * The following standard commands are not implemented:
+ * ESC-b -- Move back one word
+ * ESC-f -- Move forward one word
+ * ESC-d -- Delete back one word
+ * ESC-h -- Delete forward one word
+ * CTL-t -- Transpose two characters
+ *
+ * Minimalist vi-style command line editing available if configured.
+ *  vi mode implemented 2005 by Paul Fox <pgf at foxharp.boston.ma.us>
+ *
+ */
+
+#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
+static int vi_mode;
+
+void setvimode ( int viflag )
+{
+	vi_mode = viflag;
+}
+
+static void
+vi_Word_motion(char *command, int eat)
+{
+	while (cursor < len && !isspace(command[cursor]))
+		input_forward();
+	if (eat) while (cursor < len && isspace(command[cursor]))
+		input_forward();
+}
+
+static void
+vi_word_motion(char *command, int eat)
+{
+	if (isalnum(command[cursor]) || command[cursor] == '_') {
+		while (cursor < len &&
+		    (isalnum(command[cursor+1]) ||
+				command[cursor+1] == '_'))
+			input_forward();
+	} else if (ispunct(command[cursor])) {
+		while (cursor < len &&
+		    (ispunct(command[cursor+1])))
+			input_forward();
+	}
+
+	if (cursor < len)
+		input_forward();
+
+	if (eat && cursor < len && isspace(command[cursor]))
+		while (cursor < len && isspace(command[cursor]))
+			input_forward();
+}
+
+static void
+vi_End_motion(char *command)
+{
+	input_forward();
+	while (cursor < len && isspace(command[cursor]))
+		input_forward();
+	while (cursor < len-1 && !isspace(command[cursor+1]))
+		input_forward();
+}
+
+static void
+vi_end_motion(char *command)
+{
+	if (cursor >= len-1)
+		return;
+	input_forward();
+	while (cursor < len-1 && isspace(command[cursor]))
+		input_forward();
+	if (cursor >= len-1)
+		return;
+	if (isalnum(command[cursor]) || command[cursor] == '_') {
+		while (cursor < len-1 &&
+		    (isalnum(command[cursor+1]) ||
+				command[cursor+1] == '_'))
+			input_forward();
+	} else if (ispunct(command[cursor])) {
+		while (cursor < len-1 &&
+		    (ispunct(command[cursor+1])))
+			input_forward();
+	}
+}
+
+static void
+vi_Back_motion(char *command)
+{
+	while (cursor > 0 && isspace(command[cursor-1]))
+		input_backward(1);
+	while (cursor > 0 && !isspace(command[cursor-1]))
+		input_backward(1);
+}
+
+static void
+vi_back_motion(char *command)
+{
+	if (cursor <= 0)
+		return;
+	input_backward(1);
+	while (cursor > 0 && isspace(command[cursor]))
+		input_backward(1);
+	if (cursor <= 0)
+		return;
+	if (isalnum(command[cursor]) || command[cursor] == '_') {
+		while (cursor > 0 &&
+		    (isalnum(command[cursor-1]) ||
+				command[cursor-1] == '_'))
+			input_backward(1);
+	} else if (ispunct(command[cursor])) {
+		while (cursor > 0 &&
+		    (ispunct(command[cursor-1])))
+			input_backward(1);
+	}
+}
+#endif
+
+/*
+ * the emacs and vi modes share much of the code in the big
+ * command loop.  commands entered when in vi's command mode (aka
+ * "escape mode") get an extra bit added to distinguish them --
+ * this keeps them from being self-inserted.  this clutters the
+ * big switch a bit, but keeps all the code in one place.
+ */
+
+#define vbit 0x100
+
+/* leave out the "vi-mode"-only case labels if vi editing isn't
+ * configured. */
+#define vi_case(caselabel) USE_FEATURE_COMMAND_EDITING(caselabel)
+
+/* convert uppercase ascii to equivalent control char, for readability */
+#define CNTRL(uc_char) ((uc_char) - 0x40)
+
+
+int cmdedit_read_input(char *prompt, char command[BUFSIZ])
+{
+
+	int break_out = 0;
+	int lastWasTab = FALSE;
+	unsigned char c;
+	unsigned int ic;
+#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
+	unsigned int prevc;
+	int vi_cmdmode = 0;
+#endif
+	/* prepare before init handlers */
+	cmdedit_y = 0;  /* quasireal y, not true work if line > xt*yt */
+	len = 0;
+	command_ps = command;
+
+	getTermSettings(0, (void *) &initial_settings);
+	memcpy(&new_settings, &initial_settings, sizeof(struct termios));
+	new_settings.c_lflag &= ~ICANON;        /* unbuffered input */
+	/* Turn off echoing and CTRL-C, so we can trap it */
+	new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG);
+	/* Hmm, in linux c_cc[] not parsed if set ~ICANON */
+	new_settings.c_cc[VMIN] = 1;
+	new_settings.c_cc[VTIME] = 0;
+	/* Turn off CTRL-C, so we can trap it */
+#       ifndef _POSIX_VDISABLE
+#               define _POSIX_VDISABLE '\0'
+#       endif
+	new_settings.c_cc[VINTR] = _POSIX_VDISABLE;
+	command[0] = 0;
+
+	setTermSettings(0, (void *) &new_settings);
+	handlers_sets |= SET_RESET_TERM;
+
+	/* Now initialize things */
+	cmdedit_init();
+	/* Print out the command prompt */
+	parse_prompt(prompt);
+
+	while (1) {
+
+		fflush(stdout);                 /* buffered out to fast */
+
+		if (safe_read(0, &c, 1) < 1)
+			/* if we can't read input then exit */
+			goto prepare_to_die;
+
+		ic = c;
+
+#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
+		newdelflag = 1;
+		if (vi_cmdmode)
+			ic |= vbit;
+#endif
+		switch (ic)
+		{
+		case '\n':
+		case '\r':
+		vi_case( case '\n'|vbit: )
+		vi_case( case '\r'|vbit: )
+			/* Enter */
+			goto_new_line();
+			break_out = 1;
+			break;
+		case CNTRL('A'):
+		vi_case( case '0'|vbit: )
+			/* Control-a -- Beginning of line */
+			input_backward(cursor);
+			break;
+		case CNTRL('B'):
+		vi_case( case 'h'|vbit: )
+		vi_case( case '\b'|vbit: )
+		vi_case( case DEL|vbit: )
+			/* Control-b -- Move back one character */
+			input_backward(1);
+			break;
+		case CNTRL('C'):
+		vi_case( case CNTRL('C')|vbit: )
+			/* Control-c -- stop gathering input */
+			goto_new_line();
+#ifndef CONFIG_ASH
+			command[0] = 0;
+			len = 0;
+			lastWasTab = FALSE;
+			put_prompt();
+#else
+			len = 0;
+			break_out = -1; /* to control traps */
+#endif
+			break;
+		case CNTRL('D'):
+			/* Control-d -- Delete one character, or exit
+			 * if the len=0 and no chars to delete */
+			if (len == 0) {
+					errno = 0;
+prepare_to_die:
+#if !defined(CONFIG_ASH)
+				printf("exit");
+				goto_new_line();
+				/* cmdedit_reset_term() called in atexit */
+				exit(EXIT_SUCCESS);
+#else
+				/* to control stopped jobs */
+				len = break_out = -1;
+				break;
+#endif
+			} else {
+				input_delete(0);
+			}
+			break;
+		case CNTRL('E'):
+		vi_case( case '$'|vbit: )
+			/* Control-e -- End of line */
+			input_end();
+			break;
+		case CNTRL('F'):
+		vi_case( case 'l'|vbit: )
+		vi_case( case ' '|vbit: )
+			/* Control-f -- Move forward one character */
+			input_forward();
+			break;
+		case '\b':
+		case DEL:
+			/* Control-h and DEL */
+			input_backspace();
+			break;
+		case '\t':
+#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
+			input_tab(&lastWasTab);
+#endif
+			break;
+		case CNTRL('K'):
+			/* Control-k -- clear to end of line */
+			*(command + cursor) = 0;
+			len = cursor;
+			printf("\033[J");
+			break;
+		case CNTRL('L'):
+		vi_case( case CNTRL('L')|vbit: )
+			/* Control-l -- clear screen */
+			printf("\033[H");
+			redraw(0, len-cursor);
+			break;
+#if MAX_HISTORY >= 1
+		case CNTRL('N'):
+		vi_case( case CNTRL('N')|vbit: )
+		vi_case( case 'j'|vbit: )
+			/* Control-n -- Get next command in history */
+			if (get_next_history())
+				goto rewrite_line;
+			break;
+		case CNTRL('P'):
+		vi_case( case CNTRL('P')|vbit: )
+		vi_case( case 'k'|vbit: )
+			/* Control-p -- Get previous command from history */
+			if (cur_history > 0) {
+				get_previous_history();
+				goto rewrite_line;
+			} else {
+				beep();
+			}
+			break;
+#endif
+		case CNTRL('U'):
+		vi_case( case CNTRL('U')|vbit: )
+			/* Control-U -- Clear line before cursor */
+			if (cursor) {
+				strcpy(command, command + cursor);
+				redraw(cmdedit_y, len -= cursor);
+			}
+			break;
+		case CNTRL('W'):
+		vi_case( case CNTRL('W')|vbit: )
+			/* Control-W -- Remove the last word */
+			while (cursor > 0 && isspace(command[cursor-1]))
+				input_backspace();
+			while (cursor > 0 &&!isspace(command[cursor-1]))
+				input_backspace();
+			break;
+#if CONFIG_FEATURE_COMMAND_EDITING_VI
+		case 'i'|vbit:
+			vi_cmdmode = 0;
+			break;
+		case 'I'|vbit:
+			input_backward(cursor);
+			vi_cmdmode = 0;
+			break;
+		case 'a'|vbit:
+			input_forward();
+			vi_cmdmode = 0;
+			break;
+		case 'A'|vbit:
+			input_end();
+			vi_cmdmode = 0;
+			break;
+		case 'x'|vbit:
+			input_delete(1);
+			break;
+		case 'X'|vbit:
+			if (cursor > 0) {
+				input_backward(1);
+				input_delete(1);
+			}
+			break;
+		case 'W'|vbit:
+			vi_Word_motion(command, 1);
+			break;
+		case 'w'|vbit:
+			vi_word_motion(command, 1);
+			break;
+		case 'E'|vbit:
+			vi_End_motion(command);
+			break;
+		case 'e'|vbit:
+			vi_end_motion(command);
+			break;
+		case 'B'|vbit:
+			vi_Back_motion(command);
+			break;
+		case 'b'|vbit:
+			vi_back_motion(command);
+			break;
+		case 'C'|vbit:
+			vi_cmdmode = 0;
+			/* fall through */
+		case 'D'|vbit:
+			goto clear_to_eol;
+
+		case 'c'|vbit:
+			vi_cmdmode = 0;
+			/* fall through */
+		case 'd'|vbit:
+			{
+			int nc, sc;
+			sc = cursor;
+			prevc = ic;
+			if (safe_read(0, &c, 1) < 1)
+				goto prepare_to_die;
+			if (c == (prevc & 0xff)) {
+			    /* "cc", "dd" */
+			    input_backward(cursor);
+			    goto clear_to_eol;
+			    break;
+			}
+			switch(c) {
+			case 'w':
+			case 'W':
+			case 'e':
+			case 'E':
+			    switch (c) {
+			    case 'w':   /* "dw", "cw" */
+				    vi_word_motion(command, vi_cmdmode);
+				    break;
+			    case 'W':   /* 'dW', 'cW' */
+				    vi_Word_motion(command, vi_cmdmode);
+				    break;
+			    case 'e':   /* 'de', 'ce' */
+				    vi_end_motion(command);
+				    input_forward();
+				    break;
+			    case 'E':   /* 'dE', 'cE' */
+				    vi_End_motion(command);
+				    input_forward();
+				    break;
+			    }
+			    nc = cursor;
+			    input_backward(cursor - sc);
+			    while (nc-- > cursor)
+				    input_delete(1);
+			    break;
+			case 'b':  /* "db", "cb" */
+			case 'B':  /* implemented as B */
+			    if (c == 'b')
+				    vi_back_motion(command);
+			    else
+				    vi_Back_motion(command);
+			    while (sc-- > cursor)
+				    input_delete(1);
+			    break;
+			case ' ':  /* "d ", "c " */
+			    input_delete(1);
+			    break;
+			case '$':  /* "d$", "c$" */
+			clear_to_eol:
+			    while (cursor < len)
+				    input_delete(1);
+			    break;
+			}
+			}
+			break;
+		case 'p'|vbit:
+			input_forward();
+			/* fallthrough */
+		case 'P'|vbit:
+			put();
+			break;
+		case 'r'|vbit:
+			if (safe_read(0, &c, 1) < 1)
+				goto prepare_to_die;
+			if (c == 0)
+				beep();
+			else {
+				*(command + cursor) = c;
+				putchar(c);
+				putchar('\b');
+			}
+			break;
+#endif /* CONFIG_FEATURE_COMMAND_EDITING_VI */
+
+		case ESC:
+
+#if CONFIG_FEATURE_COMMAND_EDITING_VI
+			if (vi_mode) {
+				/* ESC: insert mode --> command mode */
+				vi_cmdmode = 1;
+				input_backward(1);
+				break;
+			}
+#endif
+			/* escape sequence follows */
+			if (safe_read(0, &c, 1) < 1)
+				goto prepare_to_die;
+			/* different vt100 emulations */
+			if (c == '[' || c == 'O') {
+		vi_case( case '['|vbit: )
+		vi_case( case 'O'|vbit: )
+				if (safe_read(0, &c, 1) < 1)
+					goto prepare_to_die;
+			}
+			if (c >= '1' && c <= '9') {
+				unsigned char dummy;
+
+				if (safe_read(0, &dummy, 1) < 1)
+					goto prepare_to_die;
+				if(dummy != '~')
+					c = 0;
+			}
+			switch (c) {
+#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
+			case '\t':                      /* Alt-Tab */
+
+				input_tab(&lastWasTab);
+				break;
+#endif
+#if MAX_HISTORY >= 1
+			case 'A':
+				/* Up Arrow -- Get previous command from history */
+				if (cur_history > 0) {
+					get_previous_history();
+					goto rewrite_line;
+				} else {
+					beep();
+				}
+				break;
+			case 'B':
+				/* Down Arrow -- Get next command in history */
+				if (!get_next_history())
+					break;
+				/* Rewrite the line with the selected history item */
+rewrite_line:
+				/* change command */
+				len = strlen(strcpy(command, history[cur_history]));
+				/* redraw and go to eol (bol, in vi */
+#if CONFIG_FEATURE_COMMAND_EDITING_VI
+				redraw(cmdedit_y, vi_mode ? 9999:0);
+#else
+				redraw(cmdedit_y, 0);
+#endif
+				break;
+#endif
+			case 'C':
+				/* Right Arrow -- Move forward one character */
+				input_forward();
+				break;
+			case 'D':
+				/* Left Arrow -- Move back one character */
+				input_backward(1);
+				break;
+			case '3':
+				/* Delete */
+				input_delete(0);
+				break;
+			case '1':
+			case 'H':
+				/* <Home> */
+				input_backward(cursor);
+				break;
+			case '4':
+			case 'F':
+				/* <End> */
+				input_end();
+				break;
+			default:
+				c = 0;
+				beep();
+			}
+			break;
+
+		default:        /* If it's regular input, do the normal thing */
+#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
+			/* Control-V -- Add non-printable symbol */
+			if (c == CNTRL('V')) {
+				if (safe_read(0, &c, 1) < 1)
+					goto prepare_to_die;
+				if (c == 0) {
+					beep();
+					break;
+				}
+			} else
+#endif
+			{
+#if CONFIG_FEATURE_COMMAND_EDITING_VI
+				if (vi_cmdmode)  /* don't self-insert */
+					break;
+#endif
+				if (!Isprint(c)) /* Skip non-printable characters */
+					break;
+			}
+
+			if (len >= (BUFSIZ - 2))        /* Need to leave space for enter */
+				break;
+
+			len++;
+
+			if (cursor == (len - 1)) {      /* Append if at the end of the line */
+				*(command + cursor) = c;
+				*(command + cursor + 1) = 0;
+				cmdedit_set_out_char(0);
+			} else {                        /* Insert otherwise */
+				int sc = cursor;
+
+				memmove(command + sc + 1, command + sc, len - sc);
+				*(command + sc) = c;
+				sc++;
+				/* rewrite from cursor */
+				input_end();
+				/* to prev x pos + 1 */
+				input_backward(cursor - sc);
+			}
+
+			break;
+		}
+		if (break_out)                  /* Enter is the command terminator, no more input. */
+			break;
+
+		if (c != '\t')
+			lastWasTab = FALSE;
+	}
+
+	setTermSettings(0, (void *) &initial_settings);
+	handlers_sets &= ~SET_RESET_TERM;
+
+#if MAX_HISTORY >= 1
+	/* Handle command history log */
+	/* cleanup may be saved current command line */
+	if (len> 0) {                                      /* no put empty line */
+		int i = n_history;
+
+		free(history[MAX_HISTORY]);
+		history[MAX_HISTORY] = 0;
+			/* After max history, remove the oldest command */
+		if (i >= MAX_HISTORY) {
+			free(history[0]);
+			for(i = 0; i < (MAX_HISTORY-1); i++)
+				history[i] = history[i+1];
+		}
+		history[i++] = bb_xstrdup(command);
+		cur_history = i;
+		n_history = i;
+#if defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
+		num_ok_lines++;
+#endif
+	}
+#else  /* MAX_HISTORY < 1 */
+#if defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
+	if (len > 0) {              /* no put empty line */
+		num_ok_lines++;
+	}
+#endif
+#endif  /* MAX_HISTORY >= 1 */
+	if (break_out > 0) {
+		command[len++] = '\n';          /* set '\n' */
+		command[len] = 0;
+	}
+#if defined(CONFIG_FEATURE_CLEAN_UP) && defined(CONFIG_FEATURE_COMMAND_TAB_COMPLETION)
+	input_tab(0);                           /* strong free */
+#endif
+#if defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
+	free(cmdedit_prompt);
+#endif
+	cmdedit_reset_term();
+	return len;
+}
+
+
+
+#endif  /* CONFIG_FEATURE_COMMAND_EDITING */
+
+
+#ifdef TEST
+
+const char *bb_applet_name = "debug stuff usage";
+
+#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
+#include <locale.h>
+#endif
+
+int main(int argc, char **argv)
+{
+	char buff[BUFSIZ];
+	char *prompt =
+#if defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
+		"\\[\\033[32;1m\\]\\u@\\[\\x1b[33;1m\\]\\h:\
+\\[\\033[34;1m\\]\\w\\[\\033[35;1m\\] \
+\\!\\[\\e[36;1m\\]\\$ \\[\\E[0m\\]";
+#else
+		"% ";
+#endif
+
+#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
+	setlocale(LC_ALL, "");
+#endif
+	while(1) {
+		int l;
+		l = cmdedit_read_input(prompt, buff);
+		if(l > 0 && buff[l-1] == '\n') {
+			buff[l-1] = 0;
+			printf("*** cmdedit_read_input() returned line =%s=\n", buff);
+		} else {
+			break;
+		}
+	}
+	printf("*** cmdedit_read_input() detect ^D\n");
+	return 0;
+}
+
+#endif  /* TEST */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/cmdedit.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/cmdedit.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/cmdedit.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,19 @@
+#ifndef CMDEDIT_H
+#define CMDEDIT_H
+
+int     cmdedit_read_input(char* promptStr, char* command);
+
+#ifdef CONFIG_ASH
+extern const char *cmdedit_path_lookup;
+#endif
+
+#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
+void    load_history ( const char *fromfile );
+void    save_history ( const char *tofile );
+#endif
+
+#if CONFIG_FEATURE_COMMAND_EDITING_VI
+void	setvimode ( int viflag );
+#endif
+
+#endif /* CMDEDIT_H */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/hush.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/hush.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/hush.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2956 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * sh.c -- a prototype Bourne shell grammar parser
+ *      Intended to follow the original Thompson and Ritchie
+ *      "small and simple is beautiful" philosophy, which
+ *      incidentally is a good match to today's BusyBox.
+ *
+ * Copyright (C) 2000,2001  Larry Doolittle  <larry at doolittle.boa.org>
+ *
+ * Credits:
+ *      The parser routines proper are all original material, first
+ *      written Dec 2000 and Jan 2001 by Larry Doolittle.  The
+ *      execution engine, the builtins, and much of the underlying
+ *      support has been adapted from busybox-0.49pre's lash, which is
+ *      Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *      written by Erik Andersen <andersen at codepoet.org>.  That, in turn,
+ *      is based in part on ladsh.c, by Michael K. Johnson and Erik W.
+ *      Troan, which they placed in the public domain.  I don't know
+ *      how much of the Johnson/Troan code has survived the repeated
+ *      rewrites.
+ *
+ * Other credits:
+ *      simple_itoa() was lifted from boa-0.93.15
+ *      b_addchr() derived from similar w_addchar function in glibc-2.2
+ *      setup_redirect(), redirect_opt_num(), and big chunks of main()
+ *        and many builtins derived from contributions by Erik Andersen
+ *      miscellaneous bugfixes from Matt Kraai
+ *
+ * There are two big (and related) architecture differences between
+ * this parser and the lash parser.  One is that this version is
+ * actually designed from the ground up to understand nearly all
+ * of the Bourne grammar.  The second, consequential change is that
+ * the parser and input reader have been turned inside out.  Now,
+ * the parser is in control, and asks for input as needed.  The old
+ * way had the input reader in control, and it asked for parsing to
+ * take place as needed.  The new way makes it much easier to properly
+ * handle the recursion implicit in the various substitutions, especially
+ * across continuation lines.
+ *
+ * Bash grammar not implemented: (how many of these were in original sh?)
+ *      $@ (those sure look like weird quoting rules)
+ *      $_
+ *      ! negation operator for pipes
+ *      &> and >& redirection of stdout+stderr
+ *      Brace Expansion
+ *      Tilde Expansion
+ *      fancy forms of Parameter Expansion
+ *      aliases
+ *      Arithmetic Expansion
+ *      <(list) and >(list) Process Substitution
+ *      reserved words: case, esac, select, function
+ *      Here Documents ( << word )
+ *      Functions
+ * Major bugs:
+ *      job handling woefully incomplete and buggy
+ *      reserved word execution woefully incomplete and buggy
+ * to-do:
+ *      port selected bugfixes from post-0.49 busybox lash - done?
+ *      finish implementing reserved words: for, while, until, do, done
+ *      change { and } from special chars to reserved words
+ *      builtins: break, continue, eval, return, set, trap, ulimit
+ *      test magic exec
+ *      handle children going into background
+ *      clean up recognition of null pipes
+ *      check setting of global_argc and global_argv
+ *      control-C handling, probably with longjmp
+ *      follow IFS rules more precisely, including update semantics
+ *      figure out what to do with backslash-newline
+ *      explain why we use signal instead of sigaction
+ *      propagate syntax errors, die on resource errors?
+ *      continuation lines, both explicit and implicit - done?
+ *      memory leak finding and plugging - done?
+ *      more testing, especially quoting rules and redirection
+ *      document how quoting rules not precisely followed for variable assignments
+ *      maybe change map[] to use 2-bit entries
+ *      (eventually) remove all the printf's
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+#include <ctype.h>     /* isalpha, isdigit */
+#include <unistd.h>    /* getpid */
+#include <stdlib.h>    /* getenv, atoi */
+#include <string.h>    /* strchr */
+#include <stdio.h>     /* popen etc. */
+#include <glob.h>      /* glob, of course */
+#include <stdarg.h>    /* va_list */
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>    /* should be pretty obvious */
+
+#include <sys/stat.h>  /* ulimit */
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+/* #include <dmalloc.h> */
+/* #define DEBUG_SHELL */
+
+#if 1
+#include "cmdedit.h"
+#else
+#define bb_applet_name "hush"
+//#include "standalone.h"
+#define hush_main main
+#undef CONFIG_FEATURE_SH_FANCY_PROMPT
+#define BB_BANNER ""
+#endif
+#define SPECIAL_VAR_SYMBOL 03
+#define FLAG_EXIT_FROM_LOOP 1
+#define FLAG_PARSE_SEMICOLON (1 << 1)		/* symbol ';' is special for parser */
+#define FLAG_REPARSING		 (1 << 2)		/* >=2nd pass */
+
+typedef enum {
+	REDIRECT_INPUT     = 1,
+	REDIRECT_OVERWRITE = 2,
+	REDIRECT_APPEND    = 3,
+	REDIRECT_HEREIS    = 4,
+	REDIRECT_IO        = 5
+} redir_type;
+
+/* The descrip member of this structure is only used to make debugging
+ * output pretty */
+static const struct {int mode; int default_fd; const char *descrip;} redir_table[] = {
+	{ 0,                         0, "()" },
+	{ O_RDONLY,                  0, "<"  },
+	{ O_CREAT|O_TRUNC|O_WRONLY,  1, ">"  },
+	{ O_CREAT|O_APPEND|O_WRONLY, 1, ">>" },
+	{ O_RDONLY,                 -1, "<<" },
+	{ O_RDWR,                    1, "<>" }
+};
+
+typedef enum {
+	PIPE_SEQ = 1,
+	PIPE_AND = 2,
+	PIPE_OR  = 3,
+	PIPE_BG  = 4,
+} pipe_style;
+
+/* might eventually control execution */
+typedef enum {
+	RES_NONE  = 0,
+	RES_IF    = 1,
+	RES_THEN  = 2,
+	RES_ELIF  = 3,
+	RES_ELSE  = 4,
+	RES_FI    = 5,
+	RES_FOR   = 6,
+	RES_WHILE = 7,
+	RES_UNTIL = 8,
+	RES_DO    = 9,
+	RES_DONE  = 10,
+	RES_XXXX  = 11,
+	RES_IN    = 12,
+	RES_SNTX  = 13
+} reserved_style;
+#define FLAG_END   (1<<RES_NONE)
+#define FLAG_IF    (1<<RES_IF)
+#define FLAG_THEN  (1<<RES_THEN)
+#define FLAG_ELIF  (1<<RES_ELIF)
+#define FLAG_ELSE  (1<<RES_ELSE)
+#define FLAG_FI    (1<<RES_FI)
+#define FLAG_FOR   (1<<RES_FOR)
+#define FLAG_WHILE (1<<RES_WHILE)
+#define FLAG_UNTIL (1<<RES_UNTIL)
+#define FLAG_DO    (1<<RES_DO)
+#define FLAG_DONE  (1<<RES_DONE)
+#define FLAG_IN    (1<<RES_IN)
+#define FLAG_START (1<<RES_XXXX)
+
+/* This holds pointers to the various results of parsing */
+struct p_context {
+	struct child_prog *child;
+	struct pipe *list_head;
+	struct pipe *pipe;
+	struct redir_struct *pending_redirect;
+	reserved_style w;
+	int old_flag;				/* for figuring out valid reserved words */
+	struct p_context *stack;
+	int type;			/* define type of parser : ";$" common or special symbol */
+	/* How about quoting status? */
+};
+
+struct redir_struct {
+	redir_type type;			/* type of redirection */
+	int fd;						/* file descriptor being redirected */
+	int dup;					/* -1, or file descriptor being duplicated */
+	struct redir_struct *next;	/* pointer to the next redirect in the list */
+	glob_t word;				/* *word.gl_pathv is the filename */
+};
+
+struct child_prog {
+	pid_t pid;					/* 0 if exited */
+	char **argv;				/* program name and arguments */
+	struct pipe *group;			/* if non-NULL, first in group or subshell */
+	int subshell;				/* flag, non-zero if group must be forked */
+	struct redir_struct *redirects;	/* I/O redirections */
+	glob_t glob_result;			/* result of parameter globbing */
+	int is_stopped;				/* is the program currently running? */
+	struct pipe *family;		/* pointer back to the child's parent pipe */
+	int sp;				/* number of SPECIAL_VAR_SYMBOL */
+	int type;
+};
+
+struct pipe {
+	int jobid;					/* job number */
+	int num_progs;				/* total number of programs in job */
+	int running_progs;			/* number of programs running */
+	char *text;					/* name of job */
+	char *cmdbuf;				/* buffer various argv's point into */
+	pid_t pgrp;					/* process group ID for the job */
+	struct child_prog *progs;	/* array of commands in pipe */
+	struct pipe *next;			/* to track background commands */
+	int stopped_progs;			/* number of programs alive, but stopped */
+	int job_context;			/* bitmask defining current context */
+	pipe_style followup;		/* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
+	reserved_style r_mode;		/* supports if, for, while, until */
+};
+
+struct close_me {
+	int fd;
+	struct close_me *next;
+};
+
+struct variables {
+	char *name;
+	char *value;
+	int flg_export;
+	int flg_read_only;
+	struct variables *next;
+};
+
+/* globals, connect us to the outside world
+ * the first three support $?, $#, and $1 */
+static char **global_argv;
+static int global_argc;
+static int last_return_code;
+extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */
+
+/* "globals" within this file */
+static char *ifs;
+static unsigned char map[256];
+static int fake_mode;
+static int interactive;
+static struct close_me *close_me_head;
+static const char *cwd;
+static struct pipe *job_list;
+static unsigned int last_bg_pid;
+static int last_jobid;
+static unsigned int shell_terminal;
+static char *PS1;
+static char *PS2;
+static struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 };
+static struct variables *top_vars = &shell_ver;
+
+
+#define B_CHUNK (100)
+#define B_NOSPAC 1
+
+typedef struct {
+	char *data;
+	int length;
+	int maxlen;
+	int quote;
+	int nonnull;
+} o_string;
+#define NULL_O_STRING {NULL,0,0,0,0}
+/* used for initialization:
+	o_string foo = NULL_O_STRING; */
+
+/* I can almost use ordinary FILE *.  Is open_memstream() universally
+ * available?  Where is it documented? */
+struct in_str {
+	const char *p;
+	char peek_buf[2];
+	int __promptme;
+	int promptmode;
+	FILE *file;
+	int (*get) (struct in_str *);
+	int (*peek) (struct in_str *);
+};
+#define b_getch(input) ((input)->get(input))
+#define b_peek(input) ((input)->peek(input))
+
+#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
+
+struct built_in_command {
+	const char *cmd;			/* name */
+	const char *descr;			/* description */
+	int (*function) (struct child_prog *);	/* function ptr */
+};
+
+/* belongs in busybox.h */
+static inline int max(int a, int b) {
+	return (a>b)?a:b;
+}
+
+/* This should be in utility.c */
+#ifdef DEBUG_SHELL
+static void debug_printf(const char *format, ...)
+{
+	va_list args;
+	va_start(args, format);
+	vfprintf(stderr, format, args);
+	va_end(args);
+}
+#else
+static inline void debug_printf(const char *format ATTRIBUTE_UNUSED, ...) { }
+#endif
+#define final_printf debug_printf
+
+static void __syntax(char *file, int line) {
+	bb_error_msg("syntax error %s:%d", file, line);
+}
+#define syntax() __syntax(__FILE__, __LINE__)
+
+/* Index of subroutines: */
+/*   function prototypes for builtins */
+static int builtin_cd(struct child_prog *child);
+static int builtin_env(struct child_prog *child);
+static int builtin_eval(struct child_prog *child);
+static int builtin_exec(struct child_prog *child);
+static int builtin_exit(struct child_prog *child);
+static int builtin_export(struct child_prog *child);
+static int builtin_fg_bg(struct child_prog *child);
+static int builtin_help(struct child_prog *child);
+static int builtin_jobs(struct child_prog *child);
+static int builtin_pwd(struct child_prog *child);
+static int builtin_read(struct child_prog *child);
+static int builtin_set(struct child_prog *child);
+static int builtin_shift(struct child_prog *child);
+static int builtin_source(struct child_prog *child);
+static int builtin_umask(struct child_prog *child);
+static int builtin_unset(struct child_prog *child);
+static int builtin_not_written(struct child_prog *child);
+/*   o_string manipulation: */
+static int b_check_space(o_string *o, int len);
+static int b_addchr(o_string *o, int ch);
+static void b_reset(o_string *o);
+static int b_addqchr(o_string *o, int ch, int quote);
+static int b_adduint(o_string *o, unsigned int i);
+/*  in_str manipulations: */
+static int static_get(struct in_str *i);
+static int static_peek(struct in_str *i);
+static int file_get(struct in_str *i);
+static int file_peek(struct in_str *i);
+static void setup_file_in_str(struct in_str *i, FILE *f);
+static void setup_string_in_str(struct in_str *i, const char *s);
+/*  close_me manipulations: */
+static void mark_open(int fd);
+static void mark_closed(int fd);
+static void close_all(void);
+/*  "run" the final data structures: */
+static char *indenter(int i);
+static int free_pipe_list(struct pipe *head, int indent);
+static int free_pipe(struct pipe *pi, int indent);
+/*  really run the final data structures: */
+static int setup_redirects(struct child_prog *prog, int squirrel[]);
+static int run_list_real(struct pipe *pi);
+static void pseudo_exec(struct child_prog *child) ATTRIBUTE_NORETURN;
+static int run_pipe_real(struct pipe *pi);
+/*   extended glob support: */
+static int globhack(const char *src, int flags, glob_t *pglob);
+static int glob_needed(const char *s);
+static int xglob(o_string *dest, int flags, glob_t *pglob);
+/*   variable assignment: */
+static int is_assignment(const char *s);
+/*   data structure manipulation: */
+static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struct in_str *input);
+static void initialize_context(struct p_context *ctx);
+static int done_word(o_string *dest, struct p_context *ctx);
+static int done_command(struct p_context *ctx);
+static int done_pipe(struct p_context *ctx, pipe_style type);
+/*   primary string parsing: */
+static int redirect_dup_num(struct in_str *input);
+static int redirect_opt_num(o_string *o);
+static int process_command_subs(o_string *dest, struct p_context *ctx, struct in_str *input, int subst_end);
+static int parse_group(o_string *dest, struct p_context *ctx, struct in_str *input, int ch);
+static char *lookup_param(char *src);
+static char *make_string(char **inp);
+static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input);
+static int parse_string(o_string *dest, struct p_context *ctx, const char *src);
+static int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *input0, int end_trigger);
+/*   setup: */
+static int parse_stream_outer(struct in_str *inp, int flag);
+static int parse_string_outer(const char *s, int flag);
+static int parse_file_outer(FILE *f);
+/*   job management: */
+static int checkjobs(struct pipe* fg_pipe);
+static void insert_bg_job(struct pipe *pi);
+static void remove_bg_job(struct pipe *pi);
+/*     local variable support */
+static char **make_list_in(char **inp, char *name);
+static char *insert_var_value(char *inp);
+static char *get_local_var(const char *var);
+static void  unset_local_var(const char *name);
+static int set_local_var(const char *s, int flg_export);
+
+/* Table of built-in functions.  They can be forked or not, depending on
+ * context: within pipes, they fork.  As simple commands, they do not.
+ * When used in non-forking context, they can change global variables
+ * in the parent shell process.  If forked, of course they can not.
+ * For example, 'unset foo | whatever' will parse and run, but foo will
+ * still be set at the end. */
+static const struct built_in_command bltins[] = {
+	{"bg", "Resume a job in the background", builtin_fg_bg},
+	{"break", "Exit for, while or until loop", builtin_not_written},
+	{"cd", "Change working directory", builtin_cd},
+	{"continue", "Continue for, while or until loop", builtin_not_written},
+	{"env", "Print all environment variables", builtin_env},
+	{"eval", "Construct and run shell command", builtin_eval},
+	{"exec", "Exec command, replacing this shell with the exec'd process",
+		builtin_exec},
+	{"exit", "Exit from shell()", builtin_exit},
+	{"export", "Set environment variable", builtin_export},
+	{"fg", "Bring job into the foreground", builtin_fg_bg},
+	{"jobs", "Lists the active jobs", builtin_jobs},
+	{"pwd", "Print current directory", builtin_pwd},
+	{"read", "Input environment variable", builtin_read},
+	{"return", "Return from a function", builtin_not_written},
+	{"set", "Set/unset shell local variables", builtin_set},
+	{"shift", "Shift positional parameters", builtin_shift},
+	{"trap", "Trap signals", builtin_not_written},
+	{"ulimit","Controls resource limits", builtin_not_written},
+	{"umask","Sets file creation mask", builtin_umask},
+	{"unset", "Unset environment variable", builtin_unset},
+	{".", "Source-in and run commands in a file", builtin_source},
+	{"help", "List shell built-in commands", builtin_help},
+	{NULL, NULL, NULL}
+};
+
+static const char *set_cwd(void)
+{
+	if(cwd==bb_msg_unknown)
+		cwd = NULL;     /* xgetcwd(arg) called free(arg) */
+	cwd = xgetcwd((char *)cwd);
+	if (!cwd)
+		cwd = bb_msg_unknown;
+	return cwd;
+}
+
+/* built-in 'eval' handler */
+static int builtin_eval(struct child_prog *child)
+{
+	char *str = NULL;
+	int rcode = EXIT_SUCCESS;
+
+	if (child->argv[1]) {
+		str = make_string(child->argv + 1);
+		parse_string_outer(str, FLAG_EXIT_FROM_LOOP |
+					FLAG_PARSE_SEMICOLON);
+		free(str);
+		rcode = last_return_code;
+	}
+	return rcode;
+}
+
+/* built-in 'cd <path>' handler */
+static int builtin_cd(struct child_prog *child)
+{
+	char *newdir;
+	if (child->argv[1] == NULL)
+		newdir = getenv("HOME");
+	else
+		newdir = child->argv[1];
+	if (chdir(newdir)) {
+		printf("cd: %s: %s\n", newdir, strerror(errno));
+		return EXIT_FAILURE;
+	}
+	set_cwd();
+	return EXIT_SUCCESS;
+}
+
+/* built-in 'env' handler */
+static int builtin_env(struct child_prog *dummy ATTRIBUTE_UNUSED)
+{
+	char **e = environ;
+	if (e == NULL) return EXIT_FAILURE;
+	for (; *e; e++) {
+		puts(*e);
+	}
+	return EXIT_SUCCESS;
+}
+
+/* built-in 'exec' handler */
+static int builtin_exec(struct child_prog *child)
+{
+	if (child->argv[1] == NULL)
+		return EXIT_SUCCESS;   /* Really? */
+	child->argv++;
+	pseudo_exec(child);
+	/* never returns */
+}
+
+/* built-in 'exit' handler */
+static int builtin_exit(struct child_prog *child)
+{
+	if (child->argv[1] == NULL)
+		exit(last_return_code);
+	exit (atoi(child->argv[1]));
+}
+
+/* built-in 'export VAR=value' handler */
+static int builtin_export(struct child_prog *child)
+{
+	int res = 0;
+	char *name = child->argv[1];
+
+	if (name == NULL) {
+		return (builtin_env(child));
+	}
+
+	name = strdup(name);
+
+	if(name) {
+		char *value = strchr(name, '=');
+
+		if (!value) {
+			char *tmp;
+			/* They are exporting something without an =VALUE */
+
+			value = get_local_var(name);
+			if (value) {
+				size_t ln = strlen(name);
+
+				tmp = realloc(name, ln+strlen(value)+2);
+				if(tmp==NULL)
+					res = -1;
+				else {
+					sprintf(tmp+ln, "=%s", value);
+					name = tmp;
+				}
+			} else {
+				/* bash does not return an error when trying to export
+				 * an undefined variable.  Do likewise. */
+				res = 1;
+			}
+		}
+	}
+	if (res<0)
+		bb_perror_msg("export");
+	else if(res==0)
+		res = set_local_var(name, 1);
+	else
+		res = 0;
+	free(name);
+	return res;
+}
+
+/* built-in 'fg' and 'bg' handler */
+static int builtin_fg_bg(struct child_prog *child)
+{
+	int i, jobnum;
+	struct pipe *pi=NULL;
+
+	if (!interactive)
+		return EXIT_FAILURE;
+	/* If they gave us no args, assume they want the last backgrounded task */
+	if (!child->argv[1]) {
+		for (pi = job_list; pi; pi = pi->next) {
+			if (pi->jobid == last_jobid) {
+				break;
+			}
+		}
+		if (!pi) {
+			bb_error_msg("%s: no current job", child->argv[0]);
+			return EXIT_FAILURE;
+		}
+	} else {
+		if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) {
+			bb_error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]);
+			return EXIT_FAILURE;
+		}
+		for (pi = job_list; pi; pi = pi->next) {
+			if (pi->jobid == jobnum) {
+				break;
+			}
+		}
+		if (!pi) {
+			bb_error_msg("%s: %d: no such job", child->argv[0], jobnum);
+			return EXIT_FAILURE;
+		}
+	}
+
+	if (*child->argv[0] == 'f') {
+		/* Put the job into the foreground.  */
+		tcsetpgrp(shell_terminal, pi->pgrp);
+	}
+
+	/* Restart the processes in the job */
+	for (i = 0; i < pi->num_progs; i++)
+		pi->progs[i].is_stopped = 0;
+
+	if ( (i=kill(- pi->pgrp, SIGCONT)) < 0) {
+		if (i == ESRCH) {
+			remove_bg_job(pi);
+		} else {
+			bb_perror_msg("kill (SIGCONT)");
+		}
+	}
+
+	pi->stopped_progs = 0;
+	return EXIT_SUCCESS;
+}
+
+/* built-in 'help' handler */
+static int builtin_help(struct child_prog *dummy ATTRIBUTE_UNUSED)
+{
+	const struct built_in_command *x;
+
+	printf("\nBuilt-in commands:\n");
+	printf("-------------------\n");
+	for (x = bltins; x->cmd; x++) {
+		if (x->descr==NULL)
+			continue;
+		printf("%s\t%s\n", x->cmd, x->descr);
+	}
+	printf("\n\n");
+	return EXIT_SUCCESS;
+}
+
+/* built-in 'jobs' handler */
+static int builtin_jobs(struct child_prog *child ATTRIBUTE_UNUSED)
+{
+	struct pipe *job;
+	char *status_string;
+
+	for (job = job_list; job; job = job->next) {
+		if (job->running_progs == job->stopped_progs)
+			status_string = "Stopped";
+		else
+			status_string = "Running";
+
+		printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
+	}
+	return EXIT_SUCCESS;
+}
+
+
+/* built-in 'pwd' handler */
+static int builtin_pwd(struct child_prog *dummy ATTRIBUTE_UNUSED)
+{
+	puts(set_cwd());
+	return EXIT_SUCCESS;
+}
+
+/* built-in 'read VAR' handler */
+static int builtin_read(struct child_prog *child)
+{
+	int res;
+
+	if (child->argv[1]) {
+		char string[BUFSIZ];
+		char *var = 0;
+
+		string[0] = 0;  /* In case stdin has only EOF */
+		/* read string */
+		fgets(string, sizeof(string), stdin);
+		chomp(string);
+		var = malloc(strlen(child->argv[1])+strlen(string)+2);
+		if(var) {
+			sprintf(var, "%s=%s", child->argv[1], string);
+			res = set_local_var(var, 0);
+		} else
+			res = -1;
+		if (res)
+			bb_perror_msg("read");
+		free(var);      /* So not move up to avoid breaking errno */
+		return res;
+	} else {
+		do res=getchar(); while(res!='\n' && res!=EOF);
+		return 0;
+	}
+}
+
+/* built-in 'set VAR=value' handler */
+static int builtin_set(struct child_prog *child)
+{
+	char *temp = child->argv[1];
+	struct variables *e;
+
+	if (temp == NULL)
+		for(e = top_vars; e; e=e->next)
+			printf("%s=%s\n", e->name, e->value);
+	else
+		set_local_var(temp, 0);
+
+		return EXIT_SUCCESS;
+}
+
+
+/* Built-in 'shift' handler */
+static int builtin_shift(struct child_prog *child)
+{
+	int n=1;
+	if (child->argv[1]) {
+		n=atoi(child->argv[1]);
+	}
+	if (n>=0 && n<global_argc) {
+		/* XXX This probably breaks $0 */
+		global_argc -= n;
+		global_argv += n;
+		return EXIT_SUCCESS;
+	} else {
+		return EXIT_FAILURE;
+	}
+}
+
+/* Built-in '.' handler (read-in and execute commands from file) */
+static int builtin_source(struct child_prog *child)
+{
+	FILE *input;
+	int status;
+
+	if (child->argv[1] == NULL)
+		return EXIT_FAILURE;
+
+	/* XXX search through $PATH is missing */
+	input = fopen(child->argv[1], "r");
+	if (!input) {
+		bb_error_msg("Couldn't open file '%s'", child->argv[1]);
+		return EXIT_FAILURE;
+	}
+
+	/* Now run the file */
+	/* XXX argv and argc are broken; need to save old global_argv
+	 * (pointer only is OK!) on this stack frame,
+	 * set global_argv=child->argv+1, recurse, and restore. */
+	mark_open(fileno(input));
+	status = parse_file_outer(input);
+	mark_closed(fileno(input));
+	fclose(input);
+	return (status);
+}
+
+static int builtin_umask(struct child_prog *child)
+{
+	mode_t new_umask;
+	const char *arg = child->argv[1];
+	char *end;
+	if (arg) {
+		new_umask=strtoul(arg, &end, 8);
+		if (*end!='\0' || end == arg) {
+			return EXIT_FAILURE;
+		}
+	} else {
+		printf("%.3o\n", (unsigned int) (new_umask=umask(0)));
+	}
+	umask(new_umask);
+	return EXIT_SUCCESS;
+}
+
+/* built-in 'unset VAR' handler */
+static int builtin_unset(struct child_prog *child)
+{
+	/* bash returned already true */
+	unset_local_var(child->argv[1]);
+	return EXIT_SUCCESS;
+}
+
+static int builtin_not_written(struct child_prog *child)
+{
+	printf("builtin_%s not written\n",child->argv[0]);
+	return EXIT_FAILURE;
+}
+
+static int b_check_space(o_string *o, int len)
+{
+	/* It would be easy to drop a more restrictive policy
+	 * in here, such as setting a maximum string length */
+	if (o->length + len > o->maxlen) {
+		char *old_data = o->data;
+		/* assert (data == NULL || o->maxlen != 0); */
+		o->maxlen += max(2*len, B_CHUNK);
+		o->data = realloc(o->data, 1 + o->maxlen);
+		if (o->data == NULL) {
+			free(old_data);
+		}
+	}
+	return o->data == NULL;
+}
+
+static int b_addchr(o_string *o, int ch)
+{
+	debug_printf("b_addchr: %c %d %p\n", ch, o->length, o);
+	if (b_check_space(o, 1)) return B_NOSPAC;
+	o->data[o->length] = ch;
+	o->length++;
+	o->data[o->length] = '\0';
+	return 0;
+}
+
+static void b_reset(o_string *o)
+{
+	o->length = 0;
+	o->nonnull = 0;
+	if (o->data != NULL) *o->data = '\0';
+}
+
+static void b_free(o_string *o)
+{
+	b_reset(o);
+	free(o->data);
+	o->data = NULL;
+	o->maxlen = 0;
+}
+
+/* My analysis of quoting semantics tells me that state information
+ * is associated with a destination, not a source.
+ */
+static int b_addqchr(o_string *o, int ch, int quote)
+{
+	if (quote && strchr("*?[\\",ch)) {
+		int rc;
+		rc = b_addchr(o, '\\');
+		if (rc) return rc;
+	}
+	return b_addchr(o, ch);
+}
+
+/* belongs in utility.c */
+static char *simple_itoa(unsigned int i)
+{
+	/* 21 digits plus null terminator, good for 64-bit or smaller ints */
+	static char local[22];
+	char *p = &local[21];
+	*p-- = '\0';
+	do {
+		*p-- = '0' + i % 10;
+		i /= 10;
+	} while (i > 0);
+	return p + 1;
+}
+
+static int b_adduint(o_string *o, unsigned int i)
+{
+	int r;
+	char *p = simple_itoa(i);
+	/* no escape checking necessary */
+	do r=b_addchr(o, *p++); while (r==0 && *p);
+	return r;
+}
+
+static int static_get(struct in_str *i)
+{
+	int ch=*i->p++;
+	if (ch=='\0') return EOF;
+	return ch;
+}
+
+static int static_peek(struct in_str *i)
+{
+	return *i->p;
+}
+
+static inline void cmdedit_set_initial_prompt(void)
+{
+#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
+	PS1 = NULL;
+#else
+	PS1 = getenv("PS1");
+	if(PS1==0)
+		PS1 = "\\w \\$ ";
+#endif
+}
+
+static inline void setup_prompt_string(int promptmode, char **prompt_str)
+{
+	debug_printf("setup_prompt_string %d ",promptmode);
+#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
+	/* Set up the prompt */
+	if (promptmode == 1) {
+		free(PS1);
+		PS1=xmalloc(strlen(cwd)+4);
+		sprintf(PS1, "%s %s", cwd, ( geteuid() != 0 ) ?  "$ ":"# ");
+		*prompt_str = PS1;
+	} else {
+		*prompt_str = PS2;
+	}
+#else
+	*prompt_str = (promptmode==1)? PS1 : PS2;
+#endif
+	debug_printf("result %s\n",*prompt_str);
+}
+
+static void get_user_input(struct in_str *i)
+{
+	char *prompt_str;
+	static char the_command[BUFSIZ];
+
+	setup_prompt_string(i->promptmode, &prompt_str);
+#ifdef CONFIG_FEATURE_COMMAND_EDITING
+	/*
+	 ** enable command line editing only while a command line
+	 ** is actually being read; otherwise, we'll end up bequeathing
+	 ** atexit() handlers and other unwanted stuff to our
+	 ** child processes (rob at sysgo.de)
+	 */
+	cmdedit_read_input(prompt_str, the_command);
+#else
+	fputs(prompt_str, stdout);
+	fflush(stdout);
+	the_command[0]=fgetc(i->file);
+	the_command[1]='\0';
+#endif
+	fflush(stdout);
+	i->p = the_command;
+}
+
+/* This is the magic location that prints prompts
+ * and gets data back from the user */
+static int file_get(struct in_str *i)
+{
+	int ch;
+
+	ch = 0;
+	/* If there is data waiting, eat it up */
+	if (i->p && *i->p) {
+		ch=*i->p++;
+	} else {
+		/* need to double check i->file because we might be doing something
+		 * more complicated by now, like sourcing or substituting. */
+		if (i->__promptme && interactive && i->file == stdin) {
+			while(! i->p || (interactive && strlen(i->p)==0) ) {
+				get_user_input(i);
+			}
+			i->promptmode=2;
+			i->__promptme = 0;
+			if (i->p && *i->p) {
+				ch=*i->p++;
+			}
+		} else {
+			ch = fgetc(i->file);
+		}
+
+		debug_printf("b_getch: got a %d\n", ch);
+	}
+	if (ch == '\n') i->__promptme=1;
+	return ch;
+}
+
+/* All the callers guarantee this routine will never be
+ * used right after a newline, so prompting is not needed.
+ */
+static int file_peek(struct in_str *i)
+{
+	if (i->p && *i->p) {
+		return *i->p;
+	} else {
+		i->peek_buf[0] = fgetc(i->file);
+		i->peek_buf[1] = '\0';
+		i->p = i->peek_buf;
+		debug_printf("b_peek: got a %d\n", *i->p);
+		return *i->p;
+	}
+}
+
+static void setup_file_in_str(struct in_str *i, FILE *f)
+{
+	i->peek = file_peek;
+	i->get = file_get;
+	i->__promptme=1;
+	i->promptmode=1;
+	i->file = f;
+	i->p = NULL;
+}
+
+static void setup_string_in_str(struct in_str *i, const char *s)
+{
+	i->peek = static_peek;
+	i->get = static_get;
+	i->__promptme=1;
+	i->promptmode=1;
+	i->p = s;
+}
+
+static void mark_open(int fd)
+{
+	struct close_me *new = xmalloc(sizeof(struct close_me));
+	new->fd = fd;
+	new->next = close_me_head;
+	close_me_head = new;
+}
+
+static void mark_closed(int fd)
+{
+	struct close_me *tmp;
+	if (close_me_head == NULL || close_me_head->fd != fd)
+		bb_error_msg_and_die("corrupt close_me");
+	tmp = close_me_head;
+	close_me_head = close_me_head->next;
+	free(tmp);
+}
+
+static void close_all(void)
+{
+	struct close_me *c;
+	for (c=close_me_head; c; c=c->next) {
+		close(c->fd);
+	}
+	close_me_head = NULL;
+}
+
+/* squirrel != NULL means we squirrel away copies of stdin, stdout,
+ * and stderr if they are redirected. */
+static int setup_redirects(struct child_prog *prog, int squirrel[])
+{
+	int openfd, mode;
+	struct redir_struct *redir;
+
+	for (redir=prog->redirects; redir; redir=redir->next) {
+		if (redir->dup == -1 && redir->word.gl_pathv == NULL) {
+			/* something went wrong in the parse.  Pretend it didn't happen */
+			continue;
+		}
+		if (redir->dup == -1) {
+			mode=redir_table[redir->type].mode;
+			openfd = open(redir->word.gl_pathv[0], mode, 0666);
+			if (openfd < 0) {
+			/* this could get lost if stderr has been redirected, but
+			   bash and ash both lose it as well (though zsh doesn't!) */
+				bb_perror_msg("error opening %s", redir->word.gl_pathv[0]);
+				return 1;
+			}
+		} else {
+			openfd = redir->dup;
+		}
+
+		if (openfd != redir->fd) {
+			if (squirrel && redir->fd < 3) {
+				squirrel[redir->fd] = dup(redir->fd);
+			}
+			if (openfd == -3) {
+				close(openfd);
+			} else {
+				dup2(openfd, redir->fd);
+				if (redir->dup == -1)
+					close (openfd);
+			}
+		}
+	}
+	return 0;
+}
+
+static void restore_redirects(int squirrel[])
+{
+	int i, fd;
+	for (i=0; i<3; i++) {
+		fd = squirrel[i];
+		if (fd != -1) {
+			/* No error checking.  I sure wouldn't know what
+			 * to do with an error if I found one! */
+			dup2(fd, i);
+			close(fd);
+		}
+	}
+}
+
+/* never returns */
+/* XXX no exit() here.  If you don't exec, use _exit instead.
+ * The at_exit handlers apparently confuse the calling process,
+ * in particular stdin handling.  Not sure why? */
+static void pseudo_exec(struct child_prog *child)
+{
+	int i, rcode;
+	char *p;
+	const struct built_in_command *x;
+	if (child->argv) {
+		for (i=0; is_assignment(child->argv[i]); i++) {
+			debug_printf("pid %d environment modification: %s\n",getpid(),child->argv[i]);
+			p = insert_var_value(child->argv[i]);
+			putenv(strdup(p));
+			if (p != child->argv[i]) free(p);
+		}
+		child->argv+=i;  /* XXX this hack isn't so horrible, since we are about
+		                        to exit, and therefore don't need to keep data
+		                        structures consistent for free() use. */
+		/* If a variable is assigned in a forest, and nobody listens,
+		 * was it ever really set?
+		 */
+		if (child->argv[0] == NULL) {
+			_exit(EXIT_SUCCESS);
+		}
+
+		/*
+		 * Check if the command matches any of the builtins.
+		 * Depending on context, this might be redundant.  But it's
+		 * easier to waste a few CPU cycles than it is to figure out
+		 * if this is one of those cases.
+		 */
+		for (x = bltins; x->cmd; x++) {
+			if (strcmp(child->argv[0], x->cmd) == 0 ) {
+				debug_printf("builtin exec %s\n", child->argv[0]);
+				rcode = x->function(child);
+				fflush(stdout);
+				_exit(rcode);
+			}
+		}
+
+		/* Check if the command matches any busybox internal commands
+		 * ("applets") here.
+		 * FIXME: This feature is not 100% safe, since
+		 * BusyBox is not fully reentrant, so we have no guarantee the things
+		 * from the .bss are still zeroed, or that things from .data are still
+		 * at their defaults.  We could exec ourself from /proc/self/exe, but I
+		 * really dislike relying on /proc for things.  We could exec ourself
+		 * from global_argv[0], but if we are in a chroot, we may not be able
+		 * to find ourself... */
+#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
+		{
+			int argc_l;
+			char** argv_l=child->argv;
+			char *name = child->argv[0];
+
+			/* Count argc for use in a second... */
+			for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++);
+			optind = 1;
+			debug_printf("running applet %s\n", name);
+			run_applet_by_name(name, argc_l, child->argv);
+		}
+#endif
+		debug_printf("exec of %s\n",child->argv[0]);
+		execvp(child->argv[0],child->argv);
+		bb_perror_msg("couldn't exec: %s",child->argv[0]);
+		_exit(1);
+	} else if (child->group) {
+		debug_printf("runtime nesting to group\n");
+		interactive=0;    /* crucial!!!! */
+		rcode = run_list_real(child->group);
+		/* OK to leak memory by not calling free_pipe_list,
+		 * since this process is about to exit */
+		_exit(rcode);
+	} else {
+		/* Can happen.  See what bash does with ">foo" by itself. */
+		debug_printf("trying to pseudo_exec null command\n");
+		_exit(EXIT_SUCCESS);
+	}
+}
+
+static void insert_bg_job(struct pipe *pi)
+{
+	struct pipe *thejob;
+
+	/* Linear search for the ID of the job to use */
+	pi->jobid = 1;
+	for (thejob = job_list; thejob; thejob = thejob->next)
+		if (thejob->jobid >= pi->jobid)
+			pi->jobid = thejob->jobid + 1;
+
+	/* add thejob to the list of running jobs */
+	if (!job_list) {
+		thejob = job_list = xmalloc(sizeof(*thejob));
+	} else {
+		for (thejob = job_list; thejob->next; thejob = thejob->next) /* nothing */;
+		thejob->next = xmalloc(sizeof(*thejob));
+		thejob = thejob->next;
+	}
+
+	/* physically copy the struct job */
+	memcpy(thejob, pi, sizeof(struct pipe));
+	thejob->next = NULL;
+	thejob->running_progs = thejob->num_progs;
+	thejob->stopped_progs = 0;
+	thejob->text = xmalloc(BUFSIZ); /* cmdedit buffer size */
+
+	//if (pi->progs[0] && pi->progs[0].argv && pi->progs[0].argv[0])
+	{
+		char *bar=thejob->text;
+		char **foo=pi->progs[0].argv;
+		while(foo && *foo) {
+			bar += sprintf(bar, "%s ", *foo++);
+		}
+	}
+
+	/* we don't wait for background thejobs to return -- append it
+	   to the list of backgrounded thejobs and leave it alone */
+	printf("[%d] %d\n", thejob->jobid, thejob->progs[0].pid);
+	last_bg_pid = thejob->progs[0].pid;
+	last_jobid = thejob->jobid;
+}
+
+/* remove a backgrounded job */
+static void remove_bg_job(struct pipe *pi)
+{
+	struct pipe *prev_pipe;
+
+	if (pi == job_list) {
+		job_list = pi->next;
+	} else {
+		prev_pipe = job_list;
+		while (prev_pipe->next != pi)
+			prev_pipe = prev_pipe->next;
+		prev_pipe->next = pi->next;
+	}
+	if (job_list)
+		last_jobid = job_list->jobid;
+	else
+		last_jobid = 0;
+
+	pi->stopped_progs = 0;
+	free_pipe(pi, 0);
+	free(pi);
+}
+
+/* Checks to see if any processes have exited -- if they
+   have, figure out why and see if a job has completed */
+static int checkjobs(struct pipe* fg_pipe)
+{
+	int attributes;
+	int status;
+	int prognum = 0;
+	struct pipe *pi;
+	pid_t childpid;
+
+	attributes = WUNTRACED;
+	if (fg_pipe==NULL) {
+		attributes |= WNOHANG;
+	}
+
+	while ((childpid = waitpid(-1, &status, attributes)) > 0) {
+		if (fg_pipe) {
+			int i, rcode = 0;
+			for (i=0; i < fg_pipe->num_progs; i++) {
+				if (fg_pipe->progs[i].pid == childpid) {
+					if (i==fg_pipe->num_progs-1)
+						rcode=WEXITSTATUS(status);
+					(fg_pipe->num_progs)--;
+					return(rcode);
+				}
+			}
+		}
+
+		for (pi = job_list; pi; pi = pi->next) {
+			prognum = 0;
+			while (prognum < pi->num_progs && pi->progs[prognum].pid != childpid) {
+				prognum++;
+			}
+			if (prognum < pi->num_progs)
+				break;
+		}
+
+		if(pi==NULL) {
+			debug_printf("checkjobs: pid %d was not in our list!\n", childpid);
+			continue;
+		}
+
+		if (WIFEXITED(status) || WIFSIGNALED(status)) {
+			/* child exited */
+			pi->running_progs--;
+			pi->progs[prognum].pid = 0;
+
+			if (!pi->running_progs) {
+				printf(JOB_STATUS_FORMAT, pi->jobid, "Done", pi->text);
+				remove_bg_job(pi);
+			}
+		} else {
+			/* child stopped */
+			pi->stopped_progs++;
+			pi->progs[prognum].is_stopped = 1;
+
+#if 0
+			/* Printing this stuff is a pain, since it tends to
+			 * overwrite the prompt an inconveinient moments.  So
+			 * don't do that.  */
+			if (pi->stopped_progs == pi->num_progs) {
+				printf("\n"JOB_STATUS_FORMAT, pi->jobid, "Stopped", pi->text);
+			}
+#endif
+		}
+	}
+
+	if (childpid == -1 && errno != ECHILD)
+		bb_perror_msg("waitpid");
+
+	/* move the shell to the foreground */
+	//if (interactive && tcsetpgrp(shell_terminal, getpgid(0)))
+	//	bb_perror_msg("tcsetpgrp-2");
+	return -1;
+}
+
+/* Figure out our controlling tty, checking in order stderr,
+ * stdin, and stdout.  If check_pgrp is set, also check that
+ * we belong to the foreground process group associated with
+ * that tty.  The value of shell_terminal is needed in order to call
+ * tcsetpgrp(shell_terminal, ...); */
+#if 0
+static void controlling_tty(int check_pgrp)
+{
+	pid_t curpgrp;
+
+	if ((curpgrp = tcgetpgrp(shell_terminal = 2)) < 0
+			&& (curpgrp = tcgetpgrp(shell_terminal = 0)) < 0
+			&& (curpgrp = tcgetpgrp(shell_terminal = 1)) < 0)
+		goto shell_terminal_error;
+
+	if (check_pgrp && curpgrp != getpgid(0))
+		goto shell_terminal_error;
+
+	return;
+
+shell_terminal_error:
+		shell_terminal = -1;
+		return;
+}
+#endif
+
+/* run_pipe_real() starts all the jobs, but doesn't wait for anything
+ * to finish.  See checkjobs().
+ *
+ * return code is normally -1, when the caller has to wait for children
+ * to finish to determine the exit status of the pipe.  If the pipe
+ * is a simple builtin command, however, the action is done by the
+ * time run_pipe_real returns, and the exit code is provided as the
+ * return value.
+ *
+ * The input of the pipe is always stdin, the output is always
+ * stdout.  The outpipe[] mechanism in BusyBox-0.48 lash is bogus,
+ * because it tries to avoid running the command substitution in
+ * subshell, when that is in fact necessary.  The subshell process
+ * now has its stdout directed to the input of the appropriate pipe,
+ * so this routine is noticeably simpler.
+ */
+static int run_pipe_real(struct pipe *pi)
+{
+	int i;
+	int nextin, nextout;
+	int pipefds[2];				/* pipefds[0] is for reading */
+	struct child_prog *child;
+	const struct built_in_command *x;
+	char *p;
+
+	nextin = 0;
+	pi->pgrp = -1;
+
+	/* Check if this is a simple builtin (not part of a pipe).
+	 * Builtins within pipes have to fork anyway, and are handled in
+	 * pseudo_exec.  "echo foo | read bar" doesn't work on bash, either.
+	 */
+	if (pi->num_progs == 1) child = & (pi->progs[0]);
+	if (pi->num_progs == 1 && child->group && child->subshell == 0) {
+		int squirrel[] = {-1, -1, -1};
+		int rcode;
+		debug_printf("non-subshell grouping\n");
+		setup_redirects(child, squirrel);
+		/* XXX could we merge code with following builtin case,
+		 * by creating a pseudo builtin that calls run_list_real? */
+		rcode = run_list_real(child->group);
+		restore_redirects(squirrel);
+		return rcode;
+	} else if (pi->num_progs == 1 && pi->progs[0].argv != NULL) {
+		for (i=0; is_assignment(child->argv[i]); i++) { /* nothing */ }
+		if (i!=0 && child->argv[i]==NULL) {
+			/* assignments, but no command: set the local environment */
+			for (i=0; child->argv[i]!=NULL; i++) {
+
+				/* Ok, this case is tricky.  We have to decide if this is a
+				 * local variable, or an already exported variable.  If it is
+				 * already exported, we have to export the new value.  If it is
+				 * not exported, we need only set this as a local variable.
+				 * This junk is all to decide whether or not to export this
+				 * variable. */
+				int export_me=0;
+				char *name, *value;
+				name = bb_xstrdup(child->argv[i]);
+				debug_printf("Local environment set: %s\n", name);
+				value = strchr(name, '=');
+				if (value)
+					*value=0;
+				if ( get_local_var(name)) {
+					export_me=1;
+				}
+				free(name);
+				p = insert_var_value(child->argv[i]);
+				set_local_var(p, export_me);
+				if (p != child->argv[i]) free(p);
+			}
+			return EXIT_SUCCESS;   /* don't worry about errors in set_local_var() yet */
+		}
+		for (i = 0; is_assignment(child->argv[i]); i++) {
+			p = insert_var_value(child->argv[i]);
+			putenv(strdup(p));
+			if (p != child->argv[i]) {
+				child->sp--;
+				free(p);
+			}
+		}
+		if (child->sp) {
+			char * str = NULL;
+
+			str = make_string((child->argv + i));
+			parse_string_outer(str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING);
+			free(str);
+			return last_return_code;
+		}
+		for (x = bltins; x->cmd; x++) {
+			if (strcmp(child->argv[i], x->cmd) == 0 ) {
+				int squirrel[] = {-1, -1, -1};
+				int rcode;
+				if (x->function == builtin_exec && child->argv[i+1]==NULL) {
+					debug_printf("magic exec\n");
+					setup_redirects(child,NULL);
+					return EXIT_SUCCESS;
+				}
+				debug_printf("builtin inline %s\n", child->argv[0]);
+				/* XXX setup_redirects acts on file descriptors, not FILEs.
+				 * This is perfect for work that comes after exec().
+				 * Is it really safe for inline use?  Experimentally,
+				 * things seem to work with glibc. */
+				setup_redirects(child, squirrel);
+				child->argv+=i;  /* XXX horrible hack */
+				rcode = x->function(child);
+				child->argv-=i;  /* XXX restore hack so free() can work right */
+				restore_redirects(squirrel);
+				return rcode;
+			}
+		}
+	}
+
+	for (i = 0; i < pi->num_progs; i++) {
+		child = & (pi->progs[i]);
+
+		/* pipes are inserted between pairs of commands */
+		if ((i + 1) < pi->num_progs) {
+			if (pipe(pipefds)<0) bb_perror_msg_and_die("pipe");
+			nextout = pipefds[1];
+		} else {
+			nextout=1;
+			pipefds[0] = -1;
+		}
+
+		/* XXX test for failed fork()? */
+#if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__)
+		if (!(child->pid = fork()))
+#else
+		if (!(child->pid = vfork()))
+#endif
+		{
+			/* Set the handling for job control signals back to the default.  */
+			signal(SIGINT, SIG_DFL);
+			signal(SIGQUIT, SIG_DFL);
+			signal(SIGTERM, SIG_DFL);
+			signal(SIGTSTP, SIG_DFL);
+			signal(SIGTTIN, SIG_DFL);
+			signal(SIGTTOU, SIG_DFL);
+			signal(SIGCHLD, SIG_DFL);
+
+			close_all();
+
+			if (nextin != 0) {
+				dup2(nextin, 0);
+				close(nextin);
+			}
+			if (nextout != 1) {
+				dup2(nextout, 1);
+				close(nextout);
+			}
+			if (pipefds[0]!=-1) {
+				close(pipefds[0]);  /* opposite end of our output pipe */
+			}
+
+			/* Like bash, explicit redirects override pipes,
+			 * and the pipe fd is available for dup'ing. */
+			setup_redirects(child,NULL);
+
+			if (interactive && pi->followup!=PIPE_BG) {
+				/* If we (the child) win the race, put ourselves in the process
+				 * group whose leader is the first process in this pipe. */
+				if (pi->pgrp < 0) {
+					pi->pgrp = getpid();
+				}
+				if (setpgid(0, pi->pgrp) == 0) {
+					tcsetpgrp(2, pi->pgrp);
+				}
+			}
+
+			pseudo_exec(child);
+		}
+
+
+		/* put our child in the process group whose leader is the
+		   first process in this pipe */
+		if (pi->pgrp < 0) {
+			pi->pgrp = child->pid;
+		}
+		/* Don't check for errors.  The child may be dead already,
+		 * in which case setpgid returns error code EACCES. */
+		setpgid(child->pid, pi->pgrp);
+
+		if (nextin != 0)
+			close(nextin);
+		if (nextout != 1)
+			close(nextout);
+
+		/* If there isn't another process, nextin is garbage
+		   but it doesn't matter */
+		nextin = pipefds[0];
+	}
+	return -1;
+}
+
+static int run_list_real(struct pipe *pi)
+{
+	char *save_name = NULL;
+	char **list = NULL;
+	char **save_list = NULL;
+	struct pipe *rpipe;
+	int flag_rep = 0;
+	int save_num_progs;
+	int rcode=0, flag_skip=1;
+	int flag_restore = 0;
+	int if_code=0, next_if_code=0;  /* need double-buffer to handle elif */
+	reserved_style rmode, skip_more_in_this_rmode=RES_XXXX;
+	/* check syntax for "for" */
+	for (rpipe = pi; rpipe; rpipe = rpipe->next) {
+		if ((rpipe->r_mode == RES_IN ||
+		    rpipe->r_mode == RES_FOR) &&
+		    (rpipe->next == NULL)) {
+				syntax();
+				return 1;
+		}
+		if ((rpipe->r_mode == RES_IN &&
+			(rpipe->next->r_mode == RES_IN &&
+			rpipe->next->progs->argv != NULL))||
+			(rpipe->r_mode == RES_FOR &&
+			rpipe->next->r_mode != RES_IN)) {
+				syntax();
+				return 1;
+		}
+	}
+	for (; pi; pi = (flag_restore != 0) ? rpipe : pi->next) {
+		if (pi->r_mode == RES_WHILE || pi->r_mode == RES_UNTIL ||
+			pi->r_mode == RES_FOR) {
+				flag_restore = 0;
+				if (!rpipe) {
+					flag_rep = 0;
+					rpipe = pi;
+				}
+		}
+		rmode = pi->r_mode;
+		debug_printf("rmode=%d  if_code=%d  next_if_code=%d skip_more=%d\n", rmode, if_code, next_if_code, skip_more_in_this_rmode);
+		if (rmode == skip_more_in_this_rmode && flag_skip) {
+			if (pi->followup == PIPE_SEQ) flag_skip=0;
+			continue;
+		}
+		flag_skip = 1;
+		skip_more_in_this_rmode = RES_XXXX;
+		if (rmode == RES_THEN || rmode == RES_ELSE) if_code = next_if_code;
+		if (rmode == RES_THEN &&  if_code) continue;
+		if (rmode == RES_ELSE && !if_code) continue;
+		if (rmode == RES_ELIF && !if_code) break;
+		if (rmode == RES_FOR && pi->num_progs) {
+			if (!list) {
+				/* if no variable values after "in" we skip "for" */
+				if (!pi->next->progs->argv) continue;
+				/* create list of variable values */
+				list = make_list_in(pi->next->progs->argv,
+					pi->progs->argv[0]);
+				save_list = list;
+				save_name = pi->progs->argv[0];
+				pi->progs->argv[0] = NULL;
+				flag_rep = 1;
+			}
+			if (!(*list)) {
+				free(pi->progs->argv[0]);
+				free(save_list);
+				list = NULL;
+				flag_rep = 0;
+				pi->progs->argv[0] = save_name;
+				pi->progs->glob_result.gl_pathv[0] =
+					pi->progs->argv[0];
+				continue;
+			} else {
+				/* insert new value from list for variable */
+				if (pi->progs->argv[0])
+					free(pi->progs->argv[0]);
+				pi->progs->argv[0] = *list++;
+				pi->progs->glob_result.gl_pathv[0] =
+					pi->progs->argv[0];
+			}
+		}
+		if (rmode == RES_IN) continue;
+		if (rmode == RES_DO) {
+			if (!flag_rep) continue;
+		}
+		if ((rmode == RES_DONE)) {
+			if (flag_rep) {
+				flag_restore = 1;
+			} else {
+				rpipe = NULL;
+			}
+		}
+		if (pi->num_progs == 0) continue;
+		save_num_progs = pi->num_progs; /* save number of programs */
+		rcode = run_pipe_real(pi);
+		debug_printf("run_pipe_real returned %d\n",rcode);
+		if (rcode!=-1) {
+			/* We only ran a builtin: rcode was set by the return value
+			 * of run_pipe_real(), and we don't need to wait for anything. */
+		} else if (pi->followup==PIPE_BG) {
+			/* XXX check bash's behavior with nontrivial pipes */
+			/* XXX compute jobid */
+			/* XXX what does bash do with attempts to background builtins? */
+			insert_bg_job(pi);
+			rcode = EXIT_SUCCESS;
+		} else {
+			if (interactive) {
+				/* move the new process group into the foreground */
+				if (tcsetpgrp(shell_terminal, pi->pgrp) && errno != ENOTTY)
+					bb_perror_msg("tcsetpgrp-3");
+				rcode = checkjobs(pi);
+				/* move the shell to the foreground */
+				if (tcsetpgrp(shell_terminal, getpgid(0)) && errno != ENOTTY)
+					bb_perror_msg("tcsetpgrp-4");
+			} else {
+				rcode = checkjobs(pi);
+			}
+			debug_printf("checkjobs returned %d\n",rcode);
+		}
+		last_return_code=rcode;
+		pi->num_progs = save_num_progs; /* restore number of programs */
+		if ( rmode == RES_IF || rmode == RES_ELIF )
+			next_if_code=rcode;  /* can be overwritten a number of times */
+		if (rmode == RES_WHILE)
+			flag_rep = !last_return_code;
+		if (rmode == RES_UNTIL)
+			flag_rep = last_return_code;
+		if ( (rcode==EXIT_SUCCESS && pi->followup==PIPE_OR) ||
+		     (rcode!=EXIT_SUCCESS && pi->followup==PIPE_AND) )
+			skip_more_in_this_rmode=rmode;
+		checkjobs(NULL);
+	}
+	return rcode;
+}
+
+/* broken, of course, but OK for testing */
+static char *indenter(int i)
+{
+	static char blanks[]="                                    ";
+	return &blanks[sizeof(blanks)-i-1];
+}
+
+/* return code is the exit status of the pipe */
+static int free_pipe(struct pipe *pi, int indent)
+{
+	char **p;
+	struct child_prog *child;
+	struct redir_struct *r, *rnext;
+	int a, i, ret_code=0;
+	char *ind = indenter(indent);
+
+	if (pi->stopped_progs > 0)
+		return ret_code;
+	final_printf("%s run pipe: (pid %d)\n",ind,getpid());
+	for (i=0; i<pi->num_progs; i++) {
+		child = &pi->progs[i];
+		final_printf("%s  command %d:\n",ind,i);
+		if (child->argv) {
+			for (a=0,p=child->argv; *p; a++,p++) {
+				final_printf("%s   argv[%d] = %s\n",ind,a,*p);
+			}
+			globfree(&child->glob_result);
+			child->argv=NULL;
+		} else if (child->group) {
+			final_printf("%s   begin group (subshell:%d)\n",ind, child->subshell);
+			ret_code = free_pipe_list(child->group,indent+3);
+			final_printf("%s   end group\n",ind);
+		} else {
+			final_printf("%s   (nil)\n",ind);
+		}
+		for (r=child->redirects; r; r=rnext) {
+			final_printf("%s   redirect %d%s", ind, r->fd, redir_table[r->type].descrip);
+			if (r->dup == -1) {
+				/* guard against the case >$FOO, where foo is unset or blank */
+				if (r->word.gl_pathv) {
+					final_printf(" %s\n", *r->word.gl_pathv);
+					globfree(&r->word);
+				}
+			} else {
+				final_printf("&%d\n", r->dup);
+			}
+			rnext=r->next;
+			free(r);
+		}
+		child->redirects=NULL;
+	}
+	free(pi->progs);   /* children are an array, they get freed all at once */
+	pi->progs=NULL;
+	return ret_code;
+}
+
+static int free_pipe_list(struct pipe *head, int indent)
+{
+	int rcode=0;   /* if list has no members */
+	struct pipe *pi, *next;
+	char *ind = indenter(indent);
+	for (pi=head; pi; pi=next) {
+		final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode);
+		rcode = free_pipe(pi, indent);
+		final_printf("%s pipe followup code %d\n", ind, pi->followup);
+		next=pi->next;
+		pi->next=NULL;
+		free(pi);
+	}
+	return rcode;
+}
+
+/* Select which version we will use */
+static int run_list(struct pipe *pi)
+{
+	int rcode=0;
+	if (fake_mode==0) {
+		rcode = run_list_real(pi);
+	}
+	/* free_pipe_list has the side effect of clearing memory
+	 * In the long run that function can be merged with run_list_real,
+	 * but doing that now would hobble the debugging effort. */
+	free_pipe_list(pi,0);
+	return rcode;
+}
+
+/* The API for glob is arguably broken.  This routine pushes a non-matching
+ * string into the output structure, removing non-backslashed backslashes.
+ * If someone can prove me wrong, by performing this function within the
+ * original glob(3) api, feel free to rewrite this routine into oblivion.
+ * Return code (0 vs. GLOB_NOSPACE) matches glob(3).
+ * XXX broken if the last character is '\\', check that before calling.
+ */
+static int globhack(const char *src, int flags, glob_t *pglob)
+{
+	int cnt=0, pathc;
+	const char *s;
+	char *dest;
+	for (cnt=1, s=src; s && *s; s++) {
+		if (*s == '\\') s++;
+		cnt++;
+	}
+	dest = malloc(cnt);
+	if (!dest) return GLOB_NOSPACE;
+	if (!(flags & GLOB_APPEND)) {
+		pglob->gl_pathv=NULL;
+		pglob->gl_pathc=0;
+		pglob->gl_offs=0;
+		pglob->gl_offs=0;
+	}
+	pathc = ++pglob->gl_pathc;
+	pglob->gl_pathv = realloc(pglob->gl_pathv, (pathc+1)*sizeof(*pglob->gl_pathv));
+	if (pglob->gl_pathv == NULL) return GLOB_NOSPACE;
+	pglob->gl_pathv[pathc-1]=dest;
+	pglob->gl_pathv[pathc]=NULL;
+	for (s=src; s && *s; s++, dest++) {
+		if (*s == '\\') s++;
+		*dest = *s;
+	}
+	*dest='\0';
+	return 0;
+}
+
+/* XXX broken if the last character is '\\', check that before calling */
+static int glob_needed(const char *s)
+{
+	for (; *s; s++) {
+		if (*s == '\\') s++;
+		if (strchr("*[?",*s)) return 1;
+	}
+	return 0;
+}
+
+#if 0
+static void globprint(glob_t *pglob)
+{
+	int i;
+	debug_printf("glob_t at %p:\n", pglob);
+	debug_printf("  gl_pathc=%d  gl_pathv=%p  gl_offs=%d  gl_flags=%d\n",
+		pglob->gl_pathc, pglob->gl_pathv, pglob->gl_offs, pglob->gl_flags);
+	for (i=0; i<pglob->gl_pathc; i++)
+		debug_printf("pglob->gl_pathv[%d] = %p = %s\n", i,
+			pglob->gl_pathv[i], pglob->gl_pathv[i]);
+}
+#endif
+
+static int xglob(o_string *dest, int flags, glob_t *pglob)
+{
+	int gr;
+
+	/* short-circuit for null word */
+	/* we can code this better when the debug_printf's are gone */
+	if (dest->length == 0) {
+		if (dest->nonnull) {
+			/* bash man page calls this an "explicit" null */
+			gr = globhack(dest->data, flags, pglob);
+			debug_printf("globhack returned %d\n",gr);
+		} else {
+			return 0;
+		}
+	} else if (glob_needed(dest->data)) {
+		gr = glob(dest->data, flags, NULL, pglob);
+		debug_printf("glob returned %d\n",gr);
+		if (gr == GLOB_NOMATCH) {
+			/* quote removal, or more accurately, backslash removal */
+			gr = globhack(dest->data, flags, pglob);
+			debug_printf("globhack returned %d\n",gr);
+		}
+	} else {
+		gr = globhack(dest->data, flags, pglob);
+		debug_printf("globhack returned %d\n",gr);
+	}
+	if (gr == GLOB_NOSPACE)
+		bb_error_msg_and_die("out of memory during glob");
+	if (gr != 0) { /* GLOB_ABORTED ? */
+		bb_error_msg("glob(3) error %d",gr);
+	}
+	/* globprint(glob_target); */
+	return gr;
+}
+
+/* This is used to get/check local shell variables */
+static char *get_local_var(const char *s)
+{
+	struct variables *cur;
+
+	if (!s)
+		return NULL;
+	for (cur = top_vars; cur; cur=cur->next)
+		if(strcmp(cur->name, s)==0)
+			return cur->value;
+	return NULL;
+}
+
+/* This is used to set local shell variables
+   flg_export==0 if only local (not exporting) variable
+   flg_export==1 if "new" exporting environ
+   flg_export>1  if current startup environ (not call putenv()) */
+static int set_local_var(const char *s, int flg_export)
+{
+	char *name, *value;
+	int result=0;
+	struct variables *cur;
+
+	name=strdup(s);
+
+	/* Assume when we enter this function that we are already in
+	 * NAME=VALUE format.  So the first order of business is to
+	 * split 's' on the '=' into 'name' and 'value' */
+	value = strchr(name, '=');
+	if (value==0 && ++value==0) {
+		free(name);
+		return -1;
+	}
+	*value++ = 0;
+
+	for(cur = top_vars; cur; cur = cur->next) {
+		if(strcmp(cur->name, name)==0)
+			break;
+	}
+
+	if(cur) {
+		if(strcmp(cur->value, value)==0) {
+			if(flg_export>0 && cur->flg_export==0)
+				cur->flg_export=flg_export;
+			else
+				result++;
+		} else {
+			if(cur->flg_read_only) {
+				bb_error_msg("%s: readonly variable", name);
+				result = -1;
+			} else {
+				if(flg_export>0 || cur->flg_export>1)
+					cur->flg_export=1;
+				free(cur->value);
+
+				cur->value = strdup(value);
+			}
+		}
+	} else {
+		cur = malloc(sizeof(struct variables));
+		if(!cur) {
+			result = -1;
+		} else {
+			cur->name = strdup(name);
+			if(cur->name == 0) {
+				free(cur);
+				result = -1;
+			} else {
+				struct variables *bottom = top_vars;
+				cur->value = strdup(value);
+				cur->next = 0;
+				cur->flg_export = flg_export;
+				cur->flg_read_only = 0;
+				while(bottom->next) bottom=bottom->next;
+				bottom->next = cur;
+			}
+		}
+	}
+
+	if(result==0 && cur->flg_export==1) {
+		*(value-1) = '=';
+		result = putenv(name);
+	} else {
+		free(name);
+		if(result>0)            /* equivalent to previous set */
+			result = 0;
+	}
+	return result;
+}
+
+static void unset_local_var(const char *name)
+{
+	struct variables *cur;
+
+	if (name) {
+		for (cur = top_vars; cur; cur=cur->next) {
+			if(strcmp(cur->name, name)==0)
+				break;
+		}
+		if(cur!=0) {
+			struct variables *next = top_vars;
+			if(cur->flg_read_only) {
+				bb_error_msg("%s: readonly variable", name);
+				return;
+			} else {
+				if(cur->flg_export)
+					unsetenv(cur->name);
+				free(cur->name);
+				free(cur->value);
+				while (next->next != cur)
+					next = next->next;
+				next->next = cur->next;
+			}
+			free(cur);
+		}
+	}
+}
+
+static int is_assignment(const char *s)
+{
+	if (s==NULL || !isalpha(*s)) return 0;
+	++s;
+	while(isalnum(*s) || *s=='_') ++s;
+	return *s=='=';
+}
+
+/* the src parameter allows us to peek forward to a possible &n syntax
+ * for file descriptor duplication, e.g., "2>&1".
+ * Return code is 0 normally, 1 if a syntax error is detected in src.
+ * Resource errors (in xmalloc) cause the process to exit */
+static int setup_redirect(struct p_context *ctx, int fd, redir_type style,
+	struct in_str *input)
+{
+	struct child_prog *child=ctx->child;
+	struct redir_struct *redir = child->redirects;
+	struct redir_struct *last_redir=NULL;
+
+	/* Create a new redir_struct and drop it onto the end of the linked list */
+	while(redir) {
+		last_redir=redir;
+		redir=redir->next;
+	}
+	redir = xmalloc(sizeof(struct redir_struct));
+	redir->next=NULL;
+	redir->word.gl_pathv=NULL;
+	if (last_redir) {
+		last_redir->next=redir;
+	} else {
+		child->redirects=redir;
+	}
+
+	redir->type=style;
+	redir->fd= (fd==-1) ? redir_table[style].default_fd : fd ;
+
+	debug_printf("Redirect type %d%s\n", redir->fd, redir_table[style].descrip);
+
+	/* Check for a '2>&1' type redirect */
+	redir->dup = redirect_dup_num(input);
+	if (redir->dup == -2) return 1;  /* syntax error */
+	if (redir->dup != -1) {
+		/* Erik had a check here that the file descriptor in question
+		 * is legit; I postpone that to "run time"
+		 * A "-" representation of "close me" shows up as a -3 here */
+		debug_printf("Duplicating redirect '%d>&%d'\n", redir->fd, redir->dup);
+	} else {
+		/* We do _not_ try to open the file that src points to,
+		 * since we need to return and let src be expanded first.
+		 * Set ctx->pending_redirect, so we know what to do at the
+		 * end of the next parsed word.
+		 */
+		ctx->pending_redirect = redir;
+	}
+	return 0;
+}
+
+static struct pipe *new_pipe(void) {
+	struct pipe *pi;
+	pi = xmalloc(sizeof(struct pipe));
+	pi->num_progs = 0;
+	pi->progs = NULL;
+	pi->next = NULL;
+	pi->followup = 0;  /* invalid */
+	pi->r_mode = RES_NONE;
+	return pi;
+}
+
+static void initialize_context(struct p_context *ctx)
+{
+	ctx->pipe=NULL;
+	ctx->pending_redirect=NULL;
+	ctx->child=NULL;
+	ctx->list_head=new_pipe();
+	ctx->pipe=ctx->list_head;
+	ctx->w=RES_NONE;
+	ctx->stack=NULL;
+	ctx->old_flag=0;
+	done_command(ctx);   /* creates the memory for working child */
+}
+
+/* normal return is 0
+ * if a reserved word is found, and processed, return 1
+ * should handle if, then, elif, else, fi, for, while, until, do, done.
+ * case, function, and select are obnoxious, save those for later.
+ */
+static int reserved_word(o_string *dest, struct p_context *ctx)
+{
+	struct reserved_combo {
+		char *literal;
+		int code;
+		long flag;
+	};
+	/* Mostly a list of accepted follow-up reserved words.
+	 * FLAG_END means we are done with the sequence, and are ready
+	 * to turn the compound list into a command.
+	 * FLAG_START means the word must start a new compound list.
+	 */
+	static struct reserved_combo reserved_list[] = {
+		{ "if",    RES_IF,    FLAG_THEN | FLAG_START },
+		{ "then",  RES_THEN,  FLAG_ELIF | FLAG_ELSE | FLAG_FI },
+		{ "elif",  RES_ELIF,  FLAG_THEN },
+		{ "else",  RES_ELSE,  FLAG_FI   },
+		{ "fi",    RES_FI,    FLAG_END  },
+		{ "for",   RES_FOR,   FLAG_IN   | FLAG_START },
+		{ "while", RES_WHILE, FLAG_DO   | FLAG_START },
+		{ "until", RES_UNTIL, FLAG_DO   | FLAG_START },
+		{ "in",    RES_IN,    FLAG_DO   },
+		{ "do",    RES_DO,    FLAG_DONE },
+		{ "done",  RES_DONE,  FLAG_END  }
+	};
+	struct reserved_combo *r;
+	for (r=reserved_list;
+#define NRES sizeof(reserved_list)/sizeof(struct reserved_combo)
+		r<reserved_list+NRES; r++) {
+		if (strcmp(dest->data, r->literal) == 0) {
+			debug_printf("found reserved word %s, code %d\n",r->literal,r->code);
+			if (r->flag & FLAG_START) {
+				struct p_context *new = xmalloc(sizeof(struct p_context));
+				debug_printf("push stack\n");
+				if (ctx->w == RES_IN || ctx->w == RES_FOR) {
+					syntax();
+					free(new);
+					ctx->w = RES_SNTX;
+					b_reset(dest);
+					return 1;
+				}
+				*new = *ctx;   /* physical copy */
+				initialize_context(ctx);
+				ctx->stack=new;
+			} else if ( ctx->w == RES_NONE || ! (ctx->old_flag & (1<<r->code))) {
+				syntax();
+				ctx->w = RES_SNTX;
+				b_reset(dest);
+				return 1;
+			}
+			ctx->w=r->code;
+			ctx->old_flag = r->flag;
+			if (ctx->old_flag & FLAG_END) {
+				struct p_context *old;
+				debug_printf("pop stack\n");
+				done_pipe(ctx,PIPE_SEQ);
+				old = ctx->stack;
+				old->child->group = ctx->list_head;
+				old->child->subshell = 0;
+				*ctx = *old;   /* physical copy */
+				free(old);
+			}
+			b_reset (dest);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/* normal return is 0.
+ * Syntax or xglob errors return 1. */
+static int done_word(o_string *dest, struct p_context *ctx)
+{
+	struct child_prog *child=ctx->child;
+	glob_t *glob_target;
+	int gr, flags = 0;
+
+	debug_printf("done_word: %s %p\n", dest->data, child);
+	if (dest->length == 0 && !dest->nonnull) {
+		debug_printf("  true null, ignored\n");
+		return 0;
+	}
+	if (ctx->pending_redirect) {
+		glob_target = &ctx->pending_redirect->word;
+	} else {
+		if (child->group) {
+			syntax();
+			return 1;  /* syntax error, groups and arglists don't mix */
+		}
+		if (!child->argv && (ctx->type & FLAG_PARSE_SEMICOLON)) {
+			debug_printf("checking %s for reserved-ness\n",dest->data);
+			if (reserved_word(dest,ctx)) return ctx->w==RES_SNTX;
+		}
+		glob_target = &child->glob_result;
+		if (child->argv) flags |= GLOB_APPEND;
+	}
+	gr = xglob(dest, flags, glob_target);
+	if (gr != 0) return 1;
+
+	b_reset(dest);
+	if (ctx->pending_redirect) {
+		ctx->pending_redirect=NULL;
+		if (glob_target->gl_pathc != 1) {
+			bb_error_msg("ambiguous redirect");
+			return 1;
+		}
+	} else {
+		child->argv = glob_target->gl_pathv;
+	}
+	if (ctx->w == RES_FOR) {
+		done_word(dest,ctx);
+		done_pipe(ctx,PIPE_SEQ);
+	}
+	return 0;
+}
+
+/* The only possible error here is out of memory, in which case
+ * xmalloc exits. */
+static int done_command(struct p_context *ctx)
+{
+	/* The child is really already in the pipe structure, so
+	 * advance the pipe counter and make a new, null child.
+	 * Only real trickiness here is that the uncommitted
+	 * child structure, to which ctx->child points, is not
+	 * counted in pi->num_progs. */
+	struct pipe *pi=ctx->pipe;
+	struct child_prog *prog=ctx->child;
+
+	if (prog && prog->group == NULL
+	         && prog->argv == NULL
+	         && prog->redirects == NULL) {
+		debug_printf("done_command: skipping null command\n");
+		return 0;
+	} else if (prog) {
+		pi->num_progs++;
+		debug_printf("done_command: num_progs incremented to %d\n",pi->num_progs);
+	} else {
+		debug_printf("done_command: initializing\n");
+	}
+	pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs+1));
+
+	prog = pi->progs + pi->num_progs;
+	prog->redirects = NULL;
+	prog->argv = NULL;
+	prog->is_stopped = 0;
+	prog->group = NULL;
+	prog->glob_result.gl_pathv = NULL;
+	prog->family = pi;
+	prog->sp = 0;
+	ctx->child = prog;
+	prog->type = ctx->type;
+
+	/* but ctx->pipe and ctx->list_head remain unchanged */
+	return 0;
+}
+
+static int done_pipe(struct p_context *ctx, pipe_style type)
+{
+	struct pipe *new_p;
+	done_command(ctx);  /* implicit closure of previous command */
+	debug_printf("done_pipe, type %d\n", type);
+	ctx->pipe->followup = type;
+	ctx->pipe->r_mode = ctx->w;
+	new_p=new_pipe();
+	ctx->pipe->next = new_p;
+	ctx->pipe = new_p;
+	ctx->child = NULL;
+	done_command(ctx);  /* set up new pipe to accept commands */
+	return 0;
+}
+
+/* peek ahead in the in_str to find out if we have a "&n" construct,
+ * as in "2>&1", that represents duplicating a file descriptor.
+ * returns either -2 (syntax error), -1 (no &), or the number found.
+ */
+static int redirect_dup_num(struct in_str *input)
+{
+	int ch, d=0, ok=0;
+	ch = b_peek(input);
+	if (ch != '&') return -1;
+
+	b_getch(input);  /* get the & */
+	ch=b_peek(input);
+	if (ch == '-') {
+		b_getch(input);
+		return -3;  /* "-" represents "close me" */
+	}
+	while (isdigit(ch)) {
+		d = d*10+(ch-'0');
+		ok=1;
+		b_getch(input);
+		ch = b_peek(input);
+	}
+	if (ok) return d;
+
+	bb_error_msg("ambiguous redirect");
+	return -2;
+}
+
+/* If a redirect is immediately preceded by a number, that number is
+ * supposed to tell which file descriptor to redirect.  This routine
+ * looks for such preceding numbers.  In an ideal world this routine
+ * needs to handle all the following classes of redirects...
+ *     echo 2>foo     # redirects fd  2 to file "foo", nothing passed to echo
+ *     echo 49>foo    # redirects fd 49 to file "foo", nothing passed to echo
+ *     echo -2>foo    # redirects fd  1 to file "foo",    "-2" passed to echo
+ *     echo 49x>foo   # redirects fd  1 to file "foo",   "49x" passed to echo
+ * A -1 output from this program means no valid number was found, so the
+ * caller should use the appropriate default for this redirection.
+ */
+static int redirect_opt_num(o_string *o)
+{
+	int num;
+
+	if (o->length==0) return -1;
+	for(num=0; num<o->length; num++) {
+		if (!isdigit(*(o->data+num))) {
+			return -1;
+		}
+	}
+	/* reuse num (and save an int) */
+	num=atoi(o->data);
+	b_reset(o);
+	return num;
+}
+
+static FILE *generate_stream_from_list(struct pipe *head)
+{
+	FILE *pf;
+#if 1
+	int pid, channel[2];
+	if (pipe(channel)<0) bb_perror_msg_and_die("pipe");
+#if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__)
+	pid=fork();
+#else
+	pid=vfork();
+#endif
+	if (pid<0) {
+		bb_perror_msg_and_die("fork");
+	} else if (pid==0) {
+		close(channel[0]);
+		if (channel[1] != 1) {
+			dup2(channel[1],1);
+			close(channel[1]);
+		}
+#if 0
+#define SURROGATE "surrogate response"
+		write(1,SURROGATE,sizeof(SURROGATE));
+		_exit(run_list(head));
+#else
+		_exit(run_list_real(head));   /* leaks memory */
+#endif
+	}
+	debug_printf("forked child %d\n",pid);
+	close(channel[1]);
+	pf = fdopen(channel[0],"r");
+	debug_printf("pipe on FILE *%p\n",pf);
+#else
+	free_pipe_list(head,0);
+	pf=popen("echo surrogate response","r");
+	debug_printf("started fake pipe on FILE *%p\n",pf);
+#endif
+	return pf;
+}
+
+/* this version hacked for testing purposes */
+/* return code is exit status of the process that is run. */
+static int process_command_subs(o_string *dest, struct p_context *ctx, struct in_str *input, int subst_end)
+{
+	int retcode;
+	o_string result=NULL_O_STRING;
+	struct p_context inner;
+	FILE *p;
+	struct in_str pipe_str;
+	initialize_context(&inner);
+
+	/* recursion to generate command */
+	retcode = parse_stream(&result, &inner, input, subst_end);
+	if (retcode != 0) return retcode;  /* syntax error or EOF */
+	done_word(&result, &inner);
+	done_pipe(&inner, PIPE_SEQ);
+	b_free(&result);
+
+	p=generate_stream_from_list(inner.list_head);
+	if (p==NULL) return 1;
+	mark_open(fileno(p));
+	setup_file_in_str(&pipe_str, p);
+
+	/* now send results of command back into original context */
+	retcode = parse_stream(dest, ctx, &pipe_str, '\0');
+	/* XXX In case of a syntax error, should we try to kill the child?
+	 * That would be tough to do right, so just read until EOF. */
+	if (retcode == 1) {
+		while (b_getch(&pipe_str)!=EOF) { /* discard */ };
+	}
+
+	debug_printf("done reading from pipe, pclose()ing\n");
+	/* This is the step that wait()s for the child.  Should be pretty
+	 * safe, since we just read an EOF from its stdout.  We could try
+	 * to better, by using wait(), and keeping track of background jobs
+	 * at the same time.  That would be a lot of work, and contrary
+	 * to the KISS philosophy of this program. */
+	mark_closed(fileno(p));
+	retcode=pclose(p);
+	free_pipe_list(inner.list_head,0);
+	debug_printf("pclosed, retcode=%d\n",retcode);
+	/* XXX this process fails to trim a single trailing newline */
+	return retcode;
+}
+
+static int parse_group(o_string *dest, struct p_context *ctx,
+	struct in_str *input, int ch)
+{
+	int rcode, endch=0;
+	struct p_context sub;
+	struct child_prog *child = ctx->child;
+	if (child->argv) {
+		syntax();
+		return 1;  /* syntax error, groups and arglists don't mix */
+	}
+	initialize_context(&sub);
+	switch(ch) {
+		case '(': endch=')'; child->subshell=1; break;
+		case '{': endch='}'; break;
+		default: syntax();   /* really logic error */
+	}
+	rcode=parse_stream(dest,&sub,input,endch);
+	done_word(dest,&sub); /* finish off the final word in the subcontext */
+	done_pipe(&sub, PIPE_SEQ);  /* and the final command there, too */
+	child->group = sub.list_head;
+	return rcode;
+	/* child remains "open", available for possible redirects */
+}
+
+/* basically useful version until someone wants to get fancier,
+ * see the bash man page under "Parameter Expansion" */
+static char *lookup_param(char *src)
+{
+	char *p=NULL;
+	if (src) {
+		p = getenv(src);
+		if (!p)
+			p = get_local_var(src);
+	}
+	return p;
+}
+
+/* return code: 0 for OK, 1 for syntax error */
+static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input)
+{
+	int i, advance=0;
+	char sep[]=" ";
+	int ch = input->peek(input);  /* first character after the $ */
+	debug_printf("handle_dollar: ch=%c\n",ch);
+	if (isalpha(ch)) {
+		b_addchr(dest, SPECIAL_VAR_SYMBOL);
+		ctx->child->sp++;
+		while(ch=b_peek(input),isalnum(ch) || ch=='_') {
+			b_getch(input);
+			b_addchr(dest,ch);
+		}
+		b_addchr(dest, SPECIAL_VAR_SYMBOL);
+	} else if (isdigit(ch)) {
+		i = ch-'0';  /* XXX is $0 special? */
+		if (i<global_argc) {
+			parse_string(dest, ctx, global_argv[i]); /* recursion */
+		}
+		advance = 1;
+	} else switch (ch) {
+		case '$':
+			b_adduint(dest,getpid());
+			advance = 1;
+			break;
+		case '!':
+			if (last_bg_pid > 0) b_adduint(dest, last_bg_pid);
+			advance = 1;
+			break;
+		case '?':
+			b_adduint(dest,last_return_code);
+			advance = 1;
+			break;
+		case '#':
+			b_adduint(dest,global_argc ? global_argc-1 : 0);
+			advance = 1;
+			break;
+		case '{':
+			b_addchr(dest, SPECIAL_VAR_SYMBOL);
+			ctx->child->sp++;
+			b_getch(input);
+			/* XXX maybe someone will try to escape the '}' */
+			while(ch=b_getch(input),ch!=EOF && ch!='}') {
+				b_addchr(dest,ch);
+			}
+			if (ch != '}') {
+				syntax();
+				return 1;
+			}
+			b_addchr(dest, SPECIAL_VAR_SYMBOL);
+			break;
+		case '(':
+			b_getch(input);
+			process_command_subs(dest, ctx, input, ')');
+			break;
+		case '*':
+			sep[0]=ifs[0];
+			for (i=1; i<global_argc; i++) {
+				parse_string(dest, ctx, global_argv[i]);
+				if (i+1 < global_argc) parse_string(dest, ctx, sep);
+			}
+			break;
+		case '@':
+		case '-':
+		case '_':
+			/* still unhandled, but should be eventually */
+			bb_error_msg("unhandled syntax: $%c",ch);
+			return 1;
+			break;
+		default:
+			b_addqchr(dest,'$',dest->quote);
+	}
+	/* Eat the character if the flag was set.  If the compiler
+	 * is smart enough, we could substitute "b_getch(input);"
+	 * for all the "advance = 1;" above, and also end up with
+	 * a nice size-optimized program.  Hah!  That'll be the day.
+	 */
+	if (advance) b_getch(input);
+	return 0;
+}
+
+int parse_string(o_string *dest, struct p_context *ctx, const char *src)
+{
+	struct in_str foo;
+	setup_string_in_str(&foo, src);
+	return parse_stream(dest, ctx, &foo, '\0');
+}
+
+/* return code is 0 for normal exit, 1 for syntax error */
+int parse_stream(o_string *dest, struct p_context *ctx,
+	struct in_str *input, int end_trigger)
+{
+	int ch, m;
+	int redir_fd;
+	redir_type redir_style;
+	int next;
+
+	/* Only double-quote state is handled in the state variable dest->quote.
+	 * A single-quote triggers a bypass of the main loop until its mate is
+	 * found.  When recursing, quote state is passed in via dest->quote. */
+
+	debug_printf("parse_stream, end_trigger=%d\n",end_trigger);
+	while ((ch=b_getch(input))!=EOF) {
+		m = map[ch];
+		next = (ch == '\n') ? 0 : b_peek(input);
+		debug_printf("parse_stream: ch=%c (%d) m=%d quote=%d\n",
+			ch,ch,m,dest->quote);
+		if (m==0 || ((m==1 || m==2) && dest->quote)) {
+			b_addqchr(dest, ch, dest->quote);
+		} else {
+			if (m==2) {  /* unquoted IFS */
+				if (done_word(dest, ctx)) {
+					return 1;
+				}
+				/* If we aren't performing a substitution, treat a newline as a
+				 * command separator.  */
+				if (end_trigger != '\0' && ch=='\n')
+					done_pipe(ctx,PIPE_SEQ);
+			}
+			if (ch == end_trigger && !dest->quote && ctx->w==RES_NONE) {
+				debug_printf("leaving parse_stream (triggered)\n");
+				return 0;
+			}
+#if 0
+			if (ch=='\n') {
+				/* Yahoo!  Time to run with it! */
+				done_pipe(ctx,PIPE_SEQ);
+				run_list(ctx->list_head);
+				initialize_context(ctx);
+			}
+#endif
+			if (m!=2) switch (ch) {
+		case '#':
+			if (dest->length == 0 && !dest->quote) {
+				while(ch=b_peek(input),ch!=EOF && ch!='\n') { b_getch(input); }
+			} else {
+				b_addqchr(dest, ch, dest->quote);
+			}
+			break;
+		case '\\':
+			if (next == EOF) {
+				syntax();
+				return 1;
+			}
+			b_addqchr(dest, '\\', dest->quote);
+			b_addqchr(dest, b_getch(input), dest->quote);
+			break;
+		case '$':
+			if (handle_dollar(dest, ctx, input)!=0) return 1;
+			break;
+		case '\'':
+			dest->nonnull = 1;
+			while(ch=b_getch(input),ch!=EOF && ch!='\'') {
+				b_addchr(dest,ch);
+			}
+			if (ch==EOF) {
+				syntax();
+				return 1;
+			}
+			break;
+		case '"':
+			dest->nonnull = 1;
+			dest->quote = !dest->quote;
+			break;
+		case '`':
+			process_command_subs(dest, ctx, input, '`');
+			break;
+		case '>':
+			redir_fd = redirect_opt_num(dest);
+			done_word(dest, ctx);
+			redir_style=REDIRECT_OVERWRITE;
+			if (next == '>') {
+				redir_style=REDIRECT_APPEND;
+				b_getch(input);
+			} else if (next == '(') {
+				syntax();   /* until we support >(list) Process Substitution */
+				return 1;
+			}
+			setup_redirect(ctx, redir_fd, redir_style, input);
+			break;
+		case '<':
+			redir_fd = redirect_opt_num(dest);
+			done_word(dest, ctx);
+			redir_style=REDIRECT_INPUT;
+			if (next == '<') {
+				redir_style=REDIRECT_HEREIS;
+				b_getch(input);
+			} else if (next == '>') {
+				redir_style=REDIRECT_IO;
+				b_getch(input);
+			} else if (next == '(') {
+				syntax();   /* until we support <(list) Process Substitution */
+				return 1;
+			}
+			setup_redirect(ctx, redir_fd, redir_style, input);
+			break;
+		case ';':
+			done_word(dest, ctx);
+			done_pipe(ctx,PIPE_SEQ);
+			break;
+		case '&':
+			done_word(dest, ctx);
+			if (next=='&') {
+				b_getch(input);
+				done_pipe(ctx,PIPE_AND);
+			} else {
+				done_pipe(ctx,PIPE_BG);
+			}
+			break;
+		case '|':
+			done_word(dest, ctx);
+			if (next=='|') {
+				b_getch(input);
+				done_pipe(ctx,PIPE_OR);
+			} else {
+				/* we could pick up a file descriptor choice here
+				 * with redirect_opt_num(), but bash doesn't do it.
+				 * "echo foo 2| cat" yields "foo 2". */
+				done_command(ctx);
+			}
+			break;
+		case '(':
+		case '{':
+			if (parse_group(dest, ctx, input, ch)!=0) return 1;
+			break;
+		case ')':
+		case '}':
+			syntax();   /* Proper use of this character caught by end_trigger */
+			return 1;
+			break;
+		default:
+			syntax();   /* this is really an internal logic error */
+			return 1;
+			}
+		}
+	}
+	/* complain if quote?  No, maybe we just finished a command substitution
+	 * that was quoted.  Example:
+	 * $ echo "`cat foo` plus more"
+	 * and we just got the EOF generated by the subshell that ran "cat foo"
+	 * The only real complaint is if we got an EOF when end_trigger != '\0',
+	 * that is, we were really supposed to get end_trigger, and never got
+	 * one before the EOF.  Can't use the standard "syntax error" return code,
+	 * so that parse_stream_outer can distinguish the EOF and exit smoothly. */
+	debug_printf("leaving parse_stream (EOF)\n");
+	if (end_trigger != '\0') return -1;
+	return 0;
+}
+
+static void mapset(const char *set, int code)
+{
+	const unsigned char *s;
+	for (s = (const unsigned char *)set; *s; s++) map[(int)*s] = code;
+}
+
+static void update_ifs_map(void)
+{
+	/* char *ifs and char map[256] are both globals. */
+	ifs = getenv("IFS");
+	if (ifs == NULL) ifs=" \t\n";
+	/* Precompute a list of 'flow through' behavior so it can be treated
+	 * quickly up front.  Computation is necessary because of IFS.
+	 * Special case handling of IFS == " \t\n" is not implemented.
+	 * The map[] array only really needs two bits each, and on most machines
+	 * that would be faster because of the reduced L1 cache footprint.
+	 */
+	memset(map,0,sizeof(map)); /* most characters flow through always */
+	mapset("\\$'\"`", 3);      /* never flow through */
+	mapset("<>;&|(){}#", 1);   /* flow through if quoted */
+	mapset(ifs, 2);            /* also flow through if quoted */
+}
+
+/* most recursion does not come through here, the exception is
+ * from builtin_source() */
+int parse_stream_outer(struct in_str *inp, int flag)
+{
+
+	struct p_context ctx;
+	o_string temp=NULL_O_STRING;
+	int rcode;
+	do {
+		ctx.type = flag;
+		initialize_context(&ctx);
+		update_ifs_map();
+		if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING)) mapset(";$&|", 0);
+		inp->promptmode=1;
+		rcode = parse_stream(&temp, &ctx, inp, '\n');
+		if (rcode != 1 && ctx.old_flag != 0) {
+			syntax();
+		}
+		if (rcode != 1 && ctx.old_flag == 0) {
+			done_word(&temp, &ctx);
+			done_pipe(&ctx,PIPE_SEQ);
+			run_list(ctx.list_head);
+		} else {
+			if (ctx.old_flag != 0) {
+				free(ctx.stack);
+				b_reset(&temp);
+			}
+			temp.nonnull = 0;
+			temp.quote = 0;
+			inp->p = NULL;
+			free_pipe_list(ctx.list_head,0);
+		}
+		b_free(&temp);
+	} while (rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP));   /* loop on syntax errors, return on EOF */
+	return 0;
+}
+
+static int parse_string_outer(const char *s, int flag)
+{
+	struct in_str input;
+	setup_string_in_str(&input, s);
+	return parse_stream_outer(&input, flag);
+}
+
+static int parse_file_outer(FILE *f)
+{
+	int rcode;
+	struct in_str input;
+	setup_file_in_str(&input, f);
+	rcode = parse_stream_outer(&input, FLAG_PARSE_SEMICOLON);
+	return rcode;
+}
+
+/* Make sure we have a controlling tty.  If we get started under a job
+ * aware app (like bash for example), make sure we are now in charge so
+ * we don't fight over who gets the foreground */
+static void setup_job_control(void)
+{
+	static pid_t shell_pgrp;
+	/* Loop until we are in the foreground.  */
+	while (tcgetpgrp (shell_terminal) != (shell_pgrp = getpgrp ()))
+		kill (- shell_pgrp, SIGTTIN);
+
+	/* Ignore interactive and job-control signals.  */
+	signal(SIGINT, SIG_IGN);
+	signal(SIGQUIT, SIG_IGN);
+	signal(SIGTERM, SIG_IGN);
+	signal(SIGTSTP, SIG_IGN);
+	signal(SIGTTIN, SIG_IGN);
+	signal(SIGTTOU, SIG_IGN);
+	signal(SIGCHLD, SIG_IGN);
+
+	/* Put ourselves in our own process group.  */
+	setsid();
+	shell_pgrp = getpid ();
+	setpgid (shell_pgrp, shell_pgrp);
+
+	/* Grab control of the terminal.  */
+	tcsetpgrp(shell_terminal, shell_pgrp);
+}
+
+int hush_main(int argc, char **argv)
+{
+	int opt;
+	FILE *input;
+	char **e = environ;
+
+	/* XXX what should these be while sourcing /etc/profile? */
+	global_argc = argc;
+	global_argv = argv;
+
+	/* (re?) initialize globals.  Sometimes hush_main() ends up calling
+	 * hush_main(), therefore we cannot rely on the BSS to zero out this
+	 * stuff.  Reset these to 0 every time. */
+	ifs = NULL;
+	/* map[] is taken care of with call to update_ifs_map() */
+	fake_mode = 0;
+	interactive = 0;
+	close_me_head = NULL;
+	last_bg_pid = 0;
+	job_list = NULL;
+	last_jobid = 0;
+
+	/* Initialize some more globals to non-zero values */
+	set_cwd();
+#ifdef CONFIG_FEATURE_COMMAND_EDITING
+	cmdedit_set_initial_prompt();
+#else
+	PS1 = NULL;
+#endif
+	PS2 = "> ";
+
+	/* initialize our shell local variables with the values
+	 * currently living in the environment */
+	if (e) {
+		for (; *e; e++)
+			set_local_var(*e, 2);   /* without call putenv() */
+	}
+
+	last_return_code=EXIT_SUCCESS;
+
+
+	if (argv[0] && argv[0][0] == '-') {
+		debug_printf("\nsourcing /etc/profile\n");
+		if ((input = fopen("/etc/profile", "r")) != NULL) {
+			mark_open(fileno(input));
+			parse_file_outer(input);
+			mark_closed(fileno(input));
+			fclose(input);
+		}
+	}
+	input=stdin;
+
+	while ((opt = getopt(argc, argv, "c:xif")) > 0) {
+		switch (opt) {
+			case 'c':
+				{
+					global_argv = argv+optind;
+					global_argc = argc-optind;
+					opt = parse_string_outer(optarg, FLAG_PARSE_SEMICOLON);
+					goto final_return;
+				}
+				break;
+			case 'i':
+				interactive++;
+				break;
+			case 'f':
+				fake_mode++;
+				break;
+			default:
+#ifndef BB_VER
+				fprintf(stderr, "Usage: sh [FILE]...\n"
+						"   or: sh -c command [args]...\n\n");
+				exit(EXIT_FAILURE);
+#else
+				bb_show_usage();
+#endif
+		}
+	}
+	/* A shell is interactive if the `-i' flag was given, or if all of
+	 * the following conditions are met:
+	 *	  no -c command
+	 *    no arguments remaining or the -s flag given
+	 *    standard input is a terminal
+	 *    standard output is a terminal
+	 *    Refer to Posix.2, the description of the `sh' utility. */
+	if (argv[optind]==NULL && input==stdin &&
+			isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
+		interactive++;
+	}
+
+	debug_printf("\ninteractive=%d\n", interactive);
+	if (interactive) {
+		/* Looks like they want an interactive shell */
+#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
+		printf( "\n\n%s hush - the humble shell v0.01 (testing)\n",
+			BB_BANNER);
+		printf( "Enter 'help' for a list of built-in commands.\n\n");
+#endif
+		setup_job_control();
+	}
+
+	if (argv[optind]==NULL) {
+		opt=parse_file_outer(stdin);
+		goto final_return;
+	}
+
+	debug_printf("\nrunning script '%s'\n", argv[optind]);
+	global_argv = argv+optind;
+	global_argc = argc-optind;
+	input = bb_xfopen(argv[optind], "r");
+	opt = parse_file_outer(input);
+
+#ifdef CONFIG_FEATURE_CLEAN_UP
+	fclose(input);
+	if (cwd && cwd != bb_msg_unknown)
+		free((char*)cwd);
+	{
+		struct variables *cur, *tmp;
+		for(cur = top_vars; cur; cur = tmp) {
+			tmp = cur->next;
+			if (!cur->flg_read_only) {
+				free(cur->name);
+				free(cur->value);
+				free(cur);
+			}
+		}
+	}
+#endif
+
+final_return:
+	return(opt?opt:last_return_code);
+}
+
+static char *insert_var_value(char *inp)
+{
+	int res_str_len = 0;
+	int len;
+	int done = 0;
+	char *p, *p1, *res_str = NULL;
+
+	while ((p = strchr(inp, SPECIAL_VAR_SYMBOL))) {
+		if (p != inp) {
+			len = p - inp;
+			res_str = xrealloc(res_str, (res_str_len + len));
+			strncpy((res_str + res_str_len), inp, len);
+			res_str_len += len;
+		}
+		inp = ++p;
+		p = strchr(inp, SPECIAL_VAR_SYMBOL);
+		*p = '\0';
+		if ((p1 = lookup_param(inp))) {
+			len = res_str_len + strlen(p1);
+			res_str = xrealloc(res_str, (1 + len));
+			strcpy((res_str + res_str_len), p1);
+			res_str_len = len;
+		}
+		*p = SPECIAL_VAR_SYMBOL;
+		inp = ++p;
+		done = 1;
+	}
+	if (done) {
+		res_str = xrealloc(res_str, (1 + res_str_len + strlen(inp)));
+		strcpy((res_str + res_str_len), inp);
+		while ((p = strchr(res_str, '\n'))) {
+			*p = ' ';
+		}
+	}
+	return (res_str == NULL) ? inp : res_str;
+}
+
+static char **make_list_in(char **inp, char *name)
+{
+	int len, i;
+	int name_len = strlen(name);
+	int n = 0;
+	char **list;
+	char *p1, *p2, *p3;
+
+	/* create list of variable values */
+	list = xmalloc(sizeof(*list));
+	for (i = 0; inp[i]; i++) {
+		p3 = insert_var_value(inp[i]);
+		p1 = p3;
+		while (*p1) {
+			if ((*p1 == ' ')) {
+				p1++;
+				continue;
+			}
+			if ((p2 = strchr(p1, ' '))) {
+				len = p2 - p1;
+			} else {
+				len = strlen(p1);
+				p2 = p1 + len;
+			}
+			/* we use n + 2 in realloc for list,because we add
+			 * new element and then we will add NULL element */
+			list = xrealloc(list, sizeof(*list) * (n + 2));
+			list[n] = xmalloc(2 + name_len + len);
+			strcpy(list[n], name);
+			strcat(list[n], "=");
+			strncat(list[n], p1, len);
+			list[n++][name_len + len + 1] = '\0';
+			p1 = p2;
+		}
+		if (p3 != inp[i]) free(p3);
+	}
+	list[n] = NULL;
+	return list;
+}
+
+/* Make new string for parser */
+static char * make_string(char ** inp)
+{
+	char *p;
+	char *str = NULL;
+	int n;
+	int len = 2;
+
+	for (n = 0; inp[n]; n++) {
+		p = insert_var_value(inp[n]);
+		str = xrealloc(str, (len + strlen(p)));
+		if (n) {
+			strcat(str, " ");
+		} else {
+			*str = '\0';
+		}
+		strcat(str, p);
+		len = strlen(str) + 3;
+		if (p != inp[n]) free(p);
+	}
+	len = strlen(str);
+	*(str + len) = '\n';
+	*(str + len + 1) = '\0';
+	return str;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/lash.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/lash.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/lash.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1635 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * lash -- the BusyBox Lame-Ass SHell
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Based in part on ladsh.c by Michael K. Johnson and Erik W. Troan, which is
+ * under the following liberal license: "We have placed this source code in the
+ * public domain. Use it in any project, free or commercial."
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+/* This shell's parsing engine is officially at a dead-end.  Future
+ * work shell work should be done using hush, msh, or ash.  This is
+ * still a very useful, small shell -- it just don't need any more
+ * features beyond what it already has...
+ */
+
+//For debugging/development on the shell only...
+//#define DEBUG_SHELL
+
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <termios.h>
+#include "cmdedit.h"
+
+#ifdef CONFIG_LOCALE_SUPPORT
+#include <locale.h>
+#endif
+
+#include <glob.h>
+#define expand_t	glob_t
+
+/* Always enable for the moment... */
+#define CONFIG_LASH_PIPE_N_REDIRECTS
+#define CONFIG_LASH_JOB_CONTROL
+
+static const int MAX_READ = 128;	/* size of input buffer for `read' builtin */
+#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
+
+
+#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
+enum redir_type { REDIRECT_INPUT, REDIRECT_OVERWRITE,
+	REDIRECT_APPEND
+};
+#endif
+
+enum {
+	DEFAULT_CONTEXT = 0x1,
+	IF_TRUE_CONTEXT = 0x2,
+	IF_FALSE_CONTEXT = 0x4,
+	THEN_EXP_CONTEXT = 0x8,
+	ELSE_EXP_CONTEXT = 0x10
+};
+
+#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
+struct redir_struct {
+	enum redir_type type;	/* type of redirection */
+	int fd;						/* file descriptor being redirected */
+	char *filename;				/* file to redirect fd to */
+};
+#endif
+
+struct child_prog {
+	pid_t pid;					/* 0 if exited */
+	char **argv;				/* program name and arguments */
+	int num_redirects;			/* elements in redirection array */
+	int is_stopped;				/* is the program currently running? */
+	struct job *family;			/* pointer back to the child's parent job */
+#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
+	struct redir_struct *redirects;	/* I/O redirects */
+#endif
+};
+
+struct jobset {
+	struct job *head;			/* head of list of running jobs */
+	struct job *fg;				/* current foreground job */
+};
+
+struct job {
+	int jobid;					/* job number */
+	int num_progs;				/* total number of programs in job */
+	int running_progs;			/* number of programs running */
+	char *text;					/* name of job */
+	char *cmdbuf;				/* buffer various argv's point into */
+	pid_t pgrp;					/* process group ID for the job */
+	struct child_prog *progs;	/* array of programs in job */
+	struct job *next;			/* to track background commands */
+	int stopped_progs;			/* number of programs alive, but stopped */
+	unsigned int job_context;	/* bitmask defining current context */
+	struct jobset *job_list;
+};
+
+struct built_in_command {
+	char *cmd;					/* name */
+	char *descr;				/* description */
+	int (*function) (struct child_prog *);	/* function ptr */
+};
+
+/* function prototypes for builtins */
+static int builtin_cd(struct child_prog *cmd);
+static int builtin_exec(struct child_prog *cmd);
+static int builtin_exit(struct child_prog *cmd);
+static int builtin_fg_bg(struct child_prog *cmd);
+static int builtin_help(struct child_prog *cmd);
+static int builtin_jobs(struct child_prog *dummy);
+static int builtin_pwd(struct child_prog *dummy);
+static int builtin_export(struct child_prog *cmd);
+static int builtin_source(struct child_prog *cmd);
+static int builtin_unset(struct child_prog *cmd);
+static int builtin_read(struct child_prog *cmd);
+
+
+/* function prototypes for shell stuff */
+static void checkjobs(struct jobset *job_list);
+static void remove_job(struct jobset *j_list, struct job *job);
+static int get_command(FILE * source, char *command);
+static int parse_command(char **command_ptr, struct job *job, int *inbg);
+static int run_command(struct job *newjob, int inbg, int outpipe[2]);
+static int pseudo_exec(struct child_prog *cmd) ATTRIBUTE_NORETURN;
+static int busy_loop(FILE * input);
+
+
+/* Table of built-in functions (these are non-forking builtins, meaning they
+ * can change global variables in the parent shell process but they will not
+ * work with pipes and redirects; 'unset foo | whatever' will not work) */
+static struct built_in_command bltins[] = {
+	{"bg", "Resume a job in the background", builtin_fg_bg},
+	{"cd", "Change working directory", builtin_cd},
+	{"exec", "Exec command, replacing this shell with the exec'd process", builtin_exec},
+	{"exit", "Exit from shell()", builtin_exit},
+	{"fg", "Bring job into the foreground", builtin_fg_bg},
+	{"jobs", "Lists the active jobs", builtin_jobs},
+	{"export", "Set environment variable", builtin_export},
+	{"unset", "Unset environment variable", builtin_unset},
+	{"read", "Input environment variable", builtin_read},
+	{".", "Source-in and run commands in a file", builtin_source},
+	/* to do: add ulimit */
+	{NULL, NULL, NULL}
+};
+
+/* Table of forking built-in functions (things that fork cannot change global
+ * variables in the parent process, such as the current working directory) */
+static struct built_in_command bltins_forking[] = {
+	{"pwd", "Print current directory", builtin_pwd},
+	{"help", "List shell built-in commands", builtin_help},
+	{NULL, NULL, NULL}
+};
+
+
+static int shell_context;  /* Type prompt trigger (PS1 or PS2) */
+
+
+/* Globals that are static to this file */
+static const char *cwd;
+static char *local_pending_command = NULL;
+static struct jobset job_list = { NULL, NULL };
+static int argc;
+static char **argv;
+static llist_t *close_me_list;
+static int last_return_code;
+static int last_bg_pid;
+static unsigned int last_jobid;
+static int shell_terminal;
+static char *PS1;
+static char *PS2 = "> ";
+
+
+#ifdef DEBUG_SHELL
+static inline void debug_printf(const char *format, ...)
+{
+	va_list args;
+	va_start(args, format);
+	vfprintf(stderr, format, args);
+	va_end(args);
+}
+#else
+static inline void debug_printf(const char *format, ...) { }
+#endif
+
+/*
+	Most builtins need access to the struct child_prog that has
+	their arguments, previously coded as cmd->progs[0].  That coding
+	can exhibit a bug, if the builtin is not the first command in
+	a pipeline: "echo foo | exec sort" will attempt to exec foo.
+
+builtin   previous use      notes
+------ -----------------  ---------
+cd      cmd->progs[0]
+exec    cmd->progs[0]  squashed bug: didn't look for applets or forking builtins
+exit    cmd->progs[0]
+fg_bg   cmd->progs[0], job_list->head, job_list->fg
+help    0
+jobs    job_list->head
+pwd     0
+export  cmd->progs[0]
+source  cmd->progs[0]
+unset   cmd->progs[0]
+read    cmd->progs[0]
+
+I added "struct job *family;" to struct child_prog,
+and switched API to builtin_foo(struct child_prog *child);
+So   cmd->text        becomes  child->family->text
+     cmd->job_context  becomes  child->family->job_context
+     cmd->progs[0]    becomes  *child
+     job_list          becomes  child->family->job_list
+ */
+
+/* built-in 'cd <path>' handler */
+static int builtin_cd(struct child_prog *child)
+{
+	char *newdir;
+
+	if (child->argv[1] == NULL)
+		newdir = getenv("HOME");
+	else
+		newdir = child->argv[1];
+	if (chdir(newdir)) {
+		bb_perror_msg("cd: %s", newdir);
+		return EXIT_FAILURE;
+	}
+	cwd = xgetcwd((char *)cwd);
+	if (!cwd)
+		cwd = bb_msg_unknown;
+	return EXIT_SUCCESS;
+}
+
+/* built-in 'exec' handler */
+static int builtin_exec(struct child_prog *child)
+{
+	if (child->argv[1] == NULL)
+		return EXIT_SUCCESS;   /* Really? */
+	child->argv++;
+	while(close_me_list) close((long)llist_pop(&close_me_list));
+	pseudo_exec(child);
+	/* never returns */
+}
+
+/* built-in 'exit' handler */
+static int builtin_exit(struct child_prog *child)
+{
+	if (child->argv[1] == NULL)
+		exit(EXIT_SUCCESS);
+
+	exit (atoi(child->argv[1]));
+}
+
+/* built-in 'fg' and 'bg' handler */
+static int builtin_fg_bg(struct child_prog *child)
+{
+	int i, jobnum;
+	struct job *job=NULL;
+
+	/* If they gave us no args, assume they want the last backgrounded task */
+	if (!child->argv[1]) {
+		for (job = child->family->job_list->head; job; job = job->next) {
+			if (job->jobid == last_jobid) {
+				break;
+			}
+		}
+		if (!job) {
+			bb_error_msg("%s: no current job", child->argv[0]);
+			return EXIT_FAILURE;
+		}
+	} else {
+		if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) {
+			bb_error_msg(bb_msg_invalid_arg, child->argv[1], child->argv[0]);
+			return EXIT_FAILURE;
+		}
+		for (job = child->family->job_list->head; job; job = job->next) {
+			if (job->jobid == jobnum) {
+				break;
+			}
+		}
+		if (!job) {
+			bb_error_msg("%s: %d: no such job", child->argv[0], jobnum);
+			return EXIT_FAILURE;
+		}
+	}
+
+	if (*child->argv[0] == 'f') {
+		/* Put the job into the foreground.  */
+		tcsetpgrp(shell_terminal, job->pgrp);
+
+		child->family->job_list->fg = job;
+	}
+
+	/* Restart the processes in the job */
+	for (i = 0; i < job->num_progs; i++)
+		job->progs[i].is_stopped = 0;
+
+	job->stopped_progs = 0;
+
+	if ( (i=kill(- job->pgrp, SIGCONT)) < 0) {
+		if (i == ESRCH) {
+			remove_job(&job_list, job);
+		} else {
+			bb_perror_msg("kill (SIGCONT)");
+		}
+	}
+
+	return EXIT_SUCCESS;
+}
+
+/* built-in 'help' handler */
+static int builtin_help(struct child_prog *dummy)
+{
+	struct built_in_command *x;
+
+	printf("\nBuilt-in commands:\n");
+	printf("-------------------\n");
+	for (x = bltins; x->cmd; x++) {
+		if (x->descr==NULL)
+			continue;
+		printf("%s\t%s\n", x->cmd, x->descr);
+	}
+	for (x = bltins_forking; x->cmd; x++) {
+		if (x->descr==NULL)
+			continue;
+		printf("%s\t%s\n", x->cmd, x->descr);
+	}
+	printf("\n\n");
+	return EXIT_SUCCESS;
+}
+
+/* built-in 'jobs' handler */
+static int builtin_jobs(struct child_prog *child)
+{
+	struct job *job;
+	char *status_string;
+
+	for (job = child->family->job_list->head; job; job = job->next) {
+		if (job->running_progs == job->stopped_progs)
+			status_string = "Stopped";
+		else
+			status_string = "Running";
+
+		printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
+	}
+	return EXIT_SUCCESS;
+}
+
+
+/* built-in 'pwd' handler */
+static int builtin_pwd(struct child_prog *dummy)
+{
+	cwd = xgetcwd((char *)cwd);
+	if (!cwd)
+		cwd = bb_msg_unknown;
+	puts(cwd);
+	return EXIT_SUCCESS;
+}
+
+/* built-in 'export VAR=value' handler */
+static int builtin_export(struct child_prog *child)
+{
+	int res;
+	char *v = child->argv[1];
+
+	if (v == NULL) {
+		char **e;
+		for (e = environ; *e; e++) {
+			puts(*e);
+		}
+		return 0;
+	}
+	res = putenv(v);
+	if (res)
+		bb_perror_msg("export");
+#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
+	if (strncmp(v, "PS1=", 4)==0)
+		PS1 = getenv("PS1");
+#endif
+
+#ifdef CONFIG_LOCALE_SUPPORT
+	if(strncmp(v, "LC_ALL=", 7)==0)
+		setlocale(LC_ALL, getenv("LC_ALL"));
+	if(strncmp(v, "LC_CTYPE=", 9)==0)
+		setlocale(LC_CTYPE, getenv("LC_CTYPE"));
+#endif
+
+	return (res);
+}
+
+/* built-in 'read VAR' handler */
+static int builtin_read(struct child_prog *child)
+{
+	int res = 0, len, newlen;
+	char *s;
+	char string[MAX_READ];
+
+	if (child->argv[1]) {
+		/* argument (VAR) given: put "VAR=" into buffer */
+		safe_strncpy(string, child->argv[1], MAX_READ-1);
+		len = strlen(string);
+		string[len++] = '=';
+		string[len]   = '\0';
+		fgets(&string[len], sizeof(string) - len, stdin);	/* read string */
+		newlen = strlen(string);
+		if(newlen > len)
+			string[--newlen] = '\0';	/* chomp trailing newline */
+		/*
+		** string should now contain "VAR=<value>"
+		** copy it (putenv() won't do that, so we must make sure
+		** the string resides in a static buffer!)
+		*/
+		res = -1;
+		if((s = strdup(string)))
+			res = putenv(s);
+		if (res)
+			bb_perror_msg("read");
+	}
+	else
+		fgets(string, sizeof(string), stdin);
+
+	return (res);
+}
+
+/* Built-in '.' handler (read-in and execute commands from file) */
+static int builtin_source(struct child_prog *child)
+{
+	FILE *input;
+	int status;
+
+	if (child->argv[1] == NULL)
+		return EXIT_FAILURE;
+
+	input = fopen(child->argv[1], "r");
+	if (!input) {
+		printf( "Couldn't open file '%s'\n", child->argv[1]);
+		return EXIT_FAILURE;
+	}
+
+	llist_add_to(&close_me_list, (void *)(long)fileno(input));
+	/* Now run the file */
+	status = busy_loop(input);
+	fclose(input);
+	llist_pop(&close_me_list);
+	return (status);
+}
+
+/* built-in 'unset VAR' handler */
+static int builtin_unset(struct child_prog *child)
+{
+	if (child->argv[1] == NULL) {
+		printf(bb_msg_requires_arg, "unset");
+		return EXIT_FAILURE;
+	}
+	unsetenv(child->argv[1]);
+	return EXIT_SUCCESS;
+}
+
+#ifdef CONFIG_LASH_JOB_CONTROL
+/* free up all memory from a job */
+static void free_job(struct job *cmd)
+{
+	int i;
+	struct jobset *keep;
+
+	for (i = 0; i < cmd->num_progs; i++) {
+		free(cmd->progs[i].argv);
+#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
+		if (cmd->progs[i].redirects)
+			free(cmd->progs[i].redirects);
+#endif
+	}
+	free(cmd->progs);
+	free(cmd->text);
+	free(cmd->cmdbuf);
+	keep = cmd->job_list;
+	memset(cmd, 0, sizeof(struct job));
+	cmd->job_list = keep;
+}
+
+/* remove a job from a jobset */
+static void remove_job(struct jobset *j_list, struct job *job)
+{
+	struct job *prevjob;
+
+	free_job(job);
+	if (job == j_list->head) {
+		j_list->head = job->next;
+	} else {
+		prevjob = j_list->head;
+		while (prevjob->next != job)
+			prevjob = prevjob->next;
+		prevjob->next = job->next;
+	}
+
+	if (j_list->head)
+		last_jobid = j_list->head->jobid;
+	else
+		last_jobid = 0;
+
+	free(job);
+}
+
+/* Checks to see if any background processes have exited -- if they
+   have, figure out why and see if a job has completed */
+static void checkjobs(struct jobset *j_list)
+{
+	struct job *job;
+	pid_t childpid;
+	int status;
+	int prognum = 0;
+
+	while ((childpid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
+		for (job = j_list->head; job; job = job->next) {
+			prognum = 0;
+			while (prognum < job->num_progs &&
+				   job->progs[prognum].pid != childpid) prognum++;
+			if (prognum < job->num_progs)
+				break;
+		}
+
+		/* This happens on backticked commands */
+		if(job==NULL)
+			return;
+
+		if (WIFEXITED(status) || WIFSIGNALED(status)) {
+			/* child exited */
+			job->running_progs--;
+			job->progs[prognum].pid = 0;
+
+			if (!job->running_progs) {
+				printf(JOB_STATUS_FORMAT, job->jobid, "Done", job->text);
+				last_jobid=0;
+				remove_job(j_list, job);
+			}
+		} else {
+			/* child stopped */
+			job->stopped_progs++;
+			job->progs[prognum].is_stopped = 1;
+
+#if 0
+			/* Printing this stuff is a pain, since it tends to
+			 * overwrite the prompt an inconveinient moments.  So
+			 * don't do that.  */
+			if (job->stopped_progs == job->num_progs) {
+				printf(JOB_STATUS_FORMAT, job->jobid, "Stopped",
+					   job->text);
+			}
+#endif
+		}
+	}
+
+	if (childpid == -1 && errno != ECHILD)
+		bb_perror_msg("waitpid");
+}
+#else
+static void checkjobs(struct jobset *j_list)
+{
+}
+static void free_job(struct job *cmd)
+{
+}
+static void remove_job(struct jobset *j_list, struct job *job)
+{
+}
+#endif
+
+#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
+/* squirrel != NULL means we squirrel away copies of stdin, stdout,
+ * and stderr if they are redirected. */
+static int setup_redirects(struct child_prog *prog, int squirrel[])
+{
+	int i;
+	int openfd;
+	int mode = O_RDONLY;
+	struct redir_struct *redir = prog->redirects;
+
+	for (i = 0; i < prog->num_redirects; i++, redir++) {
+		switch (redir->type) {
+		case REDIRECT_INPUT:
+			mode = O_RDONLY;
+			break;
+		case REDIRECT_OVERWRITE:
+			mode = O_WRONLY | O_CREAT | O_TRUNC;
+			break;
+		case REDIRECT_APPEND:
+			mode = O_WRONLY | O_CREAT | O_APPEND;
+			break;
+		}
+
+		openfd = open(redir->filename, mode, 0666);
+		if (openfd < 0) {
+			/* this could get lost if stderr has been redirected, but
+			   bash and ash both lose it as well (though zsh doesn't!) */
+			bb_perror_msg("error opening %s", redir->filename);
+			return 1;
+		}
+
+		if (openfd != redir->fd) {
+			if (squirrel && redir->fd < 3) {
+				squirrel[redir->fd] = dup(redir->fd);
+				fcntl (squirrel[redir->fd], F_SETFD, FD_CLOEXEC);
+			}
+			dup2(openfd, redir->fd);
+			close(openfd);
+		}
+	}
+
+	return 0;
+}
+
+static void restore_redirects(int squirrel[])
+{
+	int i, fd;
+	for (i=0; i<3; i++) {
+		fd = squirrel[i];
+		if (fd != -1) {
+			/* No error checking.  I sure wouldn't know what
+			 * to do with an error if I found one! */
+			dup2(fd, i);
+			close(fd);
+		}
+	}
+}
+#else
+static inline int setup_redirects(struct child_prog *prog, int squirrel[])
+{
+	return 0;
+}
+static inline void restore_redirects(int squirrel[])
+{
+}
+#endif
+
+static inline void cmdedit_set_initial_prompt(void)
+{
+#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
+	PS1 = NULL;
+#else
+	PS1 = getenv("PS1");
+	if(PS1==0)
+		PS1 = "\\w \\$ ";
+#endif
+}
+
+static inline void setup_prompt_string(char **prompt_str)
+{
+#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
+	/* Set up the prompt */
+	if (shell_context == 0) {
+		free(PS1);
+		PS1=xmalloc(strlen(cwd)+4);
+		sprintf(PS1, "%s %s", cwd, ( geteuid() != 0 ) ?  "$ ":"# ");
+		*prompt_str = PS1;
+	} else {
+		*prompt_str = PS2;
+	}
+#else
+	*prompt_str = (shell_context==0)? PS1 : PS2;
+#endif
+}
+
+static int get_command(FILE * source, char *command)
+{
+	char *prompt_str;
+
+	if (source == NULL) {
+		if (local_pending_command) {
+			/* a command specified (-c option): return it & mark it done */
+			strcpy(command, local_pending_command);
+			free(local_pending_command);
+			local_pending_command = NULL;
+			return 0;
+		}
+		return 1;
+	}
+
+	if (source == stdin) {
+		setup_prompt_string(&prompt_str);
+
+#ifdef CONFIG_FEATURE_COMMAND_EDITING
+		/*
+		** enable command line editing only while a command line
+		** is actually being read; otherwise, we'll end up bequeathing
+		** atexit() handlers and other unwanted stuff to our
+		** child processes (rob at sysgo.de)
+		*/
+		cmdedit_read_input(prompt_str, command);
+		return 0;
+#else
+		fputs(prompt_str, stdout);
+#endif
+	}
+
+	if (!fgets(command, BUFSIZ - 2, source)) {
+		if (source == stdin)
+			printf("\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+static char* itoa(register int i)
+{
+	static char a[7]; /* Max 7 ints */
+	register char *b = a + sizeof(a) - 1;
+	int   sign = (i < 0);
+
+	if (sign)
+		i = -i;
+	*b = 0;
+	do
+	{
+		*--b = '0' + (i % 10);
+		i /= 10;
+	}
+	while (i);
+	if (sign)
+		*--b = '-';
+	return b;
+}
+
+static char * strsep_space( char *string, int * ix)
+{
+	char *token;
+
+	/* Short circuit the trivial case */
+	if ( !string || ! string[*ix])
+		return NULL;
+
+	/* Find the end of the token. */
+	while( string[*ix] && !isspace(string[*ix]) ) {
+		(*ix)++;
+	}
+
+	/* Find the end of any whitespace trailing behind
+	 * the token and let that be part of the token */
+	while( string[*ix] && isspace(string[*ix]) ) {
+		(*ix)++;
+	}
+
+	if (!*ix) {
+		/* Nothing useful was found */
+		return NULL;
+	}
+
+	token = bb_xstrndup(string, *ix);
+
+	return token;
+}
+
+static int expand_arguments(char *command)
+{
+	int total_length=0, length, i, retval, ix = 0;
+	expand_t expand_result;
+	char *tmpcmd, *cmd, *cmd_copy;
+	char *src, *dst, *var;
+	const char *out_of_space = "out of space during expansion";
+	int flags = GLOB_NOCHECK
+#ifdef GLOB_BRACE
+		| GLOB_BRACE
+#endif
+#ifdef GLOB_TILDE
+		| GLOB_TILDE
+#endif
+		;
+
+	/* get rid of the terminating \n */
+	chomp(command);
+
+	/* Fix up escape sequences to be the Real Thing(tm) */
+	while( command && command[ix]) {
+		if (command[ix] == '\\') {
+			const char *tmp = command+ix+1;
+			command[ix] = bb_process_escape_sequence(  &tmp );
+			memmove(command+ix + 1, tmp, strlen(tmp)+1);
+		}
+		ix++;
+	}
+	/* Use glob and then fixup environment variables and such */
+
+	/* It turns out that glob is very stupid.  We have to feed it one word at a
+	 * time since it can't cope with a full string.  Here we convert command
+	 * (char*) into cmd (char**, one word per string) */
+
+	/* We need a clean copy, so strsep can mess up the copy while
+	 * we write stuff into the original (in a minute) */
+	cmd = cmd_copy = bb_xstrdup(command);
+	*command = '\0';
+	for (ix = 0, tmpcmd = cmd;
+			(tmpcmd = strsep_space(cmd, &ix)) != NULL; cmd += ix, ix=0) {
+		if (*tmpcmd == '\0')
+			break;
+		/* we need to trim() the result for glob! */
+		trim(tmpcmd);
+		retval = glob(tmpcmd, flags, NULL, &expand_result);
+		free(tmpcmd); /* Free mem allocated by strsep_space */
+		if (retval == GLOB_NOSPACE) {
+			/* Mem may have been allocated... */
+			globfree (&expand_result);
+			bb_error_msg(out_of_space);
+			return FALSE;
+		} else if (retval != 0) {
+			/* Some other error.  GLOB_NOMATCH shouldn't
+			 * happen because of the GLOB_NOCHECK flag in
+			 * the glob call. */
+			bb_error_msg("syntax error");
+			return FALSE;
+		} else {
+			/* Convert from char** (one word per string) to a simple char*,
+			 * but don't overflow command which is BUFSIZ in length */
+			for (i=0; i < expand_result.gl_pathc; i++) {
+				length=strlen(expand_result.gl_pathv[i]);
+				if (total_length+length+1 >= BUFSIZ) {
+					bb_error_msg(out_of_space);
+					return FALSE;
+				}
+				strcat(command+total_length, " ");
+				total_length+=1;
+				strcat(command+total_length, expand_result.gl_pathv[i]);
+				total_length+=length;
+			}
+			globfree (&expand_result);
+		}
+	}
+	free(cmd_copy);
+	trim(command);
+
+	/* Now do the shell variable substitutions which
+	 * wordexp can't do for us, namely $? and $! */
+	src = command;
+	while((dst = strchr(src,'$')) != NULL){
+		var = NULL;
+		switch(*(dst+1)) {
+			case '?':
+				var = itoa(last_return_code);
+				break;
+			case '!':
+				if (last_bg_pid==-1)
+					*(var)='\0';
+				else
+					var = itoa(last_bg_pid);
+				break;
+				/* Everything else like $$, $#, $[0-9], etc. should all be
+				 * expanded by wordexp(), so we can in theory skip that stuff
+				 * here, but just to be on the safe side (i.e., since uClibc
+				 * wordexp doesn't do this stuff yet), lets leave it in for
+				 * now. */
+			case '$':
+				var = itoa(getpid());
+				break;
+			case '#':
+				var = itoa(argc-1);
+				break;
+			case '0':case '1':case '2':case '3':case '4':
+			case '5':case '6':case '7':case '8':case '9':
+				{
+					int ixx=*(dst+1)-48+1;
+					if (ixx >= argc) {
+						var='\0';
+					} else {
+						var = argv[ixx];
+					}
+				}
+				break;
+
+		}
+		if (var) {
+			/* a single character construction was found, and
+			 * already handled in the case statement */
+			src=dst+2;
+		} else {
+			/* Looks like an environment variable */
+			char delim_hold;
+			int num_skip_chars=0;
+			int dstlen = strlen(dst);
+			/* Is this a ${foo} type variable? */
+			if (dstlen >=2 && *(dst+1) == '{') {
+				src=strchr(dst+1, '}');
+				num_skip_chars=1;
+			} else {
+				src=dst+1;
+				while(isalnum(*src) || *src=='_') src++;
+			}
+			if (src == NULL) {
+				src = dst+dstlen;
+			}
+			delim_hold=*src;
+			*src='\0';  /* temporary */
+			var = getenv(dst + 1 + num_skip_chars);
+			*src=delim_hold;
+			src += num_skip_chars;
+		}
+		if (var == NULL) {
+			/* Seems we got an un-expandable variable.  So delete it. */
+			var = "";
+		}
+		{
+			int subst_len = strlen(var);
+			int trail_len = strlen(src);
+			if (dst+subst_len+trail_len >= command+BUFSIZ) {
+				bb_error_msg(out_of_space);
+				return FALSE;
+			}
+			/* Move stuff to the end of the string to accommodate
+			 * filling the created gap with the new stuff */
+			memmove(dst+subst_len, src, trail_len+1);
+			/* Now copy in the new stuff */
+			memcpy(dst, var, subst_len);
+			src = dst+subst_len;
+		}
+	}
+
+	return TRUE;
+}
+
+/* Return cmd->num_progs as 0 if no command is present (e.g. an empty
+   line). If a valid command is found, command_ptr is set to point to
+   the beginning of the next command (if the original command had more
+   then one job associated with it) or NULL if no more commands are
+   present. */
+static int parse_command(char **command_ptr, struct job *job, int *inbg)
+{
+	char *command;
+	char *return_command = NULL;
+	char *src, *buf;
+	int argc_l = 0;
+	int done = 0;
+	int argv_alloced;
+	int saw_quote = 0;
+	char quote = '\0';
+	struct child_prog *prog;
+#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
+	int i;
+	char *chptr;
+#endif
+
+	/* skip leading white space */
+	while (**command_ptr && isspace(**command_ptr))
+		(*command_ptr)++;
+
+	/* this handles empty lines or leading '#' characters */
+	if (!**command_ptr || (**command_ptr == '#')) {
+		job->num_progs=0;
+		return 0;
+	}
+
+	*inbg = 0;
+	job->num_progs = 1;
+	job->progs = xmalloc(sizeof(*job->progs));
+
+	/* We set the argv elements to point inside of this string. The
+	   memory is freed by free_job(). Allocate twice the original
+	   length in case we need to quote every single character.
+
+	   Getting clean memory relieves us of the task of NULL
+	   terminating things and makes the rest of this look a bit
+	   cleaner (though it is, admittedly, a tad less efficient) */
+	job->cmdbuf = command = xzalloc(2*strlen(*command_ptr) + 1);
+	job->text = NULL;
+
+	prog = job->progs;
+	prog->num_redirects = 0;
+	prog->is_stopped = 0;
+	prog->family = job;
+#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
+	prog->redirects = NULL;
+#endif
+
+	argv_alloced = 5;
+	prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
+	prog->argv[0] = job->cmdbuf;
+
+	buf = command;
+	src = *command_ptr;
+	while (*src && !done) {
+		if (quote == *src) {
+			quote = '\0';
+		} else if (quote) {
+			if (*src == '\\') {
+				src++;
+				if (!*src) {
+					bb_error_msg("character expected after \\");
+					free_job(job);
+					return 1;
+				}
+
+				/* in shell, "\'" should yield \' */
+				if (*src != quote) {
+					*buf++ = '\\';
+					*buf++ = '\\';
+				}
+			} else if (*src == '*' || *src == '?' || *src == '[' ||
+					   *src == ']') *buf++ = '\\';
+			*buf++ = *src;
+		} else if (isspace(*src)) {
+			if (*prog->argv[argc_l] || saw_quote) {
+				buf++, argc_l++;
+				/* +1 here leaves room for the NULL which ends argv */
+				if ((argc_l + 1) == argv_alloced) {
+					argv_alloced += 5;
+					prog->argv = xrealloc(prog->argv,
+										  sizeof(*prog->argv) *
+										  argv_alloced);
+				}
+				prog->argv[argc_l] = buf;
+				saw_quote = 0;
+			}
+		} else
+			switch (*src) {
+			case '"':
+			case '\'':
+				quote = *src;
+				saw_quote = 1;
+				break;
+
+			case '#':			/* comment */
+				if (*(src-1)== '$')
+					*buf++ = *src;
+				else
+					done = 1;
+				break;
+
+#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
+			case '>':			/* redirects */
+			case '<':
+				i = prog->num_redirects++;
+				prog->redirects = xrealloc(prog->redirects,
+											  sizeof(*prog->redirects) *
+											  (i + 1));
+
+				prog->redirects[i].fd = -1;
+				if (buf != prog->argv[argc_l]) {
+					/* the stuff before this character may be the file number
+					   being redirected */
+					prog->redirects[i].fd =
+						strtol(prog->argv[argc_l], &chptr, 10);
+
+					if (*chptr && *prog->argv[argc_l]) {
+						buf++, argc_l++;
+						prog->argv[argc_l] = buf;
+					}
+				}
+
+				if (prog->redirects[i].fd == -1) {
+					if (*src == '>')
+						prog->redirects[i].fd = 1;
+					else
+						prog->redirects[i].fd = 0;
+				}
+
+				if (*src++ == '>') {
+					if (*src == '>')
+						prog->redirects[i].type =
+							REDIRECT_APPEND, src++;
+					else
+						prog->redirects[i].type = REDIRECT_OVERWRITE;
+				} else {
+					prog->redirects[i].type = REDIRECT_INPUT;
+				}
+
+				/* This isn't POSIX sh compliant. Oh well. */
+				chptr = src;
+				while (isspace(*chptr))
+					chptr++;
+
+				if (!*chptr) {
+					bb_error_msg("file name expected after %c", *(src-1));
+					free_job(job);
+					job->num_progs=0;
+					return 1;
+				}
+
+				prog->redirects[i].filename = buf;
+				while (*chptr && !isspace(*chptr))
+					*buf++ = *chptr++;
+
+				src = chptr - 1;	/* we src++ later */
+				prog->argv[argc_l] = ++buf;
+				break;
+
+			case '|':			/* pipe */
+				/* finish this command */
+				if (*prog->argv[argc_l] || saw_quote)
+					argc_l++;
+				if (!argc_l) {
+					bb_error_msg("empty command in pipe");
+					free_job(job);
+					job->num_progs=0;
+					return 1;
+				}
+				prog->argv[argc_l] = NULL;
+
+				/* and start the next */
+				job->num_progs++;
+				job->progs = xrealloc(job->progs,
+									  sizeof(*job->progs) * job->num_progs);
+				prog = job->progs + (job->num_progs - 1);
+				prog->num_redirects = 0;
+				prog->redirects = NULL;
+				prog->is_stopped = 0;
+				prog->family = job;
+				argc_l = 0;
+
+				argv_alloced = 5;
+				prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
+				prog->argv[0] = ++buf;
+
+				src++;
+				while (*src && isspace(*src))
+					src++;
+
+				if (!*src) {
+					bb_error_msg("empty command in pipe");
+					free_job(job);
+					job->num_progs=0;
+					return 1;
+				}
+				src--;			/* we'll ++ it at the end of the loop */
+
+				break;
+#endif
+
+#ifdef CONFIG_LASH_JOB_CONTROL
+			case '&':			/* background */
+				*inbg = 1;
+#endif
+			case ';':			/* multiple commands */
+				done = 1;
+				return_command = *command_ptr + (src - *command_ptr) + 1;
+				break;
+
+			case '\\':
+				src++;
+				if (!*src) {
+					bb_error_msg("character expected after \\");
+					free_job(job);
+					return 1;
+				}
+				if (*src == '*' || *src == '[' || *src == ']'
+					|| *src == '?') *buf++ = '\\';
+				/* fallthrough */
+			default:
+				*buf++ = *src;
+			}
+
+		src++;
+	}
+
+	if (*prog->argv[argc_l] || saw_quote) {
+		argc_l++;
+	}
+	if (!argc_l) {
+		free_job(job);
+		return 0;
+	}
+	prog->argv[argc_l] = NULL;
+
+	if (!return_command) {
+		job->text = bb_xstrdup(*command_ptr);
+	} else {
+		/* This leaves any trailing spaces, which is a bit sloppy */
+		job->text = bb_xstrndup(*command_ptr, return_command - *command_ptr);
+	}
+
+	*command_ptr = return_command;
+
+	return 0;
+}
+
+/* Run the child_prog, no matter what kind of command it uses.
+ */
+static int pseudo_exec(struct child_prog *child)
+{
+	struct built_in_command *x;
+
+	/* Check if the command matches any of the non-forking builtins.
+	 * Depending on context, this might be redundant.  But it's
+	 * easier to waste a few CPU cycles than it is to figure out
+	 * if this is one of those cases.
+	 */
+	for (x = bltins; x->cmd; x++) {
+		if (strcmp(child->argv[0], x->cmd) == 0 ) {
+			_exit(x->function(child));
+		}
+	}
+
+	/* Check if the command matches any of the forking builtins. */
+	for (x = bltins_forking; x->cmd; x++) {
+		if (strcmp(child->argv[0], x->cmd) == 0) {
+			bb_applet_name=x->cmd;
+			_exit (x->function(child));
+		}
+	}
+
+	/* Check if the command matches any busybox internal
+	 * commands ("applets") here.  Following discussions from
+	 * November 2000 on busybox at busybox.net, don't use
+	 * bb_get_last_path_component().  This way explicit (with
+	 * slashes) filenames will never be interpreted as an
+	 * applet, just like with builtins.  This way the user can
+	 * override an applet with an explicit filename reference.
+	 * The only downside to this change is that an explicit
+	 * /bin/foo invocation will fork and exec /bin/foo, even if
+	 * /bin/foo is a symlink to busybox.
+	 */
+
+	if (ENABLE_FEATURE_SH_STANDALONE_SHELL) {
+		char **argv_l = child->argv;
+		int argc_l;
+
+		for(argc_l=0; *argv_l; argv_l++, argc_l++);
+		optind = 1;
+		run_applet_by_name(child->argv[0], argc_l, child->argv);
+	}
+
+	execvp(child->argv[0], child->argv);
+
+	/* Do not use bb_perror_msg_and_die() here, since we must not
+	 * call exit() but should call _exit() instead */
+	bb_perror_msg("%s", child->argv[0]);
+	_exit(EXIT_FAILURE);
+}
+
+static void insert_job(struct job *newjob, int inbg)
+{
+	struct job *thejob;
+	struct jobset *j_list=newjob->job_list;
+
+	/* find the ID for thejob to use */
+	newjob->jobid = 1;
+	for (thejob = j_list->head; thejob; thejob = thejob->next)
+		if (thejob->jobid >= newjob->jobid)
+			newjob->jobid = thejob->jobid + 1;
+
+	/* add thejob to the list of running jobs */
+	if (!j_list->head) {
+		thejob = j_list->head = xmalloc(sizeof(*thejob));
+	} else {
+		for (thejob = j_list->head; thejob->next; thejob = thejob->next) /* nothing */;
+		thejob->next = xmalloc(sizeof(*thejob));
+		thejob = thejob->next;
+	}
+
+	*thejob = *newjob;   /* physically copy the struct job */
+	thejob->next = NULL;
+	thejob->running_progs = thejob->num_progs;
+	thejob->stopped_progs = 0;
+
+#ifdef CONFIG_LASH_JOB_CONTROL
+	if (inbg) {
+		/* we don't wait for background thejobs to return -- append it
+		   to the list of backgrounded thejobs and leave it alone */
+		printf("[%d] %d\n", thejob->jobid,
+			   newjob->progs[newjob->num_progs - 1].pid);
+		last_jobid = newjob->jobid;
+		last_bg_pid=newjob->progs[newjob->num_progs - 1].pid;
+	} else {
+		newjob->job_list->fg = thejob;
+
+		/* move the new process group into the foreground */
+		/* Ignore errors since child could have already exited */
+		tcsetpgrp(shell_terminal, newjob->pgrp);
+	}
+#endif
+}
+
+static int run_command(struct job *newjob, int inbg, int outpipe[2])
+{
+	/* struct job *thejob; */
+	int i;
+	int nextin, nextout;
+	int pipefds[2];				/* pipefd[0] is for reading */
+	struct built_in_command *x;
+	struct child_prog *child;
+
+	nextin = 0, nextout = 1;
+	for (i = 0; i < newjob->num_progs; i++) {
+		child = & (newjob->progs[i]);
+
+		if ((i + 1) < newjob->num_progs) {
+			if (pipe(pipefds)<0) bb_perror_msg_and_die("pipe");
+			nextout = pipefds[1];
+		} else {
+			if (outpipe[1]!=-1) {
+				nextout = outpipe[1];
+			} else {
+				nextout = 1;
+			}
+		}
+
+
+		/* Check if the command matches any non-forking builtins,
+		 * but only if this is a simple command.
+		 * Non-forking builtins within pipes have to fork anyway,
+		 * and are handled in pseudo_exec.  "echo foo | read bar"
+		 * is doomed to failure, and doesn't work on bash, either.
+		 */
+		if (newjob->num_progs == 1) {
+			/* Check if the command sets an environment variable. */
+			if (strchr(child->argv[0], '=') != NULL) {
+				child->argv[1] = child->argv[0];
+				return builtin_export(child);
+			}
+
+			for (x = bltins; x->cmd; x++) {
+				if (strcmp(child->argv[0], x->cmd) == 0 ) {
+					int rcode;
+					int squirrel[] = {-1, -1, -1};
+					setup_redirects(child, squirrel);
+					rcode = x->function(child);
+					restore_redirects(squirrel);
+					return rcode;
+				}
+			}
+		}
+
+#if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__)
+		if (!(child->pid = fork()))
+#else
+		if (!(child->pid = vfork()))
+#endif
+		{
+			/* Set the handling for job control signals back to the default.  */
+			signal(SIGINT, SIG_DFL);
+			signal(SIGQUIT, SIG_DFL);
+			signal(SIGTSTP, SIG_DFL);
+			signal(SIGTTIN, SIG_DFL);
+			signal(SIGTTOU, SIG_DFL);
+			signal(SIGCHLD, SIG_DFL);
+
+			// Close all open filehandles.
+			while(close_me_list) close((long)llist_pop(&close_me_list));
+
+			if (outpipe[1]!=-1) {
+				close(outpipe[0]);
+			}
+			if (nextin != 0) {
+				dup2(nextin, 0);
+				close(nextin);
+			}
+
+			if (nextout != 1) {
+				dup2(nextout, 1);
+				dup2(nextout, 2);  /* Really? */
+				close(nextout);
+				close(pipefds[0]);
+			}
+
+			/* explicit redirects override pipes */
+			setup_redirects(child,NULL);
+
+			pseudo_exec(child);
+		}
+		if (outpipe[1]!=-1) {
+			close(outpipe[1]);
+		}
+
+		/* put our child in the process group whose leader is the
+		   first process in this pipe */
+		setpgid(child->pid, newjob->progs[0].pid);
+		if (nextin != 0)
+			close(nextin);
+		if (nextout != 1)
+			close(nextout);
+
+		/* If there isn't another process, nextin is garbage
+		   but it doesn't matter */
+		nextin = pipefds[0];
+	}
+
+	newjob->pgrp = newjob->progs[0].pid;
+
+	insert_job(newjob, inbg);
+
+	return 0;
+}
+
+static int busy_loop(FILE * input)
+{
+	char *command;
+	char *next_command = NULL;
+	struct job newjob;
+	int i;
+	int inbg = 0;
+	int status;
+#ifdef CONFIG_LASH_JOB_CONTROL
+	pid_t  parent_pgrp;
+	/* save current owner of TTY so we can restore it on exit */
+	parent_pgrp = tcgetpgrp(shell_terminal);
+#endif
+	newjob.job_list = &job_list;
+	newjob.job_context = DEFAULT_CONTEXT;
+
+	command = xzalloc(BUFSIZ);
+
+	while (1) {
+		if (!job_list.fg) {
+			/* no job is in the foreground */
+
+			/* see if any background processes have exited */
+			checkjobs(&job_list);
+
+			if (!next_command) {
+				if (get_command(input, command))
+					break;
+				next_command = command;
+			}
+
+			if (! expand_arguments(next_command)) {
+				free(command);
+				command = xzalloc(BUFSIZ);
+				next_command = NULL;
+				continue;
+			}
+
+			if (!parse_command(&next_command, &newjob, &inbg) &&
+				newjob.num_progs) {
+				int pipefds[2] = {-1,-1};
+				debug_printf( "job=%p fed to run_command by busy_loop()'\n",
+						&newjob);
+				run_command(&newjob, inbg, pipefds);
+			}
+			else {
+				free(command);
+				command = (char *) xzalloc(BUFSIZ);
+				next_command = NULL;
+			}
+		} else {
+			/* a job is running in the foreground; wait for it */
+			i = 0;
+			while (!job_list.fg->progs[i].pid ||
+				   job_list.fg->progs[i].is_stopped == 1) i++;
+
+			if (waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED)<0) {
+				if (errno != ECHILD) {
+					bb_perror_msg_and_die("waitpid(%d)",job_list.fg->progs[i].pid);
+				}
+			}
+
+			if (WIFEXITED(status) || WIFSIGNALED(status)) {
+				/* the child exited */
+				job_list.fg->running_progs--;
+				job_list.fg->progs[i].pid = 0;
+
+				last_return_code=WEXITSTATUS(status);
+
+				if (!job_list.fg->running_progs) {
+					/* child exited */
+					remove_job(&job_list, job_list.fg);
+					job_list.fg = NULL;
+				}
+			}
+#ifdef CONFIG_LASH_JOB_CONTROL
+			else {
+				/* the child was stopped */
+				job_list.fg->stopped_progs++;
+				job_list.fg->progs[i].is_stopped = 1;
+
+				if (job_list.fg->stopped_progs == job_list.fg->running_progs) {
+					printf("\n" JOB_STATUS_FORMAT, job_list.fg->jobid,
+						   "Stopped", job_list.fg->text);
+					job_list.fg = NULL;
+				}
+			}
+
+			if (!job_list.fg) {
+				/* move the shell to the foreground */
+				/* suppress messages when run from /linuxrc mag at sysgo.de */
+				if (tcsetpgrp(shell_terminal, getpgrp()) && errno != ENOTTY)
+					bb_perror_msg("tcsetpgrp");
+			}
+#endif
+		}
+	}
+	free(command);
+
+#ifdef CONFIG_LASH_JOB_CONTROL
+	/* return controlling TTY back to parent process group before exiting */
+	if (tcsetpgrp(shell_terminal, parent_pgrp) && errno != ENOTTY)
+		bb_perror_msg("tcsetpgrp");
+#endif
+
+	/* return exit status if called with "-c" */
+	if (input == NULL && WIFEXITED(status))
+		return WEXITSTATUS(status);
+
+	return 0;
+}
+
+#ifdef CONFIG_FEATURE_CLEAN_UP
+static void free_memory(void)
+{
+	if (cwd && cwd!=bb_msg_unknown) {
+		free((char*)cwd);
+	}
+	if (local_pending_command)
+		free(local_pending_command);
+
+	if (job_list.fg && !job_list.fg->running_progs) {
+		remove_job(&job_list, job_list.fg);
+	}
+}
+#else
+void free_memory(void);
+#endif
+
+#ifdef CONFIG_LASH_JOB_CONTROL
+/* Make sure we have a controlling tty.  If we get started under a job
+ * aware app (like bash for example), make sure we are now in charge so
+ * we don't fight over who gets the foreground */
+static void setup_job_control(void)
+{
+	int status;
+	pid_t shell_pgrp;
+
+	/* Loop until we are in the foreground.  */
+	while ((status = tcgetpgrp (shell_terminal)) >= 0) {
+		if (status == (shell_pgrp = getpgrp ())) {
+			break;
+		}
+		kill (- shell_pgrp, SIGTTIN);
+	}
+
+	/* Ignore interactive and job-control signals.  */
+	signal(SIGINT, SIG_IGN);
+	signal(SIGQUIT, SIG_IGN);
+	signal(SIGTSTP, SIG_IGN);
+	signal(SIGTTIN, SIG_IGN);
+	signal(SIGTTOU, SIG_IGN);
+	signal(SIGCHLD, SIG_IGN);
+
+	/* Put ourselves in our own process group.  */
+	setsid();
+	shell_pgrp = getpid ();
+	setpgid(shell_pgrp, shell_pgrp);
+
+	/* Grab control of the terminal.  */
+	tcsetpgrp(shell_terminal, shell_pgrp);
+}
+#else
+static inline void setup_job_control(void)
+{
+}
+#endif
+
+int lash_main(int argc_l, char **argv_l)
+{
+	int opt, interactive=FALSE;
+	FILE *input = stdin;
+	argc = argc_l;
+	argv = argv_l;
+
+	/* These variables need re-initializing when recursing */
+	last_jobid = 0;
+	local_pending_command = NULL;
+	close_me_list = NULL;
+	job_list.head = NULL;
+	job_list.fg = NULL;
+	last_return_code=1;
+
+	if (argv[0] && argv[0][0] == '-') {
+		FILE *prof_input;
+		prof_input = fopen("/etc/profile", "r");
+		if (prof_input) {
+			llist_add_to(&close_me_list, (void *)(long)fileno(prof_input));
+			/* Now run the file */
+			busy_loop(prof_input);
+			fclose(prof_input);
+			llist_pop(&close_me_list);
+		}
+	}
+
+	while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) {
+		switch (opt) {
+			case 'c':
+				input = NULL;
+				if (local_pending_command != 0)
+					bb_error_msg_and_die("multiple -c arguments");
+				local_pending_command = bb_xstrdup(argv[optind]);
+				optind++;
+				argv = argv+optind;
+				break;
+			case 'i':
+				interactive++;
+				break;
+			default:
+				bb_show_usage();
+		}
+	}
+	/* A shell is interactive if the `-i' flag was given, or if all of
+	 * the following conditions are met:
+	 *	  no -c command
+	 *    no arguments remaining or the -s flag given
+	 *    standard input is a terminal
+	 *    standard output is a terminal
+	 *    Refer to Posix.2, the description of the `sh' utility. */
+	if (argv[optind]==NULL && input==stdin &&
+			isatty(STDIN_FILENO) && isatty(STDOUT_FILENO))
+	{
+		interactive++;
+	}
+	setup_job_control();
+	if (interactive) {
+		/* Looks like they want an interactive shell */
+		if (!ENABLE_FEATURE_SH_EXTRA_QUIET) {
+			printf( "\n\n%s Built-in shell (lash)\n", BB_BANNER);
+			printf( "Enter 'help' for a list of built-in commands.\n\n");
+		}
+	} else if (!local_pending_command && argv[optind]) {
+		//printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
+		input = bb_xfopen(argv[optind], "r");
+		/* be lazy, never mark this closed */
+		llist_add_to(&close_me_list, (void *)(long)fileno(input));
+	}
+
+	/* initialize the cwd -- this is never freed...*/
+	cwd = xgetcwd(0);
+	if (!cwd)
+		cwd = bb_msg_unknown;
+
+	if (ENABLE_FEATURE_CLEAN_UP) atexit(free_memory);
+
+	if (ENABLE_FEATURE_COMMAND_EDITING) cmdedit_set_initial_prompt();
+	else PS1 = NULL;
+
+	return (busy_loop(input));
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/msh.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/msh.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/shell/msh.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,5337 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Minix shell port for busybox
+ *
+ * This version of the Minix shell was adapted for use in busybox
+ * by Erik Andersen <andersen at codepoet.org>
+ *
+ * - backtick expansion did not work properly
+ *   Jonas Holmberg <jonas.holmberg at axis.com>
+ *   Robert Schwebel <r.schwebel at pengutronix.de>
+ *   Erik Andersen <andersen at codepoet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Original copyright notice is retained at the end of this file.
+ */
+
+#include "busybox.h"
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/times.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "cmdedit.h"
+
+
+/* Conditional use of "register" keyword */
+#define REGISTER register
+
+/*#define MSHDEBUG 1*/
+
+#ifdef MSHDEBUG
+int mshdbg = MSHDEBUG;
+
+#define DBGPRINTF(x)	if(mshdbg>0)printf x
+#define DBGPRINTF0(x)	if(mshdbg>0)printf x
+#define DBGPRINTF1(x)	if(mshdbg>1)printf x
+#define DBGPRINTF2(x)	if(mshdbg>2)printf x
+#define DBGPRINTF3(x)	if(mshdbg>3)printf x
+#define DBGPRINTF4(x)	if(mshdbg>4)printf x
+#define DBGPRINTF5(x)	if(mshdbg>5)printf x
+#define DBGPRINTF6(x)	if(mshdbg>6)printf x
+#define DBGPRINTF7(x)	if(mshdbg>7)printf x
+#define DBGPRINTF8(x)	if(mshdbg>8)printf x
+#define DBGPRINTF9(x)	if(mshdbg>9)printf x
+
+int mshdbg_rc = 0;
+
+#define RCPRINTF(x)		if(mshdbg_rc)printf x
+
+#else
+
+#define DBGPRINTF(x)
+#define DBGPRINTF0(x)
+#define DBGPRINTF1(x)
+#define DBGPRINTF2(x)
+#define DBGPRINTF3(x)
+#define DBGPRINTF4(x)
+#define DBGPRINTF5(x)
+#define DBGPRINTF6(x)
+#define DBGPRINTF7(x)
+#define DBGPRINTF8(x)
+#define DBGPRINTF9(x)
+
+#define RCPRINTF(x)
+
+#endif							/* MSHDEBUG */
+
+
+#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
+# define DEFAULT_ROOT_PROMPT "\\u:\\w> "
+# define DEFAULT_USER_PROMPT "\\u:\\w$ "
+#else
+# define DEFAULT_ROOT_PROMPT "# "
+# define DEFAULT_USER_PROMPT "$ "
+#endif
+
+
+/* -------- sh.h -------- */
+/*
+ * shell
+ */
+
+#define	LINELIM	  2100
+#define	NPUSH	  8				/* limit to input nesting */
+
+#undef NOFILE
+#define	NOFILE	  20			/* Number of open files */
+#define	NUFILE	  10			/* Number of user-accessible files */
+#define	FDBASE	  10			/* First file usable by Shell */
+
+/*
+ * values returned by wait
+ */
+#define	WAITSIG(s)  ((s)&0177)
+#define	WAITVAL(s)  (((s)>>8)&0377)
+#define	WAITCORE(s) (((s)&0200)!=0)
+
+/*
+ * library and system definitions
+ */
+typedef void xint;				/* base type of jmp_buf, for not broken compilers */
+
+/*
+ * shell components
+ */
+
+#define	QUOTE	0200
+
+#define	NOBLOCK	((struct op *)NULL)
+#define	NOWORD	((char *)NULL)
+#define	NOWORDS	((char **)NULL)
+#define	NOPIPE	((int *)NULL)
+
+/*
+ * Description of a command or an operation on commands.
+ * Might eventually use a union.
+ */
+struct op {
+	int type;					/* operation type, see below */
+	char **words;				/* arguments to a command */
+	struct ioword **ioact;		/* IO actions (eg, < > >>) */
+	struct op *left;
+	struct op *right;
+	char *str;					/* identifier for case and for */
+};
+
+#define	TCOM	1				/* command */
+#define	TPAREN	2				/* (c-list) */
+#define	TPIPE	3				/* a | b */
+#define	TLIST	4				/* a [&;] b */
+#define	TOR		5				/* || */
+#define	TAND	6				/* && */
+#define	TFOR	7
+#define	TDO		8
+#define	TCASE	9
+#define	TIF		10
+#define	TWHILE	11
+#define	TUNTIL	12
+#define	TELIF	13
+#define	TPAT	14				/* pattern in case */
+#define	TBRACE	15				/* {c-list} */
+#define	TASYNC	16				/* c & */
+/* Added to support "." file expansion */
+#define	TDOT	17
+
+/* Strings for names to make debug easier */
+#ifdef MSHDEBUG
+static char *T_CMD_NAMES[] = {
+	"PLACEHOLDER",
+	"TCOM",
+	"TPAREN",
+	"TPIPE",
+	"TLIST",
+	"TOR",
+	"TAND",
+	"TFOR",
+	"TDO",
+	"TCASE",
+	"TIF",
+	"TWHILE",
+	"TUNTIL",
+	"TELIF",
+	"TPAT",
+	"TBRACE",
+	"TASYNC",
+	"TDOT",
+};
+#endif
+
+/*
+ * actions determining the environment of a process
+ */
+#define	BIT(i)	(1<<(i))
+#define	FEXEC	BIT(0)			/* execute without forking */
+
+#if 0							/* Original value */
+#define AREASIZE	(65000)
+#else
+#define AREASIZE	(90000)
+#endif
+
+/*
+ * flags to control evaluation of words
+ */
+#define	DOSUB	 1				/* interpret $, `, and quotes */
+#define	DOBLANK	 2				/* perform blank interpretation */
+#define	DOGLOB	 4				/* interpret [?* */
+#define	DOKEY	 8				/* move words with `=' to 2nd arg. list */
+#define	DOTRIM	 16				/* trim resulting string */
+
+#define	DOALL	(DOSUB|DOBLANK|DOGLOB|DOKEY|DOTRIM)
+
+
+/* PROTOTYPES */
+static int newfile(char *s);
+static char *findeq(char *cp);
+static char *cclass(char *p, int sub);
+static void initarea(void);
+extern int msh_main(int argc, char **argv);
+
+
+struct brkcon {
+	jmp_buf brkpt;
+	struct brkcon *nextlev;
+};
+
+
+/*
+ * redirection
+ */
+struct ioword {
+	short io_unit;				/* unit affected */
+	short io_flag;				/* action (below) */
+	char *io_name;				/* file name */
+};
+
+#define	IOREAD	 1				/* < */
+#define	IOHERE	 2				/* << (here file) */
+#define	IOWRITE	 4				/* > */
+#define	IOCAT	 8				/* >> */
+#define	IOXHERE	 16				/* ${}, ` in << */
+#define	IODUP	 32				/* >&digit */
+#define	IOCLOSE	 64				/* >&- */
+
+#define	IODEFAULT (-1)			/* token for default IO unit */
+
+
+
+/*
+ * parsing & execution environment
+ */
+static struct env {
+	char *linep;
+	struct io *iobase;
+	struct io *iop;
+	xint *errpt;				/* void * */
+	int iofd;
+	struct env *oenv;
+} e;
+
+/*
+ * flags:
+ * -e: quit on error
+ * -k: look for name=value everywhere on command line
+ * -n: no execution
+ * -t: exit after reading and executing one command
+ * -v: echo as read
+ * -x: trace
+ * -u: unset variables net diagnostic
+ */
+static char *flag;
+
+static char *null;				/* null value for variable */
+static int intr;				/* interrupt pending */
+
+static char *trap[_NSIG + 1];
+static char ourtrap[_NSIG + 1];
+static int trapset;				/* trap pending */
+
+static int heedint;				/* heed interrupt signals */
+
+static int yynerrs;				/* yacc */
+
+static char line[LINELIM];
+static char *elinep;
+
+
+/*
+ * other functions
+ */
+static int (*inbuilt(char *s)) (struct op *);
+
+static char *rexecve(char *c, char **v, char **envp);
+static char *space(int n);
+static char *strsave(char *s, int a);
+static char *evalstr(char *cp, int f);
+static char *putn(int n);
+static char *itoa(int n);
+static char *unquote(char *as);
+static struct var *lookup(char *n);
+static int rlookup(char *n);
+static struct wdblock *glob(char *cp, struct wdblock *wb);
+static int my_getc(int ec);
+static int subgetc(char ec, int quoted);
+static char **makenv(int all, struct wdblock *wb);
+static char **eval(char **ap, int f);
+static int setstatus(int s);
+static int waitfor(int lastpid, int canintr);
+
+static void onintr(int s);		/* SIGINT handler */
+
+static int newenv(int f);
+static void quitenv(void);
+static void err(char *s);
+static int anys(char *s1, char *s2);
+static int any(int c, char *s);
+static void next(int f);
+static void setdash(void);
+static void onecommand(void);
+static void runtrap(int i);
+static int gmatch(char *s, char *p);
+
+
+/*
+ * error handling
+ */
+static void leave(void);		/* abort shell (or fail in subshell) */
+static void fail(void);			/* fail but return to process next command */
+static void warn(char *s);
+static void sig(int i);			/* default signal handler */
+
+
+
+/* -------- area stuff -------- */
+
+#define	REGSIZE	  sizeof(struct region)
+#define GROWBY	  (256)
+/* #define	SHRINKBY   (64) */
+#undef	SHRINKBY
+#define FREE	  (32767)
+#define BUSY	  (0)
+#define	ALIGN	  (sizeof(int)-1)
+
+
+struct region {
+	struct region *next;
+	int area;
+};
+
+
+
+/* -------- grammar stuff -------- */
+typedef union {
+	char *cp;
+	char **wp;
+	int i;
+	struct op *o;
+} YYSTYPE;
+
+#define	WORD	256
+#define	LOGAND	257
+#define	LOGOR	258
+#define	BREAK	259
+#define	IF		260
+#define	THEN	261
+#define	ELSE	262
+#define	ELIF	263
+#define	FI		264
+#define	CASE	265
+#define	ESAC	266
+#define	FOR		267
+#define	WHILE	268
+#define	UNTIL	269
+#define	DO		270
+#define	DONE	271
+#define	IN		272
+/* Added for "." file expansion */
+#define	DOT		273
+
+#define	YYERRCODE 300
+
+/* flags to yylex */
+#define	CONTIN	01				/* skip new lines to complete command */
+
+#define	SYNTAXERR	zzerr()
+
+static struct op *pipeline(int cf);
+static struct op *andor(void);
+static struct op *c_list(void);
+static int synio(int cf);
+static void musthave(int c, int cf);
+static struct op *simple(void);
+static struct op *nested(int type, int mark);
+static struct op *command(int cf);
+static struct op *dogroup(int onlydone);
+static struct op *thenpart(void);
+static struct op *elsepart(void);
+static struct op *caselist(void);
+static struct op *casepart(void);
+static char **pattern(void);
+static char **wordlist(void);
+static struct op *list(struct op *t1, struct op *t2);
+static struct op *block(int type, struct op *t1, struct op *t2, char **wp);
+static struct op *newtp(void);
+static struct op *namelist(struct op *t);
+static char **copyw(void);
+static void word(char *cp);
+static struct ioword **copyio(void);
+static struct ioword *io(int u, int f, char *cp);
+static void zzerr(void);
+static void yyerror(char *s);
+static int yylex(int cf);
+static int collect(int c, int c1);
+static int dual(int c);
+static void diag(int ec);
+static char *tree(unsigned size);
+
+/* -------- var.h -------- */
+
+struct var {
+	char *value;
+	char *name;
+	struct var *next;
+	char status;
+};
+
+#define	COPYV	1				/* flag to setval, suggesting copy */
+#define	RONLY	01				/* variable is read-only */
+#define	EXPORT	02				/* variable is to be exported */
+#define	GETCELL	04				/* name & value space was got with getcell */
+
+static int yyparse(void);
+static struct var *lookup(char *n);
+static void setval(struct var *vp, char *val);
+static void nameval(struct var *vp, char *val, char *name);
+static void export(struct var *vp);
+static void ronly(struct var *vp);
+static int isassign(char *s);
+static int checkname(char *cp);
+static int assign(char *s, int cf);
+static void putvlist(int f, int out);
+static int eqname(char *n1, char *n2);
+
+static int execute(struct op *t, int *pin, int *pout, int act);
+
+
+/* -------- io.h -------- */
+/* io buffer */
+struct iobuf {
+	unsigned id;				/* buffer id */
+	char buf[512];				/* buffer */
+	char *bufp;					/* pointer into buffer */
+	char *ebufp;				/* pointer to end of buffer */
+};
+
+/* possible arguments to an IO function */
+struct ioarg {
+	char *aword;
+	char **awordlist;
+	int afile;					/* file descriptor */
+	unsigned afid;				/* buffer id */
+	long afpos;					/* file position */
+	struct iobuf *afbuf;		/* buffer for this file */
+};
+
+//static struct ioarg ioargstack[NPUSH];
+#define AFID_NOBUF	(~0)
+#define AFID_ID		0
+
+/* an input generator's state */
+struct io {
+	int (*iofn) (struct ioarg *, struct io *);
+	struct ioarg *argp;
+	int peekc;
+	char prev;					/* previous character read by readc() */
+	char nlcount;				/* for `'s */
+	char xchar;					/* for `'s */
+	char task;					/* reason for pushed IO */
+};
+
+//static    struct  io  iostack[NPUSH];
+#define	XOTHER	0				/* none of the below */
+#define	XDOLL	1				/* expanding ${} */
+#define	XGRAVE	2				/* expanding `'s */
+#define	XIO	3					/* file IO */
+
+/* in substitution */
+#define	INSUB()	(e.iop->task == XGRAVE || e.iop->task == XDOLL)
+
+
+/*
+ * input generators for IO structure
+ */
+static int nlchar(struct ioarg *ap);
+static int strchar(struct ioarg *ap);
+static int qstrchar(struct ioarg *ap);
+static int filechar(struct ioarg *ap);
+static int herechar(struct ioarg *ap);
+static int linechar(struct ioarg *ap);
+static int gravechar(struct ioarg *ap, struct io *iop);
+static int qgravechar(struct ioarg *ap, struct io *iop);
+static int dolchar(struct ioarg *ap);
+static int wdchar(struct ioarg *ap);
+static void scraphere(void);
+static void freehere(int area);
+static void gethere(void);
+static void markhere(char *s, struct ioword *iop);
+static int herein(char *hname, int xdoll);
+static int run(struct ioarg *argp, int (*f) (struct ioarg *));
+
+
+/*
+ * IO functions
+ */
+static int eofc(void);
+static int readc(void);
+static void unget(int c);
+static void ioecho(char c);
+static void prs(const char *s);
+static void prn(unsigned u);
+static void closef(int i);
+static void closeall(void);
+
+
+/*
+ * IO control
+ */
+static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));
+static int remap(int fd);
+static int openpipe(int *pv);
+static void closepipe(int *pv);
+static struct io *setbase(struct io *ip);
+
+#define	PUSHIO(what,arg,gen) ((temparg.what = (arg)),pushio(&temparg,(gen)))
+#define	RUN(what,arg,gen) ((temparg.what = (arg)), run(&temparg,(gen)))
+
+/* -------- word.h -------- */
+
+#define	NSTART	16				/* default number of words to allow for initially */
+
+struct wdblock {
+	short w_bsize;
+	short w_nword;
+	/* bounds are arbitrary */
+	char *w_words[1];
+};
+
+static struct wdblock *addword(char *wd, struct wdblock *wb);
+static struct wdblock *newword(int nw);
+static char **getwords(struct wdblock *wb);
+
+/* -------- area.h -------- */
+
+/*
+ * storage allocation
+ */
+static char *getcell(unsigned nbytes);
+static void garbage(void);
+static void setarea(char *cp, int a);
+static int getarea(char *cp);
+static void freearea(int a);
+static void freecell(char *cp);
+static int areanum;				/* current allocation area */
+
+#define	NEW(type)   (type *)getcell(sizeof(type))
+#define	DELETE(obj)	freecell((char *)obj)
+
+
+/* -------- misc stuff -------- */
+
+static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp);
+static int iosetup(struct ioword *iop, int pipein, int pipeout);
+static void echo(char **wp);
+static struct op **find1case(struct op *t, char *w);
+static struct op *findcase(struct op *t, char *w);
+static void brkset(struct brkcon *bc);
+static int dolabel(struct op *t);
+static int dohelp(struct op *t);
+static int dochdir(struct op *t);
+static int doshift(struct op *t);
+static int dologin(struct op *t);
+static int doumask(struct op *t);
+static int doexec(struct op *t);
+static int dodot(struct op *t);
+static int dowait(struct op *t);
+static int doread(struct op *t);
+static int doeval(struct op *t);
+static int dotrap(struct op *t);
+static int getsig(char *s);
+static void setsig(int n, sighandler_t f);
+static int getn(char *as);
+static int dobreak(struct op *t);
+static int docontinue(struct op *t);
+static int brkcontin(char *cp, int val);
+static int doexit(struct op *t);
+static int doexport(struct op *t);
+static int doreadonly(struct op *t);
+static void rdexp(char **wp, void (*f) (struct var *), int key);
+static void badid(char *s);
+static int doset(struct op *t);
+static void varput(char *s, int out);
+static int dotimes(struct op *t);
+static int expand(char *cp, struct wdblock **wbp, int f);
+static char *blank(int f);
+static int dollar(int quoted);
+static int grave(int quoted);
+static void globname(char *we, char *pp);
+static char *generate(char *start1, char *end1, char *middle, char *end);
+static int anyspcl(struct wdblock *wb);
+static int xstrcmp(char *p1, char *p2);
+static void glob0(char *a0, unsigned int a1, int a2,
+				  int (*a3) (char *, char *));
+static void glob1(char *base, char *lim);
+static void glob2(char *i, char *j);
+static void glob3(char *i, char *j, char *k);
+static void readhere(char **name, char *s, int ec);
+static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));
+static int xxchar(struct ioarg *ap);
+
+struct here {
+	char *h_tag;
+	int h_dosub;
+	struct ioword *h_iop;
+	struct here *h_next;
+};
+
+static const char * const signame[] = {
+	"Signal 0",
+	"Hangup",
+	(char *) NULL,				/* interrupt */
+	"Quit",
+	"Illegal instruction",
+	"Trace/BPT trap",
+	"Abort",
+	"Bus error",
+	"Floating Point Exception",
+	"Killed",
+	"SIGUSR1",
+	"SIGSEGV",
+	"SIGUSR2",
+	(char *) NULL,				/* broken pipe */
+	"Alarm clock",
+	"Terminated",
+};
+
+#define	NSIGNAL (sizeof(signame)/sizeof(signame[0]))
+
+struct res {
+	const char *r_name;
+	int r_val;
+};
+static const struct res restab[] = {
+	{"for", FOR},
+	{"case", CASE},
+	{"esac", ESAC},
+	{"while", WHILE},
+	{"do", DO},
+	{"done", DONE},
+	{"if", IF},
+	{"in", IN},
+	{"then", THEN},
+	{"else", ELSE},
+	{"elif", ELIF},
+	{"until", UNTIL},
+	{"fi", FI},
+	{";;", BREAK},
+	{"||", LOGOR},
+	{"&&", LOGAND},
+	{"{", '{'},
+	{"}", '}'},
+	{".", DOT},
+	{0, 0},
+};
+
+
+struct builtincmd {
+	const char *name;
+	int (*builtinfunc) (struct op * t);
+};
+static const struct builtincmd builtincmds[] = {
+	{".", dodot},
+	{":", dolabel},
+	{"break", dobreak},
+	{"cd", dochdir},
+	{"continue", docontinue},
+	{"eval", doeval},
+	{"exec", doexec},
+	{"exit", doexit},
+	{"export", doexport},
+	{"help", dohelp},
+	{"login", dologin},
+	{"newgrp", dologin},
+	{"read", doread},
+	{"readonly", doreadonly},
+	{"set", doset},
+	{"shift", doshift},
+	{"times", dotimes},
+	{"trap", dotrap},
+	{"umask", doumask},
+	{"wait", dowait},
+	{0, 0}
+};
+
+static struct op *scantree(struct op *);
+static struct op *dowholefile(int, int);
+
+/* Globals */
+extern char **environ;			/* environment pointer */
+
+static char **dolv;
+static int dolc;
+static int exstat;
+static char gflg;
+static int interactive;			/* Is this an interactive shell */
+static int execflg;
+static int multiline;			/* \n changed to ; */
+static struct op *outtree;		/* result from parser */
+static xint *failpt;
+static xint *errpt;
+static struct brkcon *brklist;
+static int isbreak;
+static struct wdblock *wdlist;
+static struct wdblock *iolist;
+static char *trap[_NSIG + 1];
+static char ourtrap[_NSIG + 1];
+static int trapset;				/* trap pending */
+static int yynerrs;				/* yacc */
+static char line[LINELIM];
+
+#ifdef MSHDEBUG
+static struct var *mshdbg_var;
+#endif
+static struct var *vlist;		/* dictionary */
+static struct var *homedir;		/* home directory */
+static struct var *prompt;		/* main prompt */
+static struct var *cprompt;		/* continuation prompt */
+static struct var *path;		/* search path for commands */
+static struct var *shell;		/* shell to interpret command files */
+static struct var *ifs;			/* field separators */
+
+static int areanum;				/* current allocation area */
+static int intr;
+static int inparse;
+static char flags['z' - 'a' + 1];
+static char *flag = flags - 'a';
+static char *null = "";
+static int heedint = 1;
+static void (*qflag) (int) = SIG_IGN;
+static int startl;
+static int peeksym;
+static int nlseen;
+static int iounit = IODEFAULT;
+static YYSTYPE yylval;
+static char *elinep = line + sizeof(line) - 5;
+
+static struct ioarg temparg = { 0, 0, 0, AFID_NOBUF, 0 };	/* temporary for PUSHIO */
+static struct ioarg ioargstack[NPUSH];
+static struct io iostack[NPUSH];
+static struct iobuf sharedbuf = { AFID_NOBUF };
+static struct iobuf mainbuf = { AFID_NOBUF };
+static unsigned bufid = AFID_ID;	/* buffer id counter */
+
+static struct here *inhere;		/* list of hear docs while parsing */
+static struct here *acthere;	/* list of active here documents */
+static struct region *areabot;	/* bottom of area */
+static struct region *areatop;	/* top of area */
+static struct region *areanxt;	/* starting point of scan */
+static void *brktop;
+static void *brkaddr;
+
+static struct env e = {
+	line,						/* linep:  char ptr */
+	iostack,					/* iobase:  struct io ptr */
+	iostack - 1,				/* iop:  struct io ptr */
+	(xint *) NULL,				/* errpt:  void ptr for errors? */
+	FDBASE,						/* iofd:  file desc  */
+	(struct env *) NULL			/* oenv:  struct env ptr */
+};
+
+#ifdef MSHDEBUG
+void print_t(struct op *t);
+void print_t(struct op *t)
+{
+	DBGPRINTF(("T: t=%p, type %s, words=%p, IOword=%p\n", t,
+	          T_CMD_NAMES[t->type], t->words, t->ioact));
+
+	if (t->words) {
+		DBGPRINTF(("T: W1: %s", t->words[0]));
+	}
+
+	return;
+}
+
+void print_tree(struct op *head);
+void print_tree(struct op *head)
+{
+	if (head == NULL) {
+		DBGPRINTF(("PRINT_TREE: no tree\n"));
+		return;
+	}
+
+	DBGPRINTF(("NODE: %p,  left %p, right %p\n", head, head->left,
+			   head->right));
+
+	if (head->left)
+		print_tree(head->left);
+
+	if (head->right)
+		print_tree(head->right);
+
+	return;
+}
+#endif							/* MSHDEBUG */
+
+
+#ifdef CONFIG_FEATURE_COMMAND_EDITING
+static char *current_prompt;
+#endif
+
+/* -------- sh.c -------- */
+/*
+ * shell
+ */
+
+
+int msh_main(int argc, char **argv)
+{
+	REGISTER int f;
+	REGISTER char *s;
+	int cflag;
+	char *name, **ap;
+	int (*iof) (struct ioarg *);
+
+	DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ));
+
+	initarea();
+	if ((ap = environ) != NULL) {
+		while (*ap)
+			assign(*ap++, !COPYV);
+		for (ap = environ; *ap;)
+			export(lookup(*ap++));
+	}
+	closeall();
+	areanum = 1;
+
+	shell = lookup("SHELL");
+	if (shell->value == null)
+		setval(shell, (char *)DEFAULT_SHELL);
+	export(shell);
+
+	homedir = lookup("HOME");
+	if (homedir->value == null)
+		setval(homedir, "/");
+	export(homedir);
+
+	setval(lookup("$"), putn(getpid()));
+
+	path = lookup("PATH");
+	if (path->value == null) {
+		if (geteuid() == 0)
+			setval(path, "/sbin:/bin:/usr/sbin:/usr/bin");
+		else
+			setval(path, "/bin:/usr/bin");
+	}
+	export(path);
+
+	ifs = lookup("IFS");
+	if (ifs->value == null)
+		setval(ifs, " \t\n");
+
+#ifdef MSHDEBUG
+	mshdbg_var = lookup("MSHDEBUG");
+	if (mshdbg_var->value == null)
+		setval(mshdbg_var, "0");
+#endif
+
+	prompt = lookup("PS1");
+#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
+	if (prompt->value == null)
+#endif
+		setval(prompt, DEFAULT_USER_PROMPT);
+	if (geteuid() == 0) {
+		setval(prompt, DEFAULT_ROOT_PROMPT);
+		prompt->status &= ~EXPORT;
+	}
+	cprompt = lookup("PS2");
+#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
+	if (cprompt->value == null)
+#endif
+		setval(cprompt, "> ");
+
+	iof = filechar;
+	cflag = 0;
+	name = *argv++;
+	if (--argc >= 1) {
+		if (argv[0][0] == '-' && argv[0][1] != '\0') {
+			for (s = argv[0] + 1; *s; s++)
+				switch (*s) {
+				case 'c':
+					prompt->status &= ~EXPORT;
+					cprompt->status &= ~EXPORT;
+					setval(prompt, "");
+					setval(cprompt, "");
+					cflag = 1;
+					if (--argc > 0)
+						PUSHIO(aword, *++argv, iof = nlchar);
+					break;
+
+				case 'q':
+					qflag = SIG_DFL;
+					break;
+
+				case 's':
+					/* standard input */
+					break;
+
+				case 't':
+					prompt->status &= ~EXPORT;
+					setval(prompt, "");
+					iof = linechar;
+					break;
+
+				case 'i':
+					interactive++;
+				default:
+					if (*s >= 'a' && *s <= 'z')
+						flag[(int) *s]++;
+				}
+		} else {
+			argv--;
+			argc++;
+		}
+
+		if (iof == filechar && --argc > 0) {
+			setval(prompt, "");
+			setval(cprompt, "");
+			prompt->status &= ~EXPORT;
+			cprompt->status &= ~EXPORT;
+
+/* Shell is non-interactive, activate printf-based debug */
+#ifdef MSHDEBUG
+			mshdbg = (int) (((char) (mshdbg_var->value[0])) - '0');
+			if (mshdbg < 0)
+				mshdbg = 0;
+#endif
+			DBGPRINTF(("MSH_MAIN: calling newfile()\n"));
+
+			if (newfile(name = *++argv))
+				exit(1);		/* Exit on error */
+		}
+	}
+
+	setdash();
+
+	/* This won't be true if PUSHIO has been called, say from newfile() above */
+	if (e.iop < iostack) {
+		PUSHIO(afile, 0, iof);
+		if (isatty(0) && isatty(1) && !cflag) {
+			interactive++;
+#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
+#ifdef MSHDEBUG
+			printf("\n\n%s Built-in shell (msh with debug)\n", BB_BANNER);
+#else
+			printf("\n\n%s Built-in shell (msh)\n", BB_BANNER);
+#endif
+			printf("Enter 'help' for a list of built-in commands.\n\n");
+#endif
+		}
+	}
+
+	signal(SIGQUIT, qflag);
+	if (name && name[0] == '-') {
+		interactive++;
+		if ((f = open(".profile", 0)) >= 0)
+			next(remap(f));
+		if ((f = open("/etc/profile", 0)) >= 0)
+			next(remap(f));
+	}
+	if (interactive)
+		signal(SIGTERM, sig);
+
+	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+		signal(SIGINT, onintr);
+	dolv = argv;
+	dolc = argc;
+	dolv[0] = name;
+	if (dolc > 1) {
+		for (ap = ++argv; --argc > 0;) {
+			if (assign(*ap = *argv++, !COPYV)) {
+				dolc--;			/* keyword */
+			} else {
+				ap++;
+			}
+		}
+	}
+	setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
+
+	DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, e.iop %p, iostack %p\n", interactive, e.iop, iostack));
+
+	for (;;) {
+		if (interactive && e.iop <= iostack) {
+#ifdef CONFIG_FEATURE_COMMAND_EDITING
+			current_prompt = prompt->value;
+#else
+			prs(prompt->value);
+#endif
+		}
+		onecommand();
+		/* Ensure that getenv("PATH") stays current */
+		setenv("PATH", path->value, 1);
+	}
+
+	DBGPRINTF(("MSH_MAIN: returning.\n"));
+}
+
+static void setdash(void)
+{
+	REGISTER char *cp;
+	REGISTER int c;
+	char m['z' - 'a' + 1];
+
+	cp = m;
+	for (c = 'a'; c <= 'z'; c++)
+		if (flag[(int) c])
+			*cp++ = c;
+	*cp = 0;
+	setval(lookup("-"), m);
+}
+
+static int newfile(REGISTER char *s)
+{
+	REGISTER int f;
+
+	DBGPRINTF7(("NEWFILE: opening %s\n", s));
+
+	if (strcmp(s, "-") != 0) {
+		DBGPRINTF(("NEWFILE: s is %s\n", s));
+		f = open(s, 0);
+		if (f < 0) {
+			prs(s);
+			err(": cannot open");
+			return (1);
+		}
+	} else
+		f = 0;
+
+	next(remap(f));
+	return (0);
+}
+
+
+struct op *scantree(struct op *head)
+{
+	struct op *dotnode;
+
+	if (head == NULL)
+		return (NULL);
+
+	if (head->left != NULL) {
+		dotnode = scantree(head->left);
+		if (dotnode)
+			return (dotnode);
+	}
+
+	if (head->right != NULL) {
+		dotnode = scantree(head->right);
+		if (dotnode)
+			return (dotnode);
+	}
+
+	if (head->words == NULL)
+		return (NULL);
+
+	DBGPRINTF5(("SCANTREE: checking node %p\n", head));
+
+	if ((head->type != TDOT) && (strcmp(".", head->words[0]) == 0)) {
+		DBGPRINTF5(("SCANTREE: dot found in node %p\n", head));
+		return (head);
+	}
+
+	return (NULL);
+}
+
+
+static void onecommand(void)
+{
+	REGISTER int i;
+	jmp_buf m1;
+
+	DBGPRINTF(("ONECOMMAND: enter, outtree=%p\n", outtree));
+
+	while (e.oenv)
+		quitenv();
+
+	areanum = 1;
+	freehere(areanum);
+	freearea(areanum);
+	garbage();
+	wdlist = 0;
+	iolist = 0;
+	e.errpt = 0;
+	e.linep = line;
+	yynerrs = 0;
+	multiline = 0;
+	inparse = 1;
+	intr = 0;
+	execflg = 0;
+
+	setjmp(failpt = m1);		/* Bruce Evans' fix */
+	if (setjmp(failpt = m1) || yyparse() || intr) {
+
+		DBGPRINTF(("ONECOMMAND: this is not good.\n"));
+
+		while (e.oenv)
+			quitenv();
+		scraphere();
+		if (!interactive && intr)
+			leave();
+		inparse = 0;
+		intr = 0;
+		return;
+	}
+
+	inparse = 0;
+	brklist = 0;
+	intr = 0;
+	execflg = 0;
+
+	if (!flag['n']) {
+		DBGPRINTF(("ONECOMMAND: calling execute, t=outtree=%p\n",
+				   outtree));
+		execute(outtree, NOPIPE, NOPIPE, 0);
+	}
+
+	if (!interactive && intr) {
+		execflg = 0;
+		leave();
+	}
+
+	if ((i = trapset) != 0) {
+		trapset = 0;
+		runtrap(i);
+	}
+}
+
+static void fail(void)
+{
+	longjmp(failpt, 1);
+	/* NOTREACHED */
+}
+
+static void leave(void)
+{
+	DBGPRINTF(("LEAVE: leave called!\n"));
+
+	if (execflg)
+		fail();
+	scraphere();
+	freehere(1);
+	runtrap(0);
+	_exit(exstat);
+	/* NOTREACHED */
+}
+
+static void warn(REGISTER char *s)
+{
+	if (*s) {
+		prs(s);
+		exstat = -1;
+	}
+	prs("\n");
+	if (flag['e'])
+		leave();
+}
+
+static void err(char *s)
+{
+	warn(s);
+	if (flag['n'])
+		return;
+	if (!interactive)
+		leave();
+	if (e.errpt)
+		longjmp(e.errpt, 1);
+	closeall();
+	e.iop = e.iobase = iostack;
+}
+
+static int newenv(int f)
+{
+	REGISTER struct env *ep;
+
+	DBGPRINTF(("NEWENV: f=%d (indicates quitenv and return)\n", f));
+
+	if (f) {
+		quitenv();
+		return (1);
+	}
+
+	ep = (struct env *) space(sizeof(*ep));
+	if (ep == NULL) {
+		while (e.oenv)
+			quitenv();
+		fail();
+	}
+	*ep = e;
+	e.oenv = ep;
+	e.errpt = errpt;
+
+	return (0);
+}
+
+static void quitenv(void)
+{
+	REGISTER struct env *ep;
+	REGISTER int fd;
+
+	DBGPRINTF(("QUITENV: e.oenv=%p\n", e.oenv));
+
+	if ((ep = e.oenv) != NULL) {
+		fd = e.iofd;
+		e = *ep;
+		/* should close `'d files */
+		DELETE(ep);
+		while (--fd >= e.iofd)
+			close(fd);
+	}
+}
+
+/*
+ * Is any character from s1 in s2?
+ */
+static int anys(REGISTER char *s1, REGISTER char *s2)
+{
+	while (*s1)
+		if (any(*s1++, s2))
+			return (1);
+	return (0);
+}
+
+/*
+ * Is character c in s?
+ */
+static int any(REGISTER int c, REGISTER char *s)
+{
+	while (*s)
+		if (*s++ == c)
+			return (1);
+	return (0);
+}
+
+static char *putn(REGISTER int n)
+{
+	return (itoa(n));
+}
+
+static char *itoa(REGISTER int n)
+{
+	static char s[20];
+
+	snprintf(s, sizeof(s), "%u", n);
+	return (s);
+}
+
+
+static void next(int f)
+{
+	PUSHIO(afile, f, filechar);
+}
+
+static void onintr(int s)					/* ANSI C requires a parameter */
+{
+	signal(SIGINT, onintr);
+	intr = 1;
+	if (interactive) {
+		if (inparse) {
+			prs("\n");
+			fail();
+		}
+	} else if (heedint) {
+		execflg = 0;
+		leave();
+	}
+}
+
+static char *space(int n)
+{
+	REGISTER char *cp;
+
+	if ((cp = getcell(n)) == 0)
+		err("out of string space");
+	return (cp);
+}
+
+static char *strsave(REGISTER char *s, int a)
+{
+	REGISTER char *cp, *xp;
+
+	if ((cp = space(strlen(s) + 1)) != NULL) {
+		setarea((char *) cp, a);
+		for (xp = cp; (*xp++ = *s++) != '\0';);
+		return (cp);
+	}
+	return ("");
+}
+
+/*
+ * trap handling
+ */
+static void sig(REGISTER int i)
+{
+	trapset = i;
+	signal(i, sig);
+}
+
+static void runtrap(int i)
+{
+	char *trapstr;
+
+	if ((trapstr = trap[i]) == NULL)
+		return;
+
+	if (i == 0)
+		trap[i] = 0;
+
+	RUN(aword, trapstr, nlchar);
+}
+
+/* -------- var.c -------- */
+
+/*
+ * Find the given name in the dictionary
+ * and return its value.  If the name was
+ * not previously there, enter it now and
+ * return a null value.
+ */
+static struct var *lookup(REGISTER char *n)
+{
+	REGISTER struct var *vp;
+	REGISTER char *cp;
+	REGISTER int c;
+	static struct var dummy;
+
+	if (isdigit(*n)) {
+		dummy.name = n;
+		for (c = 0; isdigit(*n) && c < 1000; n++)
+			c = c * 10 + *n - '0';
+		dummy.status = RONLY;
+		dummy.value = c <= dolc ? dolv[c] : null;
+		return (&dummy);
+	}
+	for (vp = vlist; vp; vp = vp->next)
+		if (eqname(vp->name, n))
+			return (vp);
+	cp = findeq(n);
+	vp = (struct var *) space(sizeof(*vp));
+	if (vp == 0 || (vp->name = space((int) (cp - n) + 2)) == 0) {
+		dummy.name = dummy.value = "";
+		return (&dummy);
+	}
+	for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++);
+	if (*cp == 0)
+		*cp = '=';
+	*++cp = 0;
+	setarea((char *) vp, 0);
+	setarea((char *) vp->name, 0);
+	vp->value = null;
+	vp->next = vlist;
+	vp->status = GETCELL;
+	vlist = vp;
+	return (vp);
+}
+
+/*
+ * give variable at `vp' the value `val'.
+ */
+static void setval(struct var *vp, char *val)
+{
+	nameval(vp, val, (char *) NULL);
+}
+
+/*
+ * if name is not NULL, it must be
+ * a prefix of the space `val',
+ * and end with `='.
+ * this is all so that exporting
+ * values is reasonably painless.
+ */
+static void nameval(REGISTER struct var *vp, char *val, char *name)
+{
+	REGISTER char *cp, *xp;
+	char *nv;
+	int fl;
+
+	if (vp->status & RONLY) {
+		for (xp = vp->name; *xp && *xp != '=';)
+			putc(*xp++, stderr);
+		err(" is read-only");
+		return;
+	}
+	fl = 0;
+	if (name == NULL) {
+		xp = space(strlen(vp->name) + strlen(val) + 2);
+		if (xp == 0)
+			return;
+		/* make string:  name=value */
+		setarea((char *) xp, 0);
+		name = xp;
+		for (cp = vp->name; (*xp = *cp++) && *xp != '='; xp++);
+		if (*xp++ == 0)
+			xp[-1] = '=';
+		nv = xp;
+		for (cp = val; (*xp++ = *cp++) != '\0';);
+		val = nv;
+		fl = GETCELL;
+	}
+	if (vp->status & GETCELL)
+		freecell(vp->name);		/* form new string `name=value' */
+	vp->name = name;
+	vp->value = val;
+	vp->status |= fl;
+}
+
+static void export(struct var *vp)
+{
+	vp->status |= EXPORT;
+}
+
+static void ronly(struct var *vp)
+{
+	if (isalpha(vp->name[0]) || vp->name[0] == '_')	/* not an internal symbol */
+		vp->status |= RONLY;
+}
+
+static int isassign(REGISTER char *s)
+{
+	DBGPRINTF7(("ISASSIGN: enter, s=%s\n", s));
+
+	if (!isalpha((int) *s) && *s != '_')
+		return (0);
+	for (; *s != '='; s++)
+		if (*s == 0 || (!isalnum(*s) && *s != '_'))
+			return (0);
+
+	return (1);
+}
+
+static int assign(REGISTER char *s, int cf)
+{
+	REGISTER char *cp;
+	struct var *vp;
+
+	DBGPRINTF7(("ASSIGN: enter, s=%s, cf=%d\n", s, cf));
+
+	if (!isalpha(*s) && *s != '_')
+		return (0);
+	for (cp = s; *cp != '='; cp++)
+		if (*cp == 0 || (!isalnum(*cp) && *cp != '_'))
+			return (0);
+	vp = lookup(s);
+	nameval(vp, ++cp, cf == COPYV ? (char *) NULL : s);
+	if (cf != COPYV)
+		vp->status &= ~GETCELL;
+	return (1);
+}
+
+static int checkname(REGISTER char *cp)
+{
+	DBGPRINTF7(("CHECKNAME: enter, cp=%s\n", cp));
+
+	if (!isalpha(*cp++) && *(cp - 1) != '_')
+		return (0);
+	while (*cp)
+		if (!isalnum(*cp++) && *(cp - 1) != '_')
+			return (0);
+	return (1);
+}
+
+static void putvlist(REGISTER int f, REGISTER int out)
+{
+	REGISTER struct var *vp;
+
+	for (vp = vlist; vp; vp = vp->next)
+		if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) {
+			if (vp->status & EXPORT)
+				write(out, "export ", 7);
+			if (vp->status & RONLY)
+				write(out, "readonly ", 9);
+			write(out, vp->name, (int) (findeq(vp->name) - vp->name));
+			write(out, "\n", 1);
+		}
+}
+
+static int eqname(REGISTER char *n1, REGISTER char *n2)
+{
+	for (; *n1 != '=' && *n1 != 0; n1++)
+		if (*n2++ != *n1)
+			return (0);
+	return (*n2 == 0 || *n2 == '=');
+}
+
+static char *findeq(REGISTER char *cp)
+{
+	while (*cp != '\0' && *cp != '=')
+		cp++;
+	return (cp);
+}
+
+/* -------- gmatch.c -------- */
+/*
+ * int gmatch(string, pattern)
+ * char *string, *pattern;
+ *
+ * Match a pattern as in sh(1).
+ */
+
+#define	CMASK	0377
+#define	QUOTE	0200
+#define	QMASK	(CMASK&~QUOTE)
+#define	NOT	'!'					/* might use ^ */
+
+static int gmatch(REGISTER char *s, REGISTER char *p)
+{
+	REGISTER int sc, pc;
+
+	if (s == NULL || p == NULL)
+		return (0);
+	while ((pc = *p++ & CMASK) != '\0') {
+		sc = *s++ & QMASK;
+		switch (pc) {
+		case '[':
+			if ((p = cclass(p, sc)) == NULL)
+				return (0);
+			break;
+
+		case '?':
+			if (sc == 0)
+				return (0);
+			break;
+
+		case '*':
+			s--;
+			do {
+				if (*p == '\0' || gmatch(s, p))
+					return (1);
+			} while (*s++ != '\0');
+			return (0);
+
+		default:
+			if (sc != (pc & ~QUOTE))
+				return (0);
+		}
+	}
+	return (*s == 0);
+}
+
+static char *cclass(REGISTER char *p, REGISTER int sub)
+{
+	REGISTER int c, d, not, found;
+
+	if ((not = *p == NOT) != 0)
+		p++;
+	found = not;
+	do {
+		if (*p == '\0')
+			return ((char *) NULL);
+		c = *p & CMASK;
+		if (p[1] == '-' && p[2] != ']') {
+			d = p[2] & CMASK;
+			p++;
+		} else
+			d = c;
+		if (c == sub || (c <= sub && sub <= d))
+			found = !not;
+	} while (*++p != ']');
+	return (found ? p + 1 : (char *) NULL);
+}
+
+
+/* -------- area.c -------- */
+
+/*
+ * All memory between (char *)areabot and (char *)(areatop+1) is
+ * exclusively administered by the area management routines.
+ * It is assumed that sbrk() and brk() manipulate the high end.
+ */
+
+#define sbrk(X) ({ void * __q = (void *)-1; if (brkaddr + (int)(X) < brktop) { __q = brkaddr; brkaddr+=(int)(X); } __q;})
+
+static void initarea(void)
+{
+	brkaddr = xmalloc(AREASIZE);
+	brktop = brkaddr + AREASIZE;
+
+	while ((long) sbrk(0) & ALIGN)
+		sbrk(1);
+	areabot = (struct region *) sbrk(REGSIZE);
+
+	areabot->next = areabot;
+	areabot->area = BUSY;
+	areatop = areabot;
+	areanxt = areabot;
+}
+
+char *getcell(unsigned nbytes)
+{
+	REGISTER int nregio;
+	REGISTER struct region *p, *q;
+	REGISTER int i;
+
+	if (nbytes == 0) {
+		puts("getcell(0)");
+		abort();
+	}
+	/* silly and defeats the algorithm */
+	/*
+	 * round upwards and add administration area
+	 */
+	nregio = (nbytes + (REGSIZE - 1)) / REGSIZE + 1;
+	for (p = areanxt;;) {
+		if (p->area > areanum) {
+			/*
+			 * merge free cells
+			 */
+			while ((q = p->next)->area > areanum && q != areanxt)
+				p->next = q->next;
+			/*
+			 * exit loop if cell big enough
+			 */
+			if (q >= p + nregio)
+				goto found;
+		}
+		p = p->next;
+		if (p == areanxt)
+			break;
+	}
+	i = nregio >= GROWBY ? nregio : GROWBY;
+	p = (struct region *) sbrk(i * REGSIZE);
+	if (p == (struct region *) -1)
+		return ((char *) NULL);
+	p--;
+	if (p != areatop) {
+		puts("not contig");
+		abort();				/* allocated areas are contiguous */
+	}
+	q = p + i;
+	p->next = q;
+	p->area = FREE;
+	q->next = areabot;
+	q->area = BUSY;
+	areatop = q;
+  found:
+	/*
+	 * we found a FREE area big enough, pointed to by 'p', and up to 'q'
+	 */
+	areanxt = p + nregio;
+	if (areanxt < q) {
+		/*
+		 * split into requested area and rest
+		 */
+		if (areanxt + 1 > q) {
+			puts("OOM");
+			abort();			/* insufficient space left for admin */
+		}
+		areanxt->next = q;
+		areanxt->area = FREE;
+		p->next = areanxt;
+	}
+	p->area = areanum;
+	return ((char *) (p + 1));
+}
+
+static void freecell(char *cp)
+{
+	REGISTER struct region *p;
+
+	if ((p = (struct region *) cp) != NULL) {
+		p--;
+		if (p < areanxt)
+			areanxt = p;
+		p->area = FREE;
+	}
+}
+
+static void freearea(REGISTER int a)
+{
+	REGISTER struct region *p, *top;
+
+	top = areatop;
+	for (p = areabot; p != top; p = p->next)
+		if (p->area >= a)
+			p->area = FREE;
+}
+
+static void setarea(char *cp, int a)
+{
+	REGISTER struct region *p;
+
+	if ((p = (struct region *) cp) != NULL)
+		(p - 1)->area = a;
+}
+
+int getarea(char *cp)
+{
+	return ((struct region *) cp - 1)->area;
+}
+
+static void garbage(void)
+{
+	REGISTER struct region *p, *q, *top;
+
+	top = areatop;
+	for (p = areabot; p != top; p = p->next) {
+		if (p->area > areanum) {
+			while ((q = p->next)->area > areanum)
+				p->next = q->next;
+			areanxt = p;
+		}
+	}
+#ifdef SHRINKBY
+	if (areatop >= q + SHRINKBY && q->area > areanum) {
+		brk((char *) (q + 1));
+		q->next = areabot;
+		q->area = BUSY;
+		areatop = q;
+	}
+#endif
+}
+
+/* -------- csyn.c -------- */
+/*
+ * shell: syntax (C version)
+ */
+
+int yyparse(void)
+{
+	DBGPRINTF7(("YYPARSE: enter...\n"));
+
+	startl = 1;
+	peeksym = 0;
+	yynerrs = 0;
+	outtree = c_list();
+	musthave('\n', 0);
+	return (yynerrs != 0);
+}
+
+static struct op *pipeline(int cf)
+{
+	REGISTER struct op *t, *p;
+	REGISTER int c;
+
+	DBGPRINTF7(("PIPELINE: enter, cf=%d\n", cf));
+
+	t = command(cf);
+
+	DBGPRINTF9(("PIPELINE: t=%p\n", t));
+
+	if (t != NULL) {
+		while ((c = yylex(0)) == '|') {
+			if ((p = command(CONTIN)) == NULL) {
+				DBGPRINTF8(("PIPELINE: error!\n"));
+				SYNTAXERR;
+			}
+
+			if (t->type != TPAREN && t->type != TCOM) {
+				/* shell statement */
+				t = block(TPAREN, t, NOBLOCK, NOWORDS);
+			}
+
+			t = block(TPIPE, t, p, NOWORDS);
+		}
+		peeksym = c;
+	}
+
+	DBGPRINTF7(("PIPELINE: returning t=%p\n", t));
+	return (t);
+}
+
+static struct op *andor(void)
+{
+	REGISTER struct op *t, *p;
+	REGISTER int c;
+
+	DBGPRINTF7(("ANDOR: enter...\n"));
+
+	t = pipeline(0);
+
+	DBGPRINTF9(("ANDOR: t=%p\n", t));
+
+	if (t != NULL) {
+		while ((c = yylex(0)) == LOGAND || c == LOGOR) {
+			if ((p = pipeline(CONTIN)) == NULL) {
+				DBGPRINTF8(("ANDOR: error!\n"));
+				SYNTAXERR;
+			}
+
+			t = block(c == LOGAND ? TAND : TOR, t, p, NOWORDS);
+		}						/* WHILE */
+
+		peeksym = c;
+	}
+
+	DBGPRINTF7(("ANDOR: returning t=%p\n", t));
+	return (t);
+}
+
+static struct op *c_list(void)
+{
+	REGISTER struct op *t, *p;
+	REGISTER int c;
+
+	DBGPRINTF7(("C_LIST: enter...\n"));
+
+	t = andor();
+
+	if (t != NULL) {
+		if ((peeksym = yylex(0)) == '&')
+			t = block(TASYNC, t, NOBLOCK, NOWORDS);
+
+		while ((c = yylex(0)) == ';' || c == '&'
+			   || (multiline && c == '\n')) {
+
+			if ((p = andor()) == NULL)
+				return (t);
+
+			if ((peeksym = yylex(0)) == '&')
+				p = block(TASYNC, p, NOBLOCK, NOWORDS);
+
+			t = list(t, p);
+		}						/* WHILE */
+
+		peeksym = c;
+	}
+	/* IF */
+	DBGPRINTF7(("C_LIST: returning t=%p\n", t));
+	return (t);
+}
+
+static int synio(int cf)
+{
+	REGISTER struct ioword *iop;
+	REGISTER int i;
+	REGISTER int c;
+
+	DBGPRINTF7(("SYNIO: enter, cf=%d\n", cf));
+
+	if ((c = yylex(cf)) != '<' && c != '>') {
+		peeksym = c;
+		return (0);
+	}
+
+	i = yylval.i;
+	musthave(WORD, 0);
+	iop = io(iounit, i, yylval.cp);
+	iounit = IODEFAULT;
+
+	if (i & IOHERE)
+		markhere(yylval.cp, iop);
+
+	DBGPRINTF7(("SYNIO: returning 1\n"));
+	return (1);
+}
+
+static void musthave(int c, int cf)
+{
+	if ((peeksym = yylex(cf)) != c) {
+		DBGPRINTF7(("MUSTHAVE: error!\n"));
+		SYNTAXERR;
+	}
+
+	peeksym = 0;
+}
+
+static struct op *simple(void)
+{
+	REGISTER struct op *t;
+
+	t = NULL;
+	for (;;) {
+		switch (peeksym = yylex(0)) {
+		case '<':
+		case '>':
+			(void) synio(0);
+			break;
+
+		case WORD:
+			if (t == NULL) {
+				t = newtp();
+				t->type = TCOM;
+			}
+			peeksym = 0;
+			word(yylval.cp);
+			break;
+
+		default:
+			return (t);
+		}
+	}
+}
+
+static struct op *nested(int type, int mark)
+{
+	REGISTER struct op *t;
+
+	DBGPRINTF3(("NESTED: enter, type=%d, mark=%d\n", type, mark));
+
+	multiline++;
+	t = c_list();
+	musthave(mark, 0);
+	multiline--;
+	return (block(type, t, NOBLOCK, NOWORDS));
+}
+
+static struct op *command(int cf)
+{
+	REGISTER struct op *t;
+	struct wdblock *iosave;
+	REGISTER int c;
+
+	DBGPRINTF(("COMMAND: enter, cf=%d\n", cf));
+
+	iosave = iolist;
+	iolist = NULL;
+
+	if (multiline)
+		cf |= CONTIN;
+
+	while (synio(cf))
+		cf = 0;
+
+	c = yylex(cf);
+
+	switch (c) {
+	default:
+		peeksym = c;
+		if ((t = simple()) == NULL) {
+			if (iolist == NULL)
+				return ((struct op *) NULL);
+			t = newtp();
+			t->type = TCOM;
+		}
+		break;
+
+	case '(':
+		t = nested(TPAREN, ')');
+		break;
+
+	case '{':
+		t = nested(TBRACE, '}');
+		break;
+
+	case FOR:
+		t = newtp();
+		t->type = TFOR;
+		musthave(WORD, 0);
+		startl = 1;
+		t->str = yylval.cp;
+		multiline++;
+		t->words = wordlist();
+		if ((c = yylex(0)) != '\n' && c != ';')
+			peeksym = c;
+		t->left = dogroup(0);
+		multiline--;
+		break;
+
+	case WHILE:
+	case UNTIL:
+		multiline++;
+		t = newtp();
+		t->type = c == WHILE ? TWHILE : TUNTIL;
+		t->left = c_list();
+		t->right = dogroup(1);
+		t->words = NULL;
+		multiline--;
+		break;
+
+	case CASE:
+		t = newtp();
+		t->type = TCASE;
+		musthave(WORD, 0);
+		t->str = yylval.cp;
+		startl++;
+		multiline++;
+		musthave(IN, CONTIN);
+		startl++;
+
+		t->left = caselist();
+
+		musthave(ESAC, 0);
+		multiline--;
+		break;
+
+	case IF:
+		multiline++;
+		t = newtp();
+		t->type = TIF;
+		t->left = c_list();
+		t->right = thenpart();
+		musthave(FI, 0);
+		multiline--;
+		break;
+
+	case DOT:
+		t = newtp();
+		t->type = TDOT;
+
+		musthave(WORD, 0);		/* gets name of file */
+		DBGPRINTF7(("COMMAND: DOT clause, yylval.cp is %s\n", yylval.cp));
+
+		word(yylval.cp);		/* add word to wdlist */
+		word(NOWORD);			/* terminate  wdlist */
+		t->words = copyw();		/* dup wdlist */
+		break;
+
+	}
+
+	while (synio(0));
+
+	t = namelist(t);
+	iolist = iosave;
+
+	DBGPRINTF(("COMMAND: returning %p\n", t));
+
+	return (t);
+}
+
+static struct op *dowholefile(int type, int mark)
+{
+	REGISTER struct op *t;
+
+	DBGPRINTF(("DOWHOLEFILE: enter, type=%d, mark=%d\n", type, mark));
+
+	multiline++;
+	t = c_list();
+	multiline--;
+	t = block(type, t, NOBLOCK, NOWORDS);
+	DBGPRINTF(("DOWHOLEFILE: return t=%p\n", t));
+	return (t);
+}
+
+static struct op *dogroup(int onlydone)
+{
+	REGISTER int c;
+	REGISTER struct op *mylist;
+
+	c = yylex(CONTIN);
+	if (c == DONE && onlydone)
+		return ((struct op *) NULL);
+	if (c != DO)
+		SYNTAXERR;
+	mylist = c_list();
+	musthave(DONE, 0);
+	return (mylist);
+}
+
+static struct op *thenpart(void)
+{
+	REGISTER int c;
+	REGISTER struct op *t;
+
+	if ((c = yylex(0)) != THEN) {
+		peeksym = c;
+		return ((struct op *) NULL);
+	}
+	t = newtp();
+	t->type = 0;
+	t->left = c_list();
+	if (t->left == NULL)
+		SYNTAXERR;
+	t->right = elsepart();
+	return (t);
+}
+
+static struct op *elsepart(void)
+{
+	REGISTER int c;
+	REGISTER struct op *t;
+
+	switch (c = yylex(0)) {
+	case ELSE:
+		if ((t = c_list()) == NULL)
+			SYNTAXERR;
+		return (t);
+
+	case ELIF:
+		t = newtp();
+		t->type = TELIF;
+		t->left = c_list();
+		t->right = thenpart();
+		return (t);
+
+	default:
+		peeksym = c;
+		return ((struct op *) NULL);
+	}
+}
+
+static struct op *caselist(void)
+{
+	REGISTER struct op *t;
+
+	t = NULL;
+	while ((peeksym = yylex(CONTIN)) != ESAC) {
+		DBGPRINTF(("CASELIST, doing yylex, peeksym=%d\n", peeksym));
+		t = list(t, casepart());
+	}
+
+	DBGPRINTF(("CASELIST, returning t=%p\n", t));
+	return (t);
+}
+
+static struct op *casepart(void)
+{
+	REGISTER struct op *t;
+
+	DBGPRINTF7(("CASEPART: enter...\n"));
+
+	t = newtp();
+	t->type = TPAT;
+	t->words = pattern();
+	musthave(')', 0);
+	t->left = c_list();
+	if ((peeksym = yylex(CONTIN)) != ESAC)
+		musthave(BREAK, CONTIN);
+
+	DBGPRINTF7(("CASEPART: made newtp(TPAT, t=%p)\n", t));
+
+	return (t);
+}
+
+static char **pattern(void)
+{
+	REGISTER int c, cf;
+
+	cf = CONTIN;
+	do {
+		musthave(WORD, cf);
+		word(yylval.cp);
+		cf = 0;
+	} while ((c = yylex(0)) == '|');
+	peeksym = c;
+	word(NOWORD);
+
+	return (copyw());
+}
+
+static char **wordlist(void)
+{
+	REGISTER int c;
+
+	if ((c = yylex(0)) != IN) {
+		peeksym = c;
+		return ((char **) NULL);
+	}
+	startl = 0;
+	while ((c = yylex(0)) == WORD)
+		word(yylval.cp);
+	word(NOWORD);
+	peeksym = c;
+	return (copyw());
+}
+
+/*
+ * supporting functions
+ */
+static struct op *list(REGISTER struct op *t1, REGISTER struct op *t2)
+{
+	DBGPRINTF7(("LIST: enter, t1=%p, t2=%p\n", t1, t2));
+
+	if (t1 == NULL)
+		return (t2);
+	if (t2 == NULL)
+		return (t1);
+
+	return (block(TLIST, t1, t2, NOWORDS));
+}
+
+static struct op *block(int type, struct op *t1, struct op *t2, char **wp)
+{
+	REGISTER struct op *t;
+
+	DBGPRINTF7(("BLOCK: enter, type=%d (%s)\n", type, T_CMD_NAMES[type]));
+
+	t = newtp();
+	t->type = type;
+	t->left = t1;
+	t->right = t2;
+	t->words = wp;
+
+	DBGPRINTF7(("BLOCK: inserted %p between %p and %p\n", t, t1,
+				t2));
+
+	return (t);
+}
+
+/* See if given string is a shell multiline (FOR, IF, etc) */
+static int rlookup(REGISTER char *n)
+{
+	REGISTER const struct res *rp;
+
+	DBGPRINTF7(("RLOOKUP: enter, n is %s\n", n));
+
+	for (rp = restab; rp->r_name; rp++)
+		if (strcmp(rp->r_name, n) == 0) {
+			DBGPRINTF7(("RLOOKUP: match, returning %d\n", rp->r_val));
+			return (rp->r_val);	/* Return numeric code for shell multiline */
+		}
+
+	DBGPRINTF7(("RLOOKUP: NO match, returning 0\n"));
+	return (0);					/* Not a shell multiline */
+}
+
+static struct op *newtp(void)
+{
+	REGISTER struct op *t;
+
+	t = (struct op *) tree(sizeof(*t));
+	t->type = 0;
+	t->words = NULL;
+	t->ioact = NULL;
+	t->left = NULL;
+	t->right = NULL;
+	t->str = NULL;
+
+	DBGPRINTF3(("NEWTP: allocated %p\n", t));
+
+	return (t);
+}
+
+static struct op *namelist(REGISTER struct op *t)
+{
+
+	DBGPRINTF7(("NAMELIST: enter, t=%p, type %s, iolist=%p\n", t,
+				T_CMD_NAMES[t->type], iolist));
+
+	if (iolist) {
+		iolist = addword((char *) NULL, iolist);
+		t->ioact = copyio();
+	} else
+		t->ioact = NULL;
+
+	if (t->type != TCOM) {
+		if (t->type != TPAREN && t->ioact != NULL) {
+			t = block(TPAREN, t, NOBLOCK, NOWORDS);
+			t->ioact = t->left->ioact;
+			t->left->ioact = NULL;
+		}
+		return (t);
+	}
+
+	word(NOWORD);
+	t->words = copyw();
+
+
+	return (t);
+}
+
+static char **copyw(void)
+{
+	REGISTER char **wd;
+
+	wd = getwords(wdlist);
+	wdlist = 0;
+	return (wd);
+}
+
+static void word(char *cp)
+{
+	wdlist = addword(cp, wdlist);
+}
+
+static struct ioword **copyio(void)
+{
+	REGISTER struct ioword **iop;
+
+	iop = (struct ioword **) getwords(iolist);
+	iolist = 0;
+	return (iop);
+}
+
+static struct ioword *io(int u, int f, char *cp)
+{
+	REGISTER struct ioword *iop;
+
+	iop = (struct ioword *) tree(sizeof(*iop));
+	iop->io_unit = u;
+	iop->io_flag = f;
+	iop->io_name = cp;
+	iolist = addword((char *) iop, iolist);
+	return (iop);
+}
+
+static void zzerr(void)
+{
+	yyerror("syntax error");
+}
+
+static void yyerror(char *s)
+{
+	yynerrs++;
+	if (interactive && e.iop <= iostack) {
+		multiline = 0;
+		while (eofc() == 0 && yylex(0) != '\n');
+	}
+	err(s);
+	fail();
+}
+
+static int yylex(int cf)
+{
+	REGISTER int c, c1;
+	int atstart;
+
+	if ((c = peeksym) > 0) {
+		peeksym = 0;
+		if (c == '\n')
+			startl = 1;
+		return (c);
+	}
+
+
+	nlseen = 0;
+	atstart = startl;
+	startl = 0;
+	yylval.i = 0;
+	e.linep = line;
+
+/* MALAMO */
+	line[LINELIM - 1] = '\0';
+
+  loop:
+	while ((c = my_getc(0)) == ' ' || c == '\t')	/* Skip whitespace */
+		;
+
+	switch (c) {
+	default:
+		if (any(c, "0123456789")) {
+			unget(c1 = my_getc(0));
+			if (c1 == '<' || c1 == '>') {
+				iounit = c - '0';
+				goto loop;
+			}
+			*e.linep++ = c;
+			c = c1;
+		}
+		break;
+
+	case '#':					/* Comment, skip to next newline or End-of-string */
+		while ((c = my_getc(0)) != 0 && c != '\n');
+		unget(c);
+		goto loop;
+
+	case 0:
+		DBGPRINTF5(("YYLEX: return 0, c=%d\n", c));
+		return (c);
+
+	case '$':
+		DBGPRINTF9(("YYLEX: found $\n"));
+		*e.linep++ = c;
+		if ((c = my_getc(0)) == '{') {
+			if ((c = collect(c, '}')) != '\0')
+				return (c);
+			goto pack;
+		}
+		break;
+
+	case '`':
+	case '\'':
+	case '"':
+		if ((c = collect(c, c)) != '\0')
+			return (c);
+		goto pack;
+
+	case '|':
+	case '&':
+	case ';':
+		startl = 1;
+		/* If more chars process them, else return NULL char */
+		if ((c1 = dual(c)) != '\0')
+			return (c1);
+		else
+			return (c);
+
+	case '^':
+		startl = 1;
+		return ('|');
+	case '>':
+	case '<':
+		diag(c);
+		return (c);
+
+	case '\n':
+		nlseen++;
+		gethere();
+		startl = 1;
+		if (multiline || cf & CONTIN) {
+			if (interactive && e.iop <= iostack) {
+#ifdef CONFIG_FEATURE_COMMAND_EDITING
+				current_prompt = cprompt->value;
+#else
+				prs(cprompt->value);
+#endif
+			}
+			if (cf & CONTIN)
+				goto loop;
+		}
+		return (c);
+
+	case '(':
+	case ')':
+		startl = 1;
+		return (c);
+	}
+
+	unget(c);
+
+  pack:
+	while ((c = my_getc(0)) != 0 && !any(c, "`$ '\"\t;&<>()|^\n")) {
+		if (e.linep >= elinep)
+			err("word too long");
+		else
+			*e.linep++ = c;
+	};
+
+	unget(c);
+
+	if (any(c, "\"'`$"))
+		goto loop;
+
+	*e.linep++ = '\0';
+
+	if (atstart && (c = rlookup(line)) != 0) {
+		startl = 1;
+		return (c);
+	}
+
+	yylval.cp = strsave(line, areanum);
+	return (WORD);
+}
+
+
+static int collect(REGISTER int c, REGISTER int c1)
+{
+	char s[2];
+
+	DBGPRINTF8(("COLLECT: enter, c=%d, c1=%d\n", c, c1));
+
+	*e.linep++ = c;
+	while ((c = my_getc(c1)) != c1) {
+		if (c == 0) {
+			unget(c);
+			s[0] = c1;
+			s[1] = 0;
+			prs("no closing ");
+			yyerror(s);
+			return (YYERRCODE);
+		}
+		if (interactive && c == '\n' && e.iop <= iostack) {
+#ifdef CONFIG_FEATURE_COMMAND_EDITING
+			current_prompt = cprompt->value;
+#else
+			prs(cprompt->value);
+#endif
+		}
+		*e.linep++ = c;
+	}
+
+	*e.linep++ = c;
+
+	DBGPRINTF8(("COLLECT: return 0, line is %s\n", line));
+
+	return (0);
+}
+
+/* "multiline commands" helper func */
+/* see if next 2 chars form a shell multiline */
+static int dual(REGISTER int c)
+{
+	char s[3];
+	REGISTER char *cp = s;
+
+	DBGPRINTF8(("DUAL: enter, c=%d\n", c));
+
+	*cp++ = c;					/* c is the given "peek" char */
+	*cp++ = my_getc(0);			/* get next char of input */
+	*cp = 0;					/* add EOS marker */
+
+	c = rlookup(s);				/* see if 2 chars form a shell multiline */
+	if (c == 0)
+		unget(*--cp);			/* String is not a shell multiline, put peek char back */
+
+	return (c);					/* String is multiline, return numeric multiline (restab) code */
+}
+
+static void diag(REGISTER int ec)
+{
+	REGISTER int c;
+
+	DBGPRINTF8(("DIAG: enter, ec=%d\n", ec));
+
+	c = my_getc(0);
+	if (c == '>' || c == '<') {
+		if (c != ec)
+			zzerr();
+		yylval.i = ec == '>' ? IOWRITE | IOCAT : IOHERE;
+		c = my_getc(0);
+	} else
+		yylval.i = ec == '>' ? IOWRITE : IOREAD;
+	if (c != '&' || yylval.i == IOHERE)
+		unget(c);
+	else
+		yylval.i |= IODUP;
+}
+
+static char *tree(unsigned size)
+{
+	REGISTER char *t;
+
+	if ((t = getcell(size)) == NULL) {
+		DBGPRINTF2(("TREE: getcell(%d) failed!\n", size));
+		prs("command line too complicated\n");
+		fail();
+		/* NOTREACHED */
+	}
+	return (t);
+}
+
+/* VARARGS1 */
+/* ARGSUSED */
+
+/* -------- exec.c -------- */
+
+/*
+ * execute tree
+ */
+
+
+static int execute(REGISTER struct op *t, int *pin, int *pout, int act)
+{
+	REGISTER struct op *t1;
+	volatile int i, rv, a;
+	char *cp, **wp, **wp2;
+	struct var *vp;
+	struct op *outtree_save;
+	struct brkcon bc;
+
+#if __GNUC__
+	/* Avoid longjmp clobbering */
+	(void) ℘
+#endif
+
+	if (t == NULL) {
+		DBGPRINTF4(("EXECUTE: enter, t==null, returning.\n"));
+		return (0);
+	}
+
+	DBGPRINTF(("EXECUTE: t=%p, t->type=%d (%s), t->words is %s\n", t,
+			   t->type, T_CMD_NAMES[t->type],
+			   ((t->words == NULL) ? "NULL" : t->words[0])));
+
+	rv = 0;
+	a = areanum++;
+	wp = (wp2 = t->words) != NULL
+		? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY)
+		: NULL;
+
+/* Hard to know how many words there are, be careful of garbage pointer values */
+/* They are likely to cause "PCI bus fault" errors */
+#if 0
+	DBGPRINTF(("EXECUTE: t->left=%p, t->right=%p, t->words[1] is %s\n",
+			   t->left, t->right,
+			   ((t->words[1] == NULL) ? "NULL" : t->words[1])));
+	DBGPRINTF7(("EXECUTE: t->words[2] is %s, t->words[3] is %s\n",
+				((t->words[2] == NULL) ? "NULL" : t->words[2]),
+				((t->words[3] == NULL) ? "NULL" : t->words[3])));
+#endif
+
+
+	switch (t->type) {
+	case TDOT:
+		DBGPRINTF3(("EXECUTE: TDOT\n"));
+
+		outtree_save = outtree;
+
+		newfile(evalstr(t->words[0], DOALL));
+
+		t->left = dowholefile(TLIST, 0);
+		t->right = NULL;
+
+		outtree = outtree_save;
+
+		if (t->left)
+			rv = execute(t->left, pin, pout, 0);
+		if (t->right)
+			rv = execute(t->right, pin, pout, 0);
+		break;
+
+	case TPAREN:
+		rv = execute(t->left, pin, pout, 0);
+		break;
+
+	case TCOM:
+		{
+			rv = forkexec(t, pin, pout, act, wp);
+		}
+		break;
+
+	case TPIPE:
+		{
+			int pv[2];
+
+			if ((rv = openpipe(pv)) < 0)
+				break;
+			pv[0] = remap(pv[0]);
+			pv[1] = remap(pv[1]);
+			(void) execute(t->left, pin, pv, 0);
+			rv = execute(t->right, pv, pout, 0);
+		}
+		break;
+
+	case TLIST:
+		(void) execute(t->left, pin, pout, 0);
+		rv = execute(t->right, pin, pout, 0);
+		break;
+
+	case TASYNC:
+		{
+			int hinteractive = interactive;
+
+			DBGPRINTF7(("EXECUTE: TASYNC clause, calling vfork()...\n"));
+
+			i = vfork();
+			if (i != 0) {
+				interactive = hinteractive;
+				if (i != -1) {
+					setval(lookup("!"), putn(i));
+					if (pin != NULL)
+						closepipe(pin);
+					if (interactive) {
+						prs(putn(i));
+						prs("\n");
+					}
+				} else
+					rv = -1;
+				setstatus(rv);
+			} else {
+				signal(SIGINT, SIG_IGN);
+				signal(SIGQUIT, SIG_IGN);
+				if (interactive)
+					signal(SIGTERM, SIG_DFL);
+				interactive = 0;
+				if (pin == NULL) {
+					close(0);
+					open(bb_dev_null, 0);
+				}
+				_exit(execute(t->left, pin, pout, FEXEC));
+			}
+		}
+		break;
+
+	case TOR:
+	case TAND:
+		rv = execute(t->left, pin, pout, 0);
+		if ((t1 = t->right) != NULL && (rv == 0) == (t->type == TAND))
+			rv = execute(t1, pin, pout, 0);
+		break;
+
+	case TFOR:
+		if (wp == NULL) {
+			wp = dolv + 1;
+			if ((i = dolc) < 0)
+				i = 0;
+		} else {
+			i = -1;
+			while (*wp++ != NULL);
+		}
+		vp = lookup(t->str);
+		while (setjmp(bc.brkpt))
+			if (isbreak)
+				goto broken;
+		brkset(&bc);
+		for (t1 = t->left; i-- && *wp != NULL;) {
+			setval(vp, *wp++);
+			rv = execute(t1, pin, pout, 0);
+		}
+		brklist = brklist->nextlev;
+		break;
+
+	case TWHILE:
+	case TUNTIL:
+		while (setjmp(bc.brkpt))
+			if (isbreak)
+				goto broken;
+		brkset(&bc);
+		t1 = t->left;
+		while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE))
+			rv = execute(t->right, pin, pout, 0);
+		brklist = brklist->nextlev;
+		break;
+
+	case TIF:
+	case TELIF:
+		if (t->right != NULL) {
+			rv = !execute(t->left, pin, pout, 0) ?
+				execute(t->right->left, pin, pout, 0) :
+				execute(t->right->right, pin, pout, 0);
+		}
+		break;
+
+	case TCASE:
+		if ((cp = evalstr(t->str, DOSUB | DOTRIM)) == 0)
+			cp = "";
+
+		DBGPRINTF7(("EXECUTE: TCASE, t->str is %s, cp is %s\n",
+					((t->str == NULL) ? "NULL" : t->str),
+					((cp == NULL) ? "NULL" : cp)));
+
+		if ((t1 = findcase(t->left, cp)) != NULL) {
+			DBGPRINTF7(("EXECUTE: TCASE, calling execute(t=%p, t1=%p)...\n", t, t1));
+			rv = execute(t1, pin, pout, 0);
+			DBGPRINTF7(("EXECUTE: TCASE, back from execute(t=%p, t1=%p)...\n", t, t1));
+		}
+		break;
+
+	case TBRACE:
+/*
+		if (iopp = t->ioact)
+			while (*iopp)
+				if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) {
+					rv = -1;
+					break;
+				}
+*/
+		if (rv >= 0 && (t1 = t->left))
+			rv = execute(t1, pin, pout, 0);
+		break;
+
+	};
+
+  broken:
+	t->words = wp2;
+	isbreak = 0;
+	freehere(areanum);
+	freearea(areanum);
+	areanum = a;
+	if (interactive && intr) {
+		closeall();
+		fail();
+	}
+
+	if ((i = trapset) != 0) {
+		trapset = 0;
+		runtrap(i);
+	}
+
+	DBGPRINTF(("EXECUTE: returning from t=%p, rv=%d\n", t, rv));
+	return (rv);
+}
+
+static int
+forkexec(REGISTER struct op *t, int *pin, int *pout, int act, char **wp)
+{
+	pid_t newpid;
+	int i, rv;
+	int (*shcom) (struct op *) = NULL;
+	REGISTER int f;
+	char *cp = NULL;
+	struct ioword **iopp;
+	int resetsig;
+	char **owp;
+	int forked = 0;
+
+	int *hpin = pin;
+	int *hpout = pout;
+	char *hwp;
+	int hinteractive;
+	int hintr;
+	struct brkcon *hbrklist;
+	int hexecflg;
+
+#if __GNUC__
+	/* Avoid longjmp clobbering */
+	(void) &pin;
+	(void) &pout;
+	(void) ℘
+	(void) &shcom;
+	(void) &cp;
+	(void) &resetsig;
+	(void) &owp;
+#endif
+
+	DBGPRINTF(("FORKEXEC: t=%p, pin %p, pout %p, act %d\n", t, pin,
+			   pout, act));
+	DBGPRINTF7(("FORKEXEC: t->words is %s\n",
+				((t->words == NULL) ? "NULL" : t->words[0])));
+
+/* Hard to know how many words there are, be careful of garbage pointer values */
+/* They are likely to cause "PCI bus fault" errors */
+#if 0
+	DBGPRINTF7(("FORKEXEC: t->words is %s, t->words[1] is %s\n",
+				((t->words == NULL) ? "NULL" : t->words[0]),
+				((t->words == NULL) ? "NULL" : t->words[1])));
+	DBGPRINTF7(("FORKEXEC: wp is %s, wp[1] is %s\n",
+				((wp == NULL) ? "NULL" : wp[0]),
+				((wp[1] == NULL) ? "NULL" : wp[1])));
+	DBGPRINTF7(("FORKEXEC: wp2 is %s, wp[3] is %s\n",
+				((wp[2] == NULL) ? "NULL" : wp[2]),
+				((wp[3] == NULL) ? "NULL" : wp[3])));
+#endif
+
+
+	owp = wp;
+	resetsig = 0;
+	rv = -1;					/* system-detected error */
+	if (t->type == TCOM) {
+		while ((cp = *wp++) != NULL);
+		cp = *wp;
+
+		/* strip all initial assignments */
+		/* not correct wrt PATH=yyy command  etc */
+		if (flag['x']) {
+			DBGPRINTF9(("FORKEXEC: echo'ing, cp=%p, wp=%p, owp=%p\n",
+						cp, wp, owp));
+			echo(cp ? wp : owp);
+		}
+#if 0
+		DBGPRINTF9(("FORKEXEC: t->words is %s, t->words[1] is %s\n",
+					((t->words == NULL) ? "NULL" : t->words[0]),
+					((t->words == NULL) ? "NULL" : t->words[1])));
+		DBGPRINTF9(("FORKEXEC: wp is %s, wp[1] is %s\n",
+					((wp == NULL) ? "NULL" : wp[0]),
+					((wp == NULL) ? "NULL" : wp[1])));
+#endif
+
+		if (cp == NULL && t->ioact == NULL) {
+			while ((cp = *owp++) != NULL && assign(cp, COPYV));
+			DBGPRINTF(("FORKEXEC: returning setstatus()\n"));
+			return (setstatus(0));
+		} else if (cp != NULL) {
+			shcom = inbuilt(cp);
+		}
+	}
+
+	t->words = wp;
+	f = act;
+
+#if 0
+	DBGPRINTF3(("FORKEXEC: t->words is %s, t->words[1] is %s\n",
+				((t->words == NULL) ? "NULL" : t->words[0]),
+				((t->words == NULL) ? "NULL" : t->words[1])));
+#endif
+	DBGPRINTF(("FORKEXEC: shcom %p, f&FEXEC 0x%x, owp %p\n", shcom,
+			   f & FEXEC, owp));
+
+	if (shcom == NULL && (f & FEXEC) == 0) {
+		/* Save values in case the child process alters them */
+		hpin = pin;
+		hpout = pout;
+		hwp = *wp;
+		hinteractive = interactive;
+		hintr = intr;
+		hbrklist = brklist;
+		hexecflg = execflg;
+
+		DBGPRINTF3(("FORKEXEC: calling vfork()...\n"));
+
+		newpid = vfork();
+
+		if (newpid == -1) {
+			DBGPRINTF(("FORKEXEC: ERROR, unable to vfork()!\n"));
+			return (-1);
+		}
+
+
+		if (newpid > 0) {		/* Parent */
+
+			/* Restore values */
+			pin = hpin;
+			pout = hpout;
+			*wp = hwp;
+			interactive = hinteractive;
+			intr = hintr;
+			brklist = hbrklist;
+			execflg = hexecflg;
+
+/* moved up
+			if (i == -1)
+				return(rv);
+*/
+
+			if (pin != NULL)
+				closepipe(pin);
+
+			return (pout == NULL ? setstatus(waitfor(newpid, 0)) : 0);
+		}
+
+		/* Must be the child process, pid should be 0 */
+		DBGPRINTF(("FORKEXEC: child process, shcom=%p\n", shcom));
+
+		if (interactive) {
+			signal(SIGINT, SIG_IGN);
+			signal(SIGQUIT, SIG_IGN);
+			resetsig = 1;
+		}
+		interactive = 0;
+		intr = 0;
+		forked = 1;
+		brklist = 0;
+		execflg = 0;
+	}
+
+
+	if (owp != NULL)
+		while ((cp = *owp++) != NULL && assign(cp, COPYV))
+			if (shcom == NULL)
+				export(lookup(cp));
+
+#ifdef COMPIPE
+	if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) {
+		err("piping to/from shell builtins not yet done");
+		if (forked)
+			_exit(-1);
+		return (-1);
+	}
+#endif
+
+	if (pin != NULL) {
+		dup2(pin[0], 0);
+		closepipe(pin);
+	}
+	if (pout != NULL) {
+		dup2(pout[1], 1);
+		closepipe(pout);
+	}
+
+	if ((iopp = t->ioact) != NULL) {
+		if (shcom != NULL && shcom != doexec) {
+			prs(cp);
+			err(": cannot redirect shell command");
+			if (forked)
+				_exit(-1);
+			return (-1);
+		}
+		while (*iopp)
+			if (iosetup(*iopp++, pin != NULL, pout != NULL)) {
+				if (forked)
+					_exit(rv);
+				return (rv);
+			}
+	}
+
+	if (shcom) {
+		i = setstatus((*shcom) (t));
+		if (forked)
+			_exit(i);
+		DBGPRINTF(("FORKEXEC: returning i=%d\n", i));
+		return (i);
+	}
+
+	/* should use FIOCEXCL */
+	for (i = FDBASE; i < NOFILE; i++)
+		close(i);
+	if (resetsig) {
+		signal(SIGINT, SIG_DFL);
+		signal(SIGQUIT, SIG_DFL);
+	}
+
+	if (t->type == TPAREN)
+		_exit(execute(t->left, NOPIPE, NOPIPE, FEXEC));
+	if (wp[0] == NULL)
+		_exit(0);
+
+	cp = rexecve(wp[0], wp, makenv(0, NULL));
+	prs(wp[0]);
+	prs(": ");
+	err(cp);
+	if (!execflg)
+		trap[0] = NULL;
+
+	DBGPRINTF(("FORKEXEC: calling leave(), pid=%d\n", newpid));
+
+	leave();
+	/* NOTREACHED */
+	_exit(1);
+}
+
+/*
+ * 0< 1> are ignored as required
+ * within pipelines.
+ */
+static int iosetup(REGISTER struct ioword *iop, int pipein, int pipeout)
+{
+	REGISTER int u = -1;
+	char *cp = NULL, *msg;
+
+	DBGPRINTF(("IOSETUP: iop %p, pipein %i, pipeout %i\n", iop,
+			   pipein, pipeout));
+
+	if (iop->io_unit == IODEFAULT)	/* take default */
+		iop->io_unit = iop->io_flag & (IOREAD | IOHERE) ? 0 : 1;
+
+	if (pipein && iop->io_unit == 0)
+		return (0);
+
+	if (pipeout && iop->io_unit == 1)
+		return (0);
+
+	msg = iop->io_flag & (IOREAD | IOHERE) ? "open" : "create";
+	if ((iop->io_flag & IOHERE) == 0) {
+		cp = iop->io_name;
+		if ((cp = evalstr(cp, DOSUB | DOTRIM)) == NULL)
+			return (1);
+	}
+
+	if (iop->io_flag & IODUP) {
+		if (cp[1] || (!isdigit(*cp) && *cp != '-')) {
+			prs(cp);
+			err(": illegal >& argument");
+			return (1);
+		}
+		if (*cp == '-')
+			iop->io_flag = IOCLOSE;
+		iop->io_flag &= ~(IOREAD | IOWRITE);
+	}
+	switch (iop->io_flag) {
+	case IOREAD:
+		u = open(cp, 0);
+		break;
+
+	case IOHERE:
+	case IOHERE | IOXHERE:
+		u = herein(iop->io_name, iop->io_flag & IOXHERE);
+		cp = "here file";
+		break;
+
+	case IOWRITE | IOCAT:
+		if ((u = open(cp, 1)) >= 0) {
+			lseek(u, (long) 0, 2);
+			break;
+		}
+	case IOWRITE:
+		u = creat(cp, 0666);
+		break;
+
+	case IODUP:
+		u = dup2(*cp - '0', iop->io_unit);
+		break;
+
+	case IOCLOSE:
+		close(iop->io_unit);
+		return (0);
+	}
+	if (u < 0) {
+		prs(cp);
+		prs(": cannot ");
+		warn(msg);
+		return (1);
+	} else {
+		if (u != iop->io_unit) {
+			dup2(u, iop->io_unit);
+			close(u);
+		}
+	}
+	return (0);
+}
+
+static void echo(REGISTER char **wp)
+{
+	REGISTER int i;
+
+	prs("+");
+	for (i = 0; wp[i]; i++) {
+		if (i)
+			prs(" ");
+		prs(wp[i]);
+	}
+	prs("\n");
+}
+
+static struct op **find1case(struct op *t, char *w)
+{
+	REGISTER struct op *t1;
+	struct op **tp;
+	REGISTER char **wp, *cp;
+
+
+	if (t == NULL) {
+		DBGPRINTF3(("FIND1CASE: enter, t==NULL, returning.\n"));
+		return ((struct op **) NULL);
+	}
+
+	DBGPRINTF3(("FIND1CASE: enter, t->type=%d (%s)\n", t->type,
+				T_CMD_NAMES[t->type]));
+
+	if (t->type == TLIST) {
+		if ((tp = find1case(t->left, w)) != NULL) {
+			DBGPRINTF3(("FIND1CASE: found one to the left, returning tp=%p\n", tp));
+			return (tp);
+		}
+		t1 = t->right;			/* TPAT */
+	} else
+		t1 = t;
+
+	for (wp = t1->words; *wp;)
+		if ((cp = evalstr(*wp++, DOSUB)) && gmatch(w, cp)) {
+			DBGPRINTF3(("FIND1CASE: returning &t1->left= %p.\n",
+						&t1->left));
+			return (&t1->left);
+		}
+
+	DBGPRINTF(("FIND1CASE: returning NULL\n"));
+	return ((struct op **) NULL);
+}
+
+static struct op *findcase(struct op *t, char *w)
+{
+	REGISTER struct op **tp;
+
+	return ((tp = find1case(t, w)) != NULL ? *tp : (struct op *) NULL);
+}
+
+/*
+ * Enter a new loop level (marked for break/continue).
+ */
+static void brkset(struct brkcon *bc)
+{
+	bc->nextlev = brklist;
+	brklist = bc;
+}
+
+/*
+ * Wait for the last process created.
+ * Print a message for each process found
+ * that was killed by a signal.
+ * Ignore interrupt signals while waiting
+ * unless `canintr' is true.
+ */
+static int waitfor(REGISTER int lastpid, int canintr)
+{
+	REGISTER int pid, rv;
+	int s;
+	int oheedint = heedint;
+
+	heedint = 0;
+	rv = 0;
+	do {
+		pid = wait(&s);
+		if (pid == -1) {
+			if (errno != EINTR || canintr)
+				break;
+		} else {
+			if ((rv = WAITSIG(s)) != 0) {
+				if (rv < NSIGNAL) {
+					if (signame[rv] != NULL) {
+						if (pid != lastpid) {
+							prn(pid);
+							prs(": ");
+						}
+						prs(signame[rv]);
+					}
+				} else {
+					if (pid != lastpid) {
+						prn(pid);
+						prs(": ");
+					}
+					prs("Signal ");
+					prn(rv);
+					prs(" ");
+				}
+				if (WAITCORE(s))
+					prs(" - core dumped");
+				if (rv >= NSIGNAL || signame[rv])
+					prs("\n");
+				rv = -1;
+			} else
+				rv = WAITVAL(s);
+		}
+	} while (pid != lastpid);
+	heedint = oheedint;
+	if (intr) {
+		if (interactive) {
+			if (canintr)
+				intr = 0;
+		} else {
+			if (exstat == 0)
+				exstat = rv;
+			onintr(0);
+		}
+	}
+	return (rv);
+}
+
+static int setstatus(REGISTER int s)
+{
+	exstat = s;
+	setval(lookup("?"), putn(s));
+	return (s);
+}
+
+/*
+ * PATH-searching interface to execve.
+ * If getenv("PATH") were kept up-to-date,
+ * execvp might be used.
+ */
+static char *rexecve(char *c, char **v, char **envp)
+{
+	REGISTER int i;
+	REGISTER char *sp, *tp;
+	int eacces = 0, asis = 0;
+
+#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
+	char *name = c;
+
+	optind = 1;
+	if (find_applet_by_name(name)) {
+		/* We have to exec here since we vforked.  Running
+		 * run_applet_by_name() won't work and bad things
+		 * will happen. */
+		execve(CONFIG_BUSYBOX_EXEC_PATH, v, envp);
+	}
+#endif
+
+	DBGPRINTF(("REXECVE: c=%p, v=%p, envp=%p\n", c, v, envp));
+
+	sp = any('/', c) ? "" : path->value;
+	asis = *sp == '\0';
+	while (asis || *sp != '\0') {
+		asis = 0;
+		tp = e.linep;
+		for (; *sp != '\0'; tp++)
+			if ((*tp = *sp++) == ':') {
+				asis = *sp == '\0';
+				break;
+			}
+		if (tp != e.linep)
+			*tp++ = '/';
+		for (i = 0; (*tp++ = c[i++]) != '\0';);
+
+		DBGPRINTF3(("REXECVE: e.linep is %s\n", e.linep));
+
+		execve(e.linep, v, envp);
+
+		switch (errno) {
+		case ENOEXEC:
+			*v = e.linep;
+			tp = *--v;
+			*v = e.linep;
+			execve(DEFAULT_SHELL, v, envp);
+			*v = tp;
+			return ("no Shell");
+
+		case ENOMEM:
+			return ((char *) bb_msg_memory_exhausted);
+
+		case E2BIG:
+			return ("argument list too long");
+
+		case EACCES:
+			eacces++;
+			break;
+		}
+	}
+	return (errno == ENOENT ? "not found" : "cannot execute");
+}
+
+/*
+ * Run the command produced by generator `f'
+ * applied to stream `arg'.
+ */
+static int run(struct ioarg *argp, int (*f) (struct ioarg *))
+{
+	struct op *otree;
+	struct wdblock *swdlist;
+	struct wdblock *siolist;
+	jmp_buf ev, rt;
+	xint *ofail;
+	int rv;
+
+#if __GNUC__
+	/* Avoid longjmp clobbering */
+	(void) &rv;
+#endif
+
+	DBGPRINTF(("RUN: enter, areanum %d, outtree %p, failpt %p\n",
+			   areanum, outtree, failpt));
+
+	areanum++;
+	swdlist = wdlist;
+	siolist = iolist;
+	otree = outtree;
+	ofail = failpt;
+	rv = -1;
+
+	if (newenv(setjmp(errpt = ev)) == 0) {
+		wdlist = 0;
+		iolist = 0;
+		pushio(argp, f);
+		e.iobase = e.iop;
+		yynerrs = 0;
+		if (setjmp(failpt = rt) == 0 && yyparse() == 0)
+			rv = execute(outtree, NOPIPE, NOPIPE, 0);
+		quitenv();
+	} else {
+		DBGPRINTF(("RUN: error from newenv()!\n"));
+	}
+
+	wdlist = swdlist;
+	iolist = siolist;
+	failpt = ofail;
+	outtree = otree;
+	freearea(areanum--);
+
+	return (rv);
+}
+
+/* -------- do.c -------- */
+
+/*
+ * built-in commands: doX
+ */
+
+static int dohelp(struct op *t)
+{
+	int col;
+	const struct builtincmd *x;
+
+	printf("\nBuilt-in commands:\n");
+	printf("-------------------\n");
+
+	for (col = 0, x = builtincmds; x->builtinfunc != NULL; x++) {
+		if (!x->name)
+			continue;
+		col += printf("%s%s", ((col == 0) ? "\t" : " "), x->name);
+		if (col > 60) {
+			printf("\n");
+			col = 0;
+		}
+	}
+#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
+	{
+		int i;
+		const struct BB_applet *applet;
+		extern const struct BB_applet applets[];
+		extern const size_t NUM_APPLETS;
+
+		for (i = 0, applet = applets; i < NUM_APPLETS; applet++, i++) {
+			if (!applet->name)
+				continue;
+
+			col += printf("%s%s", ((col == 0) ? "\t" : " "), applet->name);
+			if (col > 60) {
+				printf("\n");
+				col = 0;
+			}
+		}
+	}
+#endif
+	printf("\n\n");
+	return EXIT_SUCCESS;
+}
+
+
+
+static int dolabel(struct op *t)
+{
+	return (0);
+}
+
+static int dochdir(REGISTER struct op *t)
+{
+	REGISTER char *cp, *er;
+
+	if ((cp = t->words[1]) == NULL && (cp = homedir->value) == NULL)
+		er = ": no home directory";
+	else if (chdir(cp) < 0)
+		er = ": bad directory";
+	else
+		return (0);
+	prs(cp != NULL ? cp : "cd");
+	err(er);
+	return (1);
+}
+
+static int doshift(REGISTER struct op *t)
+{
+	REGISTER int n;
+
+	n = t->words[1] ? getn(t->words[1]) : 1;
+	if (dolc < n) {
+		err("nothing to shift");
+		return (1);
+	}
+	dolv[n] = dolv[0];
+	dolv += n;
+	dolc -= n;
+	setval(lookup("#"), putn(dolc));
+	return (0);
+}
+
+/*
+ * execute login and newgrp directly
+ */
+static int dologin(struct op *t)
+{
+	REGISTER char *cp;
+
+	if (interactive) {
+		signal(SIGINT, SIG_DFL);
+		signal(SIGQUIT, SIG_DFL);
+	}
+	cp = rexecve(t->words[0], t->words, makenv(0, NULL));
+	prs(t->words[0]);
+	prs(": ");
+	err(cp);
+	return (1);
+}
+
+static int doumask(REGISTER struct op *t)
+{
+	REGISTER int i, n;
+	REGISTER char *cp;
+
+	if ((cp = t->words[1]) == NULL) {
+		i = umask(0);
+		umask(i);
+		for (n = 3 * 4; (n -= 3) >= 0;)
+			putc('0' + ((i >> n) & 07), stderr);
+		putc('\n', stderr);
+	} else {
+		for (n = 0; *cp >= '0' && *cp <= '9'; cp++)
+			n = n * 8 + (*cp - '0');
+		umask(n);
+	}
+	return (0);
+}
+
+static int doexec(REGISTER struct op *t)
+{
+	REGISTER int i;
+	jmp_buf ex;
+	xint *ofail;
+
+	t->ioact = NULL;
+	for (i = 0; (t->words[i] = t->words[i + 1]) != NULL; i++);
+	if (i == 0)
+		return (1);
+	execflg = 1;
+	ofail = failpt;
+	if (setjmp(failpt = ex) == 0)
+		execute(t, NOPIPE, NOPIPE, FEXEC);
+	failpt = ofail;
+	execflg = 0;
+	return (1);
+}
+
+static int dodot(struct op *t)
+{
+	REGISTER int i;
+	REGISTER char *sp, *tp;
+	char *cp;
+	int maltmp;
+
+	DBGPRINTF(("DODOT: enter, t=%p, tleft %p, tright %p, e.linep is %s\n", t, t->left, t->right, ((e.linep == NULL) ? "NULL" : e.linep)));
+
+	if ((cp = t->words[1]) == NULL) {
+		DBGPRINTF(("DODOT: bad args, ret 0\n"));
+		return (0);
+	} else {
+		DBGPRINTF(("DODOT: cp is %s\n", cp));
+	}
+
+	sp = any('/', cp) ? ":" : path->value;
+
+	DBGPRINTF(("DODOT: sp is %s,  e.linep is %s\n",
+			   ((sp == NULL) ? "NULL" : sp),
+			   ((e.linep == NULL) ? "NULL" : e.linep)));
+
+	while (*sp) {
+		tp = e.linep;
+		while (*sp && (*tp = *sp++) != ':')
+			tp++;
+		if (tp != e.linep)
+			*tp++ = '/';
+
+		for (i = 0; (*tp++ = cp[i++]) != '\0';);
+
+		/* Original code */
+		if ((i = open(e.linep, 0)) >= 0) {
+			exstat = 0;
+			maltmp = remap(i);
+			DBGPRINTF(("DODOT: remap=%d, exstat=%d, e.iofd %d, i %d, e.linep is %s\n", maltmp, exstat, e.iofd, i, e.linep));
+
+			next(maltmp);		/* Basically a PUSHIO */
+
+			DBGPRINTF(("DODOT: returning exstat=%d\n", exstat));
+
+			return (exstat);
+		}
+
+	}							/* While */
+
+	prs(cp);
+	err(": not found");
+
+	return (-1);
+}
+
+static int dowait(struct op *t)
+{
+	REGISTER int i;
+	REGISTER char *cp;
+
+	if ((cp = t->words[1]) != NULL) {
+		i = getn(cp);
+		if (i == 0)
+			return (0);
+	} else
+		i = -1;
+	setstatus(waitfor(i, 1));
+	return (0);
+}
+
+static int doread(struct op *t)
+{
+	REGISTER char *cp, **wp;
+	REGISTER int nb = 0;
+	REGISTER int nl = 0;
+
+	if (t->words[1] == NULL) {
+		err("Usage: read name ...");
+		return (1);
+	}
+	for (wp = t->words + 1; *wp; wp++) {
+		for (cp = e.linep; !nl && cp < elinep - 1; cp++)
+			if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) ||
+				(nl = (*cp == '\n')) || (wp[1] && any(*cp, ifs->value)))
+				break;
+		*cp = 0;
+		if (nb <= 0)
+			break;
+		setval(lookup(*wp), e.linep);
+	}
+	return (nb <= 0);
+}
+
+static int doeval(REGISTER struct op *t)
+{
+	return (RUN(awordlist, t->words + 1, wdchar));
+}
+
+static int dotrap(REGISTER struct op *t)
+{
+	REGISTER int n, i;
+	REGISTER int resetsig;
+
+	if (t->words[1] == NULL) {
+		for (i = 0; i <= _NSIG; i++)
+			if (trap[i]) {
+				prn(i);
+				prs(": ");
+				prs(trap[i]);
+				prs("\n");
+			}
+		return (0);
+	}
+	resetsig = isdigit(*t->words[1]);
+	for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) {
+		n = getsig(t->words[i]);
+		freecell(trap[n]);
+		trap[n] = 0;
+		if (!resetsig) {
+			if (*t->words[1] != '\0') {
+				trap[n] = strsave(t->words[1], 0);
+				setsig(n, sig);
+			} else
+				setsig(n, SIG_IGN);
+		} else {
+			if (interactive)
+				if (n == SIGINT)
+					setsig(n, onintr);
+				else
+					setsig(n, n == SIGQUIT ? SIG_IGN : SIG_DFL);
+			else
+				setsig(n, SIG_DFL);
+		}
+	}
+	return (0);
+}
+
+static int getsig(char *s)
+{
+	REGISTER int n;
+
+	if ((n = getn(s)) < 0 || n > _NSIG) {
+		err("trap: bad signal number");
+		n = 0;
+	}
+	return (n);
+}
+
+static void setsig(REGISTER int n, sighandler_t f)
+{
+	if (n == 0)
+		return;
+	if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) {
+		ourtrap[n] = 1;
+		signal(n, f);
+	}
+}
+
+static int getn(char *as)
+{
+	REGISTER char *s;
+	REGISTER int n, m;
+
+	s = as;
+	m = 1;
+	if (*s == '-') {
+		m = -1;
+		s++;
+	}
+	for (n = 0; isdigit(*s); s++)
+		n = (n * 10) + (*s - '0');
+	if (*s) {
+		prs(as);
+		err(": bad number");
+	}
+	return (n * m);
+}
+
+static int dobreak(struct op *t)
+{
+	return (brkcontin(t->words[1], 1));
+}
+
+static int docontinue(struct op *t)
+{
+	return (brkcontin(t->words[1], 0));
+}
+
+static int brkcontin(REGISTER char *cp, int val)
+{
+	REGISTER struct brkcon *bc;
+	REGISTER int nl;
+
+	nl = cp == NULL ? 1 : getn(cp);
+	if (nl <= 0)
+		nl = 999;
+	do {
+		if ((bc = brklist) == NULL)
+			break;
+		brklist = bc->nextlev;
+	} while (--nl);
+	if (nl) {
+		err("bad break/continue level");
+		return (1);
+	}
+	isbreak = val;
+	longjmp(bc->brkpt, 1);
+	/* NOTREACHED */
+}
+
+static int doexit(struct op *t)
+{
+	REGISTER char *cp;
+
+	execflg = 0;
+	if ((cp = t->words[1]) != NULL)
+		setstatus(getn(cp));
+
+	DBGPRINTF(("DOEXIT: calling leave(), t=%p\n", t));
+
+	leave();
+	/* NOTREACHED */
+	return (0);
+}
+
+static int doexport(struct op *t)
+{
+	rdexp(t->words + 1, export, EXPORT);
+	return (0);
+}
+
+static int doreadonly(struct op *t)
+{
+	rdexp(t->words + 1, ronly, RONLY);
+	return (0);
+}
+
+static void rdexp(char **wp, void (*f) (struct var *), int key)
+{
+	DBGPRINTF6(("RDEXP: enter, wp=%p, func=%p, key=%d\n", wp, f, key));
+	DBGPRINTF6(("RDEXP: *wp=%s\n", *wp));
+
+	if (*wp != NULL) {
+		for (; *wp != NULL; wp++) {
+			if (isassign(*wp)) {
+				char *cp;
+
+				assign(*wp, COPYV);
+				for (cp = *wp; *cp != '='; cp++);
+				*cp = '\0';
+			}
+			if (checkname(*wp))
+				(*f) (lookup(*wp));
+			else
+				badid(*wp);
+		}
+	} else
+		putvlist(key, 1);
+}
+
+static void badid(REGISTER char *s)
+{
+	prs(s);
+	err(": bad identifier");
+}
+
+static int doset(REGISTER struct op *t)
+{
+	REGISTER struct var *vp;
+	REGISTER char *cp;
+	REGISTER int n;
+
+	if ((cp = t->words[1]) == NULL) {
+		for (vp = vlist; vp; vp = vp->next)
+			varput(vp->name, 1);
+		return (0);
+	}
+	if (*cp == '-') {
+		/* bad: t->words++; */
+		for (n = 0; (t->words[n] = t->words[n + 1]) != NULL; n++);
+		if (*++cp == 0)
+			flag['x'] = flag['v'] = 0;
+		else
+			for (; *cp; cp++)
+				switch (*cp) {
+				case 'e':
+					if (!interactive)
+						flag['e']++;
+					break;
+
+				default:
+					if (*cp >= 'a' && *cp <= 'z')
+						flag[(int) *cp]++;
+					break;
+				}
+		setdash();
+	}
+	if (t->words[1]) {
+		t->words[0] = dolv[0];
+		for (n = 1; t->words[n]; n++)
+			setarea((char *) t->words[n], 0);
+		dolc = n - 1;
+		dolv = t->words;
+		setval(lookup("#"), putn(dolc));
+		setarea((char *) (dolv - 1), 0);
+	}
+	return (0);
+}
+
+static void varput(REGISTER char *s, int out)
+{
+	if (isalnum(*s) || *s == '_') {
+		write(out, s, strlen(s));
+		write(out, "\n", 1);
+	}
+}
+
+
+/*
+ * Copyright (c) 1999 Herbert Xu <herbert at debian.org>
+ * This file contains code for the times builtin.
+ */
+static int dotimes(struct op *t)
+{
+	struct tms buf;
+	long int clk_tck = sysconf(_SC_CLK_TCK);
+
+	times(&buf);
+	printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
+		   (int) (buf.tms_utime / clk_tck / 60),
+		   ((double) buf.tms_utime) / clk_tck,
+		   (int) (buf.tms_stime / clk_tck / 60),
+		   ((double) buf.tms_stime) / clk_tck,
+		   (int) (buf.tms_cutime / clk_tck / 60),
+		   ((double) buf.tms_cutime) / clk_tck,
+		   (int) (buf.tms_cstime / clk_tck / 60),
+		   ((double) buf.tms_cstime) / clk_tck);
+	return 0;
+}
+
+
+static int (*inbuilt(char *s)) (struct op *) {
+	const struct builtincmd *bp;
+
+	for (bp = builtincmds; bp->name != NULL; bp++)
+		if (strcmp(bp->name, s) == 0)
+			return (bp->builtinfunc);
+
+	return (NULL);
+}
+
+/* -------- eval.c -------- */
+
+/*
+ * ${}
+ * `command`
+ * blank interpretation
+ * quoting
+ * glob
+ */
+
+static char **eval(char **ap, int f)
+{
+	struct wdblock *wb;
+	char **wp;
+	char **wf;
+	jmp_buf ev;
+
+#if __GNUC__
+	/* Avoid longjmp clobbering */
+	(void) ℘
+	(void) ≈
+#endif
+
+	DBGPRINTF4(("EVAL: enter, f=%d\n", f));
+
+	wp = NULL;
+	wb = NULL;
+	wf = NULL;
+	if (newenv(setjmp(errpt = ev)) == 0) {
+		while (*ap && isassign(*ap))
+			expand(*ap++, &wb, f & ~DOGLOB);
+		if (flag['k']) {
+			for (wf = ap; *wf; wf++) {
+				if (isassign(*wf))
+					expand(*wf, &wb, f & ~DOGLOB);
+			}
+		}
+		for (wb = addword((char *) 0, wb); *ap; ap++) {
+			if (!flag['k'] || !isassign(*ap))
+				expand(*ap, &wb, f & ~DOKEY);
+		}
+		wb = addword((char *) 0, wb);
+		wp = getwords(wb);
+		quitenv();
+	} else
+		gflg = 1;
+
+	return (gflg ? (char **) NULL : wp);
+}
+
+/*
+ * Make the exported environment from the exported
+ * names in the dictionary. Keyword assignments
+ * will already have been done.
+ */
+static char **makenv(int all, struct wdblock *wb)
+{
+	REGISTER struct var *vp;
+
+	DBGPRINTF5(("MAKENV: enter, all=%d\n", all));
+
+	for (vp = vlist; vp; vp = vp->next)
+		if (all || vp->status & EXPORT)
+			wb = addword(vp->name, wb);
+	wb = addword((char *) 0, wb);
+	return (getwords(wb));
+}
+
+static char *evalstr(REGISTER char *cp, int f)
+{
+	struct wdblock *wb;
+
+	DBGPRINTF6(("EVALSTR: enter, cp=%p, f=%d\n", cp, f));
+
+	wb = NULL;
+	if (expand(cp, &wb, f)) {
+		if (wb == NULL || wb->w_nword == 0
+			|| (cp = wb->w_words[0]) == NULL)
+			cp = "";
+		DELETE(wb);
+	} else
+		cp = NULL;
+	return (cp);
+}
+
+static int expand(char *cp, REGISTER struct wdblock **wbp, int f)
+{
+	jmp_buf ev;
+
+#if __GNUC__
+	/* Avoid longjmp clobbering */
+	(void) &cp;
+#endif
+
+	DBGPRINTF3(("EXPAND: enter, f=%d\n", f));
+
+	gflg = 0;
+
+	if (cp == NULL)
+		return (0);
+
+	if (!anys("$`'\"", cp) &&
+		!anys(ifs->value, cp) && ((f & DOGLOB) == 0 || !anys("[*?", cp))) {
+		cp = strsave(cp, areanum);
+		if (f & DOTRIM)
+			unquote(cp);
+		*wbp = addword(cp, *wbp);
+		return (1);
+	}
+	if (newenv(setjmp(errpt = ev)) == 0) {
+		PUSHIO(aword, cp, strchar);
+		e.iobase = e.iop;
+		while ((cp = blank(f)) && gflg == 0) {
+			e.linep = cp;
+			cp = strsave(cp, areanum);
+			if ((f & DOGLOB) == 0) {
+				if (f & DOTRIM)
+					unquote(cp);
+				*wbp = addword(cp, *wbp);
+			} else
+				*wbp = glob(cp, *wbp);
+		}
+		quitenv();
+	} else
+		gflg = 1;
+	return (gflg == 0);
+}
+
+/*
+ * Blank interpretation and quoting
+ */
+static char *blank(int f)
+{
+	REGISTER int c, c1;
+	REGISTER char *sp;
+	int scanequals, foundequals;
+
+	DBGPRINTF3(("BLANK: enter, f=%d\n", f));
+
+	sp = e.linep;
+	scanequals = f & DOKEY;
+	foundequals = 0;
+
+  loop:
+	switch (c = subgetc('"', foundequals)) {
+	case 0:
+		if (sp == e.linep)
+			return (0);
+		*e.linep++ = 0;
+		return (sp);
+
+	default:
+		if (f & DOBLANK && any(c, ifs->value))
+			goto loop;
+		break;
+
+	case '"':
+	case '\'':
+		scanequals = 0;
+		if (INSUB())
+			break;
+		for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
+			if (c == 0)
+				break;
+			if (c == '\'' || !any(c, "$`\""))
+				c |= QUOTE;
+			*e.linep++ = c;
+		}
+		c = 0;
+	}
+	unget(c);
+	if (!isalpha(c) && c != '_')
+		scanequals = 0;
+	for (;;) {
+		c = subgetc('"', foundequals);
+		if (c == 0 ||
+			f & (DOBLANK && any(c, ifs->value)) ||
+			(!INSUB() && any(c, "\"'"))) {
+			scanequals = 0;
+			unget(c);
+			if (any(c, "\"'"))
+				goto loop;
+			break;
+		}
+		if (scanequals) {
+			if (c == '=') {
+				foundequals = 1;
+				scanequals = 0;
+			} else if (!isalnum(c) && c != '_')
+				scanequals = 0;
+		}
+		*e.linep++ = c;
+	}
+	*e.linep++ = 0;
+	return (sp);
+}
+
+/*
+ * Get characters, substituting for ` and $
+ */
+static int subgetc(REGISTER char ec, int quoted)
+{
+	REGISTER char c;
+
+	DBGPRINTF3(("SUBGETC: enter, quoted=%d\n", quoted));
+
+  again:
+	c = my_getc(ec);
+	if (!INSUB() && ec != '\'') {
+		if (c == '`') {
+			if (grave(quoted) == 0)
+				return (0);
+			e.iop->task = XGRAVE;
+			goto again;
+		}
+		if (c == '$' && (c = dollar(quoted)) == 0) {
+			e.iop->task = XDOLL;
+			goto again;
+		}
+	}
+	return (c);
+}
+
+/*
+ * Prepare to generate the string returned by ${} substitution.
+ */
+static int dollar(int quoted)
+{
+	int otask;
+	struct io *oiop;
+	char *dolp;
+	REGISTER char *s, c, *cp = NULL;
+	struct var *vp;
+
+	DBGPRINTF3(("DOLLAR: enter, quoted=%d\n", quoted));
+
+	c = readc();
+	s = e.linep;
+	if (c != '{') {
+		*e.linep++ = c;
+		if (isalpha(c) || c == '_') {
+			while ((c = readc()) != 0 && (isalnum(c) || c == '_'))
+				if (e.linep < elinep)
+					*e.linep++ = c;
+			unget(c);
+		}
+		c = 0;
+	} else {
+		oiop = e.iop;
+		otask = e.iop->task;
+
+		e.iop->task = XOTHER;
+		while ((c = subgetc('"', 0)) != 0 && c != '}' && c != '\n')
+			if (e.linep < elinep)
+				*e.linep++ = c;
+		if (oiop == e.iop)
+			e.iop->task = otask;
+		if (c != '}') {
+			err("unclosed ${");
+			gflg++;
+			return (c);
+		}
+	}
+	if (e.linep >= elinep) {
+		err("string in ${} too long");
+		gflg++;
+		e.linep -= 10;
+	}
+	*e.linep = 0;
+	if (*s)
+		for (cp = s + 1; *cp; cp++)
+			if (any(*cp, "=-+?")) {
+				c = *cp;
+				*cp++ = 0;
+				break;
+			}
+	if (s[1] == 0 && (*s == '*' || *s == '@')) {
+		if (dolc > 1) {
+			/* currently this does not distinguish $* and $@ */
+			/* should check dollar */
+			e.linep = s;
+			PUSHIO(awordlist, dolv + 1, dolchar);
+			return (0);
+		} else {				/* trap the nasty ${=} */
+			s[0] = '1';
+			s[1] = 0;
+		}
+	}
+	vp = lookup(s);
+	if ((dolp = vp->value) == null) {
+		switch (c) {
+		case '=':
+			if (isdigit(*s)) {
+				err("cannot use ${...=...} with $n");
+				gflg++;
+				break;
+			}
+			setval(vp, cp);
+			dolp = vp->value;
+			break;
+
+		case '-':
+			dolp = strsave(cp, areanum);
+			break;
+
+		case '?':
+			if (*cp == 0) {
+				prs("missing value for ");
+				err(s);
+			} else
+				err(cp);
+			gflg++;
+			break;
+		}
+	} else if (c == '+')
+		dolp = strsave(cp, areanum);
+	if (flag['u'] && dolp == null) {
+		prs("unset variable: ");
+		err(s);
+		gflg++;
+	}
+	e.linep = s;
+	PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
+	return (0);
+}
+
+/*
+ * Run the command in `...` and read its output.
+ */
+
+static int grave(int quoted)
+{
+	char *cp;
+	REGISTER int i;
+	int j;
+	int pf[2];
+	static char child_cmd[LINELIM];
+	char *src;
+	char *dest;
+	int count;
+	int ignore;
+	int ignore_once;
+	char *argument_list[4];
+	struct wdblock *wb = NULL;
+
+#if __GNUC__
+	/* Avoid longjmp clobbering */
+	(void) &cp;
+#endif
+
+	for (cp = e.iop->argp->aword; *cp != '`'; cp++)
+		if (*cp == 0) {
+			err("no closing `");
+			return (0);
+		}
+
+	/* string copy with dollar expansion */
+	src = e.iop->argp->aword;
+	dest = child_cmd;
+	count = 0;
+	ignore = 0;
+	ignore_once = 0;
+	while ((*src != '`') && (count < LINELIM)) {
+		if (*src == '\'')
+			ignore = !ignore;
+		if (*src == '\\')
+			ignore_once = 1;
+		if (*src == '$' && !ignore && !ignore_once) {
+			struct var *vp;
+			char var_name[LINELIM];
+			char alt_value[LINELIM];
+			int var_index = 0;
+			int alt_index = 0;
+			char operator = 0;
+			int braces = 0;
+			char *value;
+
+			src++;
+			if (*src == '{') {
+				braces = 1;
+				src++;
+			}
+
+			var_name[var_index++] = *src++;
+			while (isalnum(*src) || *src=='_')
+				var_name[var_index++] = *src++;
+			var_name[var_index] = 0;
+
+			if (braces) {
+				switch (*src) {
+				case '}':
+					break;
+				case '-':
+				case '=':
+				case '+':
+				case '?':
+					operator = * src;
+					break;
+				default:
+					err("unclosed ${\n");
+					return (0);
+				}
+				if (operator) {
+					src++;
+					while (*src && (*src != '}')) {
+						alt_value[alt_index++] = *src++;
+					}
+					alt_value[alt_index] = 0;
+					if (*src != '}') {
+						err("unclosed ${\n");
+						return (0);
+					}
+				}
+				src++;
+			}
+
+			if (isalpha(*var_name)) {
+				/* let subshell handle it instead */
+
+				char *namep = var_name;
+
+				*dest++ = '$';
+				if (braces)
+					*dest++ = '{';
+				while (*namep)
+					*dest++ = *namep++;
+				if (operator) {
+					char *altp = alt_value;
+					*dest++ = operator;
+					while (*altp)
+						*dest++ = *altp++;
+				}
+				if (braces)
+					*dest++ = '}';
+
+				wb = addword(lookup(var_name)->name, wb);
+			} else {
+				/* expand */
+
+				vp = lookup(var_name);
+				if (vp->value != null)
+					value = (operator == '+') ?
+						alt_value : vp->value;
+				else if (operator == '?') {
+					err(alt_value);
+					return (0);
+				} else if (alt_index && (operator != '+')) {
+					value = alt_value;
+					if (operator == '=')
+						setval(vp, value);
+				} else
+					continue;
+
+				while (*value && (count < LINELIM)) {
+					*dest++ = *value++;
+					count++;
+				}
+			}
+		} else {
+			*dest++ = *src++;
+			count++;
+			ignore_once = 0;
+		}
+	}
+	*dest = '\0';
+
+	if (openpipe(pf) < 0)
+		return (0);
+
+	while ((i = vfork()) == -1 && errno == EAGAIN);
+
+	DBGPRINTF3(("GRAVE: i is %p\n", io));
+
+	if (i < 0) {
+		closepipe(pf);
+		err((char *) bb_msg_memory_exhausted);
+		return (0);
+	}
+	if (i != 0) {
+		waitpid(i, NULL, 0);
+		e.iop->argp->aword = ++cp;
+		close(pf[1]);
+		PUSHIO(afile, remap(pf[0]),
+			   (int (*)(struct ioarg *)) ((quoted) ? qgravechar :
+										  gravechar));
+		return (1);
+	}
+	/* allow trapped signals */
+	/* XXX - Maybe this signal stuff should go as well? */
+	for (j = 0; j <= _NSIG; j++)
+		if (ourtrap[j] && signal(j, SIG_IGN) != SIG_IGN)
+			signal(j, SIG_DFL);
+
+	dup2(pf[1], 1);
+	closepipe(pf);
+
+	argument_list[0] = (char *) DEFAULT_SHELL;
+	argument_list[1] = "-c";
+	argument_list[2] = child_cmd;
+	argument_list[3] = 0;
+
+	cp = rexecve(argument_list[0], argument_list, makenv(1, wb));
+	prs(argument_list[0]);
+	prs(": ");
+	err(cp);
+	_exit(1);
+}
+
+
+static char *unquote(REGISTER char *as)
+{
+	REGISTER char *s;
+
+	if ((s = as) != NULL)
+		while (*s)
+			*s++ &= ~QUOTE;
+	return (as);
+}
+
+/* -------- glob.c -------- */
+
+/*
+ * glob
+ */
+
+#define	scopy(x) strsave((x), areanum)
+#define	BLKSIZ	512
+#define	NDENT	((BLKSIZ+sizeof(struct dirent)-1)/sizeof(struct dirent))
+
+static struct wdblock *cl, *nl;
+static char spcl[] = "[?*";
+
+static struct wdblock *glob(char *cp, struct wdblock *wb)
+{
+	REGISTER int i;
+	REGISTER char *pp;
+
+	if (cp == 0)
+		return (wb);
+	i = 0;
+	for (pp = cp; *pp; pp++)
+		if (any(*pp, spcl))
+			i++;
+		else if (!any(*pp & ~QUOTE, spcl))
+			*pp &= ~QUOTE;
+	if (i != 0) {
+		for (cl = addword(scopy(cp), (struct wdblock *) 0); anyspcl(cl);
+			 cl = nl) {
+			nl = newword(cl->w_nword * 2);
+			for (i = 0; i < cl->w_nword; i++) {	/* for each argument */
+				for (pp = cl->w_words[i]; *pp; pp++)
+					if (any(*pp, spcl)) {
+						globname(cl->w_words[i], pp);
+						break;
+					}
+				if (*pp == '\0')
+					nl = addword(scopy(cl->w_words[i]), nl);
+			}
+			for (i = 0; i < cl->w_nword; i++)
+				DELETE(cl->w_words[i]);
+			DELETE(cl);
+		}
+		for (i = 0; i < cl->w_nword; i++)
+			unquote(cl->w_words[i]);
+		glob0((char *) cl->w_words, cl->w_nword, sizeof(char *), xstrcmp);
+		if (cl->w_nword) {
+			for (i = 0; i < cl->w_nword; i++)
+				wb = addword(cl->w_words[i], wb);
+			DELETE(cl);
+			return (wb);
+		}
+	}
+	wb = addword(unquote(cp), wb);
+	return (wb);
+}
+
+static void globname(char *we, REGISTER char *pp)
+{
+	REGISTER char *np, *cp;
+	char *name, *gp, *dp;
+	int k;
+	DIR *dirp;
+	struct dirent *de;
+	char dname[NAME_MAX + 1];
+	struct stat dbuf;
+
+	for (np = we; np != pp; pp--)
+		if (pp[-1] == '/')
+			break;
+	for (dp = cp = space((int) (pp - np) + 3); np < pp;)
+		*cp++ = *np++;
+	*cp++ = '.';
+	*cp = '\0';
+	for (gp = cp = space(strlen(pp) + 1); *np && *np != '/';)
+		*cp++ = *np++;
+	*cp = '\0';
+	dirp = opendir(dp);
+	if (dirp == 0) {
+		DELETE(dp);
+		DELETE(gp);
+		return;
+	}
+	dname[NAME_MAX] = '\0';
+	while ((de = readdir(dirp)) != NULL) {
+		/* XXX Hmmm... What this could be? (abial) */
+		/*
+		   if (ent[j].d_ino == 0)
+		   continue;
+		 */
+		strncpy(dname, de->d_name, NAME_MAX);
+		if (dname[0] == '.')
+			if (*gp != '.')
+				continue;
+		for (k = 0; k < NAME_MAX; k++)
+			if (any(dname[k], spcl))
+				dname[k] |= QUOTE;
+		if (gmatch(dname, gp)) {
+			name = generate(we, pp, dname, np);
+			if (*np && !anys(np, spcl)) {
+				if (stat(name, &dbuf)) {
+					DELETE(name);
+					continue;
+				}
+			}
+			nl = addword(name, nl);
+		}
+	}
+	closedir(dirp);
+	DELETE(dp);
+	DELETE(gp);
+}
+
+/*
+ * generate a pathname as below.
+ * start..end1 / middle end
+ * the slashes come for free
+ */
+static char *generate(char *start1, REGISTER char *end1, char *middle, char *end)
+{
+	char *p;
+	REGISTER char *op, *xp;
+
+	p = op =
+		space((int) (end1 - start1) + strlen(middle) + strlen(end) + 2);
+	for (xp = start1; xp != end1;)
+		*op++ = *xp++;
+	for (xp = middle; (*op++ = *xp++) != '\0';);
+	op--;
+	for (xp = end; (*op++ = *xp++) != '\0';);
+	return (p);
+}
+
+static int anyspcl(REGISTER struct wdblock *wb)
+{
+	REGISTER int i;
+	REGISTER char **wd;
+
+	wd = wb->w_words;
+	for (i = 0; i < wb->w_nword; i++)
+		if (anys(spcl, *wd++))
+			return (1);
+	return (0);
+}
+
+static int xstrcmp(char *p1, char *p2)
+{
+	return (strcmp(*(char **) p1, *(char **) p2));
+}
+
+/* -------- word.c -------- */
+
+static struct wdblock *newword(REGISTER int nw)
+{
+	REGISTER struct wdblock *wb;
+
+	wb = (struct wdblock *) space(sizeof(*wb) + nw * sizeof(char *));
+	wb->w_bsize = nw;
+	wb->w_nword = 0;
+	return (wb);
+}
+
+static struct wdblock *addword(char *wd, REGISTER struct wdblock *wb)
+{
+	REGISTER struct wdblock *wb2;
+	REGISTER int nw;
+
+	if (wb == NULL)
+		wb = newword(NSTART);
+	if ((nw = wb->w_nword) >= wb->w_bsize) {
+		wb2 = newword(nw * 2);
+		memcpy((char *) wb2->w_words, (char *) wb->w_words,
+			   nw * sizeof(char *));
+		wb2->w_nword = nw;
+		DELETE(wb);
+		wb = wb2;
+	}
+	wb->w_words[wb->w_nword++] = wd;
+	return (wb);
+}
+
+static
+char **getwords(REGISTER struct wdblock *wb)
+{
+	REGISTER char **wd;
+	REGISTER int nb;
+
+	if (wb == NULL)
+		return ((char **) NULL);
+	if (wb->w_nword == 0) {
+		DELETE(wb);
+		return ((char **) NULL);
+	}
+	wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
+	memcpy((char *) wd, (char *) wb->w_words, nb);
+	DELETE(wb);					/* perhaps should done by caller */
+	return (wd);
+}
+
+static int (*func) (char *, char *);
+static int globv;
+
+static void glob0(char *a0, unsigned a1, int a2, int (*a3) (char *, char *))
+{
+	func = a3;
+	globv = a2;
+	glob1(a0, a0 + a1 * a2);
+}
+
+static void glob1(char *base, char *lim)
+{
+	REGISTER char *i, *j;
+	int v2;
+	char *lptr, *hptr;
+	int c;
+	unsigned n;
+
+
+	v2 = globv;
+
+  top:
+	if ((n = (int) (lim - base)) <= v2)
+		return;
+	n = v2 * (n / (2 * v2));
+	hptr = lptr = base + n;
+	i = base;
+	j = lim - v2;
+	for (;;) {
+		if (i < lptr) {
+			if ((c = (*func) (i, lptr)) == 0) {
+				glob2(i, lptr -= v2);
+				continue;
+			}
+			if (c < 0) {
+				i += v2;
+				continue;
+			}
+		}
+
+	  begin:
+		if (j > hptr) {
+			if ((c = (*func) (hptr, j)) == 0) {
+				glob2(hptr += v2, j);
+				goto begin;
+			}
+			if (c > 0) {
+				if (i == lptr) {
+					glob3(i, hptr += v2, j);
+					i = lptr += v2;
+					goto begin;
+				}
+				glob2(i, j);
+				j -= v2;
+				i += v2;
+				continue;
+			}
+			j -= v2;
+			goto begin;
+		}
+
+
+		if (i == lptr) {
+			if (lptr - base >= lim - hptr) {
+				glob1(hptr + v2, lim);
+				lim = lptr;
+			} else {
+				glob1(base, lptr);
+				base = hptr + v2;
+			}
+			goto top;
+		}
+
+
+		glob3(j, lptr -= v2, i);
+		j = hptr -= v2;
+	}
+}
+
+static void glob2(char *i, char *j)
+{
+	REGISTER char *index1, *index2, c;
+	int m;
+
+	m = globv;
+	index1 = i;
+	index2 = j;
+	do {
+		c = *index1;
+		*index1++ = *index2;
+		*index2++ = c;
+	} while (--m);
+}
+
+static void glob3(char *i, char *j, char *k)
+{
+	REGISTER char *index1, *index2, *index3;
+	int c;
+	int m;
+
+	m = globv;
+	index1 = i;
+	index2 = j;
+	index3 = k;
+	do {
+		c = *index1;
+		*index1++ = *index3;
+		*index3++ = *index2;
+		*index2++ = c;
+	} while (--m);
+}
+
+/* -------- io.c -------- */
+
+/*
+ * shell IO
+ */
+
+static int my_getc(int ec)
+{
+	REGISTER int c;
+
+	if (e.linep > elinep) {
+		while ((c = readc()) != '\n' && c);
+		err("input line too long");
+		gflg++;
+		return (c);
+	}
+	c = readc();
+	if ((ec != '\'') && (ec != '`') && (e.iop->task != XGRAVE)) {
+		if (c == '\\') {
+			c = readc();
+			if (c == '\n' && ec != '\"')
+				return (my_getc(ec));
+			c |= QUOTE;
+		}
+	}
+	return (c);
+}
+
+static void unget(int c)
+{
+	if (e.iop >= e.iobase)
+		e.iop->peekc = c;
+}
+
+static int eofc(void)
+{
+	return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0);
+}
+
+static int readc(void)
+{
+	REGISTER int c;
+
+	RCPRINTF(("READC: e.iop %p, e.iobase %p\n", e.iop, e.iobase));
+
+	for (; e.iop >= e.iobase; e.iop--) {
+		RCPRINTF(("READC: e.iop %p, peekc 0x%x\n", e.iop, e.iop->peekc));
+		if ((c = e.iop->peekc) != '\0') {
+			e.iop->peekc = 0;
+			return (c);
+		} else {
+			if (e.iop->prev != 0) {
+				if ((c = (*e.iop->iofn) (e.iop->argp, e.iop)) != '\0') {
+					if (c == -1) {
+						e.iop++;
+						continue;
+					}
+					if (e.iop == iostack)
+						ioecho(c);
+					return (e.iop->prev = c);
+				} else if (e.iop->task == XIO && e.iop->prev != '\n') {
+					e.iop->prev = 0;
+					if (e.iop == iostack)
+						ioecho('\n');
+					return '\n';
+				}
+			}
+			if (e.iop->task == XIO) {
+				if (multiline) {
+					return e.iop->prev = 0;
+				}
+				if (interactive && e.iop == iostack + 1) {
+#ifdef CONFIG_FEATURE_COMMAND_EDITING
+					current_prompt = prompt->value;
+#else
+					prs(prompt->value);
+#endif
+				}
+			}
+		}
+
+	}							/* FOR */
+
+	if (e.iop >= iostack) {
+		RCPRINTF(("READC: return 0, e.iop %p\n", e.iop));
+		return (0);
+	}
+
+	DBGPRINTF(("READC: leave()...\n"));
+	leave();
+
+	/* NOTREACHED */
+	return (0);
+}
+
+static void ioecho(char c)
+{
+	if (flag['v'])
+		write(2, &c, sizeof c);
+}
+
+
+static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *))
+{
+	DBGPRINTF(("PUSHIO: argp %p, argp->afid 0x%x, e.iop %p\n", argp,
+			   argp->afid, e.iop));
+
+	/* Set env ptr for io source to next array spot and check for array overflow */
+	if (++e.iop >= &iostack[NPUSH]) {
+		e.iop--;
+		err("Shell input nested too deeply");
+		gflg++;
+		return;
+	}
+
+	/* We did not overflow the NPUSH array spots so setup data structs */
+
+	e.iop->iofn = (int (*)(struct ioarg *, struct io *)) fn;	/* Store data source func ptr */
+
+	if (argp->afid != AFID_NOBUF)
+		e.iop->argp = argp;
+	else {
+
+		e.iop->argp = ioargstack + (e.iop - iostack);	/* MAL - index into stack */
+		*e.iop->argp = *argp;	/* copy data from temp area into stack spot */
+
+		/* MAL - mainbuf is for 1st data source (command line?) and all nested use a single shared buffer? */
+
+		if (e.iop == &iostack[0])
+			e.iop->argp->afbuf = &mainbuf;
+		else
+			e.iop->argp->afbuf = &sharedbuf;
+
+		/* MAL - if not a termimal AND (commandline OR readable file) then give it a buffer id? */
+		/* This line appears to be active when running scripts from command line */
+		if ((isatty(e.iop->argp->afile) == 0)
+			&& (e.iop == &iostack[0]
+				|| lseek(e.iop->argp->afile, 0L, 1) != -1)) {
+			if (++bufid == AFID_NOBUF)	/* counter rollover check, AFID_NOBUF = 11111111  */
+				bufid = AFID_ID;	/* AFID_ID = 0 */
+
+			e.iop->argp->afid = bufid;	/* assign buffer id */
+		}
+
+		DBGPRINTF(("PUSHIO: iostack %p,  e.iop %p, afbuf %p\n",
+				   iostack, e.iop, e.iop->argp->afbuf));
+		DBGPRINTF(("PUSHIO: mbuf %p, sbuf %p, bid %d, e.iop %p\n",
+				   &mainbuf, &sharedbuf, bufid, e.iop));
+
+	}
+
+	e.iop->prev = ~'\n';
+	e.iop->peekc = 0;
+	e.iop->xchar = 0;
+	e.iop->nlcount = 0;
+
+	if (fn == filechar || fn == linechar)
+		e.iop->task = XIO;
+	else if (fn == (int (*)(struct ioarg *)) gravechar
+			 || fn == (int (*)(struct ioarg *)) qgravechar)
+		e.iop->task = XGRAVE;
+	else
+		e.iop->task = XOTHER;
+
+	return;
+}
+
+static struct io *setbase(struct io *ip)
+{
+	REGISTER struct io *xp;
+
+	xp = e.iobase;
+	e.iobase = ip;
+	return (xp);
+}
+
+/*
+ * Input generating functions
+ */
+
+/*
+ * Produce the characters of a string, then a newline, then EOF.
+ */
+static int nlchar(REGISTER struct ioarg *ap)
+{
+	REGISTER int c;
+
+	if (ap->aword == NULL)
+		return (0);
+	if ((c = *ap->aword++) == 0) {
+		ap->aword = NULL;
+		return ('\n');
+	}
+	return (c);
+}
+
+/*
+ * Given a list of words, produce the characters
+ * in them, with a space after each word.
+ */
+static int wdchar(REGISTER struct ioarg *ap)
+{
+	REGISTER char c;
+	REGISTER char **wl;
+
+	if ((wl = ap->awordlist) == NULL)
+		return (0);
+	if (*wl != NULL) {
+		if ((c = *(*wl)++) != 0)
+			return (c & 0177);
+		ap->awordlist++;
+		return (' ');
+	}
+	ap->awordlist = NULL;
+	return ('\n');
+}
+
+/*
+ * Return the characters of a list of words,
+ * producing a space between them.
+ */
+static int dolchar(REGISTER struct ioarg *ap)
+{
+	REGISTER char *wp;
+
+	if ((wp = *ap->awordlist++) != NULL) {
+		PUSHIO(aword, wp, *ap->awordlist == NULL ? strchar : xxchar);
+		return (-1);
+	}
+	return (0);
+}
+
+static int xxchar(REGISTER struct ioarg *ap)
+{
+	REGISTER int c;
+
+	if (ap->aword == NULL)
+		return (0);
+	if ((c = *ap->aword++) == '\0') {
+		ap->aword = NULL;
+		return (' ');
+	}
+	return (c);
+}
+
+/*
+ * Produce the characters from a single word (string).
+ */
+static int strchar(REGISTER struct ioarg *ap)
+{
+	REGISTER int c;
+
+	if (ap->aword == NULL || (c = *ap->aword++) == 0)
+		return (0);
+	return (c);
+}
+
+/*
+ * Produce quoted characters from a single word (string).
+ */
+static int qstrchar(REGISTER struct ioarg *ap)
+{
+	REGISTER int c;
+
+	if (ap->aword == NULL || (c = *ap->aword++) == 0)
+		return (0);
+	return (c | QUOTE);
+}
+
+/*
+ * Return the characters from a file.
+ */
+static int filechar(REGISTER struct ioarg *ap)
+{
+	REGISTER int i;
+	char c;
+	struct iobuf *bp = ap->afbuf;
+
+	if (ap->afid != AFID_NOBUF) {
+		if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) {
+
+			if (i)
+				lseek(ap->afile, ap->afpos, 0);
+
+			i = safe_read(ap->afile, bp->buf, sizeof(bp->buf));
+
+			if (i <= 0) {
+				closef(ap->afile);
+				return 0;
+			}
+
+			bp->id = ap->afid;
+			bp->ebufp = (bp->bufp = bp->buf) + i;
+		}
+
+		ap->afpos++;
+		return *bp->bufp++ & 0177;
+	}
+#ifdef CONFIG_FEATURE_COMMAND_EDITING
+	if (interactive && isatty(ap->afile)) {
+		static char mycommand[BUFSIZ];
+		static int position = 0, size = 0;
+
+		while (size == 0 || position >= size) {
+			cmdedit_read_input(current_prompt, mycommand);
+			size = strlen(mycommand);
+			position = 0;
+		}
+		c = mycommand[position];
+		position++;
+		return (c);
+	} else
+#endif
+
+	{
+		i = safe_read(ap->afile, &c, sizeof(c));
+		return (i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0));
+	}
+}
+
+/*
+ * Return the characters from a here temp file.
+ */
+static int herechar(REGISTER struct ioarg *ap)
+{
+	char c;
+
+
+	if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) {
+		close(ap->afile);
+		c = 0;
+	}
+	return (c);
+
+}
+
+/*
+ * Return the characters produced by a process (`...`).
+ * Quote them if required, and remove any trailing newline characters.
+ */
+static int gravechar(struct ioarg *ap, struct io *iop)
+{
+	REGISTER int c;
+
+	if ((c = qgravechar(ap, iop) & ~QUOTE) == '\n')
+		c = ' ';
+	return (c);
+}
+
+static int qgravechar(REGISTER struct ioarg *ap, struct io *iop)
+{
+	REGISTER int c;
+
+	DBGPRINTF3(("QGRAVECHAR: enter, ap=%p, iop=%p\n", ap, iop));
+
+	if (iop->xchar) {
+		if (iop->nlcount) {
+			iop->nlcount--;
+			return ('\n' | QUOTE);
+		}
+		c = iop->xchar;
+		iop->xchar = 0;
+	} else if ((c = filechar(ap)) == '\n') {
+		iop->nlcount = 1;
+		while ((c = filechar(ap)) == '\n')
+			iop->nlcount++;
+		iop->xchar = c;
+		if (c == 0)
+			return (c);
+		iop->nlcount--;
+		c = '\n';
+	}
+	return (c != 0 ? c | QUOTE : 0);
+}
+
+/*
+ * Return a single command (usually the first line) from a file.
+ */
+static int linechar(REGISTER struct ioarg *ap)
+{
+	REGISTER int c;
+
+	if ((c = filechar(ap)) == '\n') {
+		if (!multiline) {
+			closef(ap->afile);
+			ap->afile = -1;		/* illegal value */
+		}
+	}
+	return (c);
+}
+
+static void prs(REGISTER const char *s)
+{
+	if (*s)
+		write(2, s, strlen(s));
+}
+
+static void prn(unsigned u)
+{
+	prs(itoa(u));
+}
+
+static void closef(REGISTER int i)
+{
+	if (i > 2)
+		close(i);
+}
+
+static void closeall(void)
+{
+	REGISTER int u;
+
+	for (u = NUFILE; u < NOFILE;)
+		close(u++);
+}
+
+
+/*
+ * remap fd into Shell's fd space
+ */
+static int remap(REGISTER int fd)
+{
+	REGISTER int i;
+	int map[NOFILE];
+	int newfd;
+
+
+	DBGPRINTF(("REMAP: fd=%d, e.iofd=%d\n", fd, e.iofd));
+
+	if (fd < e.iofd) {
+		for (i = 0; i < NOFILE; i++)
+			map[i] = 0;
+
+		do {
+			map[fd] = 1;
+			newfd = dup(fd);
+			fd = newfd;
+		} while (fd >= 0 && fd < e.iofd);
+
+		for (i = 0; i < NOFILE; i++)
+			if (map[i])
+				close(i);
+
+		if (fd < 0)
+			err("too many files open in shell");
+	}
+
+	return (fd);
+}
+
+static int openpipe(REGISTER int *pv)
+{
+	REGISTER int i;
+
+	if ((i = pipe(pv)) < 0)
+		err("can't create pipe - try again");
+	return (i);
+}
+
+static void closepipe(REGISTER int *pv)
+{
+	if (pv != NULL) {
+		close(*pv++);
+		close(*pv);
+	}
+}
+
+/* -------- here.c -------- */
+
+/*
+ * here documents
+ */
+
+static void markhere(REGISTER char *s, struct ioword *iop)
+{
+	REGISTER struct here *h, *lh;
+
+	DBGPRINTF7(("MARKHERE: enter, s=%p\n", s));
+
+	h = (struct here *) space(sizeof(struct here));
+	if (h == 0)
+		return;
+
+	h->h_tag = evalstr(s, DOSUB);
+	if (h->h_tag == 0)
+		return;
+
+	h->h_iop = iop;
+	iop->io_name = 0;
+	h->h_next = NULL;
+	if (inhere == 0)
+		inhere = h;
+	else
+		for (lh = inhere; lh != NULL; lh = lh->h_next)
+			if (lh->h_next == 0) {
+				lh->h_next = h;
+				break;
+			}
+	iop->io_flag |= IOHERE | IOXHERE;
+	for (s = h->h_tag; *s; s++)
+		if (*s & QUOTE) {
+			iop->io_flag &= ~IOXHERE;
+			*s &= ~QUOTE;
+		}
+	h->h_dosub = iop->io_flag & IOXHERE;
+}
+
+static void gethere(void)
+{
+	REGISTER struct here *h, *hp;
+
+	DBGPRINTF7(("GETHERE: enter...\n"));
+
+	/* Scan here files first leaving inhere list in place */
+	for (hp = h = inhere; h != NULL; hp = h, h = h->h_next)
+		readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub ? 0 : '\'');
+
+	/* Make inhere list active - keep list intact for scraphere */
+	if (hp != NULL) {
+		hp->h_next = acthere;
+		acthere = inhere;
+		inhere = NULL;
+	}
+}
+
+static void readhere(char **name, REGISTER char *s, int ec)
+{
+	int tf;
+	char tname[30] = ".msh_XXXXXX";
+	REGISTER int c;
+	jmp_buf ev;
+	char myline[LINELIM + 1];
+	char *thenext;
+
+	DBGPRINTF7(("READHERE: enter, name=%p, s=%p\n", name, s));
+
+	tf = mkstemp(tname);
+	if (tf < 0)
+		return;
+
+	*name = strsave(tname, areanum);
+	if (newenv(setjmp(errpt = ev)) != 0)
+		unlink(tname);
+	else {
+		pushio(e.iop->argp, (int (*)(struct ioarg *)) e.iop->iofn);
+		e.iobase = e.iop;
+		for (;;) {
+			if (interactive && e.iop <= iostack) {
+#ifdef CONFIG_FEATURE_COMMAND_EDITING
+				current_prompt = cprompt->value;
+#else
+				prs(cprompt->value);
+#endif
+			}
+			thenext = myline;
+			while ((c = my_getc(ec)) != '\n' && c) {
+				if (ec == '\'')
+					c &= ~QUOTE;
+				if (thenext >= &myline[LINELIM]) {
+					c = 0;
+					break;
+				}
+				*thenext++ = c;
+			}
+			*thenext = 0;
+			if (strcmp(s, myline) == 0 || c == 0)
+				break;
+			*thenext++ = '\n';
+			write(tf, myline, (int) (thenext - myline));
+		}
+		if (c == 0) {
+			prs("here document `");
+			prs(s);
+			err("' unclosed");
+		}
+		quitenv();
+	}
+	close(tf);
+}
+
+/*
+ * open here temp file.
+ * if unquoted here, expand here temp file into second temp file.
+ */
+static int herein(char *hname, int xdoll)
+{
+	REGISTER int hf;
+	int tf;
+
+#if __GNUC__
+	/* Avoid longjmp clobbering */
+	(void) &tf;
+#endif
+	if (hname == NULL)
+		return (-1);
+
+	DBGPRINTF7(("HEREIN: hname is %s, xdoll=%d\n", hname, xdoll));
+
+	hf = open(hname, 0);
+	if (hf < 0)
+		return (-1);
+
+	if (xdoll) {
+		char c;
+		char tname[30] = ".msh_XXXXXX";
+		jmp_buf ev;
+
+		tf = mkstemp(tname);
+		if (tf < 0)
+			return (-1);
+		if (newenv(setjmp(errpt = ev)) == 0) {
+			PUSHIO(afile, hf, herechar);
+			setbase(e.iop);
+			while ((c = subgetc(0, 0)) != 0) {
+				c &= ~QUOTE;
+				write(tf, &c, sizeof c);
+			}
+			quitenv();
+		} else
+			unlink(tname);
+		close(tf);
+		tf = open(tname, 0);
+		unlink(tname);
+		return (tf);
+	} else
+		return (hf);
+}
+
+static void scraphere(void)
+{
+	REGISTER struct here *h;
+
+	DBGPRINTF7(("SCRAPHERE: enter...\n"));
+
+	for (h = inhere; h != NULL; h = h->h_next) {
+		if (h->h_iop && h->h_iop->io_name)
+			unlink(h->h_iop->io_name);
+	}
+	inhere = NULL;
+}
+
+/* unlink here temp files before a freearea(area) */
+static void freehere(int area)
+{
+	REGISTER struct here *h, *hl;
+
+	DBGPRINTF6(("FREEHERE: enter, area=%d\n", area));
+
+	hl = NULL;
+	for (h = acthere; h != NULL; h = h->h_next)
+		if (getarea((char *) h) >= area) {
+			if (h->h_iop->io_name != NULL)
+				unlink(h->h_iop->io_name);
+			if (hl == NULL)
+				acthere = h->h_next;
+			else
+				hl->h_next = h->h_next;
+		} else
+			hl = h;
+}
+
+
+
+/*
+ * Copyright (c) 1987,1997, Prentice Hall
+ * All rights reserved.
+ *
+ * Redistribution and use of the MINIX operating system in source and
+ * binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * Neither the name of Prentice Hall nor the names of the software
+ * authors or contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,109 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "System Logging Utilities"
+
+config CONFIG_SYSLOGD
+	bool "syslogd"
+	default n
+	help
+	  The syslogd utility is used to record logs of all the
+	  significant events that occur on a system.  Every
+	  message that is logged records the date and time of the
+	  event, and will generally also record the name of the
+	  application that generated the message.  When used in
+	  conjunction with klogd, messages from the Linux kernel
+	  can also be recorded.  This is terribly useful,
+	  especially for finding what happened when something goes
+	  wrong.  And something almost always will go wrong if
+	  you wait long enough....
+
+config CONFIG_FEATURE_ROTATE_LOGFILE
+	bool "Rotate message files"
+	default n
+	depends on CONFIG_SYSLOGD
+	help
+	  This enables syslogd to rotate the message files
+	  on his own. No need to use an external rotatescript.
+
+config CONFIG_FEATURE_REMOTE_LOG
+	bool "Remote Log support"
+	default n
+	depends on CONFIG_SYSLOGD
+	help
+	  When you enable this feature, the syslogd utility can
+	  be used to send system log messages to another system
+	  connected via a network.  This allows the remote
+	  machine to log all the system messages, which can be
+	  terribly useful for reducing the number of serial
+	  cables you use.  It can also be a very good security
+	  measure to prevent system logs from being tampered with
+	  by an intruder.
+
+config CONFIG_FEATURE_IPC_SYSLOG
+	bool "Circular Buffer support"
+	default n
+	depends on CONFIG_SYSLOGD
+	help
+	  When you enable this feature, the syslogd utility will
+	  use a circular buffer to record system log messages.
+	  When the buffer is filled it will continue to overwrite
+	  the oldest messages.  This can be very useful for
+	  systems with little or no permanent storage, since
+	  otherwise system logs can eventually fill up your
+	  entire filesystem, which may cause your system to
+	  break badly.
+
+config CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE
+	int "    Circular buffer size in Kbytes (minimum 4KB)"
+	default 16
+	depends on CONFIG_FEATURE_IPC_SYSLOG
+	help
+	  This option sets the size of the circular buffer
+	  used to record system log messages.
+
+config CONFIG_LOGREAD
+	bool "logread"
+	default y
+	depends on CONFIG_FEATURE_IPC_SYSLOG
+	help
+	  If you enabled Circular Buffer support, you almost
+	  certainly want to enable this feature as well.  This
+	  utility will allow you to read the messages that are
+	  stored in the syslogd circular buffer.
+
+config CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
+	bool "logread double buffering"
+	default n
+	depends on CONFIG_LOGREAD
+	help
+	  'logread' ouput to slow serial terminals can have
+	  side effects on syslog because of the semaphore.
+	  This option make logread to double buffer copy
+	  from circular buffer, minimizing semaphore
+	  contention at some minor memory expense.
+
+config CONFIG_KLOGD
+	bool "klogd"
+	default n
+	depends on CONFIG_SYSLOGD
+	help
+	  klogd is a utility which intercepts and logs all
+	  messages from the Linux kernel and sends the messages
+	  out to the 'syslogd' utility so they can be logged.  If
+	  you wish to record the messages produced by the kernel,
+	  you should enable this option.
+
+config CONFIG_LOGGER
+	bool "logger"
+	default n
+	help
+	    The logger utility allows you to send arbitrary text
+	    messages to the system log (i.e. the 'syslogd' utility) so
+	    they can be logged.  This is generally used to help locate
+	    problems that occur within programs and scripts.
+
+endmenu
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,22 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/sysklogd
+SYSKLOGD_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,32 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+SYSKLOGD_AR:=sysklogd.a
+ifndef $(SYSKLOGD_DIR)
+SYSKLOGD_DIR:=$(top_builddir)/sysklogd/
+endif
+srcdir=$(top_srcdir)/sysklogd
+
+SYSKLOGD-y:=
+SYSKLOGD-$(CONFIG_KLOGD)		+= klogd.o
+SYSKLOGD-$(CONFIG_LOGGER)		+= logger.o
+SYSKLOGD-$(CONFIG_LOGREAD)		+= logread.o
+SYSKLOGD-$(CONFIG_SYSLOGD)		+= syslogd.o
+
+ifneq ($(strip $(SYSKLOGD-y)),)
+libraries-y+=$(SYSKLOGD_DIR)$(SYSKLOGD_AR)
+endif
+
+SYSKLOGD_SRC-y:=$(patsubst %.o,$(srcdir)/%.c,$(SYSKLOGD-y))
+SYSKLOGD_SRC-a:=$(wildcard $(srcdir)/*.c)
+APPLET_SRC-y+=$(SYSKLOGD_SRC-y)
+APPLET_SRC-a+=$(SYSKLOGD_SRC-a)
+
+$(SYSKLOGD_DIR)$(SYSKLOGD_AR): $(patsubst %,$(SYSKLOGD_DIR)%, $(SYSKLOGD-y))
+	$(do_ar)
+
+$(SYSKLOGD_DIR)%.o: $(srcdir)/%.c
+	$(compile.c)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/klogd.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/klogd.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/klogd.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,131 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini klogd implementation for busybox
+ *
+ * Copyright (C) 2001 by Gennady Feldman <gfeldman at gena01.com>.
+ * Changes: Made this a standalone busybox module which uses standalone
+ *					syslog() client interface.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Copyright (C) 2000 by Karl M. Hegbloom <karlheg at debian.org>
+ *
+ * "circular buffer" Copyright (C) 2000 by Gennady Feldman <gfeldman at gena01.com>
+ *
+ * Maintainer: Gennady Feldman <gfeldman at gena01.com> as of Mar 12, 2001
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>		/* for our signal() handlers */
+#include <string.h>		/* strncpy() */
+#include <errno.h>		/* errno and friends */
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/syslog.h>
+#include <sys/klog.h>
+
+static void klogd_signal(int sig ATTRIBUTE_UNUSED)
+{
+	klogctl(7, NULL, 0);
+	klogctl(0, 0, 0);
+	/* logMessage(0, "Kernel log daemon exiting."); */
+	syslog(LOG_NOTICE, "Kernel log daemon exiting.");
+	exit(EXIT_SUCCESS);
+}
+
+#define OPT_LEVEL        1
+#define OPT_FOREGROUND   2
+
+#define KLOGD_LOGBUF_SIZE 4096
+
+int klogd_main(int argc, char **argv)
+{
+	RESERVE_CONFIG_BUFFER(log_buffer, KLOGD_LOGBUF_SIZE);
+	int console_log_level = -1;
+	int priority = LOG_INFO;
+	int i, n, lastc;
+	char *start;
+
+
+	{
+		unsigned long opt;
+
+		/* do normal option parsing */
+		opt = bb_getopt_ulflags(argc, argv, "c:n", &start);
+
+		if (opt & OPT_LEVEL) {
+			/* Valid levels are between 1 and 8 */
+			console_log_level = bb_xgetlarg(start, 10, 1, 8);
+		}
+
+		if (!(opt & OPT_FOREGROUND)) {
+#ifdef BB_NOMMU
+			vfork_daemon_rexec(0, 1, argc, argv, "-n");
+#else
+			bb_xdaemon(0, 1);
+#endif
+		}
+	}
+
+	openlog("kernel", 0, LOG_KERN);
+
+	/* Set up sig handlers */
+	signal(SIGINT, klogd_signal);
+	signal(SIGKILL, klogd_signal);
+	signal(SIGTERM, klogd_signal);
+	signal(SIGHUP, SIG_IGN);
+
+	/* "Open the log. Currently a NOP." */
+	klogctl(1, NULL, 0);
+
+	/* Set level of kernel console messaging.. */
+	if (console_log_level != -1)
+		klogctl(8, NULL, console_log_level);
+
+	syslog(LOG_NOTICE, "klogd started: %s", BB_BANNER);
+
+	while (1) {
+		/* Use kernel syscalls */
+		memset(log_buffer, '\0', KLOGD_LOGBUF_SIZE);
+		n = klogctl(2, log_buffer, KLOGD_LOGBUF_SIZE);
+		if (n < 0) {
+			if (errno == EINTR)
+				continue;
+			syslog(LOG_ERR, "klogd: Error from sys_sycall: %d - %m.\n",
+				   errno);
+			exit(EXIT_FAILURE);
+		}
+
+		/* klogctl buffer parsing modelled after code in dmesg.c */
+		start = &log_buffer[0];
+		lastc = '\0';
+		for (i = 0; i < n; i++) {
+			if (lastc == '\0' && log_buffer[i] == '<') {
+				priority = 0;
+				i++;
+				while (log_buffer[i] >= '0' && log_buffer[i] <= '9') {
+					priority = priority * 10 + (log_buffer[i] - '0');
+					i++;
+				}
+				if (log_buffer[i] == '>')
+					i++;
+				start = &log_buffer[i];
+			}
+			if (log_buffer[i] == '\n') {
+				log_buffer[i] = '\0';	/* zero terminate this message */
+				syslog(priority, "%s", start);
+				start = &log_buffer[i + 1];
+				priority = LOG_INFO;
+			}
+			lastc = log_buffer[i];
+		}
+	}
+	if (ENABLE_FEATURE_CLEAN_UP)
+		RELEASE_CONFIG_BUFFER(log_buffer);
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/logger.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/logger.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/logger.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,191 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini logger implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if !defined CONFIG_SYSLOGD
+
+#define SYSLOG_NAMES
+#include <sys/syslog.h>
+
+#else
+#include <sys/syslog.h>
+#  ifndef __dietlibc__
+	/* We have to do this since the header file defines static
+	 * structures.  Argh.... bad libc, bad, bad...
+	 */
+	typedef struct _code {
+		char *c_name;
+		int c_val;
+	} CODE;
+	extern CODE prioritynames[];
+	extern CODE facilitynames[];
+#  endif
+#endif
+
+/* Decode a symbolic name to a numeric value
+ * this function is based on code
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California.  All rights reserved.
+ *
+ * Original copyright notice is retained at the end of this file.
+ */
+static int decode(char *name, CODE * codetab)
+{
+	CODE *c;
+
+	if (isdigit(*name))
+		return (atoi(name));
+	for (c = codetab; c->c_name; c++) {
+		if (!strcasecmp(name, c->c_name)) {
+			return (c->c_val);
+		}
+	}
+
+	return (-1);
+}
+
+/* Decode a symbolic name to a numeric value
+ * this function is based on code
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California.  All rights reserved.
+ *
+ * Original copyright notice is retained at the end of this file.
+ */
+static int pencode(char *s)
+{
+	char *save;
+	int lev, fac = LOG_USER;
+
+	for (save = s; *s && *s != '.'; ++s);
+	if (*s) {
+		*s = '\0';
+		fac = decode(save, facilitynames);
+		if (fac < 0)
+			bb_error_msg_and_die("unknown facility name: %s", save);
+		*s++ = '.';
+	} else {
+		s = save;
+	}
+	lev = decode(s, prioritynames);
+	if (lev < 0)
+		bb_error_msg_and_die("unknown priority name: %s", save);
+	return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
+}
+
+
+int logger_main(int argc, char **argv)
+{
+	int pri = LOG_USER | LOG_NOTICE;
+	int option = 0;
+	int c, i, opt;
+	char buf[1024], name[128];
+
+	/* Fill out the name string early (may be overwritten later) */
+	bb_getpwuid(name, geteuid(), sizeof(name));
+
+	/* Parse any options */
+	while ((opt = getopt(argc, argv, "p:st:")) > 0) {
+		switch (opt) {
+			case 's':
+				option |= LOG_PERROR;
+				break;
+			case 'p':
+				pri = pencode(optarg);
+				break;
+			case 't':
+				safe_strncpy(name, optarg, sizeof(name));
+				break;
+			default:
+				bb_show_usage();
+		}
+	}
+
+	openlog(name, option, 0);
+	if (optind == argc) {
+		do {
+			/* read from stdin */
+			i = 0;
+			while ((c = getc(stdin)) != EOF && c != '\n' &&
+					i < (sizeof(buf)-1)) {
+				buf[i++] = c;
+			}
+			if (i > 0) {
+				buf[i++] = '\0';
+				syslog(pri, "%s", buf);
+			}
+		} while (c != EOF);
+	} else {
+		char *message = NULL;
+		int len = argc - optind; /* for the space between the args
+					    and  '\0' */
+		opt = len;
+		argv += optind;
+		for (i = 0; i < opt; i++) {
+			len += strlen(*argv);
+			message = xrealloc(message, len);
+			if(!i)
+				message[0] = 0;
+			else
+				strcat(message, " ");
+			strcat(message, *argv);
+			argv++;
+		}
+		syslog(pri, "%s", message);
+	}
+
+	closelog();
+	return EXIT_SUCCESS;
+}
+
+
+/*-
+ * Copyright (c) 1983, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This is the original license statement for the decode and pencode functions.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
+ *		ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
+ *
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/logread.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/logread.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/logread.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,171 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * circular buffer syslog implementation for busybox
+ *
+ * Copyright (C) 2000 by Gennady Feldman <gfeldman at gena01.com>
+ *
+ * Maintainer: Gennady Feldman <gfeldman at gena01.com> as of Mar 12, 2001
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ipc.h>
+#include <sys/types.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <unistd.h>
+
+static const long KEY_ID = 0x414e4547; /*"GENA"*/
+
+static struct shbuf_ds {
+	int size;		// size of data written
+	int head;		// start of message list
+	int tail;		// end of message list
+	char data[1];		// data/messages
+} *buf = NULL;			// shared memory pointer
+
+
+// Semaphore operation structures
+static struct sembuf SMrup[1] = {{0, -1, IPC_NOWAIT | SEM_UNDO}}; // set SMrup
+static struct sembuf SMrdn[2] = {{1, 0}, {0, +1, SEM_UNDO}}; // set SMrdn
+
+static int	log_shmid = -1;	// ipc shared memory id
+static int	log_semid = -1;	// ipc semaphore id
+static jmp_buf	jmp_env;
+
+static void error_exit(const char *str);
+static void interrupted(int sig);
+
+/*
+ * sem_up - up()'s a semaphore.
+ */
+static inline void sem_up(int semid)
+{
+	if ( semop(semid, SMrup, 1) == -1 )
+		error_exit("semop[SMrup]");
+}
+
+/*
+ * sem_down - down()'s a semaphore
+ */
+static inline void sem_down(int semid)
+{
+	if ( semop(semid, SMrdn, 2) == -1 )
+		error_exit("semop[SMrdn]");
+}
+
+int logread_main(int argc, char **argv)
+{
+	int i;
+	int follow=0;
+
+	if (argc == 2 && argv[1][0]=='-' && argv[1][1]=='f') {
+		follow = 1;
+	} else {
+		/* no options, no getopt */
+		if (argc > 1)
+			bb_show_usage();
+	}
+
+	// handle interrupt signal
+	if (setjmp(jmp_env)) goto output_end;
+
+	// attempt to redefine ^C signal
+	signal(SIGINT, interrupted);
+
+	if ( (log_shmid = shmget(KEY_ID, 0, 0)) == -1)
+		error_exit("Can't find circular buffer");
+
+	// Attach shared memory to our char*
+	if ( (buf = shmat(log_shmid, NULL, SHM_RDONLY)) == NULL)
+		error_exit("Can't get access to circular buffer from syslogd");
+
+	if ( (log_semid = semget(KEY_ID, 0, 0)) == -1)
+		error_exit("Can't get access to semaphone(s) for circular buffer from syslogd");
+
+	// Suppose atomic memory move
+	i = follow ? buf->tail : buf->head;
+
+	do {
+#ifdef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
+		char *buf_data;
+		int log_len,j;
+#endif
+
+		sem_down(log_semid);
+
+		//printf("head: %i tail: %i size: %i\n",buf->head,buf->tail,buf->size);
+		if (buf->head == buf->tail || i==buf->tail) {
+			if (follow) {
+				sem_up(log_semid);
+				sleep(1);	/* TODO: replace me with a sleep_on */
+				continue;
+			} else {
+				printf("<empty syslog>\n");
+			}
+		}
+
+		// Read Memory
+#ifdef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
+		log_len = buf->tail - i;
+		if (log_len < 0)
+			log_len += buf->size;
+		buf_data = (char *)xmalloc(log_len);
+
+		if (buf->tail < i) {
+			memcpy(buf_data, buf->data+i, buf->size-i);
+			memcpy(buf_data+buf->size-i, buf->data, buf->tail);
+		} else {
+			memcpy(buf_data, buf->data+i, buf->tail-i);
+		}
+		i = buf->tail;
+
+#else
+		while ( i != buf->tail) {
+			printf("%s", buf->data+i);
+			i+= strlen(buf->data+i) + 1;
+			if (i >= buf->size )
+				i=0;
+		}
+#endif
+		// release the lock on the log chain
+		sem_up(log_semid);
+
+#ifdef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
+		for (j=0; j < log_len; j+=strlen(buf_data+j)+1) {
+			printf("%s", buf_data+j);
+			if (follow)
+				fflush(stdout);
+		}
+		free(buf_data);
+#endif
+		fflush(stdout);
+	} while (follow);
+
+output_end:
+	if (log_shmid != -1)
+		shmdt(buf);
+
+	return EXIT_SUCCESS;
+}
+
+static void interrupted(int sig){
+	signal(SIGINT, SIG_IGN);
+	longjmp(jmp_env, 1);
+}
+
+static void error_exit(const char *str){
+	bb_perror_msg(str);
+	//release all acquired resources
+	if (log_shmid != -1)
+		shmdt(buf);
+
+	exit(1);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/syslogd.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/syslogd.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/sysklogd/syslogd.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,681 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini syslogd implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Copyright (C) 2000 by Karl M. Hegbloom <karlheg at debian.org>
+ *
+ * "circular buffer" Copyright (C) 2001 by Gennady Feldman <gfeldman at gena01.com>
+ *
+ * Maintainer: Gennady Feldman <gfeldman at gena01.com> as of Mar 12, 2001
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <time.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <sys/param.h>
+
+/* SYSLOG_NAMES defined to pull some extra junk from syslog.h */
+#define SYSLOG_NAMES
+#include <sys/syslog.h>
+#include <sys/uio.h>
+
+/* Path for the file where all log messages are written */
+#define __LOG_FILE "/var/log/messages"
+
+/* Path to the unix socket */
+static char lfile[MAXPATHLEN];
+
+static const char *logFilePath = __LOG_FILE;
+
+#ifdef CONFIG_FEATURE_ROTATE_LOGFILE
+/* max size of message file before being rotated */
+static int logFileSize = 200 * 1024;
+
+/* number of rotated message files */
+static int logFileRotate = 1;
+#endif
+
+/* interval between marks in seconds */
+static int MarkInterval = 20 * 60;
+
+/* localhost's name */
+static char LocalHostName[64];
+
+#ifdef CONFIG_FEATURE_REMOTE_LOG
+#include <netinet/in.h>
+/* udp socket for logging to remote host */
+static int remotefd = -1;
+static struct sockaddr_in remoteaddr;
+
+/* where do we log? */
+static char *RemoteHost;
+
+/* what port to log to? */
+static int RemotePort = 514;
+
+/* To remote log or not to remote log, that is the question. */
+static int doRemoteLog = FALSE;
+static int local_logging = FALSE;
+#endif
+
+/* Make loging output smaller. */
+static bool small = false;
+
+
+#define MAXLINE         1024	/* maximum line length */
+
+
+/* circular buffer variables/structures */
+#ifdef CONFIG_FEATURE_IPC_SYSLOG
+
+#if CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE < 4
+#error Sorry, you must set the syslogd buffer size to at least 4KB.
+#error Please check CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE
+#endif
+
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+
+/* our shared key */
+static const long KEY_ID = 0x414e4547;	/*"GENA" */
+
+// Semaphore operation structures
+static struct shbuf_ds {
+	int size;			// size of data written
+	int head;			// start of message list
+	int tail;			// end of message list
+	char data[1];		// data/messages
+} *buf = NULL;			// shared memory pointer
+
+static struct sembuf SMwup[1] = { {1, -1, IPC_NOWAIT} };	// set SMwup
+static struct sembuf SMwdn[3] = { {0, 0}, {1, 0}, {1, +1} };	// set SMwdn
+
+static int shmid = -1;	// ipc shared memory id
+static int s_semid = -1;	// ipc semaphore id
+static int shm_size = ((CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE)*1024);	// default shm size
+static int circular_logging = FALSE;
+
+/*
+ * sem_up - up()'s a semaphore.
+ */
+static inline void sem_up(int semid)
+{
+	if (semop(semid, SMwup, 1) == -1) {
+		bb_perror_msg_and_die("semop[SMwup]");
+	}
+}
+
+/*
+ * sem_down - down()'s a semaphore
+ */
+static inline void sem_down(int semid)
+{
+	if (semop(semid, SMwdn, 3) == -1) {
+		bb_perror_msg_and_die("semop[SMwdn]");
+	}
+}
+
+
+static void ipcsyslog_cleanup(void)
+{
+	printf("Exiting Syslogd!\n");
+	if (shmid != -1) {
+		shmdt(buf);
+	}
+
+	if (shmid != -1) {
+		shmctl(shmid, IPC_RMID, NULL);
+	}
+	if (s_semid != -1) {
+		semctl(s_semid, 0, IPC_RMID, 0);
+	}
+}
+
+static void ipcsyslog_init(void)
+{
+	if (buf == NULL) {
+		if ((shmid = shmget(KEY_ID, shm_size, IPC_CREAT | 1023)) == -1) {
+			bb_perror_msg_and_die("shmget");
+		}
+
+		if ((buf = shmat(shmid, NULL, 0)) == NULL) {
+			bb_perror_msg_and_die("shmat");
+		}
+
+		buf->size = shm_size - sizeof(*buf);
+		buf->head = buf->tail = 0;
+
+		// we'll trust the OS to set initial semval to 0 (let's hope)
+		if ((s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023)) == -1) {
+			if (errno == EEXIST) {
+				if ((s_semid = semget(KEY_ID, 2, 0)) == -1) {
+					bb_perror_msg_and_die("semget");
+				}
+			} else {
+				bb_perror_msg_and_die("semget");
+			}
+		}
+	} else {
+		printf("Buffer already allocated just grab the semaphore?");
+	}
+}
+
+/* write message to buffer */
+static void circ_message(const char *msg)
+{
+	int l = strlen(msg) + 1;	/* count the whole message w/ '\0' included */
+
+	sem_down(s_semid);
+
+	/*
+	 * Circular Buffer Algorithm:
+	 * --------------------------
+	 *
+	 * Start-off w/ empty buffer of specific size SHM_SIZ
+	 * Start filling it up w/ messages. I use '\0' as separator to break up messages.
+	 * This is also very handy since we can do printf on message.
+	 *
+	 * Once the buffer is full we need to get rid of the first message in buffer and
+	 * insert the new message. (Note: if the message being added is >1 message then
+	 * we will need to "remove" >1 old message from the buffer). The way this is done
+	 * is the following:
+	 *      When we reach the end of the buffer we set a mark and start from the beginning.
+	 *      Now what about the beginning and end of the buffer? Well we have the "head"
+	 *      index/pointer which is the starting point for the messages and we have "tail"
+	 *      index/pointer which is the ending point for the messages. When we "display" the
+	 *      messages we start from the beginning and continue until we reach "tail". If we
+	 *      reach end of buffer, then we just start from the beginning (offset 0). "head" and
+	 *      "tail" are actually offsets from the beginning of the buffer.
+	 *
+	 * Note: This algorithm uses Linux IPC mechanism w/ shared memory and semaphores to provide
+	 *       a threadsafe way of handling shared memory operations.
+	 */
+	if ((buf->tail + l) < buf->size) {
+		/* before we append the message we need to check the HEAD so that we won't
+		   overwrite any of the message that we still need and adjust HEAD to point
+		   to the next message! */
+		if (buf->tail < buf->head) {
+			if ((buf->tail + l) >= buf->head) {
+				/* we need to move the HEAD to point to the next message
+				 * Theoretically we have enough room to add the whole message to the
+				 * buffer, because of the first outer IF statement, so we don't have
+				 * to worry about overflows here!
+				 */
+				int k = buf->tail + l - buf->head;	/* we need to know how many bytes
+													   we are overwriting to make
+													   enough room */
+				char *c =
+					memchr(buf->data + buf->head + k, '\0',
+						   buf->size - (buf->head + k));
+				if (c != NULL) {	/* do a sanity check just in case! */
+					buf->head = c - buf->data + 1;	/* we need to convert pointer to
+													   offset + skip the '\0' since
+													   we need to point to the beginning
+													   of the next message */
+					/* Note: HEAD is only used to "retrieve" messages, it's not used
+					   when writing messages into our buffer */
+				} else {	/* show an error message to know we messed up? */
+					printf("Weird! Can't find the terminator token?\n");
+					buf->head = 0;
+				}
+			}
+		}
+
+		/* in other cases no overflows have been done yet, so we don't care! */
+		/* we should be ok to append the message now */
+		strncpy(buf->data + buf->tail, msg, l);	/* append our message */
+		buf->tail += l;	/* count full message w/ '\0' terminating char */
+	} else {
+		/* we need to break up the message and "circle" it around */
+		char *c;
+		int k = buf->tail + l - buf->size;	/* count # of bytes we don't fit */
+
+		/* We need to move HEAD! This is always the case since we are going
+		 * to "circle" the message.
+		 */
+		c = memchr(buf->data + k, '\0', buf->size - k);
+
+		if (c != NULL) {	/* if we don't have '\0'??? weird!!! */
+			/* move head pointer */
+			buf->head = c - buf->data + 1;
+
+			/* now write the first part of the message */
+			strncpy(buf->data + buf->tail, msg, l - k - 1);
+
+			/* ALWAYS terminate end of buffer w/ '\0' */
+			buf->data[buf->size - 1] = '\0';
+
+			/* now write out the rest of the string to the beginning of the buffer */
+			strcpy(buf->data, &msg[l - k - 1]);
+
+			/* we need to place the TAIL at the end of the message */
+			buf->tail = k + 1;
+		} else {
+			printf
+				("Weird! Can't find the terminator token from the beginning?\n");
+			buf->head = buf->tail = 0;	/* reset buffer, since it's probably corrupted */
+		}
+
+	}
+	sem_up(s_semid);
+}
+#endif							/* CONFIG_FEATURE_IPC_SYSLOG */
+
+/* Note: There is also a function called "message()" in init.c */
+/* Print a message to the log file. */
+static void message(char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
+static void message(char *fmt, ...)
+{
+	int fd;
+	struct flock fl;
+	va_list arguments;
+
+	fl.l_whence = SEEK_SET;
+	fl.l_start = 0;
+	fl.l_len = 1;
+
+#ifdef CONFIG_FEATURE_IPC_SYSLOG
+	if ((circular_logging == TRUE) && (buf != NULL)) {
+		char b[1024];
+
+		va_start(arguments, fmt);
+		vsnprintf(b, sizeof(b) - 1, fmt, arguments);
+		va_end(arguments);
+		circ_message(b);
+
+	} else
+#endif
+	if ((fd = device_open(logFilePath,
+					O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND |
+							 O_NONBLOCK)) >= 0) {
+		fl.l_type = F_WRLCK;
+		fcntl(fd, F_SETLKW, &fl);
+#ifdef CONFIG_FEATURE_ROTATE_LOGFILE
+		if ( logFileSize > 0 ) {
+			struct stat statf;
+			int r = fstat(fd, &statf);
+			if( !r && (statf.st_mode & S_IFREG)
+				&& (lseek(fd,0,SEEK_END) > logFileSize) ) {
+				if(logFileRotate > 0) {
+					int i;
+					char oldFile[(strlen(logFilePath)+4)], newFile[(strlen(logFilePath)+4)];
+					for(i=logFileRotate-1;i>0;i--) {
+						sprintf(oldFile, "%s.%d", logFilePath, i-1);
+						sprintf(newFile, "%s.%d", logFilePath, i);
+						rename(oldFile, newFile);
+					}
+					sprintf(newFile, "%s.%d", logFilePath, 0);
+					fl.l_type = F_UNLCK;
+					fcntl (fd, F_SETLKW, &fl);
+					close(fd);
+					rename(logFilePath, newFile);
+					fd = device_open (logFilePath,
+						   O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND |
+						   O_NONBLOCK);
+					fl.l_type = F_WRLCK;
+					fcntl (fd, F_SETLKW, &fl);
+				} else {
+					ftruncate( fd, 0 );
+				}
+			}
+		}
+#endif
+		va_start(arguments, fmt);
+		vdprintf(fd, fmt, arguments);
+		va_end(arguments);
+		fl.l_type = F_UNLCK;
+		fcntl(fd, F_SETLKW, &fl);
+		close(fd);
+	} else {
+		/* Always send console messages to /dev/console so people will see them. */
+		if ((fd = device_open(_PATH_CONSOLE,
+						 O_WRONLY | O_NOCTTY | O_NONBLOCK)) >= 0) {
+			va_start(arguments, fmt);
+			vdprintf(fd, fmt, arguments);
+			va_end(arguments);
+			close(fd);
+		} else {
+			fprintf(stderr, "Bummer, can't print: ");
+			va_start(arguments, fmt);
+			vfprintf(stderr, fmt, arguments);
+			fflush(stderr);
+			va_end(arguments);
+		}
+	}
+}
+
+#ifdef CONFIG_FEATURE_REMOTE_LOG
+static void init_RemoteLog(void)
+{
+	memset(&remoteaddr, 0, sizeof(remoteaddr));
+	remotefd = bb_xsocket(AF_INET, SOCK_DGRAM, 0);
+	remoteaddr.sin_family = AF_INET;
+	remoteaddr.sin_addr = *(struct in_addr *) *(xgethostbyname(RemoteHost))->h_addr_list;
+	remoteaddr.sin_port = htons(RemotePort);
+}
+#endif
+
+static void logMessage(int pri, char *msg)
+{
+	time_t now;
+	char *timestamp;
+	static char res[20];
+#ifdef CONFIG_FEATURE_REMOTE_LOG
+	static char line[MAXLINE + 1];
+#endif
+	CODE *c_pri, *c_fac;
+
+	if (pri != 0) {
+		for (c_fac = facilitynames;
+			 c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri) << 3); c_fac++);
+		for (c_pri = prioritynames;
+			 c_pri->c_name && !(c_pri->c_val == LOG_PRI(pri)); c_pri++);
+		if (c_fac->c_name == NULL || c_pri->c_name == NULL) {
+			snprintf(res, sizeof(res), "<%d>", pri);
+		} else {
+			snprintf(res, sizeof(res), "%s.%s", c_fac->c_name, c_pri->c_name);
+		}
+	}
+
+	if (strlen(msg) < 16 || msg[3] != ' ' || msg[6] != ' ' ||
+		msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') {
+		time(&now);
+		timestamp = ctime(&now) + 4;
+		timestamp[15] = '\0';
+	} else {
+		timestamp = msg;
+		timestamp[15] = '\0';
+		msg += 16;
+	}
+
+	/* todo: supress duplicates */
+
+#ifdef CONFIG_FEATURE_REMOTE_LOG
+	if (doRemoteLog == TRUE) {
+		/* trying connect the socket */
+		if (-1 == remotefd) {
+			init_RemoteLog();
+		}
+
+		/* if we have a valid socket, send the message */
+		if (-1 != remotefd) {
+			now = 1;
+			snprintf(line, sizeof(line), "<%d>%s", pri, msg);
+
+		retry:
+			/* send message to remote logger */
+			if(( -1 == sendto(remotefd, line, strlen(line), 0,
+							(struct sockaddr *) &remoteaddr,
+							sizeof(remoteaddr))) && (errno == EINTR)) {
+				/* sleep now seconds and retry (with now * 2) */
+				sleep(now);
+				now *= 2;
+				goto retry;
+			}
+		}
+	}
+
+	if (local_logging == TRUE)
+#endif
+	{
+		/* now spew out the message to wherever it is supposed to go */
+		if (small)
+			message("%s %s\n", timestamp, msg);
+		else
+			message("%s %s %s %s\n", timestamp, LocalHostName, res, msg);
+	}
+}
+
+static void quit_signal(int sig)
+{
+	logMessage(LOG_SYSLOG | LOG_INFO, "System log daemon exiting.");
+	unlink(lfile);
+#ifdef CONFIG_FEATURE_IPC_SYSLOG
+	ipcsyslog_cleanup();
+#endif
+
+	exit(TRUE);
+}
+
+static void domark(int sig)
+{
+	if (MarkInterval > 0) {
+		logMessage(LOG_SYSLOG | LOG_INFO, "-- MARK --");
+		alarm(MarkInterval);
+	}
+}
+
+/* This must be a #define, since when CONFIG_DEBUG and BUFFERS_GO_IN_BSS are
+ * enabled, we otherwise get a "storage size isn't constant error. */
+static int serveConnection(char *tmpbuf, int n_read)
+{
+	char *p = tmpbuf;
+
+	while (p < tmpbuf + n_read) {
+
+		int pri = (LOG_USER | LOG_NOTICE);
+		int num_lt = 0;
+		char line[MAXLINE + 1];
+		unsigned char c;
+		char *q = line;
+
+		while ((c = *p) && q < &line[sizeof(line) - 1]) {
+			if (c == '<' && num_lt == 0) {
+				/* Parse the magic priority number. */
+				num_lt++;
+				pri = 0;
+				while (isdigit(*(++p))) {
+					pri = 10 * pri + (*p - '0');
+				}
+				if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) {
+					pri = (LOG_USER | LOG_NOTICE);
+				}
+			} else if (c == '\n') {
+				*q++ = ' ';
+			} else if (iscntrl(c) && (c < 0177)) {
+				*q++ = '^';
+				*q++ = c ^ 0100;
+			} else {
+				*q++ = c;
+			}
+			p++;
+		}
+		*q = '\0';
+		p++;
+		/* Now log it */
+		logMessage(pri, line);
+	}
+	return n_read;
+}
+
+static void doSyslogd(void) ATTRIBUTE_NORETURN;
+static void doSyslogd(void)
+{
+	struct sockaddr_un sunx;
+	socklen_t addrLength;
+
+	int sock_fd;
+	fd_set fds;
+
+	/* Set up signal handlers. */
+	signal(SIGINT, quit_signal);
+	signal(SIGTERM, quit_signal);
+	signal(SIGQUIT, quit_signal);
+	signal(SIGHUP, SIG_IGN);
+	signal(SIGCHLD, SIG_IGN);
+#ifdef SIGCLD
+	signal(SIGCLD, SIG_IGN);
+#endif
+	signal(SIGALRM, domark);
+	alarm(MarkInterval);
+
+	/* Create the syslog file so realpath() can work. */
+	if (realpath(_PATH_LOG, lfile) != NULL) {
+		unlink(lfile);
+	}
+
+	memset(&sunx, 0, sizeof(sunx));
+	sunx.sun_family = AF_UNIX;
+	strncpy(sunx.sun_path, lfile, sizeof(sunx.sun_path));
+	sock_fd = bb_xsocket(AF_UNIX, SOCK_DGRAM, 0);
+	addrLength = sizeof(sunx.sun_family) + strlen(sunx.sun_path);
+	if (bind(sock_fd, (struct sockaddr *) &sunx, addrLength) < 0) {
+		bb_perror_msg_and_die("Could not connect to socket " _PATH_LOG);
+	}
+
+	if (chmod(lfile, 0666) < 0) {
+		bb_perror_msg_and_die("Could not set permission on " _PATH_LOG);
+	}
+#ifdef CONFIG_FEATURE_IPC_SYSLOG
+	if (circular_logging == TRUE) {
+		ipcsyslog_init();
+	}
+#endif
+
+#ifdef CONFIG_FEATURE_REMOTE_LOG
+	if (doRemoteLog == TRUE) {
+		init_RemoteLog();
+	}
+#endif
+
+	logMessage(LOG_SYSLOG | LOG_INFO, "syslogd started: " "BusyBox v" BB_VER );
+
+	for (;;) {
+
+		FD_ZERO(&fds);
+		FD_SET(sock_fd, &fds);
+
+		if (select(sock_fd + 1, &fds, NULL, NULL, NULL) < 0) {
+			if (errno == EINTR) {
+				/* alarm may have happened. */
+				continue;
+			}
+			bb_perror_msg_and_die("select error");
+		}
+
+		if (FD_ISSET(sock_fd, &fds)) {
+			int i;
+#if MAXLINE > BUFSIZ
+# define TMP_BUF_SZ BUFSIZ
+#else
+# define TMP_BUF_SZ MAXLINE
+#endif
+#define tmpbuf bb_common_bufsiz1
+
+			if ((i = recv(sock_fd, tmpbuf, TMP_BUF_SZ, 0)) > 0) {
+				tmpbuf[i] = '\0';
+				serveConnection(tmpbuf, i);
+			} else {
+				bb_perror_msg_and_die("UNIX socket error");
+			}
+		}				/* FD_ISSET() */
+	}					/* for main loop */
+}
+
+int syslogd_main(int argc, char **argv)
+{
+	int opt;
+
+	int doFork = TRUE;
+
+	char *p;
+
+	/* do normal option parsing */
+	while ((opt = getopt(argc, argv, "m:nO:s:Sb:R:LC::")) > 0) {
+		switch (opt) {
+		case 'm':
+			MarkInterval = atoi(optarg) * 60;
+			break;
+		case 'n':
+			doFork = FALSE;
+			break;
+		case 'O':
+			logFilePath = optarg;
+			break;
+#ifdef CONFIG_FEATURE_ROTATE_LOGFILE
+		case 's':
+			logFileSize = atoi(optarg) * 1024;
+			break;
+		case 'b':
+			logFileRotate = atoi(optarg);
+			if( logFileRotate > 99 ) logFileRotate = 99;
+			break;
+#endif
+#ifdef CONFIG_FEATURE_REMOTE_LOG
+		case 'R':
+			RemoteHost = bb_xstrdup(optarg);
+			if ((p = strchr(RemoteHost, ':'))) {
+				RemotePort = atoi(p + 1);
+				*p = '\0';
+			}
+			doRemoteLog = TRUE;
+			break;
+		case 'L':
+			local_logging = TRUE;
+			break;
+#endif
+#ifdef CONFIG_FEATURE_IPC_SYSLOG
+		case 'C':
+			if (optarg) {
+				int buf_size = atoi(optarg);
+				if (buf_size >= 4) {
+					shm_size = buf_size * 1024;
+				}
+			}
+			circular_logging = TRUE;
+			break;
+#endif
+		case 'S':
+			small = true;
+			break;
+		default:
+			bb_show_usage();
+		}
+	}
+
+#ifdef CONFIG_FEATURE_REMOTE_LOG
+	/* If they have not specified remote logging, then log locally */
+	if (doRemoteLog == FALSE)
+		local_logging = TRUE;
+#endif
+
+
+	/* Store away localhost's name before the fork */
+	gethostname(LocalHostName, sizeof(LocalHostName));
+	if ((p = strchr(LocalHostName, '.'))) {
+		*p = '\0';
+	}
+
+	umask(0);
+
+	if (doFork == TRUE) {
+#ifdef BB_NOMMU
+		vfork_daemon_rexec(0, 1, argc, argv, "-n");
+#else
+		bb_xdaemon(0, 1);
+#endif
+	}
+	doSyslogd();
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/[
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/[	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/[	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/[
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/[[
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/[[	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/[[	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/[[
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/awk
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/awk	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/awk	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/awk
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/basename
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/basename	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/basename	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/basename
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/busybox
===================================================================
(Binary files differ)


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/busybox
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cal
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cal	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cal	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cal
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cat
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cat	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cat	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cat
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/chmod
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/chmod	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/chmod	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/chmod
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/clear
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/clear	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/clear	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/clear
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cmp
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cmp	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cmp	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cmp
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cp
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cp	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cp	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cp
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/crontab
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/crontab	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/crontab	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/crontab
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cut
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cut	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cut	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/cut
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/date
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/date	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/date	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/date
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/dd
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/dd	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/dd	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/dd
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/df
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/df	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/df	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/df
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/diff
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/diff	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/diff	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/diff
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/dmesg
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/dmesg	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/dmesg	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/dmesg
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/dos2unix
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/dos2unix	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/dos2unix	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/dos2unix
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/du
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/du	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/du	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/du
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/echo
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/echo	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/echo	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/echo
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/env
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/env	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/env	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/env
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/expr
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/expr	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/expr	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/expr
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/false
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/false	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/false	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/false
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/find
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/find	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/find	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/find
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/fold
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/fold	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/fold	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/fold
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/free
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/free	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/free	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/free
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ftpget
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ftpget	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ftpget	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ftpget
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ftpput
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ftpput	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ftpput	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ftpput
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/grep
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/grep	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/grep	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/grep
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/head
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/head	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/head	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/head
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/hexdump
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/hexdump	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/hexdump	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/hexdump
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/hostid
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/hostid	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/hostid	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/hostid
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/kill
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/kill	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/kill	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/kill
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/killall
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/killall	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/killall	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/killall
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/length
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/length	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/length	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/length
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ln
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ln	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ln	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ln
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/logger
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/logger	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/logger	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/logger
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/logname
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/logname	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/logname	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/logname
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ls
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ls	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ls	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ls
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mesg
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mesg	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mesg	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mesg
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mkdir
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mkdir	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mkdir	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mkdir
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mktemp
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mktemp	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mktemp	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mktemp
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/more
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/more	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/more	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/more
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mount
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mount	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mount	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mount
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/msh
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/msh	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/msh	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/msh
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mv
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mv	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mv	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/mv
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/nc
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/nc	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/nc	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/nc
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/netstat
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/netstat	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/netstat	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/netstat
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/nslookup
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/nslookup	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/nslookup	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/nslookup
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/pidof
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/pidof	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/pidof	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/pidof
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ping
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ping	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ping	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ping
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/printf
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/printf	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/printf	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/printf
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ps
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ps	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ps	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/ps
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/pwd
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/pwd	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/pwd	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/pwd
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/realpath
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/realpath	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/realpath	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/realpath
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/rm
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/rm	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/rm	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/rm
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/rmdir
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/rmdir	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/rmdir	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/rmdir
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sed
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sed	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sed	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sed
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/seq
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/seq	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/seq	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/seq
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sleep
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sleep	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sleep	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sleep
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sort
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sort	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sort	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sort
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/strings
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/strings	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/strings	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/strings
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sum
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sum	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sum	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sum
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sync
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sync	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sync	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/sync
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tail
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tail	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tail	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tail
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tar
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tar	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tar	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tar
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tee
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tee	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tee	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tee
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/test
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/test	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/test	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/test
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tftp
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tftp	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tftp	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tftp
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/time
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/time	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/time	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/time
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/top
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/top	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/top	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/top
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/touch
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/touch	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/touch	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/touch
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tr
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tr	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tr	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/tr
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/traceroute
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/traceroute	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/traceroute	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/traceroute
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/true
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/true	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/true	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/true
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/umount
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/umount	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/umount	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/umount
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/uname
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/uname	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/uname	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/uname
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/uniq
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/uniq	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/uniq	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/uniq
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/unix2dos
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/unix2dos	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/unix2dos	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/unix2dos
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/uptime
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/uptime	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/uptime	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/uptime
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/usleep
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/usleep	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/usleep	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/usleep
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/wc
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/wc	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/wc	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/wc
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/wget
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/wget	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/wget	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/wget
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/which
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/which	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/which	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/which
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/who
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/who	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/who	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/who
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/whoami
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/whoami	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/whoami	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/whoami
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/xargs
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/xargs	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/xargs	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/xargs
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/yes
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/yes	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/yes	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/bin/yes
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/chroot
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/chroot	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/chroot	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link ../bin/busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/chroot
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/crond
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/crond	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/crond	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link ../bin/busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/crond
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/halt
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/halt	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/halt	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link ../bin/busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/halt
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/klogd
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/klogd	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/klogd	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link ../bin/busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/klogd
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/logread
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/logread	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/logread	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link ../bin/busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/logread
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/lsmod
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/lsmod	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/lsmod	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link ../bin/busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/lsmod
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/pivot_root
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/pivot_root	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/pivot_root	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link ../bin/busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/pivot_root
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/poweroff
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/poweroff	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/poweroff	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link ../bin/busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/poweroff
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/rdate
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/rdate	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/rdate	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link ../bin/busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/rdate
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/reboot
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/reboot	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/reboot	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link ../bin/busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/reboot
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/start-stop-daemon
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/start-stop-daemon	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/start-stop-daemon	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link ../bin/busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/start-stop-daemon
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/switch_root
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/switch_root	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/switch_root	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link ../bin/busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/switch_root
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/sysctl
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/sysctl	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/sysctl	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link ../bin/busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/sysctl
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/syslogd
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/syslogd	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/syslogd	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+link ../bin/busybox
\ No newline at end of file


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/test/sbin/syslogd
___________________________________________________________________
Name: svn:special
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/README
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/README	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/README	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,31 @@
+To run the test suite, change to this directory and run "./runtest".  It will
+run all of the test cases, and list those with unexpected outcomes.  Adding the
+-v option will cause it to show expected outcomes as well.  To only run the test
+cases for particular applets, specify them as parameters to runtest.
+
+The test cases for an applet reside in the subdirectory of the applet name.  The
+name of the test case should be the assertion that is tested.  The test case
+should be a shell fragment that returns successfully if the test case passes,
+and unsuccessfully otherwise.
+
+If the test case relies on a certain feature, it should include the string
+"FEATURE: " followed by the name of the feature in a comment.  If it is always
+expected to fail, it should include the string "XFAIL" in a comment.
+
+For the entire testsuite, the copyright is as follows:
+
+Copyright (C) 2001, 2002  Matt Kraai
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/TODO
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/TODO	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/TODO	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,26 @@
+This testsuite is quite obviously a work in progress.  As such,
+there are a number of good extensions.  If you are looking for
+something to do, feel free to tackle one or more of the following:
+
+Moving to the new format.
+	The old way was "lots of little tests files in a directory", which
+	doesn't interact well with source control systems.  The new test
+	format is command.tests files that use testing.sh.
+
+Every busybox applet needs a corresponding applet.tests.
+
+Full SUSv3 test suite.
+	Let's make the Linux Test Project jealous, shall we?  Don't just
+	audit programs for standards compliance, _prove_ it with a regression
+	test harness.
+
+	http://www.opengroup.org/onlinepubs/009695399/utilities/
+
+Some tests need root access.
+	It's hard to test things like mount or init as a normal user.
+	Possibly User Mode Linux could be used for this, or perhaps
+	Erik's buildroot.
+
+libbb unit testing
+	Being able to test the functions of libbb individually may
+	help to prevent regressions.

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/all_sourcecode.tests
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/all_sourcecode.tests	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/all_sourcecode.tests	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+# Tests for the sourcecode base itself.
+# Copyright 2006 by Mike Frysinger <vapier at gentoo.org>
+# Licensed under GPL v2, see file LICENSE for details.
+
+[ -n "$srcdir" ] || srcdir=$(pwd)
+. testing.sh
+
+
+#
+# if we don't have the sourcecode available, let's just bail
+#
+[ -s "$srcdir/../Makefile" ] || exit 0
+[ -s "$srcdir/../include/applets.h" ] || exit 0
+
+
+#
+# verify the applet order is correct in applets.h, otherwise
+# applets won't be called properly.
+#
+sed -n -e '/^USE_[A-Z]*(APPLET(/{s:.*(::;s:,.*::;s:"::g;p}' \
+	$srcdir/../include/applets.h > applet.order.current
+LC_ALL=C sort applet.order.current > applet.order.correct
+testing "Applet order" "diff -u applet.order.current applet.order.correct" "" "" ""
+rm -f applet.order.current applet.order.correct
+
+
+#
+# check for misc common typos
+#
+find $srcdir/../ \
+	'(' -type d -a '(' -name .svn -o -name testsuite ')' -prune ')' \
+	-o '(' -type f -a -print0 ')' | xargs -0 \
+	grep -I \
+		-e '\<compatability\>' \
+		-e '\<compatable\>' \
+		-e '\<fordeground\>' \
+		-e '\<depency\>' -e '\<dependancy\>' -e '\<dependancies\>' \
+		-e '\<defalt\>' \
+		-e '\<remaing\>' \
+		-e '\<queueing\>' \
+		-e '\<detatch\>' \
+		-e '\<sempahore\>' \
+		-e '\<reprenstative\>' \
+		-e '\<overriden\>' \
+		-e '\<readed\>' \
+		-e '\<formated\>' \
+		-e '\<algorithic\>' \
+		-e '\<deamon\>' \
+		-e '\<derefernce\>' \
+		| sed -e "s:^$srcdir/\.\./::g" > src.typos
+testing "Common typos" "cat src.typos" "" "" ""
+rm -f src.typos
+
+
+#
+# don't allow obsolete functions
+#
+find $srcdir/.. '(' -name '*.c' -o -name '*.h' ')' -print0 | xargs -0 \
+	grep -E -e '\<(bcmp|bcopy|bzero|getwd|index|mktemp|rindex|utimes)\>[[:space:]]*\(' \
+	| sed -e "s:^$srcdir/\.\./::g" > src.obsolete.funcs
+testing "Obsolete function usage" "cat src.obsolete.funcs" "" "" ""
+rm -f src.obsolete.funcs
+
+
+#
+# don't allow obsolete headers
+#
+find $srcdir/.. '(' -name '*.c' -o -name '*.h' ')' -print0 | xargs -0 \
+	grep -E -e '\<(malloc|memory|sys/(errno|fcntl|signal|stropts|termios|unistd))\.h\>' \
+	| sed -e "s:^$srcdir/\.\./::g" > src.obsolete.headers
+testing "Obsolete headers" "cat src.obsolete.headers" "" "" ""
+rm -f src.obsolete.headers
+
+
+exit $FAILCOUNT


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/all_sourcecode.tests
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/basename/basename-does-not-remove-identical-extension
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/basename/basename-does-not-remove-identical-extension	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/basename/basename-does-not-remove-identical-extension	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test xfoo = x`busybox basename foo foo`

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/basename/basename-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/basename/basename-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/basename/basename-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+test x$(basename $(pwd)) = x$(busybox basename $(pwd))
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/bunzip2/bunzip2-reads-from-standard-input
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/bunzip2/bunzip2-reads-from-standard-input	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/bunzip2/bunzip2-reads-from-standard-input	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+echo foo | bzip2 | busybox bunzip2 > output
+echo foo | cmp - output

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/bunzip2/bunzip2-removes-compressed-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/bunzip2/bunzip2-removes-compressed-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/bunzip2/bunzip2-removes-compressed-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+echo foo | bzip2 >foo.bz2
+busybox bunzip2 foo.bz2
+test ! -f foo.bz2

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/bunzip2/bzcat-does-not-remove-compressed-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/bunzip2/bzcat-does-not-remove-compressed-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/bunzip2/bzcat-does-not-remove-compressed-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+echo foo | bzip2 >foo.bz2
+busybox bzcat foo.bz2
+test -f foo.bz2

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/busybox.tests
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/busybox.tests	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/busybox.tests	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+# Tests for busybox applet itself.
+# Copyright 2005 by Rob Landley <rob at landley.net>
+# Licensed under GPL v2, see file LICENSE for details.
+
+. testing.sh
+
+HELPDUMP=`busybox`
+
+# We need to test under calling the binary under other names.
+
+
+testing "busybox --help busybox" "busybox --help busybox" "$HELPDUMP\n\n" "" ""
+
+ln -s `which busybox` busybox-suffix
+for i in busybox ./busybox-suffix
+do
+	# The gratuitous "\n"s are due to a shell idiosyncrasy:
+	# environment variables seem to strip trailing whitespace.
+
+	testing "" "$i" "$HELPDUMP\n\n" "" ""
+
+	testing "$i unknown" "$i unknown 2>&1" \
+		"unknown: applet not found\n" "" ""
+
+	testing "$i --help" "$i --help 2>&1" "$HELPDUMP\n\n" "" ""
+
+	optional CAT
+	testing "" "$i cat" "moo" "" "moo"
+	testing "$i --help cat" "$i --help cat 2>&1 | grep prints" \
+		"Concatenates FILE(s) and prints them to stdout.\n" "" ""
+	optional ""
+
+	testing "$i --help unknown" "$i --help unknown 2>&1" \
+		"unknown: applet not found\n" "" ""
+done
+rm busybox-suffix
+
+ln -s `which busybox` unknown
+
+testing "busybox as unknown name" "./unknown 2>&1" \
+	"unknown: applet not found\n" "" ""
+rm unknown
+
+exit $FAILCOUNT


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/busybox.tests
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cat/cat-prints-a-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cat/cat-prints-a-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cat/cat-prints-a-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+echo I WANT > foo
+busybox cat foo >bar
+cmp foo bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cat/cat-prints-a-file-and-standard-input
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cat/cat-prints-a-file-and-standard-input	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cat/cat-prints-a-file-and-standard-input	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,7 @@
+echo I WANT > foo
+echo SOMETHING | busybox cat foo - >bar
+cat >baz <<EOF
+I WANT
+SOMETHING
+EOF
+cmp bar baz

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cmp/cmp-detects-difference
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cmp/cmp-detects-difference	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cmp/cmp-detects-difference	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,9 @@
+echo foo >foo
+echo bar >bar
+set +e
+busybox cmp -s foo bar
+if [ $? != 0 ] ; then
+	exit 0;
+fi
+
+exit 1;

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-a-files-to-dir
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-a-files-to-dir	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-a-files-to-dir	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,14 @@
+echo file number one > file1
+echo file number two > file2
+ln -s file2 link1
+mkdir dir1
+touch --date='Sat Jan 29 21:24:08 PST 2000' dir1/file3
+mkdir there
+busybox cp -a file1 file2 link1 dir1 there
+test -f there/file1
+test -f there/file2
+test ! -s there/dir1/file3
+test -L there/link1
+test xfile2 = x`readlink there/link1`
+test ! dir1/file3 -ot there/dir1/file3
+test ! dir1/file3 -nt there/dir1/file3

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-a-preserves-links
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-a-preserves-links	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-a-preserves-links	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,5 @@
+touch foo
+ln -s foo bar
+busybox cp -a bar baz
+test -L baz
+test xfoo = x`readlink baz`

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-copies-empty-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-copies-empty-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-copies-empty-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+touch foo
+busybox cp foo bar
+cmp foo bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-copies-large-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-copies-large-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-copies-large-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+dd if=/dev/zero of=foo seek=10k count=1 2>/dev/null
+busybox cp foo bar
+cmp foo bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-copies-small-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-copies-small-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-copies-small-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+echo I WANT > foo
+busybox cp foo bar
+cmp foo bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-d-files-to-dir
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-d-files-to-dir	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-d-files-to-dir	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,11 @@
+echo file number one > file1
+echo file number two > file2
+touch file3
+ln -s file2 link1
+mkdir there
+busybox cp -d file1 file2 file3 link1 there
+test -f there/file1
+test -f there/file2
+test ! -s there/file3
+test -L there/link1
+test xfile2 = x`readlink there/link1`

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-dir-create-dir
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-dir-create-dir	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-dir-create-dir	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+mkdir bar 
+touch bar/baz
+busybox cp -R bar foo 
+test -f foo/baz 

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-dir-existing-dir
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-dir-existing-dir	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-dir-existing-dir	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,5 @@
+mkdir bar 
+touch bar/baz
+mkdir foo
+busybox cp -R bar foo 
+test -f foo/bar/baz 

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-does-not-copy-unreadable-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-does-not-copy-unreadable-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-does-not-copy-unreadable-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,6 @@
+touch foo
+chmod a-r foo
+set +e
+busybox cp foo bar
+set -e
+test ! -f bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-files-to-dir
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-files-to-dir	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-files-to-dir	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,11 @@
+echo file number one > file1
+echo file number two > file2
+touch file3
+ln -s file2 link1
+mkdir there
+busybox cp file1 file2 file3 link1 there
+test -f there/file1
+test -f there/file2
+test ! -s there/file3
+test -f there/link1
+cmp there/file2 there/link1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-follows-links
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-follows-links	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-follows-links	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+touch foo
+ln -s foo bar
+busybox cp bar baz
+test -f baz

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-preserves-hard-links
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-preserves-hard-links	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-preserves-hard-links	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,6 @@
+# FEATURE: CONFIG_FEATURE_PRESERVE_HARDLINKS
+touch foo
+ln foo bar
+mkdir baz
+busybox cp -d foo bar baz
+test baz/foo -ef baz/bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-preserves-links
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-preserves-links	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-preserves-links	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,5 @@
+touch foo
+ln -s foo bar
+busybox cp -d bar baz
+test -L baz
+test xfoo = x`readlink baz`

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-preserves-source-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-preserves-source-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cp/cp-preserves-source-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+touch foo
+busybox cp foo bar
+test -f foo

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-a-character
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-a-character	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-a-character	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test $(echo abcd | busybox cut -c 3) = c

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-a-closed-range
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-a-closed-range	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-a-closed-range	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test $(echo abcd | busybox cut -c 1-2) = ab

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-a-field
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-a-field	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-a-field	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test $(echo -e "f1\tf2\tf3" | busybox cut -f 2) = f2

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-an-open-range
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-an-open-range	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-an-open-range	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test $(echo abcd | busybox cut -c -3) = abc

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-an-unclosed-range
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-an-unclosed-range	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/cut/cut-cuts-an-unclosed-range	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test $(echo abcd | busybox cut -c 3-) = cd

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/date-R-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/date-R-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/date-R-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+test x"`date -R`" = x"`busybox date -R`"
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/date-format-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/date-format-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/date-format-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test x"`date +%d/%m/%y`" = x"`busybox date +%d/%m/%y`"

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/date-u-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/date-u-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/date-u-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+test x"`date -u`" = x"`busybox date -u`"
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/date-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/date-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/date/date-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+test x"`date`" = x"`busybox date`"
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/dd-accepts-if
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/dd-accepts-if	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/dd-accepts-if	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+echo I WANT >foo
+test "$(busybox dd if=foo 2>/dev/null)" = "I WANT"

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/dd-accepts-of
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/dd-accepts-of	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/dd-accepts-of	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+echo I WANT | busybox dd of=foo 2>/dev/null
+echo I WANT | cmp foo -

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/dd-copies-from-standard-input-to-standard-output
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/dd-copies-from-standard-input-to-standard-output	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/dd-copies-from-standard-input-to-standard-output	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test "$(echo I WANT | busybox dd 2>/dev/null)" = "I WANT"

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/dd-prints-count-to-standard-error
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/dd-prints-count-to-standard-error	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dd/dd-prints-count-to-standard-error	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+echo I WANT | busybox dd of=foo >/dev/null 2>bar
+grep -q records bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-absolute-path
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-absolute-path	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-absolute-path	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test $(busybox dirname /foo/bar/baz) = /foo/bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-empty-path
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-empty-path	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-empty-path	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test $(busybox dirname '') = .

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-multiple-slashes
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-multiple-slashes	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-multiple-slashes	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test $(busybox dirname foo/bar///baz) = foo/bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-relative-path
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-relative-path	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-relative-path	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test $(busybox dirname foo/bar/baz) = foo/bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-root
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-root	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-root	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test $(busybox dirname /) = /

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-single-component
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-single-component	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-handles-single-component	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test $(busybox dirname foo) = .

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/dirname/dirname-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+test x$(dirname $(pwd)) = x$(busybox dirname $(pwd))
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-h-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-h-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-h-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+[ -n "$d" ] || d=..
+du -h "$d" > logfile.gnu
+busybox du -h "$d" > logfile.bb
+cmp logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-k-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-k-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-k-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+[ -n "$d" ] || d=..
+du -k "$d" > logfile.gnu
+busybox du -k "$d" > logfile.bb
+cmp logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-l-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-l-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-l-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+[ -n "$d" ] || d=..
+du -l "$d" > logfile.gnu
+busybox du -l "$d" > logfile.bb
+cmp logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-m-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-m-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-m-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+[ -n "$d" ] || d=..
+du -m "$d" > logfile.gnu
+busybox du -m "$d" > logfile.bb
+cmp logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-s-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-s-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-s-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+[ -n "$d" ] || d=..
+du -s "$d" > logfile.gnu
+busybox du -s "$d" > logfile.bb
+cmp logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/du/du-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+[ -n "$d" ] || d=..
+du "$d" > logfile.gnu
+busybox du "$d" > logfile.bb
+cmp logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/echo-does-not-print-newline
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/echo-does-not-print-newline	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/echo-does-not-print-newline	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test `busybox echo -n word | wc -c` -eq 4

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/echo-prints-argument
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/echo-prints-argument	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/echo-prints-argument	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test xfubar = x`busybox echo fubar`

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/echo-prints-arguments
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/echo-prints-arguments	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/echo-prints-arguments	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test "`busybox echo foo bar`" = "foo bar"

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/echo-prints-newline
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/echo-prints-newline	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/echo/echo-prints-newline	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test `busybox echo word | wc -c` -eq 5

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/expr/expr-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/expr/expr-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/expr/expr-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,59 @@
+# busybox expr
+busybox expr 1 \| 1
+busybox expr 1 \| 0
+busybox expr 0 \| 1
+busybox expr 1 \& 1
+busybox expr 0 \< 1
+busybox expr 1 \> 0
+busybox expr 0 \<= 1
+busybox expr 1 \<= 1
+busybox expr 1 \>= 0
+busybox expr 1 \>= 1
+busybox expr 1 + 2
+busybox expr 2 - 1
+busybox expr 2 \* 3
+busybox expr 12 / 2
+busybox expr 12 % 5
+
+
+set +e
+busybox expr 0 \| 0
+if [ $? != 1 ] ; then
+	exit 1;
+fi;
+
+busybox expr 1 \& 0
+if [ $? != 1 ] ; then
+	exit 1;
+fi;
+
+busybox expr 0 \& 1
+if [ $? != 1 ] ; then
+	exit 1;
+fi;
+
+busybox expr 0 \& 0
+if [ $? != 1 ] ; then
+	exit 1;
+fi;
+
+busybox expr 1 \< 0
+if [ $? != 1 ] ; then
+	exit 1;
+fi;
+
+busybox expr 0 \> 1
+if [ $? != 1 ] ; then
+	exit 1;
+fi;
+
+busybox expr 1 \<= 0
+if [ $? != 1 ] ; then
+	exit 1;
+fi;
+
+busybox expr 0 \>= 1
+if [ $? != 1 ] ; then
+	exit 1;
+fi;
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/false/false-is-silent
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/false/false-is-silent	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/false/false-is-silent	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+busybox false 2>&1 | cmp - /dev/null

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/false/false-returns-failure
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/false/false-returns-failure	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/false/false-returns-failure	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+! busybox false

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/find/find-supports-minus-xdev
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/find/find-supports-minus-xdev	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/find/find-supports-minus-xdev	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+busybox find . -xdev >/dev/null 2>&1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/grep.tests
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/grep.tests	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/grep.tests	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,84 @@
+#!/bin/sh
+
+# grep tests.
+# Copyright 2005 by Rob Landley <rob at landley.net>
+# Licensed under GPL v2, see file LICENSE for details.
+
+# AUDIT: 
+
+. testing.sh
+
+# testing "test name" "options" "expected result" "file input" "stdin"
+#   file input will be file called "input"
+#   test can create a file "actual" instead of writing to stdout
+
+# Test exit status
+
+testing "grep (exit with error)" "grep nonexistent 2> /dev/null ; echo \$?" \
+	"1\n" "" ""
+testing "grep (exit success)" "grep grep $0 > /dev/null 2>&1 ; echo \$?" "0\n" \
+	"" ""
+# Test various data sources and destinations
+
+testing "grep (default to stdin)" "grep two" "two\n" "" \
+	"one\ntwo\nthree\nthree\nthree\n"
+testing "grep - (specify stdin)" "grep two -" "two\n" "" \
+	"one\ntwo\nthree\nthree\nthree\n"
+testing "grep input (specify file)" "grep two input" "two\n" \
+	"one\ntwo\nthree\nthree\nthree\n" ""
+
+testing "grep (no newline at EOL)" "grep bug" "bug" "bug" ""
+
+# Note that this assumes actual is empty.
+testing "grep input actual (two files)" "grep two input actual 2> /dev/null" \
+	"input:two\n" "one\ntwo\nthree\nthree\nthree\n" ""
+
+testing "grep - infile (specify stdin and file)" "grep two - input" \
+	"(standard input):two\ninput:two\n" "one\ntwo\nthree\n" \
+	"one\ntwo\ntoo\nthree\nthree\n"
+
+# Check if we see the correct return value if both stdin and non-existing file
+# are given.
+testing "grep - nofile (specify stdin and nonexisting file)" \
+	"grep two - nonexistent 2> /dev/null ; echo \$?" \
+	"(standard input):two\n(standard input):two\n2\n" \
+	"" "one\ntwo\ntwo\nthree\nthree\nthree\n"
+testing "grep -q - nofile (specify stdin and nonexisting file, no match)" \
+	"grep -q nomatch - nonexistent 2> /dev/null ; echo \$?" \
+	"2\n" "" "one\ntwo\ntwo\nthree\nthree\nthree\n"
+# SUSv3: If the -q option is specified, the exit status shall be zero
+#        if an input line is selected, even if an error was detected.
+testing "grep -q - nofile (specify stdin and nonexisting file, match)" \
+	"grep -q two - nonexistent ; echo \$?" \
+	"0\n" "" "one\ntwo\ntwo\nthree\nthree\nthree\n"
+
+# Test various command line options
+# -s no error messages
+testing "grep -s nofile (nonexisting file, no match)" \
+	"grep -s nomatch nonexistent ; echo \$?" "2\n" "" ""
+testing "grep -s nofile - (stdin and nonexisting file, match)" \
+	"grep -s domatch nonexistent - ; echo \$?" \
+	"(standard input):domatch\n2\n" "" "nomatch\ndomatch\nend\n"
+
+# This doesn't match GNU behaviour (Binary file input matches)
+# acts like GNU grep -a
+testing "grep handles binary files" "grep foo input" "foo\n" "\0foo\n\n" ""
+# This doesn't match GNU behaviour (Binary file (standard input) matches)
+# acts like GNU grep -a
+testing "grep handles binary stdin" "grep foo" "foo\n" "" "\0foo\n\n"
+
+testing "grep matches NUL" "grep . input > /dev/null 2>&1 ; echo \$?" \
+	"0\n" "\0\n" ""
+
+# -e regex
+testing "grep handles multiple regexps" "grep -e one -e two input ; echo \$?" \
+	"one\ntwo\n0\n" "one\ntwo\n" ""
+
+optional FEATURE_GREP_EGREP_ALIAS
+testing "grep -E supports extended regexps" "grep -E fo+" "foo\n" "" \
+	"b\ar\nfoo\nbaz"
+testing "grep is also egrep" "egrep foo" "foo\n" "" "foo\nbar\n"
+testing "egrep is not case insensitive" \
+	"egrep foo ; [ \$? -ne 0 ] && echo yes" "yes\n" "" "FOO\n"
+
+exit $FAILCOUNT


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/grep.tests
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gunzip/gunzip-reads-from-standard-input
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gunzip/gunzip-reads-from-standard-input	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gunzip/gunzip-reads-from-standard-input	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+echo foo | gzip | busybox gunzip > output
+echo foo | cmp - output

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gzip/gzip-accepts-multiple-files
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gzip/gzip-accepts-multiple-files	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gzip/gzip-accepts-multiple-files	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+touch foo bar
+busybox gzip foo bar
+test -f foo.gz -a -f bar.gz

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gzip/gzip-accepts-single-minus
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gzip/gzip-accepts-single-minus	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gzip/gzip-accepts-single-minus	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+echo foo | busybox gzip - >/dev/null

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gzip/gzip-removes-original-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gzip/gzip-removes-original-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/gzip/gzip-removes-original-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+touch foo
+busybox gzip foo
+test ! -f foo

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/head/head-n-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/head/head-n-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/head/head-n-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+[ -n "$d" ] || d=..
+head -n 2 "$d/README" > logfile.gnu
+busybox head -n 2 "$d/README" > logfile.bb
+cmp logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/head/head-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/head/head-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/head/head-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+[ -n "$d" ] || d=..
+head "$d/README" > logfile.gnu
+busybox head "$d/README" > logfile.bb
+cmp logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostid/hostid-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostid/hostid-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostid/hostid-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+test x$(hostid) = x$(busybox hostid)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/hostname-d-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/hostname-d-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/hostname-d-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+test x$(hostname -d) = x$(busybox hostname -d)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/hostname-i-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/hostname-i-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/hostname-i-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+test x$(hostname -i) = x$(busybox hostname -i)
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/hostname-s-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/hostname-s-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/hostname-s-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test x$(hostname -s) = x$(busybox hostname -s)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/hostname-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/hostname-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/hostname/hostname-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test x$(hostname) = x$(busybox hostname)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/id-g-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/id-g-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/id-g-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test x$(id -g) = x$(busybox id -g)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/id-u-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/id-u-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/id-u-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test x$(id -u) = x$(busybox id -u)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/id-un-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/id-un-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/id-un-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test x$(id -un) = x$(busybox id -un)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/id-ur-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/id-ur-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/id/id-ur-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test x$(id -ur) = x$(busybox id -ur)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-creates-hard-links
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-creates-hard-links	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-creates-hard-links	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+echo file number one > file1
+busybox ln file1 link1
+test -f file1
+test -f link1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-creates-soft-links
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-creates-soft-links	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-creates-soft-links	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+echo file number one > file1
+busybox ln -s file1 link1
+test -L link1
+test xfile1 = x`readlink link1`

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-force-creates-hard-links
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-force-creates-hard-links	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-force-creates-hard-links	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,5 @@
+echo file number one > file1
+echo file number two > link1
+busybox ln -f file1 link1
+test -f file1
+test -f link1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-force-creates-soft-links
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-force-creates-soft-links	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-force-creates-soft-links	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,5 @@
+echo file number one > file1
+echo file number two > link1
+busybox ln -f -s file1 link1
+test -L link1
+test xfile1 = x`readlink link1`

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-preserves-hard-links
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-preserves-hard-links	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-preserves-hard-links	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,8 @@
+echo file number one > file1
+echo file number two > link1
+set +e
+busybox ln file1 link1
+if [ $? != 0 ] ; then
+	exit 0;
+fi
+exit 1;

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-preserves-soft-links
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-preserves-soft-links	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ln/ln-preserves-soft-links	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,9 @@
+echo file number one > file1
+echo file number two > link1
+set +e
+busybox ln -s file1 link1
+if [ $? != 0 ] ; then
+	exit 0;
+fi
+exit 1;
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/ls-1-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/ls-1-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/ls-1-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+[ -n "$d" ] || d=..
+ls -1 "$d" > logfile.gnu
+busybox ls -1 "$d" > logfile.bb
+cmp logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/ls-h-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/ls-h-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/ls-h-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+[ -n "$d" ] || d=..
+ls -h "$d" > logfile.gnu
+busybox ls -h "$d" > logfile.bb
+cmp logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/ls-l-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/ls-l-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/ls-l-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+[ -n "$d" ] || d=..
+LC_ALL=C ls -l "$d" > logfile.gnu
+busybox ls -l "$d" > logfile.bb
+diff -w logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/ls-s-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/ls-s-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/ls/ls-s-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+[ -n "$d" ] || d=..
+LC_ALL=C ls -1s "$d" > logfile.gnu
+busybox ls -1s "$d" > logfile.bb
+cmp logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/md5sum/md5sum-verifies-non-binary-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/md5sum/md5sum-verifies-non-binary-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/md5sum/md5sum-verifies-non-binary-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+touch foo
+md5sum foo > bar
+busybox md5sum -c bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mkdir/mkdir-makes-a-directory
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mkdir/mkdir-makes-a-directory	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mkdir/mkdir-makes-a-directory	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+busybox mkdir foo
+test -d foo

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mkdir/mkdir-makes-parent-directories
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mkdir/mkdir-makes-parent-directories	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mkdir/mkdir-makes-parent-directories	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+busybox mkdir -p foo/bar
+test -d foo -a -d foo/bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mount.testroot
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mount.testroot	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mount.testroot	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,183 @@
+#!/bin/sh
+
+# SUSv3 compliant mount and umount tests.
+# Copyright 2005 by Rob Landley <rob at landley.net>
+# Licensed under GPL v2, see file LICENSE for details.
+
+if [ -z "$TESTDIR" ]
+then
+  echo 'Need $TESTDIR'
+  exit 1
+fi
+
+cd "$TESTDIR"
+
+. testing.sh
+
+# If we aren't PID 1, barf.
+
+#if [ $$ -ne 1 ]
+#then
+#  echo "SKIPPED: mount test requires emulation environment"
+#  exit 0
+#fi
+
+# Run tests within the chroot environment.
+dochroot bash rm ls ln cat ps mknod mkdir dd grep cmp diff tail \
+	mkfs.ext2 mkfs.vfat mount umount losetup wc << EOF
+#!/bin/bash
+
+. /testing.sh
+
+mknod /dev/loop0 b 7 0
+mknod /dev/loop1 b 7 1
+
+# We need /proc to do much.  Make sure we can mount it explicitly.
+
+testing "mount no proc [GNUFAIL]" "mount 2> /dev/null || echo yes" "yes\n" "" ""
+testing "mount /proc" "mount -t proc /proc /proc && ls -d /proc/1" \
+	"/proc/1\n" "" ""
+
+# Make sure the last thing in the list is /proc
+
+testing "mount list1" "mount | tail -n 1" "/proc on /proc type proc (rw)\n" \
+	"" ""
+
+
+# Create an ext2 image
+
+mkdir -p images/{ext2.dir,vfat.dir,test1,test2,test3}
+dd if=/dev/zero of=images/ext2.img bs=1M count=1 2> /dev/null
+mkfs.ext2 -F -b 1024 images/ext2.img > /dev/null 2> /dev/null
+dd if=/dev/zero of=images/vfat.img bs=1M count=1 2> /dev/null
+mkfs.vfat images/vfat.img > /dev/null
+
+# Test mount it
+
+testing "mount vfat image (explicitly autodetect type)" \
+	"mount -t auto images/vfat.img images/vfat.dir && mount | tail -n 1 | grep -o 'vfat.dir type vfat'" \
+	"vfat.dir type vfat\n" "" ""
+testing "mount ext2 image (autodetect type)" \
+	"mount images/ext2.img images/ext2.dir 2> /dev/null && mount | tail -n 1" \
+	"/dev/loop1 on /images/ext2.dir type ext2 (rw)\n" "" ""
+testing "mount remount ext2 image noatime" \
+	"mount -o remount,noatime images/ext2.dir && mount | tail -n 1" \
+	"/dev/loop1 on /images/ext2.dir type ext2 (rw,noatime)\n" "" ""
+testing "mount remount ext2 image ro remembers noatime" \
+	"mount -o remount,ro images/ext2.dir && mount | tail -n 1" \
+	"/dev/loop1 on /images/ext2.dir type ext2 (ro,noatime)\n" "" ""
+
+umount -d images/vfat.dir
+umount -d images/ext2.dir
+
+testing "mount umount freed loop device" \
+	"mount images/ext2.img images/ext2.dir && mount | tail -n 1" \
+	"/dev/loop0 on /images/ext2.dir type ext2 (rw)\n" "" ""
+
+testing "mount block device" \
+	"mount -t ext2 /dev/loop0 images/test1 && mount | tail -n 1" \
+	"/dev/loop0 on /images/test1 type ext2 (rw)\n" "" ""
+
+umount -d images/ext2.dir images/test1
+
+testing "mount remount nonexistent directory" \
+	"mount -o remount,noatime images/ext2.dir 2> /dev/null || echo yes" \
+	"yes\n" "" ""
+
+# Fun with mount -a
+
+testing "mount -a no fstab" "mount -a 2>/dev/null || echo yes" "yes\n" "" "" 
+
+umount /proc
+
+# The first field is space delimited, the rest tabs.
+
+cat > /etc/fstab << FSTAB
+/proc             /proc			proc	defaults	0	0
+# Autodetect loop, and provide flags with commas in them.
+/images/ext2.img  /images/ext2.dir	ext2	noatime,nodev	0	0
+# autodetect filesystem, flags without commas.
+/images/vfat.img  /images/vfat.dir	auto	ro		0	0
+# A block device
+/dev/loop2        /images/test1		auto	defaults	0	0
+# tmpfs, filesystem specific flag.
+walrus		  /images/test2		tmpfs	size=42		0	0
+# Autodetect a bind mount.
+/images/test2     /images/test3		auto	defaults	0	0
+FSTAB
+
+# Put something on loop2.
+mknod /dev/loop2 b 7 2
+cat images/ext2.img > images/ext2-2.img
+losetup /dev/loop2 images/ext2-2.img
+
+testing "mount -a" "mount -a && echo hello > /images/test2/abc && cat /images/test3/abc && (mount | wc -l)" "hello\n8\n" "" ""
+
+testing "umount -a" "umount -a && ls /proc" "" "" ""
+
+#/bin/bash < /dev/tty > /dev/tty 2> /dev/tty
+mknod /dev/console c 5 1
+/bin/bash < /dev/console > /dev/console 2> /dev/console
+EOF
+
+exit 0
+
+# Run some tests
+
+losetup nonexistent device (should return error 2)
+losetup unbound loop device (should return error 1)
+losetup bind file to loop device
+losetup bound loop device (display)  (should return error 0)
+losetup filename (error)
+losetup nofile (file not found)
+losetup -d
+losetup bind with offset
+losetup -f (print first loop device)
+losetup -f filename (associate file with first loop device)
+losetup -o (past end of file) -f filename
+
+mount -a
+  with multiple entries in fstab
+  with duplicate entries in fstab
+  with relative paths in fstab
+  with user entries in fstab
+mount -o async,sync,atime,noatime,dev,nodev,exec,noexec,loop,suid,nosuid,remount,ro,rw,bind,move
+mount -r
+mount -o rw -r
+mount -w -o ro
+mount -t auto
+
+mount with relative path in fstab
+mount block device
+mount char device
+mount file (autoloop)
+mount directory (autobind)
+
+
+testing "umount with no /proc"
+testing "umount curdir"
+
+# The basic tests.  These should work even with the small busybox.
+
+testing "sort" "input" "a\nb\nc\n" "c\na\nb\n" ""
+testing "sort #2" "input" "010\n1\n3\n" "3\n1\n010\n" ""
+testing "sort stdin" "" "a\nb\nc\n" "" "b\na\nc\n"
+testing "sort numeric" "-n input" "1\n3\n010\n" "3\n1\n010\n" ""
+testing "sort reverse" "-r input" "wook\nwalrus\npoint\npabst\naargh\n" \
+	"point\nwook\npabst\naargh\nwalrus\n" ""
+
+optional FEATURE_MOUNT_LOOP
+testing "umount -D"
+
+optional FEATURE_MTAB_SUPPORT
+optional FEATURE_MOUNT_NFS
+# No idea what to test here.
+
+optional UMOUNT
+optional FEATURE_UMOUNT_ALL
+testing "umount -a"
+testing "umount -r"
+testing "umount -l"
+testing "umount -f"
+
+exit $FAILCOUNT


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mount.testroot
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/msh/msh-supports-underscores-in-variable-names
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/msh/msh-supports-underscores-in-variable-names	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/msh/msh-supports-underscores-in-variable-names	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test "`busybox msh -c 'FOO_BAR=foo; echo $FOO_BAR'`" = foo

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-files-to-dir
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-files-to-dir	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-files-to-dir	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,16 @@
+echo file number one > file1
+echo file number two > file2
+ln -s file2 link1
+mkdir dir1
+touch --date='Sat Jan 29 21:24:08 PST 2000' dir1/file3
+mkdir there
+busybox mv file1 file2 link1 dir1 there
+test -f there/file1
+test -f there/file2
+test -f there/dir1/file3
+test -L there/link1
+test xfile2 = x`readlink there/link1`
+test ! -e file1
+test ! -e file2
+test ! -e link1
+test ! -e dir1/file3

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-follows-links
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-follows-links	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-follows-links	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+touch foo
+ln -s foo bar
+busybox mv bar baz
+test -f baz

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-empty-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-empty-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-empty-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+touch foo
+busybox mv foo bar
+test ! -e foo
+test -f bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+touch foo
+busybox mv foo bar
+test ! -f foo -a -f bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-hardlinks
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-hardlinks	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-hardlinks	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+touch foo
+ln foo bar
+busybox mv bar baz
+test ! -f bar -a -f baz

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-large-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-large-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-large-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+dd if=/dev/zero of=foo seek=10k count=1 2>/dev/null
+busybox mv foo bar
+test ! -e foo
+test -f bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-small-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-small-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-small-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+echo I WANT > foo
+busybox mv foo bar
+test ! -e foo
+test -f bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-symlinks
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-symlinks	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-symlinks	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,6 @@
+touch foo
+ln -s foo bar
+busybox mv bar baz
+test -f foo
+test ! -e bar
+test -L baz

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-unreadable-files
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-unreadable-files	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-moves-unreadable-files	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,5 @@
+touch foo
+chmod a-r foo
+busybox mv foo bar
+test ! -e foo
+test -f bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-preserves-hard-links
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-preserves-hard-links	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-preserves-hard-links	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,6 @@
+# FEATURE: CONFIG_FEATURE_PRESERVE_HARDLINKS
+touch foo
+ln foo bar
+mkdir baz
+busybox mv foo bar baz
+test baz/foo -ef baz/bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-preserves-links
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-preserves-links	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-preserves-links	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,5 @@
+touch foo
+ln -s foo bar
+busybox mv bar baz
+test -L baz
+test xfoo = x`readlink baz`

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-refuses-mv-dir-to-subdir
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-refuses-mv-dir-to-subdir	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-refuses-mv-dir-to-subdir	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,23 @@
+echo file number one > file1
+echo file number two > file2
+ln -s file2 link1
+mkdir dir1
+touch --date='Sat Jan 29 21:24:08 PST 2000' dir1/file3
+mkdir there
+busybox mv file1 file2 link1 dir1 there
+test -f there/file1
+test -f there/file2
+test -f there/dir1/file3
+test -L there/link1
+test xfile2 = x`readlink there/link1`
+test ! -e file1
+test ! -e file2
+test ! -e link1
+test ! -e dir1/file3
+set +e
+busybox mv there there/dir1
+if [ $? != 0 ] ; then
+	exit 0;
+fi
+
+exit 1;

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-removes-source-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-removes-source-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/mv/mv-removes-source-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+touch foo
+busybox mv foo bar
+test ! -e foo
+test -f bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/pidof.tests
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/pidof.tests	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/pidof.tests	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# pidof tests.
+# Copyright 2005 by Bernhard Fischer
+# Licensed under GPL v2, see file LICENSE for details.
+
+# AUDIT: 
+
+. testing.sh
+
+# testing "test name" "options" "expected result" "file input" "stdin"
+
+testing "pidof (exit with error)" \
+	"pidof veryunlikelyoccuringbinaryname ; echo \$?" "1\n" "" ""
+testing "pidof (exit with success)" "pidof pidof > /dev/null; echo \$?" \
+	"0\n" "" ""
+# We can get away with this because it says #!/bin/sh up top.
+
+testing "pidof this" "pidof pidof.tests | grep -o -w $$" "$$\n" "" ""
+
+optional FEATURE_PIDOF_SINGLE
+testing "pidof -s" "pidof -s init" "1\n" "" ""
+
+optional FEATURE_PIDOF_OMIT
+testing "pidof -o %PPID" "pidof -o %PPID pidof.tests | grep -o -w $$" "" "" ""
+testing "pidof -o %PPID NOP" "pidof -o %PPID -s init" "1\n" "" ""
+testing "pidof -o init" "pidof -o 1 init | grep -o -w 1" "" "" "" 
+
+exit $FAILCOUNT


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/pidof.tests
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/pwd/pwd-prints-working-directory
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/pwd/pwd-prints-working-directory	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/pwd/pwd-prints-working-directory	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test $(pwd) = $(busybox pwd)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/readlink.tests
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/readlink.tests	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/readlink.tests	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# Readlink tests.
+# Copyright 2006 by Natanael Copa <n at tanael.org>
+# Licensed under GPL v2, see file LICENSE for details.
+
+. testing.sh
+
+TESTDIR=readlink_testdir
+TESTFILE="$TESTDIR/testfile"
+TESTLINK="testlink"
+FAILLINK="$TESTDIR/$TESTDIR/testlink"
+
+# create the dir and test files
+mkdir -p "./$TESTDIR"
+touch "./$TESTFILE"
+ln -s "./$TESTFILE" "./$TESTLINK"
+
+testing "readlink on a file" "readlink ./$TESTFILE" "" "" ""
+testing "readlink on a link" "readlink ./$TESTLINK" "./$TESTFILE\n" "" ""
+
+optional FEATURE_READLINK_FOLLOW
+
+testing "readlink -f on a file" "readlink -f ./$TESTFILE" "$PWD/$TESTFILE\n" "" ""
+testing "readlink -f on a link" "readlink -f ./$TESTLINK" "$PWD/$TESTFILE\n" "" ""
+testing "readlink -f on an invalid link" "readlink -f ./$FAILLINK" "" "" ""
+testing "readlink -f on a wierd dir" "readlink -f $TESTDIR/../$TESTFILE" "$PWD/$TESTFILE\n" "" ""
+
+
+# clean up
+rm -r "$TESTLINK" "$TESTDIR" 
+


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/readlink.tests
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/rm/rm-removes-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/rm/rm-removes-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/rm/rm-removes-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+touch foo
+busybox rm foo
+test ! -f foo

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/rmdir/rmdir-removes-parent-directories
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/rmdir/rmdir-removes-parent-directories	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/rmdir/rmdir-removes-parent-directories	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+mkdir -p foo/bar
+busybox rmdir -p foo/bar
+test ! -d foo

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/runtest
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/runtest	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/runtest	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,140 @@
+#!/bin/sh
+
+[ -n "$srcdir" ] || srcdir=$(pwd)
+[ -n "$bindir" ] || bindir=$(dirname $(pwd))
+PATH=$bindir:$PATH
+
+# Run old-style test.
+
+function run_applet_testcase
+{
+	local applet=$1
+	local testcase=$2
+
+	local status=0
+	local RES=
+
+	local uc_applet=$(echo $applet | tr a-z A-Z)
+	local testname=$(basename $testcase)
+
+	if grep -q "^# CONFIG_${uc_applet} is not set$" $bindir/.config; then
+		echo UNTESTED: $testname
+		return 0
+	fi
+
+	if grep -q "^# FEATURE: " $testcase; then
+		local feature=`sed -ne 's/^# FEATURE: //p' $testcase`
+
+		if grep -q "^# ${feature} is not set$" $bindir/.config; then
+			echo UNTESTED: $testname
+			return 0
+		fi
+	fi
+
+	rm -rf tmp
+	mkdir -p tmp
+	pushd tmp > /dev/null
+
+	d=$srcdir sh -x -e $testcase >.logfile.txt 2>&1 || status=$?
+
+	if [ $status -ne 0 ] ; then
+		echo FAIL: $testname
+		if [ $verbose -gt 0 ]; then
+			cat .logfile.txt
+		fi
+		status=$?
+	else
+		echo PASS: $testname
+		rm -f .logfile.txt
+		status=$?
+	fi
+
+	popd > /dev/null
+	rm -rf tmp
+
+	return $status
+}
+
+run_applet_tests ()
+{
+	local applet=$1
+
+	local status=0
+
+	for testcase in $srcdir/$applet/*; do
+		if [ "$testcase" = "$srcdir/$applet/CVS" ]; then
+			continue
+		fi
+
+		if run_applet_testcase $applet $testcase; then
+			:
+		else
+			status=1
+		fi
+	done
+
+	return $status
+}
+
+
+status=0
+verbose=0
+
+if [ x"$1" = x"-v" ]; then
+	verbose=1
+	export VERBOSE=$verbose
+	shift
+fi
+
+if [ $# -ne 0 ]; then
+	applets=$(cd $srcdir ; for i in $@; do ls ${i}* ; done)
+else
+	applets=$(ls $srcdir)
+fi
+
+# Populate a directory with links to all busybox applets
+
+LINKSDIR="${bindir}/runtest-tempdir-links"
+rm -rf "$LINKSDIR" 2>/dev/null
+mkdir "$LINKSDIR"
+for i in $(sed 's@/[a-z0-9/\[]*/@@' $bindir/busybox.links 2>/dev/null)
+do
+	ln -s $bindir/busybox "$LINKSDIR"/$i
+done
+
+# Set up option flags so tests can be selective.
+
+configfile=${bindir:-../../}/.config
+export OPTIONFLAGS=:$(echo $(sed -nr 's/^CONFIG_(.*)=.*/\1/p' $configfile) | sed 's/ /:/g')
+
+for applet in $applets; do
+	if [ "$applet" = "links" ]; then continue; fi
+	if [ "$applet" != "CVS" -a -d "$srcdir/$applet" ]; then
+		if run_applet_tests $applet; then
+			:
+		else
+			status=1
+		fi
+	fi
+
+	# Is this a new-style test?
+	applet=$(echo "$applet" | sed -n 's/\.tests$//p')
+	if [ ${#applet} -ne 0 ]
+	then
+		if [ ! -h "$LINKSDIR/$applet" ] && [ "${applet:0:4}" != "all_" ]
+		then
+			echo "SKIPPED: $applet (not built)"
+			continue
+		fi
+		if PATH="$LINKSDIR":$srcdir:$bindir:$PATH \
+			"${srcdir:-.}/$applet".tests
+		then
+		  :
+		else
+		  status=1
+		fi
+	fi
+
+done
+rm -rf "$LINKSDIR"
+exit $status


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/runtest
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/sed.tests
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/sed.tests	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/sed.tests	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,185 @@
+#!/bin/sh
+
+# SUSv3 compliant sed tests.
+# Copyright 2005 by Rob Landley <rob at landley.net>
+# Licensed under GPL v2, see file LICENSE for details.
+
+. testing.sh
+
+# testing "description" "arguments" "result" "infile" "stdin"
+
+# Corner cases
+testing "sed no files (stdin)" 'sed ""' "hello\n" "" "hello\n"
+testing "sed explicit stdin" 'sed "" -' "hello\n" "" "hello\n"
+testing "sed handles empty lines" "sed -e 's/\$/@/'" "@\n" "" "\n"
+testing "sed stdin twice" 'sed "" - -' "hello" "" "hello"
+
+# Trailing EOF.
+#	Match $, at end of each file or all files?
+
+# -e corner cases
+#	without -e
+#	multiple -e
+#		interact with a
+#	-eee arg1 arg2 arg3
+# -f corner cases
+#	-e -f -e
+# -n corner cases
+#	no newline at EOF?
+# -r corner cases
+#	Just make sure it works.
+# -i corner cases:
+#	sed -i -
+#	permissions
+#	-i on a symlink
+#	on a directory
+#       With $ last-line test
+# Continue with \
+#       End of script with trailing \
+
+# command list
+testing "sed accepts blanks before command" "sed -e '1 d'" "" "" ""
+testing "sed accepts newlines in -e" "sed -e 'i\
+1
+a\
+3'" "1\n2\n3\n" "" "2\n"
+testing "sed accepts multiple -e" "sed -e 'i\' -e '1' -e 'a\' -e '3'" \
+	"1\n2\n3\n" "" "2\n"
+
+# substitutions
+testing "sed -n" "sed -n -e s/foo/bar/ -e s/bar/baz/" "" "" "foo\n"
+testing "sed s//p" "sed -e s/foo/bar/p -e s/bar/baz/p" "bar\nbaz\nbaz\n" \
+	"" "foo\n"
+testing "sed -n s//p" "sed -ne s/abc/def/p" "def\n" "" "abc\n"
+testing "sed s//g (exhaustive)" "sed -e 's/[[:space:]]*/,/g'" ",1,2,3,4,5,\n" \
+	"" "12345\n"
+testing "sed s arbitrary delimiter" "sed -e 's woo boing '" "boing\n" "" "woo\n"
+testing "sed s chains" "sed -e s/foo/bar/ -e s/bar/baz/" "baz\n" "" "foo\n"
+testing "sed s chains2" "sed -e s/foo/bar/ -e s/baz/nee/" "bar\n" "" "foo\n"
+testing "sed s [delimiter]" "sed -e 's@[@]@@'" "onetwo" "" "one at two"
+
+# branch
+testing "sed b (branch)" "sed -e 'b one;p;: one'" "foo\n" "" "foo\n"
+testing "sed b (branch with no label jumps to end)" "sed -e 'b;p'" \
+	"foo\n" "" "foo\n"
+
+# test and branch
+testing "sed t (test/branch)" "sed -e 's/a/1/;t one;p;: one;p'" \
+	"1\n1\nb\nb\nb\nc\nc\nc\n" "" "a\nb\nc\n"
+testing "sed t (test/branch clears test bit)" "sed -e 's/a/b/;:loop;t loop'" \
+	"b\nb\nc\n" "" "a\nb\nc\n"
+testing "sed T (!test/branch)" "sed -e 's/a/1/;T notone;p;: notone;p'" \
+	"1\n1\n1\nb\nb\nc\nc\n" "" "a\nb\nc\n"
+
+# Normal sed end-of-script doesn't print "c" because n flushed the pattern
+# space.  If n hits EOF, pattern space is empty when script ends.
+# Query: how does this interact with no newline at EOF?
+testing "sed n (flushes pattern space, terminates early)" "sed -e 'n;p'" \
+	"a\nb\nb\nc\n" "" "a\nb\nc\n"
+# N does _not_ flush pattern space, therefore c is still in there @ script end.
+testing "sed N (doesn't flush pattern space when terminating)" "sed -e 'N;p'" \
+	"a\nb\na\nb\nc\n" "" "a\nb\nc\n"
+testing "sed address match newline" 'sed "/b/N;/b\\nc/i woo"' \
+	"a\nwoo\nb\nc\nd\n" "" "a\nb\nc\nd\n"
+
+# Multiple lines in pattern space
+testing "sed N (stops at end of input) and P (prints to first newline only)" \
+	"sed -n 'N;P;p'" "a\na\nb\n" "" "a\nb\nc\n"
+
+# Hold space
+testing "sed G (append hold space to pattern space)" 'sed G' "a\n\nb\n\nc\n\n" \
+	"" "a\nb\nc\n"
+#testing "sed g/G (swap/append hold and patter space)"
+#testing "sed g (swap hold/pattern space)"
+
+testing "sed d ends script iteration" \
+	"sed -e '/ook/d;s/ook/ping/p;i woot'" "" "" "ook\n"
+testing "sed d ends script iteration (2)" \
+	"sed -e '/ook/d;a\' -e 'bang'" "woot\nbang\n" "" "ook\nwoot\n"
+
+# Multiple files, with varying newlines and NUL bytes
+testing "sed embedded NUL" "sed -e 's/woo/bang/'" "\0bang\0woo\0" "" \
+	"\0woo\0woo\0"
+testing "sed embedded NUL g" "sed -e 's/woo/bang/g'" "bang\0bang\0" "" \
+	"woo\0woo\0"
+echo -e "/woo/a he\0llo" > sed.commands
+testing "sed NUL in command" "sed -f sed.commands" "woo\nhe\0llo\n" "" "woo"
+rm sed.commands
+
+# sed has funky behavior with newlines at the end of file.  Test lots of
+# corner cases with the optional newline appending behavior.
+
+testing "sed normal newlines" "sed -e 's/woo/bang/' input -" "bang\nbang\n" \
+	"woo\n" "woo\n"
+testing "sed leave off trailing newline" "sed -e 's/woo/bang/' input -" \
+	"bang\nbang" "woo\n" "woo"
+testing "sed autoinsert newline" "sed -e 's/woo/bang/' input -" "bang\nbang" \
+	"woo" "woo"
+testing "sed empty file plus cat" "sed -e 's/nohit//' input -" "one\ntwo" \
+	"" "one\ntwo" 
+testing "sed cat plus empty file" "sed -e 's/nohit//' input -" "one\ntwo" \
+	"one\ntwo" ""
+testing "sed append autoinserts newline" "sed -e '/woot/a woo' -" \
+	"woot\nwoo\n" "" "woot"
+testing "sed insert doesn't autoinsert newline" "sed -e '/woot/i woo' -" \
+	"woo\nwoot" "" "woot"
+testing "sed print autoinsert newlines" "sed -e 'p' -" "one\none" "" "one"
+testing "sed print autoinsert newlines two files" "sed -e 'p' input -" \
+	"one\none\ntwo\ntwo" "one" "two"
+testing "sed noprint, no match, no newline" "sed -ne 's/woo/bang/' input" \
+	"" "no\n" ""
+testing "sed selective matches with one nl" "sed -ne 's/woo/bang/p' input -" \
+	"a bang\nc bang\n" "a woo\nb no" "c woo\nd no"
+testing "sed selective matches insert newline" \
+	"sed -ne 's/woo/bang/p' input -" "a bang\nb bang\nd bang" \
+	"a woo\nb woo" "c no\nd woo"
+testing "sed selective matches noinsert newline" \
+	"sed -ne 's/woo/bang/p' input -" "a bang\nb bang" "a woo\nb woo" \
+	"c no\nd no"
+testing "sed clusternewline" \
+	"sed -e '/one/a 111' -e '/two/i 222' -e p input -" \
+	"one\none\n111\n222\ntwo\ntwo" "one" "two" 
+
+# Test end-of-file matching behavior
+
+testing "sed match EOF" "sed -e '"'$p'"'" "hello\nthere\nthere" "" \
+	"hello\nthere"
+testing "sed match EOF two files" "sed -e '"'$p'"' input -" \
+	"one\ntwo\nthree\nfour\nfour" "one\ntwo" "three\nfour"
+echo -ne "three\nfour" > input2
+testing "sed match EOF inline" \
+	"sed -e '"'$i ook'"' -i input input2 && cat input input2" \
+	"one\nook\ntwothree\nook\nfour" "one\ntwo" ""
+rm input2
+
+# Test lie-to-autoconf
+
+testing "sed lie-to-autoconf" "sed --version | grep -o 'GNU sed version '" \
+	"GNU sed version \n" "" ""
+
+# Jump to nonexistent label
+testing "sed nonexistent label" "sed -e 'b walrus' 2> /dev/null || echo yes" \
+	"yes\n" "" ""
+
+testing "sed backref from empty s uses range regex" \
+	"sed -e '/woot/s//eep \0 eep/'" "eep woot eep" "" "woot"
+
+testing "sed backref from empty s uses range regex with newline" \
+	"sed -e '/woot/s//eep \0 eep/'" "eep woot eep\n" "" "woot\n"
+
+# -i with no filename
+
+touch ./-  # Detect gnu failure mode here.
+testing "sed -i with no arg [GNUFAIL]" "sed -e '' -i 2> /dev/null || echo yes" \
+	"yes\n" "" ""
+rm ./-     # Clean up
+
+# Ponder this a bit more, why "woo not found" from gnu version?
+#testing "sed doesn't substitute in deleted line" \
+#	"sed -e '/ook/d;s/ook//;t woo;a bang;'" "bang" "" "ook\n"
+
+# This makes both seds very unhappy.  Why?
+#testing "sed -g (exhaustive)" "sed -e 's/[[:space:]]*/,/g'" ",1,2,3,4,5," \
+#	"" "12345"
+
+exit $FAILCOUNT


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/sed.tests
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/seq.tests
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/seq.tests	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/seq.tests	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+# SUSv3 compliant seq tests.
+# Copyright 2006 by Rob Landley <rob at landley.net>
+# Licensed under GPL v2, see file LICENSE for details.
+
+# AUDIT: Full SUSv3 coverage (except internationalization).
+
+. testing.sh
+
+# testing "test name" "options" "expected result" "file input" "stdin"
+#   file input will be file called "input"
+#   test can create a file "actual" instead of writing to stdout
+
+# Test exit status
+
+testing "seq (exit with error)" "seq 2> /dev/null || echo yes" "yes\n" "" ""
+testing "seq (exit with error)" "seq 1 2 3 4 2> /dev/null || echo yes" \
+	"yes\n" "" ""
+testing "seq one argument" "seq 3" "1\n2\n3\n" "" ""
+testing "seq two arguments" "seq 5 7" "5\n6\n7\n" "" ""
+testing "seq two arguments reversed" "seq 7 5" "" "" ""
+testing "seq two arguments equal" "seq 3 3" "3\n" "" ""
+testing "seq two arguments equal, arbitrary negative step" "seq 1 -15 1" \
+	"1\n" "" ""
+testing "seq two arguments equal, arbitrary positive step" "seq 1 +15 1" \
+	"1\n" "" ""
+testing "seq count up by 2" "seq 4 2 8" "4\n6\n8\n" "" ""
+testing "seq count down by 2" "seq 8 -2 4" "8\n6\n4\n" "" ""
+testing "seq count wrong way #1" "seq 4 -2 8" "" "" ""
+testing "seq count wrong way #2" "seq 8 2 4" "" "" ""
+testing "seq count by .3" "seq 3 .3 4" "3\n3.3\n3.6\n3.9\n" "" ""
+testing "seq count by -.9" "seq .7 -.9 -2.2" "0.7\n-0.2\n-1.1\n-2\n" "" ""
+testing "seq count by zero" "seq 4 0 8 | head -n 10" "" "" ""
+
+exit $FAILCOUNT


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/seq.tests
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/sort.tests
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/sort.tests	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/sort.tests	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+# SUSv3 compliant sort tests.
+# Copyright 2005 by Rob Landley <rob at landley.net>
+# Licensed under GPL v2, see file LICENSE for details.
+
+. testing.sh
+
+# The basic tests.  These should work even with the small busybox.
+
+testing "sort" "sort input" "a\nb\nc\n" "c\na\nb\n" ""
+testing "sort #2" "sort input" "010\n1\n3\n" "3\n1\n010\n" ""
+testing "sort stdin" "sort" "a\nb\nc\n" "" "b\na\nc\n"
+testing "sort numeric" "sort -n input" "1\n3\n010\n" "3\n1\n010\n" ""
+testing "sort reverse" "sort -r input" "wook\nwalrus\npoint\npabst\naargh\n" \
+	"point\nwook\npabst\naargh\nwalrus\n" ""
+
+# These tests require the full option set.
+
+optional FEATURE_SORT_BIG
+# Longish chunk of data re-used by the next few tests
+
+data="42	1	3	woot
+42	1	010	zoology
+egg	1	2	papyrus
+7	3	42	soup
+999	3	0	algebra
+"
+
+# Sorting with keys
+
+testing "sort one key" "sort -k4,4 input" \
+"999	3	0	algebra
+egg	1	2	papyrus
+7	3	42	soup
+42	1	3	woot
+42	1	010	zoology
+" "$data" ""
+
+testing "sort key range with numeric option" "sort -k2,3n input" \
+"42	1	010	zoology
+42	1	3	woot
+egg	1	2	papyrus
+7	3	42	soup
+999	3	0	algebra
+" "$data" ""
+
+# Busybox is definitely doing this one wrong just now.  FIXME
+
+testing "sort key range with numeric option and global reverse" \
+"sort -k2,3n -r input" \
+"egg	1	2	papyrus
+42	1	3	woot
+42	1	010	zoology
+999	3	0	algebra
+7	3	42	soup
+" "$data" ""
+
+# 
+
+testing "sort key range with multiple options" "sort -k2,3rn input" \
+"7	3	42	soup
+999	3	0	algebra
+42	1	010	zoology
+42	1	3	woot
+egg	1	2	papyrus
+" "$data" ""
+
+testing "sort key doesn't strip leading blanks, disables fallback global sort" \
+"sort -n -k2 -t ' '" " a \n 1 \n 2 \n" "" " 2 \n 1 \n a \n" 
+
+testing "sort key edge case with -t" "sort -n -k4 -t/" \
+"/usr/lib/finish-install.d/1
+/usr/lib/finish-install.d/4
+/usr/lib/prebaseconfig.d/2
+/usr/lib/prebaseconfig.d/6
+" "" "/usr/lib/finish-install.d/1
+/usr/lib/prebaseconfig.d/2
+/usr/lib/finish-install.d/4
+/usr/lib/prebaseconfig.d/6
+"
+
+exit $FAILCOUNT


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/sort.tests
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/strings/strings-works-like-GNU
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/strings/strings-works-like-GNU	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/strings/strings-works-like-GNU	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,9 @@
+rm -f foo bar
+strings -af ../../busybox > foo
+busybox strings -af ../../busybox > bar
+set +e
+test ! -f foo -a -f bar
+if [ $? = 0 ] ; then
+	set -e
+	diff -q foo bar
+fi

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tail/tail-n-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tail/tail-n-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tail/tail-n-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+[ -n "$d" ] || d=..
+tail -n 2 "$d/README" > logfile.gnu
+busybox tail -n 2 "$d/README" > logfile.bb
+cmp logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tail/tail-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tail/tail-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tail/tail-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+[ -n "$d" ] || d=..
+tail -n 2 "$d/README" > logfile.gnu
+busybox tail -n 2 "$d/README" > logfile.bb
+cmp logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-archives-multiple-files
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-archives-multiple-files	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-archives-multiple-files	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,6 @@
+# FEATURE: CONFIG_FEATURE_TAR_CREATE
+touch foo bar
+busybox tar cf foo.tar foo bar
+rm foo bar
+tar xf foo.tar
+test -f foo -a -f bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-complains-about-missing-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-complains-about-missing-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-complains-about-missing-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+touch foo
+tar cf foo.tar foo
+! busybox tar xf foo.tar bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-demands-at-least-one-ctx
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-demands-at-least-one-ctx	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-demands-at-least-one-ctx	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+! busybox tar v

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-demands-at-most-one-ctx
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-demands-at-most-one-ctx	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-demands-at-most-one-ctx	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+! busybox tar tx

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-extracts-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-extracts-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-extracts-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,5 @@
+touch foo
+tar cf foo.tar foo
+rm foo
+busybox tar xf foo.tar
+test -f foo

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-extracts-from-standard-input
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-extracts-from-standard-input	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-extracts-from-standard-input	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,5 @@
+touch foo
+tar cf foo.tar foo
+rm foo
+cat foo.tar | busybox tar x
+test -f foo

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-extracts-multiple-files
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-extracts-multiple-files	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-extracts-multiple-files	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,6 @@
+touch foo bar
+busybox tar cf foo.tar foo bar
+rm foo bar
+busybox tar -xf foo.tar
+test -f foo
+test -f bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-extracts-to-standard-output
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-extracts-to-standard-output	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-extracts-to-standard-output	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+echo foo > foo
+tar cf foo.tar foo
+cat foo.tar | busybox tar Ox | cmp foo -

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-cz-options
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-cz-options	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-cz-options	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,5 @@
+# FEATURE: CONFIG_FEATURE_TAR_CREATE
+# FEATURE: CONFIG_FEATURE_TAR_GZIP
+touch foo
+busybox tar czf foo.tar.gz foo
+gzip -d foo.tar.gz

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-empty-include-and-non-empty-exclude-list
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-empty-include-and-non-empty-exclude-list	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-empty-include-and-non-empty-exclude-list	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,6 @@
+# FEATURE: CONFIG_FEATURE_TAR_FROM
+# FEATURE: CONFIG_FEATURE_TAR_CREATE
+touch foo
+tar cf foo.tar foo
+echo foo >foo.exclude
+busybox tar xf foo.tar -X foo.exclude

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-exclude-and-extract-lists
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-exclude-and-extract-lists	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-exclude-and-extract-lists	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,8 @@
+# FEATURE: CONFIG_FEATURE_TAR_FROM
+# FEATURE: CONFIG_FEATURE_TAR_CREATE
+touch foo bar baz
+tar cf foo.tar foo bar baz
+echo foo >foo.exclude
+rm foo bar baz
+busybox tar xf foo.tar foo bar -X foo.exclude
+test ! -f foo -a -f bar -a ! -f baz

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-multiple-X-options
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-multiple-X-options	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-multiple-X-options	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,10 @@
+# FEATURE: CONFIG_FEATURE_TAR_FROM
+# FEATURE: CONFIG_FEATURE_TAR_CREATE
+touch foo
+touch bar
+tar cf foo.tar foo bar
+echo foo > foo.exclude
+echo bar > bar.exclude
+rm foo bar
+busybox tar xf foo.tar -X foo.exclude -X bar.exclude
+test ! -f foo -a ! -f bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-nested-exclude
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-nested-exclude	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tar/tar-handles-nested-exclude	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,9 @@
+# FEATURE: CONFIG_FEATURE_TAR_FROM
+# FEATURE: CONFIG_FEATURE_TAR_CREATE
+mkdir foo
+touch foo/bar
+tar cf foo.tar foo
+rm -rf foo
+echo foo/bar >foobar.exclude
+busybox tar xf foo.tar foo -X foobar.exclude
+test -d foo -a ! -f foo/bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tee/tee-appends-input
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tee/tee-appends-input	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tee/tee-appends-input	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,5 @@
+echo i\'m a little teapot >foo
+cp foo bar
+echo i\'m a little teapot >>foo
+echo i\'m a little teapot | busybox tee -a bar >/dev/null
+cmp foo bar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tee/tee-tees-input
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tee/tee-tees-input	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tee/tee-tees-input	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+echo i\'m a little teapot >foo
+echo i\'m a little teapot | busybox tee bar >baz
+cmp foo bar && cmp foo baz

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/testing.sh
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/testing.sh	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/testing.sh	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,154 @@
+# Simple test harness infrastructurei for BusyBox
+#
+# Copyright 2005 by Rob Landley
+#
+# License is GPLv2, see LICENSE in the busybox tarball for full license text.
+
+# This file defines two functions, "testing" and "optionflag"
+
+# The following environment variables may be set to enable optional behavior
+# in "testing":
+#    VERBOSE - Print the diff -u of each failed test case.
+#    DEBUG - Enable command tracing.
+#    SKIP - do not perform this test (this is set by "optionflag")
+#
+# The "testing" function takes five arguments:
+#	$1) Description to display when running command
+#	$2) Command line arguments to command
+#	$3) Expected result (on stdout)
+#	$4) Data written to file "input"
+#	$5) Data written to stdin
+#
+# The exit value of testing is the exit value of the command it ran.
+#
+# The environment variable "FAILCOUNT" contains a cumulative total of the
+# number of failed tests.
+
+# The "optional" function is used to skip certain tests, ala:
+#   optionflag CONFIG_FEATURE_THINGY
+#
+# The "optional" function checks the environment variable "OPTIONFLAGS",
+# which is either empty (in which case it always clears SKIP) or
+# else contains a colon-separated list of features (in which case the function
+# clears SKIP if the flag was found, or sets it to 1 if the flag was not found).
+
+export FAILCOUNT=0
+export SKIP=
+
+# Helper functions
+
+optional()
+{
+  option=`echo "$OPTIONFLAGS" | egrep "(^|:)$1(:|\$)"`
+  # Not set?
+  if [ -z "$1" ] || [ -z "$OPTIONFLAGS" ] || [ ${#option} -ne 0 ]
+  then
+    SKIP=""
+    return
+  fi
+  SKIP=1
+}
+
+# The testing function
+
+testing ()
+{
+  NAME="$1"
+  [ -z "$1" ] && NAME=$2
+
+  if [ $# -ne 5 ]
+  then
+    echo "Test $NAME has the wrong number of arguments ($# $*)" >&2
+    exit
+  fi
+
+  [ -n "$DEBUG" ] && set -x
+
+  if [ -n "$SKIP" ]
+  then
+    echo "SKIPPED: $NAME"
+    return 0
+  fi
+
+  echo -ne "$3" > expected
+  echo -ne "$4" > input
+  [ -z "$VERBOSE" ] || echo "echo '$5' | $2"
+  echo -ne "$5" | eval "$2" > actual
+  RETVAL=$?
+
+  cmp expected actual > /dev/null 
+  if [ $? -ne 0 ]
+  then
+    FAILCOUNT=$[$FAILCOUNT+1]
+    echo "FAIL: $NAME"
+    [ -n "$VERBOSE" ] && diff -u expected actual
+  else
+    echo "PASS: $NAME"
+  fi
+  rm -f input expected actual
+
+  [ -n "$DEBUG" ] && set +x
+
+  return $RETVAL
+}
+
+# Recursively grab an executable and all the libraries needed to run it.
+# Source paths beginning with / will be copied into destpath, otherwise
+# the file is assumed to already be there and only its library dependencies
+# are copied.
+
+function mkchroot
+{
+  [ $# -lt 2 ] && return
+
+  echo -n .
+
+  dest=$1
+  shift
+  for i in "$@"
+  do
+    [ "${i:0:1}" == "/" ] || i=$(which $i)
+    [ -f "$dest/$i" ] && continue
+    if [ -e "$i" ]
+    then
+      d=`echo "$i" | grep -o '.*/'` &&
+      mkdir -p "$dest/$d" &&
+      cat "$i" > "$dest/$i" &&
+      chmod +x "$dest/$i"
+    else
+      echo "Not found: $i"
+    fi
+    mkchroot "$dest" $(ldd "$i" | egrep -o '/.* ')
+  done
+}
+
+# Set up a chroot environment and run commands within it.
+# Needed commands listed on command line
+# Script fed to stdin.
+
+function dochroot
+{
+  mkdir tmpdir4chroot
+  mount -t ramfs tmpdir4chroot tmpdir4chroot
+  mkdir -p tmpdir4chroot/{etc,sys,proc,tmp,dev}
+  cp -L testing.sh tmpdir4chroot
+
+  # Copy utilities from command line arguments
+
+  echo -n "Setup chroot"
+  mkchroot tmpdir4chroot $*
+  echo
+
+  mknod tmpdir4chroot/dev/tty c 5 0
+  mknod tmpdir4chroot/dev/null c 1 3
+  mknod tmpdir4chroot/dev/zero c 1 5
+
+  # Copy script from stdin
+
+  cat > tmpdir4chroot/test.sh
+  chmod +x tmpdir4chroot/test.sh
+  chroot tmpdir4chroot /test.sh
+  umount -l tmpdir4chroot
+  rmdir tmpdir4chroot
+}
+


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/testing.sh
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/touch/touch-creates-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/touch/touch-creates-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/touch/touch-creates-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+busybox touch foo
+test -f foo

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/touch/touch-does-not-create-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/touch/touch-does-not-create-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/touch/touch-does-not-create-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+busybox touch -c foo
+test ! -f foo

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/touch/touch-touches-files-after-non-existent-file
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/touch/touch-touches-files-after-non-existent-file	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/touch/touch-touches-files-after-non-existent-file	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+touch -t 198001010000 bar
+busybox touch -c foo bar
+test x"`find bar -mtime -1`" = xbar

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tr/tr-d-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tr/tr-d-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tr/tr-d-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+echo testing | tr -d aeiou > logfile.gnu
+echo testing | busybox tr -d aeiou > logfile.bb
+
+cmp logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tr/tr-non-gnu
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tr/tr-non-gnu	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tr/tr-non-gnu	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+echo fdhrnzvfu bffvsentr | busybox tr '[a-z]' '[n-z][a-m]'

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tr/tr-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tr/tr-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/tr/tr-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,24 @@
+run_tr ()
+{
+	echo -n "echo '$1' | tr '$2' '$3': "
+	echo "$1" | $bb tr "$2" "$3"
+	echo
+}
+tr_test ()
+{
+	run_tr "cbaab"		abc 		zyx
+	run_tr "TESTING A B C" 	'[A-Z]' 	'[a-z]' 
+	run_tr "abc[]" 		"a[b" 		AXB
+	run_tr abc		'[:alpha:]' 	A-ZA-Z
+	run_tr abc56		'[:alnum:]' 	A-ZA-Zxxxxxxxxxx
+	run_tr 012		'[:digit:]' 	abcdefghi
+	run_tr abc56		'[:lower:]' 	'[:upper:]'
+	run_tr " 	"	'[:space:]' 	12345
+	run_tr " 	"	'[:blank:]' 	12
+	run_tr 'a b'		'[= =]' 	X
+	run_tr "[:"		'[:' 		ab
+}
+
+bb=        tr_test > logfile.gnu
+bb=busybox tr_test > logfile.bb
+cmp logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/true/true-is-silent
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/true/true-is-silent	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/true/true-is-silent	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+busybox true 2>&1 | cmp - /dev/null

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/true/true-returns-success
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/true/true-returns-success	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/true/true-returns-success	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+busybox true

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/umlwrapper.sh
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/umlwrapper.sh	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/umlwrapper.sh	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Wrapper for User Mode Linux emulation environment
+
+RUNFILE="$(pwd)/${1}.testroot"
+if [ -z "$RUNFILE" ] || [ ! -x "$RUNFILE" ]
+then
+  echo "Can't run '$RUNFILE'"
+  exit 1
+fi
+
+shift
+
+if [ -z $(which linux) ]
+then
+  echo "No User Mode Linux."
+  exit 1;
+fi
+
+linux rootfstype=hostfs rw init="$RUNFILE" TESTDIR=`pwd` PATH="$PATH" $* quiet


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/umlwrapper.sh
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/uniq.tests
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/uniq.tests	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/uniq.tests	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+# SUSv3 compliant uniq tests.
+# Copyright 2005 by Rob Landley <rob at landley.net>
+# Licensed under GPL v2, see file LICENSE for details.
+
+# AUDIT: Full SUSv3 coverage (except internationalization).
+
+. testing.sh
+
+# testing "test name" "options" "expected result" "file input" "stdin"
+#   file input will be file called "input"
+#   test can create a file "actual" instead of writing to stdout
+
+# Test exit status
+
+testing "uniq (exit with error)" "uniq nonexistent 2> /dev/null || echo yes" \
+	"yes\n" "" ""
+testing "uniq (exit success)" "uniq /dev/null && echo yes" "yes\n" "" ""
+
+# Test various data sources and destinations
+
+testing "uniq (default to stdin)" "uniq" "one\ntwo\nthree\n" "" \
+	"one\ntwo\ntwo\nthree\nthree\nthree\n"
+testing "uniq - (specify stdin)" "uniq -" "one\ntwo\nthree\n" "" \
+	"one\ntwo\ntwo\nthree\nthree\nthree\n"
+testing "uniq input (specify file)" "uniq input" "one\ntwo\nthree\n" \
+	"one\ntwo\ntwo\nthree\nthree\nthree\n" ""
+
+testing "uniq input outfile (two files)" "uniq input actual > /dev/null" \
+	"one\ntwo\nthree\n" "one\ntwo\ntwo\nthree\nthree\nthree\n" ""
+testing "uniq (stdin) outfile" "uniq - actual" \
+	"one\ntwo\nthree\n" "" "one\ntwo\ntwo\nthree\nthree\nthree\n"
+# Note: SUSv3 doesn't seem to require support for "-" output, but we do anyway.
+testing "uniq input - (specify stdout)" "uniq input -" \
+	"one\ntwo\nthree\n" "one\ntwo\ntwo\nthree\nthree\nthree\n" ""
+
+
+#-f skip fields
+#-s skip chars
+#-c occurrences
+#-d dups only
+#-u 
+
+# Test various command line options
+
+# Leading whitespace is a minor technical violation of the spec,
+# but since gnu does it...
+testing "uniq -c (occurrence count)" "uniq -c | sed 's/^[ \t]*//'" \
+	"1 one\n2 two\n3 three\n" "" \
+	"one\ntwo\ntwo\nthree\nthree\nthree\n"
+testing "uniq -d (dups only) " "uniq -d" "two\nthree\n" "" \
+	"one\ntwo\ntwo\nthree\nthree\nthree\n"
+
+testing "uniq -f -s (skip fields and chars)" "uniq -f2 -s 3" \
+"cc	dd	ee8
+aa	bb	cc9
+" "" \
+"cc	dd	ee8
+bb	cc	dd8
+aa	bb	cc9
+"
+
+# -d is "Suppress the writing fo lines that are not repeated in the input."
+# -u is "Suppress the writing of lines that are repeated in the input."
+# Therefore, together this means they should produce no output.
+testing "uniq -u and -d produce no output" "uniq -d -u" "" "" \
+	"one\ntwo\ntwo\nthree\nthree\nthree\n"
+
+exit $FAILCOUNT


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/uniq.tests
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/unzip.tests
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/unzip.tests	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/unzip.tests	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# Tests for unzip.
+# Copyright 2006 Rob Landley <rob at landley.net>
+# Copyright 2006 Glenn McGrath <bug1 at ihug.co.nz>
+# Licensed under GPL v2, see file LICENSE for details.
+
+. testing.sh
+
+# testing "test name" "options" "expected result" "file input" "stdin"
+#   file input will be file called "input"
+#   test can create a file "actual" instead of writing to stdout
+
+# Create a scratch directory
+
+mkdir temp
+cd temp
+
+# Create test file to work with.
+
+mkdir foo
+touch foo/bar
+zip foo.zip foo foo/bar > /dev/null
+rm -f foo/bar
+rmdir foo
+
+# Test that unzipping just foo doesn't create bar.
+testing "unzip (subdir only)" "unzip -q foo.zip foo/ && test -d foo && test ! -f foo/bar && echo yes" "yes\n" "" ""
+
+rmdir foo
+rm foo.zip
+
+# Clean up scratch directory.
+
+cd ..
+rm -rf temp
+
+exit $FAILCOUNT


Property changes on: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/unzip.tests
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/uptime/uptime-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/uptime/uptime-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/uptime/uptime-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+busybox uptime
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/uuencode/uuencode-sets-standard-input-mode-correctly
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/uuencode/uuencode-sets-standard-input-mode-correctly	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/uuencode/uuencode-sets-standard-input-mode-correctly	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+saved_umask=$(umask)
+umask 0
+busybox uuencode foo </dev/null | head -n 1 | grep -q 666
+umask $saved_umask

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-counts-all
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-counts-all	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-counts-all	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test "`echo i\'m a little teapot | busybox wc`" = '      1       4      20'

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-counts-characters
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-counts-characters	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-counts-characters	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test `echo i\'m a little teapot | busybox wc -c` -eq 20

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-counts-lines
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-counts-lines	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-counts-lines	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test `echo i\'m a little teapot | busybox wc -l` -eq 1

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-counts-words
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-counts-words	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-counts-words	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test `echo i\'m a little teapot | busybox wc -w` -eq 4

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-prints-longest-line-length
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-prints-longest-line-length	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wc/wc-prints-longest-line-length	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+test `echo i\'m a little teapot | busybox wc -L` -eq 19

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/wget--O-overrides--P
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/wget--O-overrides--P	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/wget--O-overrides--P	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+mkdir foo
+busybox wget -q -O index.html -P foo http://www.google.com/
+test -s index.html

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/wget-handles-empty-path
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/wget-handles-empty-path	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/wget-handles-empty-path	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1 @@
+busybox wget http://www.google.com

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/wget-retrieves-google-index
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/wget-retrieves-google-index	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/wget-retrieves-google-index	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,2 @@
+busybox wget -q -O foo http://www.google.com/
+test -s foo

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/wget-supports--P
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/wget-supports--P	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/wget/wget-supports--P	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,3 @@
+mkdir foo
+busybox wget -q -P foo http://www.google.com/
+test -s foo/index.html

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/which/which-uses-default-path
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/which/which-uses-default-path	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/which/which-uses-default-path	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+BUSYBOX=$(type -p busybox)
+SAVED_PATH=$PATH
+unset PATH
+$BUSYBOX which ls

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/xargs/xargs-works
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/xargs/xargs-works	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/testsuite/xargs/xargs-works	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,4 @@
+[ -n "$d" ] || d=..
+find "$d" -name \*works -type f | xargs md5sum > logfile.gnu
+find "$d" -name \*works -type f | busybox xargs md5sum > logfile.bb
+diff -u logfile.gnu logfile.bb

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/Config.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/Config.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/Config.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,480 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Linux System Utilities"
+
+config CONFIG_DMESG
+	bool "dmesg"
+	default n
+	help
+	  dmesg is used to examine or control the kernel ring buffer.  When the
+	  Linux kernel prints messages to the system log, they are stored in
+	  the kernel ring buffer.  You can use dmesg to print the kernel's ring
+	  buffer, clear the kernel ring buffer, change the size of the kernel
+	  ring buffer, and change the priority level at which kernel messages
+	  are also logged to the system console.  Enable this option if you
+	  wish to enable the 'dmesg' utility.
+
+config CONFIG_FBSET
+	bool "fbset"
+	default n
+	help
+	  fbset is used to show or change the settings of a Linux frame buffer
+	  device.  The frame buffer device provides a simple and unique
+	  interface to access a graphics display.  Enable this option
+	  if you wish to enable the 'fbset' utility.
+
+config CONFIG_FEATURE_FBSET_FANCY
+	bool "Turn on extra fbset options"
+	default n
+	depends on CONFIG_FBSET
+	help
+	  This option enables extended fbset options, allowing one to set the
+	  framebuffer size, color depth, etc.  interface to access a graphics
+	  display.  Enable this option if you wish to enable extended fbset
+	  options.
+
+config CONFIG_FEATURE_FBSET_READMODE
+	bool "Turn on fbset readmode support"
+	default n
+	depends on CONFIG_FBSET
+	help
+	  This option allows fbset to read the video mode database stored by
+	  default as /etc/fb.modes, which can be used to set frame buffer
+	  device to pre-defined video modes.
+
+config CONFIG_FDFLUSH
+	bool "fdflush"
+	default n
+	help
+	  fdflush is only needed when changing media on slightly-broken
+	  removable media drives.  It is used to make Linux believe that a
+	  hardware disk-change switch has been actuated, which causes Linux to
+	  forget anything it has cached from the previous media.  If you have
+	  such a slightly-broken drive, you will need to run fdflush every time
+	  you change a disk.  Most people have working hardware and can safely
+	  leave this disabled.
+
+config CONFIG_FDFORMAT
+	bool "fdformat"
+	default n
+	help
+	  fdformat is used to low-level format a floppy disk.
+
+config CONFIG_FDISK
+	bool "fdisk"
+	default n
+	help
+	  The fdisk utility is used to divide hard disks into one or more
+	  logical disks, which are generally called partitions.  This utility
+	  can be used to list and edit the set of partitions or BSD style
+	  'disk slices' that are defined on a hard drive.
+
+config FDISK_SUPPORT_LARGE_DISKS
+	bool "support over 4GB disks"
+	default y
+	depends on CONFIG_FDISK
+	help
+	  Enable this option to support large disks > 4GB.
+
+config CONFIG_FEATURE_FDISK_WRITABLE
+	bool "Write support"
+	default y
+	depends on CONFIG_FDISK
+	help
+	  Enabling this option allows you to create or change a partition table
+	  and write those changes out to disk.  If you leave this option
+	  disabled, you will only be able to view the partition table.
+
+config CONFIG_FEATURE_AIX_LABEL
+	bool "Support AIX disklabels"
+	default n
+	depends on CONFIG_FDISK && CONFIG_FEATURE_FDISK_WRITABLE
+	help
+	  Enabling this option allows you to create or change AIX disklabels.
+	  Most people can safely leave this option disabled.
+
+config CONFIG_FEATURE_SGI_LABEL
+	bool "Support SGI disklabels"
+	default n
+	depends on CONFIG_FDISK && CONFIG_FEATURE_FDISK_WRITABLE
+	help
+	  Enabling this option allows you to create or change SGI disklabels.
+	  Most people can safely leave this option disabled.
+
+config CONFIG_FEATURE_SUN_LABEL
+	bool "Support SUN disklabels"
+	default n
+ 	depends on CONFIG_FDISK && CONFIG_FEATURE_FDISK_WRITABLE
+	help
+	  Enabling this option allows you to create or change SUN disklabels.
+	  Most people can safely leave this option disabled.
+
+config CONFIG_FEATURE_OSF_LABEL
+	bool "Support BSD disklabels"
+	default n
+	depends on CONFIG_FDISK && CONFIG_FEATURE_FDISK_WRITABLE
+	help
+	  Enabling this option allows you to create or change BSD disklabels
+	  and define and edit BSD disk slices.
+
+config CONFIG_FEATURE_FDISK_ADVANCED
+	bool "Support expert mode"
+	default n
+	depends on CONFIG_FDISK && CONFIG_FEATURE_FDISK_WRITABLE
+	help
+	  Enabling this option allows you to do terribly unsafe things like
+	  define arbitrary drive geometry, move the beginning of data in a
+	  partition, and similarly evil things.  Unless you have a very good
+	  reason you would be wise to leave this disabled.
+
+config CONFIG_FREERAMDISK
+	bool "freeramdisk"
+	default n
+	help
+	  Linux allows you to create ramdisks.  This utility allows you to
+	  delete them and completely free all memory that was used for the
+	  ramdisk.  For example, if you boot Linux into a ramdisk and later
+	  pivot_root, you may want to free the memory that is allocated to the
+	  ramdisk.  If you have no use for freeing memory from a ramdisk, leave
+	  this disabled.
+
+config CONFIG_FSCK_MINIX
+	bool "fsck_minix"
+	default n
+	help
+	  The minix filesystem is a nice, small, compact, read-write filesystem
+	  with little overhead.  It is not a journaling filesystem however and
+	  can experience corruption if it is not properly unmounted or if the
+	  power goes off in the middle of a write.  This utility allows you to
+	  check for and attempt to repair any corruption that occurs to a minix
+	  filesystem.
+
+config CONFIG_MKFS_MINIX
+	bool "mkfs_minix"
+	default n
+	help
+	  The minix filesystem is a nice, small, compact, read-write filesystem
+	  with little overhead.  If you wish to be able to create minix filesystems
+	  this utility will do the job for you.
+
+comment "Minix filesystem support"
+    depends on CONFIG_FSCK_MINIX || CONFIG_MKFS_MINIX
+
+config CONFIG_FEATURE_MINIX2
+	bool "Support Minix fs v2 (fsck_minix/mkfs_minix)"
+	default y
+	depends on CONFIG_FSCK_MINIX || CONFIG_MKFS_MINIX
+	help
+	  If you wish to be able to create version 2 minix filesystems, enable this.
+	  If you enabled 'mkfs_minix' then you almost certainly want to be using the
+	  version 2 filesystem support.
+
+config CONFIG_GETOPT
+	bool "getopt"
+	default n
+	help
+	  The getopt utility is used to break up (parse) options in command
+	  lines to make it easy to write complex shell scripts that also check
+	  for legal (and illegal) options.  If you want to write horribly
+	  complex shell scripts, or use some horribly complex shell script
+	  written by others, this utility may be for you.  Most people will
+	  wisely leave this disabled.
+
+config CONFIG_HEXDUMP
+	bool "hexdump"
+	default n
+	help
+	  The hexdump utility is used to display binary data in a readable
+	  way that is comparable to the output from most hex editors.
+
+config CONFIG_HWCLOCK
+	bool "hwclock"
+	default n
+	help
+	  The hwclock utility is used to read and set the hardware clock
+	  on a system.  This is primarily used to set the current time on
+	  shutdown in the hardware clock, so the hardware will keep the
+	  correct time when Linux is _not_ running.
+
+config CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS
+	bool "Support long options (--hctosys,...)"
+	default n
+	depends on CONFIG_HWCLOCK && CONFIG_GETOPT_LONG
+	help
+	  By default, the hwclock utility only uses short options.  If you
+	  are overly fond of its long options, such as --hctosys, --utc, etc)
+	  then enable this option.
+
+config CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS
+	bool "Use FHS /var/lib/hwclock/adjtime"
+	default y
+	depends on CONFIG_HWCLOCK
+	help
+	  Starting with FHS 2.3, the adjtime state file is supposed to exist
+	  at /var/lib/hwclock/adjtime instead of /etc/adjtime.  If you wish
+	  to use the FHS behavior, answer Y here, otherwise answer N for the
+	  classic /etc/adjtime path.
+
+	  http://www.pathname.com/fhs/pub/fhs-2.3.html#VARLIBHWCLOCKSTATEDIRECTORYFORHWCLO
+
+config CONFIG_IPCRM
+	bool "ipcrm"
+	default n
+	select CONFIG_FEATURE_SUID
+	help
+	  The ipcrm utility allows the removal of System V interprocess
+	  communication (IPC) objects and the associated data structures
+	  from the system.
+
+config CONFIG_IPCS
+	bool "ipcs"
+	default n
+	select CONFIG_FEATURE_SUID
+	help
+	  The ipcs utility is used to provide information on the currently
+	  allocated System V interprocess (IPC) objects in the system.
+
+config CONFIG_LOSETUP
+	bool "losetup"
+	default n
+	help
+	  losetup is used to associate or detach a loop device with a regular
+	  file or block device, and to query the status of a loop device.  This
+	  version does not currently support enabling data encryption.
+
+config CONFIG_MDEV
+	bool "mdev"
+	default n
+	help
+	  mdev is a mini-udev implementation: call it with -s to populate
+	  /dev from /sys, then "echo /sbin/mdev > /proc/sys/kernel/hotplug" to
+	  have it handle hotplug events afterwards.  Device names are taken
+	  from sysfs.
+
+config CONFIG_FEATURE_MDEV_CONF
+	bool "Support /etc/mdev.conf"
+	default n
+	depends on CONFIG_MDEV
+	help
+	  The mdev config file contains lines that look like:
+
+	    hd[a-z][0-9]* 0:3 660
+
+	  That's device name (with regex match), uid:gid, and permissions.
+
+	  Config file parsing stops on the first matching line.  If no config
+	  entry is matched, devices are created with default 0:0 660.  (Make
+	  the last line match .* to override this.)
+
+config CONFIG_FEATURE_MDEV_EXEC
+	bool "Support command execution at device addition/removal"
+	default n
+	depends on CONFIG_FEATURE_MDEV_CONF
+	help
+	  This adds support for an optional field to /etc/mdev.conf, consisting
+	  of a special character and a command line to run after creating the
+	  corresponding device(s) and before removing, ala:
+
+	    hdc root:cdrom 660  *ln -s $MDEV cdrom
+
+	  The $MDEV environment variable is set to the name of the device.
+
+	  The special characters and their meanings are:
+	    @ Run after creating the device.
+	    $ Run before removing the device.
+	    * Run both after creating and before removing the device.
+
+	  Commands are executed via system() so you need /bin/sh, meaning you
+	  probably want to select a default shell in the Shells menu.
+
+config CONFIG_MKSWAP
+	bool "mkswap"
+	default n
+	help
+	  The mkswap utility is used to configure a file or disk partition as
+	  Linux swap space.  This allows Linux to use the entire file or
+	  partition as if it were additional RAM, which can greatly increase
+	  the capability of low-memory machines.  This additional memory is
+	  much slower than real RAM, but can be very helpful at preventing your
+	  applications being killed by the Linux out of memory (OOM) killer.
+	  Once you have created swap space using 'mkswap' you need to enable
+	  the swap space using the 'swapon' utility.
+
+config CONFIG_FEATURE_MKSWAP_V0
+	bool "version 0 support"
+	default n
+	depends on CONFIG_MKSWAP
+#	depends on CONFIG_MKSWAP && CONFIG_DEPRECATED
+	help
+	  Enable support for the old v0 style.
+	  If your kernel is older than 2.1.117, then v0 support is the
+	  only option.
+
+config CONFIG_MORE
+	bool "more"
+	default n
+	help
+	  more is a simple utility which allows you to read text one screen
+	  sized page at a time.  If you want to read text that is larger than
+	  the screen, and you are using anything faster than a 300 baud modem,
+	  you will probably find this utility very helpful.  If you don't have
+	  any need to reading text files, you can leave this disabled.
+
+config CONFIG_FEATURE_USE_TERMIOS
+	bool "Use termios to manipulate the screen"
+	default y
+	depends on CONFIG_MORE
+	help
+	  This option allows utilities such as 'more' and 'top' to determine
+	  the size of the screen.  If you leave this disabled, your utilities
+	  that display things on the screen will be especially primitive and
+	  will be unable to determine the current screen size, and will be
+	  unable to move the cursor.
+
+config CONFIG_MOUNT
+	bool "mount"
+	default n
+	help
+	  All files and filesystems in Unix are arranged into one big directory
+	  tree.  The 'mount' utility is used to graft a filesystem onto a
+	  particular part of the tree.  A filesystem can either live on a block
+	  device, or it can be accessible over the network, as is the case with
+	  NFS filesystems.  Most people using BusyBox will also want to enable
+	  the 'mount' utility.
+
+config CONFIG_FEATURE_MOUNT_NFS
+	bool "Support mounting NFS file systems"
+	default n
+	depends on CONFIG_MOUNT
+	help
+	 Enable mounting of NFS file systems.
+
+config CONFIG_PIVOT_ROOT
+	bool "pivot_root"
+	default n
+	help
+	  The pivot_root utility swaps the mount points for the root filesystem
+	  with some other mounted filesystem.  This allows you to do all sorts
+	  of wild and crazy things with your Linux system and is far more
+	  powerful than 'chroot'.
+
+	  Note: This is for initrd in linux 2.4.  Under initramfs (introduced
+	  in linux 2.6) use switch_root instead.
+
+config CONFIG_RDATE
+	bool "rdate"
+	default n
+	help
+	  The rdate utility allows you to synchronize the date and time of your
+	  system clock with the date and time of a remote networked system using
+	  the RFC868 protocol, which is built into the inetd daemon on most
+	  systems.
+
+config CONFIG_READPROFILE
+	bool "readprofile"
+	default n
+	help
+	  This allows you to parse /proc/profile for basic profiling.
+
+config CONFIG_SETARCH
+	bool "setarch"
+	default n
+	help
+	  The linux32 utility is used to create a 32bit environment for the
+	  specified program (usually a shell).  It only makes sense to have
+	  this util on a system that supports both 64bit and 32bit userland
+	  (like amd64/x86, ppc64/ppc, sparc64/sparc, etc...).
+
+config CONFIG_SWAPONOFF
+	bool "swaponoff"
+	default n
+	help
+	  This option enables both the 'swapon' and the 'swapoff' utilities.
+	  Once you have created some swap space using 'mkswap', you also need
+	  to enable your swap space with the 'swapon' utility.  The 'swapoff'
+	  utility is used, typically at system shutdown, to disable any swap
+	  space.  If you are not using any swap space, you can leave this
+	  option disabled.
+
+config CONFIG_SWITCH_ROOT
+	bool "switch_root"
+	default n
+	help
+	  The switch_root utility is used from initramfs to select a new
+	  root device.  Under initramfs, you have to use this instead of
+	  pivot_root.  (Stop reading here if you don't care why.)
+
+	  Booting with initramfs extracts a gzipped cpio archive into rootfs
+	  (which is a variant of ramfs/tmpfs).  Because rootfs can't be moved
+	  or unmounted*, pivot_root will not work from initramfs.  Instead,
+	  switch_root deletes everything out of rootfs (including itself),
+	  does a mount --move that overmounts rootfs with the new root, and
+	  then execs the specified init program.
+
+	  * Because the Linux kernel uses rootfs internally as the starting
+	  and ending point for searching through the kernel's doubly linked
+	  list of active mount points.  That's why.
+
+config CONFIG_UMOUNT
+	bool "umount"
+	default n
+	help
+	  When you want to remove a mounted filesystem from its current mount point,
+	  for example when you are shutting down the system, the 'umount' utility is
+	  the tool to use.  If you enabled the 'mount' utility, you almost certainly
+	  also want to enable 'umount'.
+
+config CONFIG_FEATURE_UMOUNT_ALL
+	bool "umount -a option"
+	default n
+	depends on CONFIG_UMOUNT
+	help
+	  Support -a option to unmount all currently mounted filesystems.
+
+comment "Common options for mount/umount"
+	depends on CONFIG_MOUNT || CONFIG_UMOUNT
+
+config CONFIG_FEATURE_MOUNT_LOOP
+	bool "Support loopback mounts"
+	default n
+	depends on CONFIG_MOUNT || CONFIG_UMOUNT
+	help
+	  Enabling this feature allows automatic mounting of files (containing
+	  filesystem images) via the linux kernel's loopback devices.  The mount
+	  command will detect you are trying to mount a file instead of a block
+	  device, and transparently associate the file with a loopback device.
+	  The umount command will also free that loopback device.
+
+	  You can still use the 'losetup' utility (to manually associate files
+          with loop devices) if you need to do something advanced, such as
+	  specify an offset or cryptographic options to the loopback device.
+	  (If you don't want umount to free the loop device, use "umount -D".)
+
+config CONFIG_FEATURE_MTAB_SUPPORT
+	bool "Support for the old /etc/mtab file"
+	default n
+	depends on CONFIG_MOUNT || CONFIG_UMOUNT
+	help
+	  Historically, Unix systems kept track of the currently mounted
+	  partitions in the file "/etc/mtab".  These days, the kernel exports
+	  the list of currently mounted partitions in "/proc/mounts", rendering
+	  the old mtab file obsolete.  (In modern systems, /etc/mtab should be
+	  a symlink to /proc/mounts.)
+
+	  The only reason to have mount maintain an /etc/mtab file itself is if
+	  your stripped-down embedded system does not have a /proc directory.
+	  If you must use this, keep in mind it's inherently brittle (for
+	  example a mount under chroot won't update it), can't handle modern
+	  features like separate per-process filesystem namespaces, requires
+	  that your /etc directory be writeable, tends to get easily confused
+	  by --bind or --move mounts, won't update if you rename a directory
+	  that contains a mount point, and so on.  (In brief: avoid.)
+
+	  About the only reason to use this is if you've removed /proc from
+	  your kernel.
+
+endmenu
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/Makefile
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/Makefile	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/Makefile	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,22 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+ifndef top_srcdir
+top_srcdir=..
+endif
+ifndef top_builddir
+top_builddir=..
+endif
+srcdir=$(top_srcdir)/util-linux
+UTILLINUX_DIR:=./
+include $(top_srcdir)/Rules.mak
+include $(top_builddir)/.config
+include Makefile.in
+all: $(libraries-y)
+-include $(top_builddir)/.depend
+
+clean:
+	rm -f *.o *.a $(AR_TARGET)

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/Makefile.in
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/Makefile.in	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/Makefile.in	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,63 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen at codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+UTILLINUX_AR:=util-linux.a
+ifndef $(UTILLINUX_DIR)
+UTILLINUX_DIR:=$(top_builddir)/util-linux/
+endif
+srcdir=$(top_srcdir)/util-linux
+
+UTILLINUX-y:=
+UTILLINUX-$(CONFIG_DMESG)         +=dmesg.o
+UTILLINUX-$(CONFIG_FBSET)         +=fbset.o
+UTILLINUX-$(CONFIG_FDFLUSH)       +=freeramdisk.o
+UTILLINUX-$(CONFIG_FDFORMAT)      +=fdformat.o
+UTILLINUX-$(CONFIG_FDISK)         +=fdisk.o
+UTILLINUX-$(CONFIG_FREERAMDISK)   +=freeramdisk.o
+UTILLINUX-$(CONFIG_FSCK_MINIX)    +=fsck_minix.o
+UTILLINUX-$(CONFIG_GETOPT)        +=getopt.o
+UTILLINUX-$(CONFIG_HEXDUMP)       +=hexdump.o
+UTILLINUX-$(CONFIG_HWCLOCK)       +=hwclock.o
+UTILLINUX-$(CONFIG_IPCRM)         +=ipcrm.o
+UTILLINUX-$(CONFIG_IPCS)          +=ipcs.o
+UTILLINUX-$(CONFIG_LOSETUP)       +=losetup.o
+UTILLINUX-$(CONFIG_MDEV)          +=mdev.o
+UTILLINUX-$(CONFIG_MKFS_MINIX)    +=mkfs_minix.o
+UTILLINUX-$(CONFIG_MKSWAP)        +=mkswap.o
+UTILLINUX-$(CONFIG_MORE)          +=more.o
+UTILLINUX-$(CONFIG_MOUNT)         +=mount.o
+UTILLINUX-$(CONFIG_FEATURE_MOUNT_NFS)	+=nfsmount.o
+UTILLINUX-$(CONFIG_PIVOT_ROOT)    +=pivot_root.o
+UTILLINUX-$(CONFIG_RDATE)         +=rdate.o
+UTILLINUX-$(CONFIG_READPROFILE)   +=readprofile.o
+UTILLINUX-$(CONFIG_SETARCH)       +=setarch.o
+UTILLINUX-$(CONFIG_SWAPONOFF)     +=swaponoff.o
+UTILLINUX-$(CONFIG_SWITCH_ROOT)   +=switch_root.o
+UTILLINUX-$(CONFIG_UMOUNT)        +=umount.o
+
+UTILLINUX-y:=$(sort $(UTILLINUX-y))
+
+ifneq ($(strip $(UTILLINUX-y)),)
+libraries-y+=$(UTILLINUX_DIR)$(UTILLINUX_AR)
+endif
+
+UTILLINUX_SRC-y:=$(patsubst %.o,$(srcdir)/%.c,$(UTILLINUX-y))
+UTILLINUX_SRC-a:=$(wildcard $(srcdir)/*.c)
+APPLET_SRC-y+=$(UTILLINUX_SRC-y)
+APPLET_SRC-a+=$(UTILLINUX_SRC-a)
+
+$(UTILLINUX_DIR)$(UTILLINUX_AR): $(patsubst %,$(UTILLINUX_DIR)%, $(UTILLINUX-y))
+	$(do_ar)
+
+$(UTILLINUX_DIR)%.o: $(srcdir)/%.c
+	$(compile.c)
+
+ifneq ($(strip $(CONFIG_LFS)),y)
+ifeq ($(strip $(FDISK_SUPPORT_LARGE_DISKS)),y)
+$(UTILLINUX_DIR)fdisk.o: $(srcdir)/fdisk.c
+	$(compile.c) -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+endif
+endif

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/dmesg.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/dmesg.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/dmesg.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,35 @@
+/* vi: set ts=4:
+ * 
+ * dmesg - display/control kernel ring buffer.
+ *
+ * Copyring 2006 Rob Landley <rob at landley.net>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <unistd.h>
+#include <sys/klog.h>
+
+int dmesg_main(int argc, char *argv[])
+{
+	char *size, *level;
+	int flags = bb_getopt_ulflags(argc, argv, "cs:n:", &size, &level);
+
+	if (flags & 4) {
+		if(klogctl(8, NULL, bb_xgetlarg(level, 10, 0, 10)))
+			bb_perror_msg_and_die("klogctl");
+	} else {
+		int len;
+		char *buf;
+
+		len = (flags & 2) ? bb_xgetlarg(size, 10, 2, INT_MAX) : 16384;
+		buf = xmalloc(len);
+		if (0 > (len = klogctl(3 + (flags & 1), buf, len)))
+			bb_perror_msg_and_die("klogctl");
+		write(1,buf,len);
+		if (len && buf[len-1]!='\n') putchar('\n');
+	}
+
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/fbset.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/fbset.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/fbset.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,418 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini fbset implementation for busybox
+ *
+ * Copyright (C) 1999 by Randolph Chung <tausq at debian.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * This is a from-scratch implementation of fbset; but the de facto fbset
+ * implementation was a good reference. fbset (original) is released under
+ * the GPL, and is (c) 1995-1999 by:
+ *     Geert Uytterhoeven (Geert.Uytterhoeven at cs.kuleuven.ac.be)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include "busybox.h"
+
+#define DEFAULTFBDEV  FB_0
+#define DEFAULTFBMODE "/etc/fb.modes"
+
+enum {
+	OPT_CHANGE   = (1 << 0),
+	OPT_INFO     = (1 << 1),
+	OPT_READMODE = (1 << 2),
+
+	CMD_FB = 1,
+	CMD_DB = 2,
+	CMD_GEOMETRY = 3,
+	CMD_TIMING = 4,
+	CMD_ACCEL = 5,
+	CMD_HSYNC = 6,
+	CMD_VSYNC = 7,
+	CMD_LACED = 8,
+	CMD_DOUBLE = 9,
+/*	CMD_XCOMPAT =     10, */
+	CMD_ALL = 11,
+	CMD_INFO = 12,
+	CMD_CHANGE = 13,
+
+#ifdef CONFIG_FEATURE_FBSET_FANCY
+	CMD_XRES = 100,
+	CMD_YRES = 101,
+	CMD_VXRES = 102,
+	CMD_VYRES = 103,
+	CMD_DEPTH = 104,
+	CMD_MATCH = 105,
+	CMD_PIXCLOCK = 106,
+	CMD_LEFT = 107,
+	CMD_RIGHT = 108,
+	CMD_UPPER = 109,
+	CMD_LOWER = 110,
+	CMD_HSLEN = 111,
+	CMD_VSLEN = 112,
+	CMD_CSYNC = 113,
+	CMD_GSYNC = 114,
+	CMD_EXTSYNC = 115,
+	CMD_BCAST = 116,
+	CMD_RGBA = 117,
+	CMD_STEP = 118,
+	CMD_MOVE = 119,
+#endif
+};
+
+static unsigned int g_options = 0;
+
+/* Stuff stolen from the kernel's fb.h */
+enum {
+	FBIOGET_VSCREENINFO = 0x4600,
+	FBIOPUT_VSCREENINFO = 0x4601
+};
+struct fb_bitfield {
+	uint32_t offset;			/* beginning of bitfield	*/
+	uint32_t length;			/* length of bitfield		*/
+	uint32_t msb_right;		/* != 0 : Most significant bit is */
+					/* right */
+};
+struct fb_var_screeninfo {
+	uint32_t xres;			/* visible resolution		*/
+	uint32_t yres;
+	uint32_t xres_virtual;		/* virtual resolution		*/
+	uint32_t yres_virtual;
+	uint32_t xoffset;			/* offset from virtual to visible */
+	uint32_t yoffset;			/* resolution			*/
+
+	uint32_t bits_per_pixel;		/* guess what			*/
+	uint32_t grayscale;		/* != 0 Graylevels instead of colors */
+
+	struct fb_bitfield red;		/* bitfield in fb mem if true color, */
+	struct fb_bitfield green;	/* else only length is significant */
+	struct fb_bitfield blue;
+	struct fb_bitfield transp;	/* transparency			*/
+
+	uint32_t nonstd;			/* != 0 Non standard pixel format */
+
+	uint32_t activate;			/* see FB_ACTIVATE_*		*/
+
+	uint32_t height;			/* height of picture in mm    */
+	uint32_t width;			/* width of picture in mm     */
+
+	uint32_t accel_flags;		/* acceleration flags (hints)	*/
+
+	/* Timing: All values in pixclocks, except pixclock (of course) */
+	uint32_t pixclock;			/* pixel clock in ps (pico seconds) */
+	uint32_t left_margin;		/* time from sync to picture	*/
+	uint32_t right_margin;		/* time from picture to sync	*/
+	uint32_t upper_margin;		/* time from sync to picture	*/
+	uint32_t lower_margin;
+	uint32_t hsync_len;		/* length of horizontal sync	*/
+	uint32_t vsync_len;		/* length of vertical sync	*/
+	uint32_t sync;			/* see FB_SYNC_*		*/
+	uint32_t vmode;			/* see FB_VMODE_*		*/
+	uint32_t reserved[6];		/* Reserved for future compatibility */
+};
+
+
+static const struct cmdoptions_t {
+	const char *name;
+	const unsigned char param_count;
+	const unsigned char code;
+} g_cmdoptions[] = {
+	{
+	"-fb", 1, CMD_FB}, {
+	"-db", 1, CMD_DB}, {
+	"-a", 0, CMD_ALL}, {
+	"-i", 0, CMD_INFO}, {
+	"-g", 5, CMD_GEOMETRY}, {
+	"-t", 7, CMD_TIMING}, {
+	"-accel", 1, CMD_ACCEL}, {
+	"-hsync", 1, CMD_HSYNC}, {
+	"-vsync", 1, CMD_VSYNC}, {
+	"-laced", 1, CMD_LACED}, {
+	"-double", 1, CMD_DOUBLE}, {
+	"-n", 0, CMD_CHANGE}, {
+#ifdef CONFIG_FEATURE_FBSET_FANCY
+	"-all", 0, CMD_ALL}, {
+	"-xres", 1, CMD_XRES}, {
+	"-yres", 1, CMD_YRES}, {
+	"-vxres", 1, CMD_VXRES}, {
+	"-vyres", 1, CMD_VYRES}, {
+	"-depth", 1, CMD_DEPTH}, {
+	"-match", 0, CMD_MATCH}, {
+	"-geometry", 5, CMD_GEOMETRY}, {
+	"-pixclock", 1, CMD_PIXCLOCK}, {
+	"-left", 1, CMD_LEFT}, {
+	"-right", 1, CMD_RIGHT}, {
+	"-upper", 1, CMD_UPPER}, {
+	"-lower", 1, CMD_LOWER}, {
+	"-hslen", 1, CMD_HSLEN}, {
+	"-vslen", 1, CMD_VSLEN}, {
+	"-timings", 7, CMD_TIMING}, {
+	"-csync", 1, CMD_CSYNC}, {
+	"-gsync", 1, CMD_GSYNC}, {
+	"-extsync", 1, CMD_EXTSYNC}, {
+	"-bcast", 1, CMD_BCAST}, {
+	"-rgba", 1, CMD_RGBA}, {
+	"-step", 1, CMD_STEP}, {
+	"-move", 1, CMD_MOVE}, {
+#endif
+	0, 0, 0}
+};
+
+#ifdef CONFIG_FEATURE_FBSET_READMODE
+/* taken from linux/fb.h */
+enum {
+	FB_VMODE_INTERLACED = 1,	/* interlaced	*/
+	FB_VMODE_DOUBLE = 2,	/* double scan */
+	FB_SYNC_HOR_HIGH_ACT = 1,	/* horizontal sync high active	*/
+	FB_SYNC_VERT_HIGH_ACT = 2,	/* vertical sync high active	*/
+	FB_SYNC_EXT = 4,	/* external sync		*/
+	FB_SYNC_COMP_HIGH_ACT = 8	/* composite sync high active   */
+};
+#endif
+static int readmode(struct fb_var_screeninfo *base, const char *fn,
+					const char *mode)
+{
+#ifdef CONFIG_FEATURE_FBSET_READMODE
+	FILE *f;
+	char buf[256];
+	char *p = buf;
+
+	f = bb_xfopen(fn, "r");
+	while (!feof(f)) {
+		fgets(buf, sizeof(buf), f);
+		if ((p = strstr(buf, "mode ")) || (p = strstr(buf, "mode\t"))) {
+			p += 5;
+			if ((p = strstr(buf, mode))) {
+				p += strlen(mode);
+				if (!isspace(*p) && (*p != 0) && (*p != '"')
+					&& (*p != '\r') && (*p != '\n'))
+					continue;	/* almost, but not quite */
+				while (!feof(f)) {
+					fgets(buf, sizeof(buf), f);
+
+		    if ((p = strstr(buf, "geometry "))) {
+			p += 9;
+
+			sscanf(p, "%d %d %d %d %d",
+				&(base->xres), &(base->yres),
+				&(base->xres_virtual), &(base->yres_virtual),
+				&(base->bits_per_pixel));
+		    } else if ((p = strstr(buf, "timings "))) {
+			p += 8;
+
+			sscanf(p, "%d %d %d %d %d %d %d",
+				&(base->pixclock),
+				&(base->left_margin), &(base->right_margin),
+				&(base->upper_margin), &(base->lower_margin),
+				&(base->hsync_len), &(base->vsync_len));
+		    } else if ((p = strstr(buf, "laced "))) {
+			p += 6;
+
+			if (strstr(buf, "false")) {
+			    base->vmode &= ~FB_VMODE_INTERLACED;
+			} else {
+			    base->vmode |= FB_VMODE_INTERLACED;
+			}
+		    } else if ((p = strstr(buf, "double "))) {
+			p += 7;
+
+			if (strstr(buf, "false")) {
+			    base->vmode &= ~FB_VMODE_DOUBLE;
+			} else {
+			    base->vmode |= FB_VMODE_DOUBLE;
+			}
+		    } else if ((p = strstr(buf, "vsync "))) {
+			p += 6;
+
+			if (strstr(buf, "low")) {
+			    base->sync &= ~FB_SYNC_VERT_HIGH_ACT;
+			} else {
+			    base->sync |= FB_SYNC_VERT_HIGH_ACT;
+			}
+		    } else if ((p = strstr(buf, "hsync "))) {
+			p += 6;
+
+			if (strstr(buf, "low")) {
+			    base->sync &= ~FB_SYNC_HOR_HIGH_ACT;
+			} else {
+			    base->sync |= FB_SYNC_HOR_HIGH_ACT;
+			}
+		    } else if ((p = strstr(buf, "csync "))) {
+			p += 6;
+
+			if (strstr(buf, "low")) {
+			    base->sync &= ~FB_SYNC_COMP_HIGH_ACT;
+			} else {
+			    base->sync |= FB_SYNC_COMP_HIGH_ACT;
+			}
+		    } else if ((p = strstr(buf, "extsync "))) {
+			p += 8;
+
+			if (strstr(buf, "false")) {
+			    base->sync &= ~FB_SYNC_EXT;
+			} else {
+			    base->sync |= FB_SYNC_EXT;
+			}
+		    }
+
+					if (strstr(buf, "endmode"))
+						return 1;
+				}
+			}
+		}
+	}
+#else
+	bb_error_msg( "mode reading not compiled in");
+#endif
+	return 0;
+}
+
+static inline void setmode(struct fb_var_screeninfo *base,
+					struct fb_var_screeninfo *set)
+{
+	if ((int) set->xres > 0)
+		base->xres = set->xres;
+	if ((int) set->yres > 0)
+		base->yres = set->yres;
+	if ((int) set->xres_virtual > 0)
+		base->xres_virtual = set->xres_virtual;
+	if ((int) set->yres_virtual > 0)
+		base->yres_virtual = set->yres_virtual;
+	if ((int) set->bits_per_pixel > 0)
+		base->bits_per_pixel = set->bits_per_pixel;
+}
+
+static inline void showmode(struct fb_var_screeninfo *v)
+{
+	double drate = 0, hrate = 0, vrate = 0;
+
+	if (v->pixclock) {
+		drate = 1e12 / v->pixclock;
+		hrate =
+			drate / (v->left_margin + v->xres + v->right_margin +
+					 v->hsync_len);
+		vrate =
+			hrate / (v->upper_margin + v->yres + v->lower_margin +
+					 v->vsync_len);
+	}
+	printf("\nmode \"%ux%u-%u\"\n"
+#ifdef CONFIG_FEATURE_FBSET_FANCY
+	"\t# D: %.3f MHz, H: %.3f kHz, V: %.3f Hz\n"
+#endif
+	"\tgeometry %u %u %u %u %u\n\ttimings %u %u %u %u %u %u %u\n\taccel %s\n\trgba %u/%u,%u/%u,%u/%u,%u/%u\nendmode\n\n",
+		   v->xres, v->yres, (int) (vrate + 0.5),
+#ifdef CONFIG_FEATURE_FBSET_FANCY
+		   drate / 1e6, hrate / 1e3, vrate,
+#endif
+		   v->xres, v->yres, v->xres_virtual, v->yres_virtual,
+		   v->bits_per_pixel, v->pixclock, v->left_margin,
+		   v->right_margin, v->upper_margin, v->lower_margin, v->hsync_len,
+		   v->vsync_len, (v->accel_flags > 0 ? "true" : "false"), v->red.length,
+		   v->red.offset, v->green.length, v->green.offset, v->blue.length,
+		   v->blue.offset, v->transp.length, v->transp.offset);
+}
+
+#ifdef STANDALONE
+int main(int argc, char **argv)
+#else
+int fbset_main(int argc, char **argv)
+#endif
+{
+	struct fb_var_screeninfo var, varset;
+	int fh, i;
+	char *fbdev = DEFAULTFBDEV;
+	char *modefile = DEFAULTFBMODE;
+	char *thisarg, *mode = NULL;
+
+	memset(&varset, 0xFF, sizeof(varset));
+
+	/* parse cmd args.... why do they have to make things so difficult? */
+	argv++;
+	argc--;
+	for (; argc > 0 && (thisarg = *argv); argc--, argv++) {
+		for (i = 0; g_cmdoptions[i].name; i++) {
+			if (!strcmp(thisarg, g_cmdoptions[i].name)) {
+				if (argc - 1 < g_cmdoptions[i].param_count)
+					bb_show_usage();
+				switch (g_cmdoptions[i].code) {
+				case CMD_FB:
+					fbdev = argv[1];
+					break;
+				case CMD_DB:
+					modefile = argv[1];
+					break;
+				case CMD_GEOMETRY:
+					varset.xres = strtoul(argv[1], 0, 0);
+					varset.yres = strtoul(argv[2], 0, 0);
+					varset.xres_virtual = strtoul(argv[3], 0, 0);
+					varset.yres_virtual = strtoul(argv[4], 0, 0);
+					varset.bits_per_pixel = strtoul(argv[5], 0, 0);
+					break;
+				case CMD_TIMING:
+					varset.pixclock = strtoul(argv[1], 0, 0);
+					varset.left_margin = strtoul(argv[2], 0, 0);
+					varset.right_margin = strtoul(argv[3], 0, 0);
+					varset.upper_margin = strtoul(argv[4], 0, 0);
+					varset.lower_margin = strtoul(argv[5], 0, 0);
+					varset.hsync_len = strtoul(argv[6], 0, 0);
+					varset.vsync_len = strtoul(argv[7], 0, 0);
+					break;
+		case CMD_CHANGE:
+		    g_options |= OPT_CHANGE;
+		    break;
+#ifdef CONFIG_FEATURE_FBSET_FANCY
+				case CMD_XRES:
+					varset.xres = strtoul(argv[1], 0, 0);
+					break;
+				case CMD_YRES:
+					varset.yres = strtoul(argv[1], 0, 0);
+					break;
+			   case CMD_DEPTH:
+					varset.bits_per_pixel = strtoul(argv[1], 0, 0);
+					break;
+#endif
+				}
+				argc -= g_cmdoptions[i].param_count;
+				argv += g_cmdoptions[i].param_count;
+				break;
+			}
+		}
+		if (!g_cmdoptions[i].name) {
+			if (argc == 1) {
+				mode = *argv;
+				g_options |= OPT_READMODE;
+			} else {
+				bb_show_usage();
+			}
+		}
+	}
+
+	fh = bb_xopen(fbdev, O_RDONLY);
+	if (ioctl(fh, FBIOGET_VSCREENINFO, &var))
+		bb_perror_msg_and_die("fbset(ioctl)");
+	if (g_options & OPT_READMODE) {
+		if (!readmode(&var, modefile, mode)) {
+			bb_error_msg("Unknown video mode `%s'", mode);
+			return EXIT_FAILURE;
+		}
+	}
+
+	setmode(&var, &varset);
+	if (g_options & OPT_CHANGE)
+		if (ioctl(fh, FBIOPUT_VSCREENINFO, &var))
+			bb_perror_msg_and_die("fbset(ioctl)");
+	showmode(&var);
+	/* Don't close the file, as exiting will take care of that */
+	/* close(fh); */
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/fdformat.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/fdformat.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/fdformat.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,161 @@
+/* fdformat.c  -  Low-level formats a floppy disk - Werner Almesberger */
+
+/* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek at pld.ORG.PL>
+ * - added Native Language Support
+ * 1999-03-20 Arnaldo Carvalho de Melo <acme at conectiva.com.br>
+ * - more i18n/nls translatable strings marked
+ *
+ * 5 July 2003 -- modified for Busybox by Erik Andersen
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include "busybox.h"
+
+
+/* Stuff extracted from linux/fd.h */
+struct floppy_struct {
+	unsigned int	size,		/* nr of sectors total */
+			sect,		/* sectors per track */
+			head,		/* nr of heads */
+			track,		/* nr of tracks */
+			stretch;	/* !=0 means double track steps */
+#define FD_STRETCH 1
+#define FD_SWAPSIDES 2
+
+	unsigned char	gap,		/* gap1 size */
+
+			rate,		/* data rate. |= 0x40 for perpendicular */
+#define FD_2M 0x4
+#define FD_SIZECODEMASK 0x38
+#define FD_SIZECODE(floppy) (((((floppy)->rate&FD_SIZECODEMASK)>> 3)+ 2) %8)
+#define FD_SECTSIZE(floppy) ( (floppy)->rate & FD_2M ? \
+			     512 : 128 << FD_SIZECODE(floppy) )
+#define FD_PERP 0x40
+
+			spec1,		/* stepping rate, head unload time */
+			fmt_gap;	/* gap2 size */
+	const char	* name; /* used only for predefined formats */
+};
+struct format_descr {
+	unsigned int device,head,track;
+};
+#define FDFMTBEG _IO(2,0x47)
+#define	FDFMTTRK _IOW(2,0x48, struct format_descr)
+#define FDFMTEND _IO(2,0x49)
+#define FDGETPRM _IOR(2, 0x04, struct floppy_struct)
+#define FD_FILL_BYTE 0xF6 /* format fill byte. */
+
+static void print_and_flush(const char * __restrict format, ...)
+{
+	va_list arg;
+
+	va_start(arg, format);
+	bb_vfprintf(stdout, format, arg);
+	va_end(arg);
+	bb_xfflush_stdout();
+}
+
+static void bb_xioctl(int fd, int request, void *argp, const char *string)
+{
+	if (ioctl (fd, request, argp) < 0) {
+		bb_perror_msg_and_die(string);
+	}
+}
+
+int fdformat_main(int argc,char **argv)
+{
+	int fd, n, cyl, read_bytes, verify;
+	unsigned char *data;
+	struct stat st;
+	struct floppy_struct param;
+	struct format_descr descr;
+
+	if (argc < 2) {
+		bb_show_usage();
+	}
+	verify = !bb_getopt_ulflags(argc, argv, "n");
+	argv += optind;
+
+	/* R_OK is needed for verifying */
+	if (stat(*argv,&st) < 0 || access(*argv,W_OK | R_OK ) < 0) {
+		bb_perror_msg_and_die("%s",*argv);
+	}
+	if (!S_ISBLK(st.st_mode)) {
+		bb_error_msg_and_die("%s: not a block device",*argv);
+		/* do not test major - perhaps this was an USB floppy */
+	}
+
+
+	/* O_RDWR for formatting and verifying */
+	fd = bb_xopen(*argv,O_RDWR );
+
+	bb_xioctl(fd, FDGETPRM, &param, "FDGETPRM");/*original message was: "Could not determine current format type" */
+
+	print_and_flush("%s-sided, %d tracks, %d sec/track. Total capacity %d kB.\n",
+		(param.head == 2) ? "Double" : "Single",
+		param.track, param.sect, param.size >> 1);
+
+	/* FORMAT */
+	print_and_flush("Formatting ... ", NULL);
+	bb_xioctl(fd, FDFMTBEG,NULL,"FDFMTBEG");
+
+	/* n == track */
+	for (n = 0; n < param.track; n++)
+	{
+	    descr.head = 0;
+	    descr.track = n;
+	    bb_xioctl(fd, FDFMTTRK,&descr,"FDFMTTRK");
+	    print_and_flush("%3d\b\b\b", n);
+	    if (param.head == 2) {
+		descr.head = 1;
+		bb_xioctl(fd, FDFMTTRK,&descr,"FDFMTTRK");
+	    }
+	}
+
+	bb_xioctl(fd,FDFMTEND,NULL,"FDFMTEND");
+	print_and_flush("done\n", NULL);
+
+	/* VERIFY */
+	if(verify) {
+		/* n == cyl_size */
+		n = param.sect*param.head*512;
+
+		data = xmalloc(n);
+		print_and_flush("Verifying ... ", NULL);
+		for (cyl = 0; cyl < param.track; cyl++) {
+			print_and_flush("%3d\b\b\b", cyl);
+			if((read_bytes = safe_read(fd,data,n))!= n ) {
+				if(read_bytes < 0) {
+					bb_perror_msg(bb_msg_read_error);
+				}
+				bb_error_msg_and_die("Problem reading cylinder %d, expected %d, read %d", cyl, n, read_bytes);
+			}
+			/* Check backwards so we don't need a counter */
+			while(--read_bytes>=0) {
+				if( data[read_bytes] != FD_FILL_BYTE) {
+					 print_and_flush("bad data in cyl %d\nContinuing ... ",cyl);
+				}
+			}
+		}
+		/* There is no point in freeing blocks at the end of a program, because
+		all of the program's space is given back to the system when the process
+		terminates.*/
+
+		if (ENABLE_FEATURE_CLEAN_UP) free(data);
+
+		print_and_flush("done\n", NULL);
+	}
+
+	if (ENABLE_FEATURE_CLEAN_UP) close(fd);
+
+	/* Don't bother closing.  Exit does
+	 * that, so we can save a few bytes */
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/fdisk.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/fdisk.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/fdisk.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,5958 @@
+/* fdisk.c -- Partition table manipulator for Linux.
+ *
+ * Copyright (C) 1992  A. V. Le Blanc (LeBlanc at mcc.ac.uk)
+ * Copyright (C) 2001,2002 Vladimir Oleynik <dzo at simtreas.ru> (initial bb port)
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+/* Current changes have not compatibility with this version */
+#define UTIL_LINUX_VERSION "2.12"
+
+
+#define _(x) x
+
+#define PROC_PARTITIONS "/proc/partitions"
+
+#include <features.h>
+#include <sys/types.h>
+#include <sys/stat.h>           /* stat */
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <assert.h>             /* assert */
+#include <getopt.h>
+#include <endian.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/sysmacros.h>     /* major */
+
+#include <stdint.h>        /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
+
+/* Copied from linux/major.h */
+#define FLOPPY_MAJOR    2
+
+#include <sys/utsname.h>
+
+#include "busybox.h"
+
+#define DKTYPENAMES
+
+/*
+   fdisk.h
+*/
+
+#define DEFAULT_SECTOR_SIZE     512
+#define MAX_SECTOR_SIZE 2048
+#define SECTOR_SIZE     512     /* still used in BSD code */
+#define MAXIMUM_PARTS   60
+
+#define ACTIVE_FLAG     0x80
+
+#define EXTENDED        0x05
+#define WIN98_EXTENDED  0x0f
+#define LINUX_PARTITION 0x81
+#define LINUX_SWAP      0x82
+#define LINUX_NATIVE    0x83
+#define LINUX_EXTENDED  0x85
+#define LINUX_LVM       0x8e
+#define LINUX_RAID      0xfd
+
+#define SUNOS_SWAP 3
+#define WHOLE_DISK 5
+
+#define IS_EXTENDED(i) \
+	((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
+
+#define SIZE(a) (sizeof(a)/sizeof((a)[0]))
+
+#define cround(n)       (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
+#define scround(x)      (((x)+units_per_sector-1)/units_per_sector)
+
+#ifdef CONFIG_FEATURE_SUN_LABEL
+#define SCSI_IOCTL_GET_IDLUN 0x5382
+#endif
+
+
+/* including <linux/hdreg.h> also fails */
+struct hd_geometry {
+	unsigned char heads;
+	unsigned char sectors;
+	unsigned short cylinders;
+	unsigned long start;
+};
+
+#define HDIO_GETGEO             0x0301  /* get device geometry */
+
+
+struct systypes {
+	const char *name;
+};
+
+static uint sector_size = DEFAULT_SECTOR_SIZE;
+static uint user_set_sector_size;
+static uint sector_offset = 1;
+
+/*
+ * Raw disk label. For DOS-type partition tables the MBR,
+ * with descriptions of the primary partitions.
+ */
+#if (MAX_SECTOR_SIZE) > (BUFSIZ+1)
+static char MBRbuffer[MAX_SECTOR_SIZE];
+#else
+# define MBRbuffer bb_common_bufsiz1
+#endif
+
+#ifdef CONFIG_FEATURE_OSF_LABEL
+static int possibly_osf_label;
+#endif
+
+static uint heads, sectors, cylinders;
+static void update_units(void);
+
+
+/*
+ * return partition name - uses static storage unless buf is supplied
+ */
+static const char *
+partname(const char *dev, int pno, int lth)
+{
+	static char buffer[80];
+	const char *p;
+	int w, wp;
+	int bufsiz;
+	char *bufp;
+
+	bufp = buffer;
+	bufsiz = sizeof(buffer);
+
+	w = strlen(dev);
+	p = "";
+
+	if (isdigit(dev[w-1]))
+		p = "p";
+
+	/* devfs kludge - note: fdisk partition names are not supposed
+	   to equal kernel names, so there is no reason to do this */
+	if (strcmp(dev + w - 4, "disc") == 0) {
+		w -= 4;
+		p = "part";
+	}
+
+	wp = strlen(p);
+
+	if (lth) {
+		snprintf(bufp, bufsiz, "%*.*s%s%-2u",
+			 lth-wp-2, w, dev, p, pno);
+	} else {
+		snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
+	}
+	return bufp;
+}
+
+struct partition {
+	unsigned char boot_ind;         /* 0x80 - active */
+	unsigned char head;             /* starting head */
+	unsigned char sector;           /* starting sector */
+	unsigned char cyl;              /* starting cylinder */
+	unsigned char sys_ind;          /* What partition type */
+	unsigned char end_head;         /* end head */
+	unsigned char end_sector;       /* end sector */
+	unsigned char end_cyl;          /* end cylinder */
+	unsigned char start4[4];        /* starting sector counting from 0 */
+	unsigned char size4[4];         /* nr of sectors in partition */
+} ATTRIBUTE_PACKED;
+
+enum failure {
+	ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
+	unable_to_write
+};
+
+enum label_type{
+	label_dos, label_sun, label_sgi, label_aix, label_osf
+};
+
+enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
+
+static enum label_type current_label_type;
+
+static const char *disk_device;
+static int fd;                  /* the disk */
+static int partitions = 4;      /* maximum partition + 1 */
+static uint display_in_cyl_units = 1;
+static uint units_per_sector = 1;
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static char *line_ptr;
+static void change_units(void);
+static void reread_partition_table(int leave);
+static void delete_partition(int i);
+static int get_partition(int warn, int max);
+static void list_types(const struct systypes *sys);
+static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
+#endif
+static const char *partition_type(unsigned char type);
+static void fdisk_fatal(enum failure why) ATTRIBUTE_NORETURN;
+static void get_geometry(void);
+static int get_boot(enum action what);
+
+#define PLURAL   0
+#define SINGULAR 1
+
+#define hex_val(c)      ({ \
+				char _c = (c); \
+				isdigit(_c) ? _c - '0' : \
+				tolower(_c) + 10 - 'a'; \
+			})
+
+
+#define LINE_LENGTH     800
+#define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
+				(n) * sizeof(struct partition)))
+#define sector(s)       ((s) & 0x3f)
+#define cylinder(s, c)  ((c) | (((s) & 0xc0) << 2))
+
+#define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
+				((h) + heads * cylinder(s,c)))
+#define set_hsc(h,s,c,sector) { \
+				s = sector % sectors + 1;       \
+				sector /= sectors;      \
+				h = sector % heads;     \
+				sector /= heads;        \
+				c = sector & 0xff;      \
+				s |= (sector >> 2) & 0xc0;      \
+			}
+
+
+static int32_t get_start_sect(const struct partition *p);
+static int32_t get_nr_sects(const struct partition *p);
+
+/*
+ * per partition table entry data
+ *
+ * The four primary partitions have the same sectorbuffer (MBRbuffer)
+ * and have NULL ext_pointer.
+ * Each logical partition table entry has two pointers, one for the
+ * partition and one link to the next one.
+ */
+static struct pte {
+	struct partition *part_table;   /* points into sectorbuffer */
+	struct partition *ext_pointer;  /* points into sectorbuffer */
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+	char changed;           /* boolean */
+#endif
+	off_t offset;            /* disk sector number */
+	char *sectorbuffer;     /* disk sector contents */
+} ptes[MAXIMUM_PARTS];
+
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static void
+set_all_unchanged(void)
+{
+	int i;
+
+	for (i = 0; i < MAXIMUM_PARTS; i++)
+		ptes[i].changed = 0;
+}
+
+static void
+set_changed(int i)
+{
+	ptes[i].changed = 1;
+}
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
+
+#if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
+static struct partition *
+get_part_table(int i)
+{
+	return ptes[i].part_table;
+}
+#endif
+
+static const char *
+str_units(int n)
+{      /* n==1: use singular */
+	if (n == 1)
+		return display_in_cyl_units ? _("cylinder") : _("sector");
+	else
+		return display_in_cyl_units ? _("cylinders") : _("sectors");
+}
+
+static int
+valid_part_table_flag(const char *mbuffer) {
+	const unsigned char *b = (const unsigned char *)mbuffer;
+	return (b[510] == 0x55 && b[511] == 0xaa);
+}
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static char  line_buffer[LINE_LENGTH];
+
+/* read line; return 0 or first char */
+static int
+read_line(void)
+{
+	static int got_eof = 0;
+
+	fflush (stdout);         /* requested by niles at scyld.com */
+	line_ptr = line_buffer;
+	if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
+		if (feof(stdin))
+			got_eof++;      /* user typed ^D ? */
+		if (got_eof >= 3) {
+			fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
+			exit(1);
+		}
+		return 0;
+	}
+	while (*line_ptr && !isgraph(*line_ptr))
+		line_ptr++;
+	return *line_ptr;
+}
+
+static char
+read_char(const char *mesg)
+{
+	do {
+		fputs(mesg, stdout);
+	} while (!read_line());
+	return *line_ptr;
+}
+
+static char
+read_chars(const char *mesg)
+{
+	fputs(mesg, stdout);
+	if (!read_line()) {
+		*line_ptr = '\n';
+		line_ptr[1] = 0;
+	}
+	return *line_ptr;
+}
+
+static int
+read_hex(const struct systypes *sys)
+{
+	int hex;
+
+	while (1) {
+		read_char(_("Hex code (type L to list codes): "));
+		if (*line_ptr == 'l' || *line_ptr == 'L')
+			list_types(sys);
+		else if (isxdigit (*line_ptr)) {
+			hex = 0;
+			do
+				hex = hex << 4 | hex_val(*line_ptr++);
+			while (isxdigit(*line_ptr));
+			return hex;
+		}
+	}
+}
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
+
+#ifdef CONFIG_FEATURE_AIX_LABEL
+/*
+ * Copyright (C) Andreas Neuper, Sep 1998.
+ *      This file may be redistributed under
+ *      the terms of the GNU Public License.
+ */
+
+typedef struct {
+	unsigned int   magic;        /* expect AIX_LABEL_MAGIC */
+	unsigned int   fillbytes1[124];
+	unsigned int   physical_volume_id;
+	unsigned int   fillbytes2[124];
+} aix_partition;
+
+#define AIX_LABEL_MAGIC         0xc9c2d4c1
+#define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
+#define AIX_INFO_MAGIC          0x00072959
+#define AIX_INFO_MAGIC_SWAPPED  0x59290700
+
+#define aixlabel ((aix_partition *)MBRbuffer)
+
+
+/*
+  Changes:
+  * 1999-03-20 Arnaldo Carvalho de Melo <acme at conectiva.com.br>
+  *     Internationalization
+  *
+  * 2003-03-20 Phillip Kesling <pkesling at sgi.com>
+  *      Some fixes
+*/
+
+static int aix_other_endian;
+static short aix_volumes = 1;
+
+/*
+ * only dealing with free blocks here
+ */
+
+static void
+aix_info(void)
+{
+	puts(
+		_("\n\tThere is a valid AIX label on this disk.\n"
+		"\tUnfortunately Linux cannot handle these\n"
+		"\tdisks at the moment.  Nevertheless some\n"
+		"\tadvice:\n"
+		"\t1. fdisk will destroy its contents on write.\n"
+		"\t2. Be sure that this disk is NOT a still vital\n"
+		"\t   part of a volume group. (Otherwise you may\n"
+		"\t   erase the other disks as well, if unmirrored.)\n"
+		"\t3. Before deleting this physical volume be sure\n"
+		"\t   to remove the disk logically from your AIX\n"
+		"\t   machine.  (Otherwise you become an AIXpert).")
+	);
+}
+
+static int
+check_aix_label(void)
+{
+	if (aixlabel->magic != AIX_LABEL_MAGIC &&
+		aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
+		current_label_type = 0;
+		aix_other_endian = 0;
+		return 0;
+	}
+	aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
+	update_units();
+	current_label_type = label_aix;
+	partitions = 1016;
+	aix_volumes = 15;
+	aix_info();
+	/*aix_nolabel();*/              /* %% */
+	/*aix_label = 1;*/              /* %% */
+	return 1;
+}
+#endif  /* AIX_LABEL */
+
+#ifdef CONFIG_FEATURE_OSF_LABEL
+/*
+ * Copyright (c) 1987, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#ifndef BSD_DISKMAGIC
+#define BSD_DISKMAGIC     ((uint32_t) 0x82564557)
+#endif
+
+#ifndef BSD_MAXPARTITIONS
+#define BSD_MAXPARTITIONS 16
+#endif
+
+#define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
+
+#if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__m68k__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
+#define BSD_LABELSECTOR   1
+#define BSD_LABELOFFSET   0
+#elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
+#define BSD_LABELSECTOR   0
+#define BSD_LABELOFFSET   64
+#elif defined (__s390__) || defined (__s390x__)
+#define BSD_LABELSECTOR   1
+#define BSD_LABELOFFSET   0
+#else
+#error unknown architecture
+#endif
+
+#define BSD_BBSIZE        8192          /* size of boot area, with label */
+#define BSD_SBSIZE        8192          /* max size of fs superblock */
+
+struct xbsd_disklabel {
+	uint32_t   d_magic;                /* the magic number */
+	int16_t    d_type;                 /* drive type */
+	int16_t    d_subtype;              /* controller/d_type specific */
+	char       d_typename[16];         /* type name, e.g. "eagle" */
+	char       d_packname[16];                 /* pack identifier */
+			/* disk geometry: */
+	uint32_t   d_secsize;              /* # of bytes per sector */
+	uint32_t   d_nsectors;             /* # of data sectors per track */
+	uint32_t   d_ntracks;              /* # of tracks per cylinder */
+	uint32_t   d_ncylinders;           /* # of data cylinders per unit */
+	uint32_t   d_secpercyl;            /* # of data sectors per cylinder */
+	uint32_t   d_secperunit;           /* # of data sectors per unit */
+	/*
+	 * Spares (bad sector replacements) below
+	 * are not counted in d_nsectors or d_secpercyl.
+	 * Spare sectors are assumed to be physical sectors
+	 * which occupy space at the end of each track and/or cylinder.
+	 */
+	uint16_t   d_sparespertrack;       /* # of spare sectors per track */
+	uint16_t   d_sparespercyl;         /* # of spare sectors per cylinder */
+	/*
+	 * Alternate cylinders include maintenance, replacement,
+	 * configuration description areas, etc.
+	 */
+	uint32_t   d_acylinders;           /* # of alt. cylinders per unit */
+
+			/* hardware characteristics: */
+	/*
+	 * d_interleave, d_trackskew and d_cylskew describe perturbations
+	 * in the media format used to compensate for a slow controller.
+	 * Interleave is physical sector interleave, set up by the formatter
+	 * or controller when formatting.  When interleaving is in use,
+	 * logically adjacent sectors are not physically contiguous,
+	 * but instead are separated by some number of sectors.
+	 * It is specified as the ratio of physical sectors traversed
+	 * per logical sector.  Thus an interleave of 1:1 implies contiguous
+	 * layout, while 2:1 implies that logical sector 0 is separated
+	 * by one sector from logical sector 1.
+	 * d_trackskew is the offset of sector 0 on track N
+	 * relative to sector 0 on track N-1 on the same cylinder.
+	 * Finally, d_cylskew is the offset of sector 0 on cylinder N
+	 * relative to sector 0 on cylinder N-1.
+	 */
+	uint16_t   d_rpm;                  /* rotational speed */
+	uint16_t   d_interleave;           /* hardware sector interleave */
+	uint16_t   d_trackskew;            /* sector 0 skew, per track */
+	uint16_t   d_cylskew;              /* sector 0 skew, per cylinder */
+	uint32_t   d_headswitch;           /* head switch time, usec */
+	uint32_t   d_trkseek;              /* track-to-track seek, usec */
+	uint32_t   d_flags;                /* generic flags */
+#define NDDATA 5
+	uint32_t   d_drivedata[NDDATA];    /* drive-type specific information */
+#define NSPARE 5
+	uint32_t   d_spare[NSPARE];        /* reserved for future use */
+	uint32_t   d_magic2;               /* the magic number (again) */
+	uint16_t   d_checksum;             /* xor of data incl. partitions */
+			/* filesystem and partition information: */
+	uint16_t   d_npartitions;          /* number of partitions in following */
+	uint32_t   d_bbsize;               /* size of boot area at sn0, bytes */
+	uint32_t   d_sbsize;               /* max size of fs superblock, bytes */
+	struct xbsd_partition    {      /* the partition table */
+		uint32_t   p_size;         /* number of sectors in partition */
+		uint32_t   p_offset;       /* starting sector */
+		uint32_t   p_fsize;        /* filesystem basic fragment size */
+		uint8_t    p_fstype;       /* filesystem type, see below */
+		uint8_t    p_frag;         /* filesystem fragments per block */
+		uint16_t   p_cpg;          /* filesystem cylinders per group */
+	} d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
+};
+
+/* d_type values: */
+#define BSD_DTYPE_SMD           1               /* SMD, XSMD; VAX hp/up */
+#define BSD_DTYPE_MSCP          2               /* MSCP */
+#define BSD_DTYPE_DEC           3               /* other DEC (rk, rl) */
+#define BSD_DTYPE_SCSI          4               /* SCSI */
+#define BSD_DTYPE_ESDI          5               /* ESDI interface */
+#define BSD_DTYPE_ST506         6               /* ST506 etc. */
+#define BSD_DTYPE_HPIB          7               /* CS/80 on HP-IB */
+#define BSD_DTYPE_HPFL          8               /* HP Fiber-link */
+#define BSD_DTYPE_FLOPPY        10              /* floppy */
+
+/* d_subtype values: */
+#define BSD_DSTYPE_INDOSPART    0x8             /* is inside dos partition */
+#define BSD_DSTYPE_DOSPART(s)   ((s) & 3)       /* dos partition number */
+#define BSD_DSTYPE_GEOMETRY     0x10            /* drive params in label */
+
+#ifdef DKTYPENAMES
+static const char * const xbsd_dktypenames[] = {
+	"unknown",
+	"SMD",
+	"MSCP",
+	"old DEC",
+	"SCSI",
+	"ESDI",
+	"ST506",
+	"HP-IB",
+	"HP-FL",
+	"type 9",
+	"floppy",
+	0
+};
+#define BSD_DKMAXTYPES  (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
+#endif
+
+/*
+ * Filesystem type and version.
+ * Used to interpret other filesystem-specific
+ * per-partition information.
+ */
+#define BSD_FS_UNUSED   0               /* unused */
+#define BSD_FS_SWAP     1               /* swap */
+#define BSD_FS_V6       2               /* Sixth Edition */
+#define BSD_FS_V7       3               /* Seventh Edition */
+#define BSD_FS_SYSV     4               /* System V */
+#define BSD_FS_V71K     5               /* V7 with 1K blocks (4.1, 2.9) */
+#define BSD_FS_V8       6               /* Eighth Edition, 4K blocks */
+#define BSD_FS_BSDFFS   7               /* 4.2BSD fast file system */
+#define BSD_FS_BSDLFS   9               /* 4.4BSD log-structured file system */
+#define BSD_FS_OTHER    10              /* in use, but unknown/unsupported */
+#define BSD_FS_HPFS     11              /* OS/2 high-performance file system */
+#define BSD_FS_ISO9660  12              /* ISO-9660 filesystem (cdrom) */
+#define BSD_FS_ISOFS    BSD_FS_ISO9660
+#define BSD_FS_BOOT     13              /* partition contains bootstrap */
+#define BSD_FS_ADOS     14              /* AmigaDOS fast file system */
+#define BSD_FS_HFS      15              /* Macintosh HFS */
+#define BSD_FS_ADVFS    16              /* Digital Unix AdvFS */
+
+/* this is annoying, but it's also the way it is :-( */
+#ifdef __alpha__
+#define BSD_FS_EXT2     8               /* ext2 file system */
+#else
+#define BSD_FS_MSDOS    8               /* MS-DOS file system */
+#endif
+
+#ifdef  DKTYPENAMES
+static const struct systypes xbsd_fstypes[] = {
+	{ "\x00" "unused" },            /* BSD_FS_UNUSED  */
+	{ "\x01" "swap" },              /* BSD_FS_SWAP    */
+	{ "\x02" "Version 6" },         /* BSD_FS_V6      */
+	{ "\x03" "Version 7" },         /* BSD_FS_V7      */
+	{ "\x04" "System V" },          /* BSD_FS_SYSV    */
+	{ "\x05" "4.1BSD" },            /* BSD_FS_V71K    */
+	{ "\x06" "Eighth Edition" },    /* BSD_FS_V8      */
+	{ "\x07" "4.2BSD" },            /* BSD_FS_BSDFFS  */
+#ifdef __alpha__
+	{ "\x08" "ext2" },              /* BSD_FS_EXT2    */
+#else
+	{ "\x08" "MS-DOS" },            /* BSD_FS_MSDOS   */
+#endif
+	{ "\x09" "4.4LFS" },            /* BSD_FS_BSDLFS  */
+	{ "\x0a" "unknown" },           /* BSD_FS_OTHER   */
+	{ "\x0b" "HPFS" },              /* BSD_FS_HPFS    */
+	{ "\x0c" "ISO-9660" },          /* BSD_FS_ISO9660 */
+	{ "\x0d" "boot" },              /* BSD_FS_BOOT    */
+	{ "\x0e" "ADOS" },              /* BSD_FS_ADOS    */
+	{ "\x0f" "HFS" },               /* BSD_FS_HFS     */
+	{ "\x10" "AdvFS" },             /* BSD_FS_ADVFS   */
+	{ NULL }
+};
+#define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
+
+#endif
+
+/*
+ * flags shared by various drives:
+ */
+#define BSD_D_REMOVABLE 0x01            /* removable media */
+#define BSD_D_ECC       0x02            /* supports ECC */
+#define BSD_D_BADSECT   0x04            /* supports bad sector forw. */
+#define BSD_D_RAMDISK   0x08            /* disk emulator */
+#define BSD_D_CHAIN     0x10            /* can do back-back transfers */
+#define BSD_D_DOSPART   0x20            /* within MSDOS partition */
+
+#endif /* OSF_LABEL */
+
+/*
+ * Copyright (C) Andreas Neuper, Sep 1998.
+ *      This file may be modified and redistributed under
+ *      the terms of the GNU Public License.
+ */
+
+struct device_parameter { /* 48 bytes */
+	unsigned char  skew;
+	unsigned char  gap1;
+	unsigned char  gap2;
+	unsigned char  sparecyl;
+	unsigned short pcylcount;
+	unsigned short head_vol0;
+	unsigned short ntrks;   /* tracks in cyl 0 or vol 0 */
+	unsigned char  cmd_tag_queue_depth;
+	unsigned char  unused0;
+	unsigned short unused1;
+	unsigned short nsect;   /* sectors/tracks in cyl 0 or vol 0 */
+	unsigned short bytes;
+	unsigned short ilfact;
+	unsigned int   flags;           /* controller flags */
+	unsigned int   datarate;
+	unsigned int   retries_on_error;
+	unsigned int   ms_per_word;
+	unsigned short xylogics_gap1;
+	unsigned short xylogics_syncdelay;
+	unsigned short xylogics_readdelay;
+	unsigned short xylogics_gap2;
+	unsigned short xylogics_readgate;
+	unsigned short xylogics_writecont;
+};
+
+#define SGI_VOLHDR      0x00
+/* 1 and 2 were used for drive types no longer supported by SGI */
+#define SGI_SWAP        0x03
+/* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
+#define SGI_VOLUME      0x06
+#define SGI_EFS         0x07
+#define SGI_LVOL        0x08
+#define SGI_RLVOL       0x09
+#define SGI_XFS         0x0a
+#define SGI_XFSLOG      0x0b
+#define SGI_XLV         0x0c
+#define SGI_XVM         0x0d
+#define ENTIRE_DISK     SGI_VOLUME
+/*
+ * controller flags
+ */
+#define SECTOR_SLIP     0x01
+#define SECTOR_FWD      0x02
+#define TRACK_FWD       0x04
+#define TRACK_MULTIVOL  0x08
+#define IGNORE_ERRORS   0x10
+#define RESEEK          0x20
+#define ENABLE_CMDTAGQ  0x40
+
+typedef struct {
+	unsigned int   magic;            /* expect SGI_LABEL_MAGIC */
+	unsigned short boot_part;        /* active boot partition */
+	unsigned short swap_part;        /* active swap partition */
+	unsigned char  boot_file[16];    /* name of the bootfile */
+	struct device_parameter devparam;       /*  1 * 48 bytes */
+	struct volume_directory {               /* 15 * 16 bytes */
+		unsigned char vol_file_name[8]; /* a character array */
+		unsigned int  vol_file_start;   /* number of logical block */
+		unsigned int  vol_file_size;    /* number of bytes */
+	} directory[15];
+	struct sgi_partition {                  /* 16 * 12 bytes */
+		unsigned int num_sectors;       /* number of blocks */
+		unsigned int start_sector;      /* must be cylinder aligned */
+		unsigned int id;
+	} partitions[16];
+	unsigned int   csum;
+	unsigned int   fillbytes;
+} sgi_partition;
+
+typedef struct {
+	unsigned int   magic;           /* looks like a magic number */
+	unsigned int   a2;
+	unsigned int   a3;
+	unsigned int   a4;
+	unsigned int   b1;
+	unsigned short b2;
+	unsigned short b3;
+	unsigned int   c[16];
+	unsigned short d[3];
+	unsigned char  scsi_string[50];
+	unsigned char  serial[137];
+	unsigned short check1816;
+	unsigned char  installer[225];
+} sgiinfo;
+
+#define SGI_LABEL_MAGIC         0x0be5a941
+#define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
+#define SGI_INFO_MAGIC          0x00072959
+#define SGI_INFO_MAGIC_SWAPPED  0x59290700
+#define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
+				 : (uint16_t)(x))
+#define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
+				 : (uint32_t)(x))
+
+#define sgilabel ((sgi_partition *)MBRbuffer)
+#define sgiparam (sgilabel->devparam)
+
+typedef struct {
+	unsigned char info[128];   /* Informative text string */
+	unsigned char spare0[14];
+	struct sun_info {
+		unsigned char spare1;
+		unsigned char id;
+		unsigned char spare2;
+		unsigned char flags;
+	} infos[8];
+	unsigned char spare1[246]; /* Boot information etc. */
+	unsigned short rspeed;     /* Disk rotational speed */
+	unsigned short pcylcount;  /* Physical cylinder count */
+	unsigned short sparecyl;   /* extra sects per cylinder */
+	unsigned char spare2[4];   /* More magic... */
+	unsigned short ilfact;     /* Interleave factor */
+	unsigned short ncyl;       /* Data cylinder count */
+	unsigned short nacyl;      /* Alt. cylinder count */
+	unsigned short ntrks;      /* Tracks per cylinder */
+	unsigned short nsect;      /* Sectors per track */
+	unsigned char spare3[4];   /* Even more magic... */
+	struct sun_partition {
+		uint32_t start_cylinder;
+		uint32_t num_sectors;
+	} partitions[8];
+	unsigned short magic;      /* Magic number */
+	unsigned short csum;       /* Label xor'd checksum */
+} sun_partition;
+
+
+#define SUN_LABEL_MAGIC          0xDABE
+#define SUN_LABEL_MAGIC_SWAPPED  0xBEDA
+#define sunlabel ((sun_partition *)MBRbuffer)
+#define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
+				 : (uint16_t)(x))
+#define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
+				 : (uint32_t)(x))
+
+
+#ifdef CONFIG_FEATURE_OSF_LABEL
+/*
+   Changes:
+   19990319 - Arnaldo Carvalho de Melo <acme at conectiva.com.br> - i18n/nls
+
+   20000101 - David Huggins-Daines <dhuggins at linuxcare.com> - Better
+   support for OSF/1 disklabels on Alpha.
+   Also fixed unaligned accesses in alpha_bootblock_checksum()
+*/
+
+#define FREEBSD_PARTITION       0xa5
+#define NETBSD_PARTITION        0xa9
+
+static void xbsd_delete_part(void);
+static void xbsd_new_part(void);
+static void xbsd_write_disklabel(void);
+static int xbsd_create_disklabel(void);
+static void xbsd_edit_disklabel(void);
+static void xbsd_write_bootstrap(void);
+static void xbsd_change_fstype(void);
+static int xbsd_get_part_index(int max);
+static int xbsd_check_new_partition(int *i);
+static void xbsd_list_types(void);
+static u_short xbsd_dkcksum(struct xbsd_disklabel *lp);
+static int xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d);
+static int xbsd_readlabel(struct partition *p, struct xbsd_disklabel *d);
+static int xbsd_writelabel(struct partition *p, struct xbsd_disklabel *d);
+
+#if defined (__alpha__)
+static void alpha_bootblock_checksum(char *boot);
+#endif
+
+#if !defined (__alpha__)
+static int xbsd_translate_fstype(int linux_type);
+static void xbsd_link_part(void);
+static struct partition *xbsd_part;
+static int xbsd_part_index;
+#endif
+
+#if defined (__alpha__)
+/* We access this through a uint64_t * when checksumming */
+static char disklabelbuffer[BSD_BBSIZE] ATTRIBUTE_ALIGNED(8);
+#else
+static char disklabelbuffer[BSD_BBSIZE];
+#endif
+
+static struct xbsd_disklabel xbsd_dlabel;
+
+#define bsd_cround(n) \
+	(display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
+
+/*
+ * Test whether the whole disk has BSD disk label magic.
+ *
+ * Note: often reformatting with DOS-type label leaves the BSD magic,
+ * so this does not mean that there is a BSD disk label.
+ */
+static int
+check_osf_label(void)
+{
+	if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
+		return 0;
+	return 1;
+}
+
+static void xbsd_print_disklabel(int);
+
+static int
+btrydev(const char * dev)
+{
+	if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
+		return -1;
+	printf(_("\nBSD label for device: %s\n"), dev);
+	xbsd_print_disklabel (0);
+	return 0;
+}
+
+static void
+bmenu(void)
+{
+	puts (_("Command action"));
+	puts (_("\td\tdelete a BSD partition"));
+	puts (_("\te\tedit drive data"));
+	puts (_("\ti\tinstall bootstrap"));
+	puts (_("\tl\tlist known filesystem types"));
+	puts (_("\tm\tprint this menu"));
+	puts (_("\tn\tadd a new BSD partition"));
+	puts (_("\tp\tprint BSD partition table"));
+	puts (_("\tq\tquit without saving changes"));
+	puts (_("\tr\treturn to main menu"));
+	puts (_("\ts\tshow complete disklabel"));
+	puts (_("\tt\tchange a partition's filesystem id"));
+	puts (_("\tu\tchange units (cylinders/sectors)"));
+	puts (_("\tw\twrite disklabel to disk"));
+#if !defined (__alpha__)
+	puts (_("\tx\tlink BSD partition to non-BSD partition"));
+#endif
+}
+
+#if !defined (__alpha__)
+static int
+hidden(int type)
+{
+	return type ^ 0x10;
+}
+
+static int
+is_bsd_partition_type(int type)
+{
+	return (type == FREEBSD_PARTITION ||
+		type == hidden(FREEBSD_PARTITION) ||
+		type == NETBSD_PARTITION ||
+		type == hidden(NETBSD_PARTITION));
+}
+#endif
+
+static void
+bselect(void)
+{
+#if !defined (__alpha__)
+	int t, ss;
+	struct partition *p;
+
+	for (t = 0; t < 4; t++) {
+		p = get_part_table(t);
+		if (p && is_bsd_partition_type(p->sys_ind)) {
+			xbsd_part = p;
+			xbsd_part_index = t;
+			ss = get_start_sect(xbsd_part);
+			if (ss == 0) {
+				fprintf(stderr, _("Partition %s has invalid starting sector 0.\n"),
+					partname(disk_device, t+1, 0));
+				return;
+			}
+				printf(_("Reading disklabel of %s at sector %d.\n"),
+					partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
+			if (xbsd_readlabel(xbsd_part, &xbsd_dlabel) == 0)
+				if (xbsd_create_disklabel() == 0)
+					return;
+				break;
+		}
+	}
+
+	if (t == 4) {
+		printf(_("There is no *BSD partition on %s.\n"), disk_device);
+		return;
+	}
+
+#elif defined (__alpha__)
+
+	if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
+		if (xbsd_create_disklabel() == 0)
+			exit (EXIT_SUCCESS);
+
+#endif
+
+	while (1) {
+		putchar('\n');
+		switch (tolower(read_char(_("BSD disklabel command (m for help): ")))) {
+		case 'd':
+			xbsd_delete_part();
+			break;
+		case 'e':
+			xbsd_edit_disklabel();
+			break;
+		case 'i':
+			xbsd_write_bootstrap();
+			break;
+		case 'l':
+			xbsd_list_types();
+			break;
+		case 'n':
+			xbsd_new_part();
+			break;
+		case 'p':
+			xbsd_print_disklabel(0);
+			break;
+		case 'q':
+			close(fd);
+			exit(EXIT_SUCCESS);
+		case 'r':
+			return;
+		case 's':
+			xbsd_print_disklabel(1);
+			break;
+		case 't':
+			xbsd_change_fstype();
+			break;
+		case 'u':
+			change_units();
+			break;
+		case 'w':
+			xbsd_write_disklabel();
+			break;
+#if !defined (__alpha__)
+		case 'x':
+			xbsd_link_part();
+			break;
+#endif
+		default:
+			bmenu();
+			break;
+		}
+	}
+}
+
+static void
+xbsd_delete_part(void)
+{
+	int i;
+
+	i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
+	xbsd_dlabel.d_partitions[i].p_size   = 0;
+	xbsd_dlabel.d_partitions[i].p_offset = 0;
+	xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
+	if (xbsd_dlabel.d_npartitions == i + 1)
+		while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
+			xbsd_dlabel.d_npartitions--;
+}
+
+static void
+xbsd_new_part(void)
+{
+	off_t begin, end;
+	char mesg[256];
+	int i;
+
+	if (!xbsd_check_new_partition(&i))
+		return;
+
+#if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
+	begin = get_start_sect(xbsd_part);
+	end = begin + get_nr_sects(xbsd_part) - 1;
+#else
+	begin = 0;
+	end = xbsd_dlabel.d_secperunit - 1;
+#endif
+
+	snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
+	begin = read_int(bsd_cround(begin), bsd_cround(begin), bsd_cround(end),
+		0, mesg);
+
+	if (display_in_cyl_units)
+		begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
+
+	snprintf(mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
+		str_units(SINGULAR));
+	end = read_int(bsd_cround (begin), bsd_cround (end), bsd_cround (end),
+		bsd_cround (begin), mesg);
+
+	if (display_in_cyl_units)
+		end = end * xbsd_dlabel.d_secpercyl - 1;
+
+	xbsd_dlabel.d_partitions[i].p_size   = end - begin + 1;
+	xbsd_dlabel.d_partitions[i].p_offset = begin;
+	xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
+}
+
+static void
+xbsd_print_disklabel(int show_all)
+{
+	struct xbsd_disklabel *lp = &xbsd_dlabel;
+	struct xbsd_partition *pp;
+	int i, j;
+
+	if (show_all) {
+#if defined (__alpha__)
+		printf("# %s:\n", disk_device);
+#else
+		printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
+#endif
+		if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
+			printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
+		else
+			printf(_("type: %d\n"), lp->d_type);
+		printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
+		printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
+		printf(_("flags:"));
+		if (lp->d_flags & BSD_D_REMOVABLE)
+			printf(_(" removable"));
+		if (lp->d_flags & BSD_D_ECC)
+			printf(_(" ecc"));
+		if (lp->d_flags & BSD_D_BADSECT)
+			printf(_(" badsect"));
+		printf("\n");
+		/* On various machines the fields of *lp are short/int/long */
+		/* In order to avoid problems, we cast them all to long. */
+		printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
+		printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
+		printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
+		printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
+		printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
+		printf(_("rpm: %d\n"), lp->d_rpm);
+		printf(_("interleave: %d\n"), lp->d_interleave);
+		printf(_("trackskew: %d\n"), lp->d_trackskew);
+		printf(_("cylinderskew: %d\n"), lp->d_cylskew);
+		printf(_("headswitch: %ld\t\t# milliseconds\n"),
+			(long) lp->d_headswitch);
+		printf(_("track-to-track seek: %ld\t# milliseconds\n"),
+			(long) lp->d_trkseek);
+		printf(_("drivedata: "));
+		for (i = NDDATA - 1; i >= 0; i--)
+			if (lp->d_drivedata[i])
+				break;
+		if (i < 0)
+			i = 0;
+		for (j = 0; j <= i; j++)
+			printf("%ld ", (long) lp->d_drivedata[j]);
+	}
+	printf(_("\n%d partitions:\n"), lp->d_npartitions);
+	printf(_("#       start       end      size     fstype   [fsize bsize   cpg]\n"));
+	pp = lp->d_partitions;
+	for (i = 0; i < lp->d_npartitions; i++, pp++) {
+		if (pp->p_size) {
+			if (display_in_cyl_units && lp->d_secpercyl) {
+				printf("  %c: %8ld%c %8ld%c %8ld%c  ",
+					'a' + i,
+					(long) pp->p_offset / lp->d_secpercyl + 1,
+					(pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
+					(long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl,
+					((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
+					(long) pp->p_size / lp->d_secpercyl,
+					(pp->p_size % lp->d_secpercyl) ? '*' : ' '
+				);
+			} else {
+				printf("  %c: %8ld  %8ld  %8ld   ",
+					'a' + i,
+					(long) pp->p_offset,
+					(long) pp->p_offset + pp->p_size - 1,
+					(long) pp->p_size
+				);
+			}
+
+			if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
+				printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
+			else
+				printf("%8x", pp->p_fstype);
+
+			switch (pp->p_fstype) {
+			case BSD_FS_UNUSED:
+				printf("    %5ld %5ld %5.5s ",
+					(long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
+				break;
+			case BSD_FS_BSDFFS:
+				printf("    %5ld %5ld %5d ",
+					(long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, pp->p_cpg);
+				break;
+			default:
+				printf("%22.22s", "");
+				break;
+			}
+			printf("\n");
+		}
+	}
+}
+
+static void
+xbsd_write_disklabel(void)
+{
+#if defined (__alpha__)
+	printf(_("Writing disklabel to %s.\n"), disk_device);
+	xbsd_writelabel(NULL, &xbsd_dlabel);
+#else
+	printf(_("Writing disklabel to %s.\n"),
+		partname(disk_device, xbsd_part_index + 1, 0));
+	xbsd_writelabel(xbsd_part, &xbsd_dlabel);
+#endif
+	reread_partition_table(0);      /* no exit yet */
+}
+
+static int
+xbsd_create_disklabel(void)
+{
+	char c;
+
+#if defined (__alpha__)
+	fprintf(stderr, _("%s contains no disklabel.\n"), disk_device);
+#else
+	fprintf(stderr, _("%s contains no disklabel.\n"),
+		partname(disk_device, xbsd_part_index + 1, 0));
+#endif
+
+	while (1) {
+		c = read_char(_("Do you want to create a disklabel? (y/n) "));
+		if (c == 'y' || c == 'Y') {
+			if (xbsd_initlabel(
+#if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
+	defined (__s390__) || defined (__s390x__)
+				NULL, &xbsd_dlabel
+#else
+				xbsd_part, &xbsd_dlabel/* not used, xbsd_part_index*/
+#endif
+				) == 1) {
+				xbsd_print_disklabel (1);
+				return 1;
+			} else
+				return 0;
+		} else if (c == 'n')
+			return 0;
+	}
+}
+
+static int
+edit_int(int def, char *mesg)
+{
+	do {
+		fputs(mesg, stdout);
+		printf(" (%d): ", def);
+		if (!read_line())
+			return def;
+	}
+	while (!isdigit(*line_ptr));	/* FIXME: ?!! */
+	return atoi(line_ptr);
+}
+
+static void
+xbsd_edit_disklabel(void)
+{
+	struct xbsd_disklabel *d;
+
+	d = &xbsd_dlabel;
+
+#if defined (__alpha__) || defined (__ia64__)
+	d->d_secsize    = (u_long) edit_int((u_long) d->d_secsize     ,_("bytes/sector"));
+	d->d_nsectors   = (u_long) edit_int((u_long) d->d_nsectors    ,_("sectors/track"));
+	d->d_ntracks    = (u_long) edit_int((u_long) d->d_ntracks     ,_("tracks/cylinder"));
+	d->d_ncylinders = (u_long) edit_int((u_long) d->d_ncylinders  ,_("cylinders"));
+#endif
+
+  /* d->d_secpercyl can be != d->d_nsectors * d->d_ntracks */
+	while (1) {
+		d->d_secpercyl = (u_long) edit_int((u_long) d->d_nsectors * d->d_ntracks,
+				_("sectors/cylinder"));
+		if (d->d_secpercyl <= d->d_nsectors * d->d_ntracks)
+			break;
+
+		printf(_("Must be <= sectors/track * tracks/cylinder (default).\n"));
+	}
+	d->d_rpm        = (u_short) edit_int((u_short) d->d_rpm       ,_("rpm"));
+	d->d_interleave = (u_short) edit_int((u_short) d->d_interleave,_("interleave"));
+	d->d_trackskew  = (u_short) edit_int((u_short) d->d_trackskew ,_("trackskew"));
+	d->d_cylskew    = (u_short) edit_int((u_short) d->d_cylskew   ,_("cylinderskew"));
+	d->d_headswitch = (u_long) edit_int((u_long) d->d_headswitch  ,_("headswitch"));
+	d->d_trkseek    = (u_long) edit_int((u_long) d->d_trkseek     ,_("track-to-track seek"));
+
+	d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
+}
+
+static int
+xbsd_get_bootstrap (char *path, void *ptr, int size)
+{
+	int fdb;
+
+	if ((fdb = open (path, O_RDONLY)) < 0) {
+		perror(path);
+		return 0;
+	}
+	if (read(fdb, ptr, size) < 0) {
+		perror(path);
+		close(fdb);
+		return 0;
+	}
+	printf(" ... %s\n", path);
+	close(fdb);
+	return 1;
+}
+
+static void
+sync_disks(void)
+{
+	printf(_("\nSyncing disks.\n"));
+	sync();
+	sleep(4); /* What? */
+}
+
+static void
+xbsd_write_bootstrap(void)
+{
+	char *bootdir = BSD_LINUX_BOOTDIR;
+	char path[MAXPATHLEN];
+	char *dkbasename;
+	struct xbsd_disklabel dl;
+	char *d, *p, *e;
+	int sector;
+
+	if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
+		dkbasename = "sd";
+	else
+		dkbasename = "wd";
+
+	printf(_("Bootstrap: %sboot -> boot%s (%s): "),
+		dkbasename, dkbasename, dkbasename);
+	if (read_line()) {
+		line_ptr[strlen(line_ptr)-1] = '\0';
+		dkbasename = line_ptr;
+	}
+	snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
+	if (!xbsd_get_bootstrap(path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
+		return;
+
+/* We need a backup of the disklabel (xbsd_dlabel might have changed). */
+	d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
+	memmove(&dl, d, sizeof(struct xbsd_disklabel));
+
+/* The disklabel will be overwritten by 0's from bootxx anyway */
+	memset(d, 0, sizeof(struct xbsd_disklabel));
+
+	snprintf(path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
+	if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
+			  (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
+		return;
+
+	e = d + sizeof(struct xbsd_disklabel);
+	for (p = d; p < e; p++)
+		if (*p) {
+			fprintf(stderr, _("Bootstrap overlaps with disk label!\n"));
+			exit(EXIT_FAILURE);
+		}
+
+	memmove(d, &dl, sizeof(struct xbsd_disklabel));
+
+#if defined (__powerpc__) || defined (__hppa__)
+	sector = 0;
+#elif defined (__alpha__)
+	sector = 0;
+	alpha_bootblock_checksum(disklabelbuffer);
+#else
+	sector = get_start_sect(xbsd_part);
+#endif
+
+	if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
+		fdisk_fatal(unable_to_seek);
+	if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
+		fdisk_fatal(unable_to_write);
+
+#if defined (__alpha__)
+	printf(_("Bootstrap installed on %s.\n"), disk_device);
+#else
+	printf(_("Bootstrap installed on %s.\n"),
+		partname (disk_device, xbsd_part_index+1, 0));
+#endif
+
+	sync_disks();
+}
+
+static void
+xbsd_change_fstype(void)
+{
+	int i;
+
+	i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
+	xbsd_dlabel.d_partitions[i].p_fstype = read_hex(xbsd_fstypes);
+}
+
+static int
+xbsd_get_part_index(int max)
+{
+	char prompt[256];
+	char l;
+
+	snprintf(prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
+	do
+			l = tolower(read_char(prompt));
+	while (l < 'a' || l > 'a' + max - 1);
+	return l - 'a';
+}
+
+static int
+xbsd_check_new_partition(int *i)
+{
+	/* room for more? various BSD flavours have different maxima */
+	if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
+		int t;
+
+		for (t = 0; t < BSD_MAXPARTITIONS; t++)
+			if (xbsd_dlabel.d_partitions[t].p_size == 0)
+				break;
+
+		if (t == BSD_MAXPARTITIONS) {
+			fprintf(stderr, _("The maximum number of partitions "
+					   "has been created\n"));
+			return 0;
+		}
+	}
+
+	*i = xbsd_get_part_index (BSD_MAXPARTITIONS);
+
+	if (*i >= xbsd_dlabel.d_npartitions)
+		xbsd_dlabel.d_npartitions = (*i) + 1;
+
+	if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
+		fprintf(stderr, _("This partition already exists.\n"));
+		return 0;
+	}
+
+	return 1;
+}
+
+static void
+xbsd_list_types(void)
+{
+	list_types(xbsd_fstypes);
+}
+
+static u_short
+xbsd_dkcksum(struct xbsd_disklabel *lp)
+{
+	u_short *start, *end;
+	u_short sum = 0;
+
+	start = (u_short *) lp;
+	end = (u_short *) &lp->d_partitions[lp->d_npartitions];
+	while (start < end)
+		sum ^= *start++;
+	return sum;
+}
+
+static int
+xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d)
+{
+	struct xbsd_partition *pp;
+
+	get_geometry();
+	memset(d, 0, sizeof(struct xbsd_disklabel));
+
+	d->d_magic = BSD_DISKMAGIC;
+
+	if (strncmp(disk_device, "/dev/sd", 7) == 0)
+		d->d_type = BSD_DTYPE_SCSI;
+	else
+		d->d_type = BSD_DTYPE_ST506;
+
+#if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
+	d->d_subtype = BSD_DSTYPE_INDOSPART & pindex;
+#endif
+
+#if !defined (__alpha__)
+	d->d_flags = BSD_D_DOSPART;
+#else
+	d->d_flags = 0;
+#endif
+	d->d_secsize = SECTOR_SIZE;           /* bytes/sector  */
+	d->d_nsectors = sectors;            /* sectors/track */
+	d->d_ntracks = heads;               /* tracks/cylinder (heads) */
+	d->d_ncylinders = cylinders;
+	d->d_secpercyl  = sectors * heads;/* sectors/cylinder */
+	if (d->d_secpercyl == 0)
+		d->d_secpercyl = 1;           /* avoid segfaults */
+	d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
+
+	d->d_rpm = 3600;
+	d->d_interleave = 1;
+	d->d_trackskew = 0;
+	d->d_cylskew = 0;
+	d->d_headswitch = 0;
+	d->d_trkseek = 0;
+
+	d->d_magic2 = BSD_DISKMAGIC;
+	d->d_bbsize = BSD_BBSIZE;
+	d->d_sbsize = BSD_SBSIZE;
+
+#if !defined (__alpha__)
+	d->d_npartitions = 4;
+	pp = &d->d_partitions[2];             /* Partition C should be
+						   the NetBSD partition */
+	pp->p_offset = get_start_sect(p);
+	pp->p_size   = get_nr_sects(p);
+	pp->p_fstype = BSD_FS_UNUSED;
+	pp = &d->d_partitions[3];             /* Partition D should be
+						   the whole disk */
+	pp->p_offset = 0;
+	pp->p_size   = d->d_secperunit;
+	pp->p_fstype = BSD_FS_UNUSED;
+#elif defined (__alpha__)
+	d->d_npartitions = 3;
+	pp = &d->d_partitions[2];             /* Partition C should be
+						   the whole disk */
+	pp->p_offset = 0;
+	pp->p_size   = d->d_secperunit;
+	pp->p_fstype = BSD_FS_UNUSED;
+#endif
+
+	return 1;
+}
+
+/*
+ * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
+ * If it has the right magic, return 1.
+ */
+static int
+xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
+{
+	int t, sector;
+
+	/* p is used only to get the starting sector */
+#if !defined (__alpha__)
+	sector = (p ? get_start_sect(p) : 0);
+#elif defined (__alpha__)
+	sector = 0;
+#endif
+
+	if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
+		fdisk_fatal(unable_to_seek);
+	if (BSD_BBSIZE != read(fd, disklabelbuffer, BSD_BBSIZE))
+		fdisk_fatal(unable_to_read);
+
+	memmove(d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
+		   sizeof(struct xbsd_disklabel));
+
+	if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC)
+		return 0;
+
+	for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) {
+		d->d_partitions[t].p_size   = 0;
+		d->d_partitions[t].p_offset = 0;
+		d->d_partitions[t].p_fstype = BSD_FS_UNUSED;
+	}
+
+	if (d->d_npartitions > BSD_MAXPARTITIONS)
+		fprintf(stderr, _("Warning: too many partitions "
+				"(%d, maximum is %d).\n"),
+			d->d_npartitions, BSD_MAXPARTITIONS);
+	return 1;
+}
+
+static int
+xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
+{
+	unsigned int sector;
+
+#if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
+	sector = get_start_sect(p) + BSD_LABELSECTOR;
+#else
+	sector = BSD_LABELSECTOR;
+#endif
+
+	d->d_checksum = 0;
+	d->d_checksum = xbsd_dkcksum (d);
+
+	/* This is necessary if we want to write the bootstrap later,
+	   otherwise we'd write the old disklabel with the bootstrap.
+	*/
+	memmove(&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
+		d, sizeof(struct xbsd_disklabel));
+
+#if defined (__alpha__) && BSD_LABELSECTOR == 0
+	alpha_bootblock_checksum (disklabelbuffer);
+	if (lseek(fd, 0, SEEK_SET) == -1)
+		fdisk_fatal(unable_to_seek);
+	if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
+		fdisk_fatal(unable_to_write);
+#else
+	if (lseek(fd, sector * SECTOR_SIZE + BSD_LABELOFFSET, SEEK_SET) == -1)
+		fdisk_fatal(unable_to_seek);
+	if (sizeof(struct xbsd_disklabel) != write(fd, d, sizeof(struct xbsd_disklabel)))
+		fdisk_fatal(unable_to_write);
+#endif
+	sync_disks();
+	return 1;
+}
+
+
+#if !defined (__alpha__)
+static int
+xbsd_translate_fstype(int linux_type)
+{
+	switch (linux_type) {
+	case 0x01: /* DOS 12-bit FAT   */
+	case 0x04: /* DOS 16-bit <32M  */
+	case 0x06: /* DOS 16-bit >=32M */
+	case 0xe1: /* DOS access       */
+	case 0xe3: /* DOS R/O          */
+	case 0xf2: /* DOS secondary    */
+		return BSD_FS_MSDOS;
+	case 0x07: /* OS/2 HPFS        */
+		return BSD_FS_HPFS;
+	default:
+		return BSD_FS_OTHER;
+	}
+}
+
+static void
+xbsd_link_part(void)
+{
+	int k, i;
+	struct partition *p;
+
+	k = get_partition(1, partitions);
+
+	if (!xbsd_check_new_partition(&i))
+		return;
+
+	p = get_part_table(k);
+
+	xbsd_dlabel.d_partitions[i].p_size   = get_nr_sects(p);
+	xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
+	xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
+}
+#endif
+
+#if defined (__alpha__)
+
+#if !defined(__GLIBC__)
+typedef unsigned long long uint64_t;
+#endif
+
+static void
+alpha_bootblock_checksum(char *boot)
+{
+	uint64_t *dp, sum;
+	int i;
+
+	dp = (uint64_t *)boot;
+	sum = 0;
+	for (i = 0; i < 63; i++)
+		sum += dp[i];
+	dp[63] = sum;
+}
+#endif /* __alpha__ */
+
+#endif /* OSF_LABEL */
+
+#if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
+static inline unsigned short
+__swap16(unsigned short x)
+{
+	return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
+}
+
+static inline uint32_t
+__swap32(uint32_t x)
+{
+	return (((x & 0xFF) << 24) |
+		((x & 0xFF00) << 8) |
+		((x & 0xFF0000) >> 8) |
+		((x & 0xFF000000) >> 24));
+}
+#endif
+
+#ifdef CONFIG_FEATURE_SGI_LABEL
+/*
+ *
+ * fdisksgilabel.c
+ *
+ * Copyright (C) Andreas Neuper, Sep 1998.
+ *      This file may be modified and redistributed under
+ *      the terms of the GNU Public License.
+ *
+ * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme at conectiva.com.br>
+ *      Internationalization
+ */
+
+
+static int sgi_other_endian;
+static int debug;
+static short sgi_volumes = 1;
+
+/*
+ * only dealing with free blocks here
+ */
+
+typedef struct {
+	unsigned int first;
+	unsigned int last;
+} freeblocks;
+static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
+
+static void
+setfreelist(int i, unsigned int f, unsigned int l)
+{
+	freelist[i].first = f;
+	freelist[i].last = l;
+}
+
+static void
+add2freelist(unsigned int f, unsigned int l)
+{
+	int i;
+	for (i = 0; i < 17 ; i++)
+		if (freelist[i].last == 0)
+			break;
+	setfreelist(i, f, l);
+}
+
+static void
+clearfreelist(void)
+{
+	int i;
+
+	for (i = 0; i < 17 ; i++)
+		setfreelist(i, 0, 0);
+}
+
+static unsigned int
+isinfreelist(unsigned int b)
+{
+	int i;
+
+	for (i = 0; i < 17 ; i++)
+		if (freelist[i].first <= b && freelist[i].last >= b)
+			return freelist[i].last;
+	return 0;
+}
+	/* return last vacant block of this stride (never 0). */
+	/* the '>=' is not quite correct, but simplifies the code */
+/*
+ * end of free blocks section
+ */
+
+static const struct systypes sgi_sys_types[] = {
+/* SGI_VOLHDR   */	{ "\x00" "SGI volhdr"   },
+/* 0x01         */	{ "\x01" "SGI trkrepl"  },
+/* 0x02         */	{ "\x02" "SGI secrepl"  },
+/* SGI_SWAP     */	{ "\x03" "SGI raw"      },
+/* 0x04         */	{ "\x04" "SGI bsd"      },
+/* 0x05         */	{ "\x05" "SGI sysv"     },
+/* ENTIRE_DISK  */	{ "\x06" "SGI volume"   },
+/* SGI_EFS      */	{ "\x07" "SGI efs"      },
+/* 0x08         */	{ "\x08" "SGI lvol"     },
+/* 0x09         */	{ "\x09" "SGI rlvol"    },
+/* SGI_XFS      */	{ "\x0a" "SGI xfs"      },
+/* SGI_XFSLOG   */	{ "\x0b" "SGI xfslog"   },
+/* SGI_XLV      */	{ "\x0c" "SGI xlv"      },
+/* SGI_XVM      */	{ "\x0d" "SGI xvm"      },
+/* LINUX_SWAP   */	{ "\x82" "Linux swap"   },
+/* LINUX_NATIVE */	{ "\x83" "Linux native" },
+/* LINUX_LVM    */	{ "\x8d" "Linux LVM"    },
+/* LINUX_RAID   */	{ "\xfd" "Linux RAID"   },
+			{ NULL             }
+};
+
+
+static int
+sgi_get_nsect(void)
+{
+	return SGI_SSWAP16(sgilabel->devparam.nsect);
+}
+
+static int
+sgi_get_ntrks(void)
+{
+	return SGI_SSWAP16(sgilabel->devparam.ntrks);
+}
+
+static unsigned int
+two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */)
+{
+	int i = 0;
+	unsigned int sum = 0;
+
+	size /= sizeof(unsigned int);
+	for (i = 0; i < size; i++)
+		sum -= SGI_SSWAP32(base[i]);
+	return sum;
+}
+
+static int
+check_sgi_label(void)
+{
+	if (sizeof(sgilabel) > 512) {
+		fprintf(stderr,
+			_("According to MIPS Computer Systems, Inc the "
+			"Label must not contain more than 512 bytes\n"));
+		exit(1);
+	}
+
+	if (sgilabel->magic != SGI_LABEL_MAGIC
+	 && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
+		current_label_type = label_dos;
+		return 0;
+	}
+
+	sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
+	/*
+	 * test for correct checksum
+	 */
+	if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
+				sizeof(*sgilabel))) {
+		fprintf(stderr,
+			_("Detected sgi disklabel with wrong checksum.\n"));
+	}
+	update_units();
+	current_label_type = label_sgi;
+	partitions = 16;
+	sgi_volumes = 15;
+	return 1;
+}
+
+static unsigned int
+sgi_get_start_sector(int i)
+{
+	return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
+}
+
+static unsigned int
+sgi_get_num_sectors(int i)
+{
+	return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
+}
+
+static int
+sgi_get_sysid(int i)
+{
+	return SGI_SSWAP32(sgilabel->partitions[i].id);
+}
+
+static int
+sgi_get_bootpartition(void)
+{
+	return SGI_SSWAP16(sgilabel->boot_part);
+}
+
+static int
+sgi_get_swappartition(void)
+{
+	return SGI_SSWAP16(sgilabel->swap_part);
+}
+
+static void
+sgi_list_table(int xtra)
+{
+	int i, w, wd;
+	int kpi = 0;                /* kernel partition ID */
+
+	if(xtra) {
+		printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
+			"%d cylinders, %d physical cylinders\n"
+			"%d extra sects/cyl, interleave %d:1\n"
+			"%s\n"
+			"Units = %s of %d * 512 bytes\n\n"),
+			disk_device, heads, sectors, cylinders,
+			SGI_SSWAP16(sgiparam.pcylcount),
+			SGI_SSWAP16(sgiparam.sparecyl),
+			SGI_SSWAP16(sgiparam.ilfact),
+			(char *)sgilabel,
+			str_units(PLURAL), units_per_sector);
+	} else {
+		printf( _("\nDisk %s (SGI disk label): "
+			"%d heads, %d sectors, %d cylinders\n"
+			"Units = %s of %d * 512 bytes\n\n"),
+			disk_device, heads, sectors, cylinders,
+			str_units(PLURAL), units_per_sector );
+	}
+
+	w = strlen(disk_device);
+	wd = strlen(_("Device"));
+	if (w < wd)
+	w = wd;
+
+	printf(_("----- partitions -----\n"
+		"Pt# %*s  Info     Start       End   Sectors  Id  System\n"),
+		w + 2, _("Device"));
+	for (i = 0 ; i < partitions; i++) {
+		if( sgi_get_num_sectors(i) || debug ) {
+			uint32_t start = sgi_get_start_sector(i);
+			uint32_t len = sgi_get_num_sectors(i);
+			kpi++;              /* only count nonempty partitions */
+			printf(
+			"%2d: %s %4s %9ld %9ld %9ld  %2x  %s\n",
+/* fdisk part number */	i+1,
+/* device */            partname(disk_device, kpi, w+3),
+/* flags */             (sgi_get_swappartition() == i) ? "swap" :
+/* flags */             (sgi_get_bootpartition() == i) ? "boot" : "    ",
+/* start */             (long) scround(start),
+/* end */               (long) scround(start+len)-1,
+/* no odd flag on end */(long) len,
+/* type id */           sgi_get_sysid(i),
+/* type name */         partition_type(sgi_get_sysid(i)));
+		}
+	}
+	printf(_("----- Bootinfo -----\nBootfile: %s\n"
+		"----- Directory Entries -----\n"),
+		sgilabel->boot_file);
+	for (i = 0 ; i < sgi_volumes; i++) {
+		if (sgilabel->directory[i].vol_file_size) {
+			uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
+			uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
+			unsigned char *name = sgilabel->directory[i].vol_file_name;
+
+			printf(_("%2d: %-10s sector%5u size%8u\n"),
+				i, (char*)name, (unsigned int) start, (unsigned int) len);
+		}
+	}
+}
+
+static void
+sgi_set_bootpartition(int i)
+{
+	sgilabel->boot_part = SGI_SSWAP16(((short)i));
+}
+
+static unsigned int
+sgi_get_lastblock(void)
+{
+	return heads * sectors * cylinders;
+}
+
+static void
+sgi_set_swappartition(int i)
+{
+	sgilabel->swap_part = SGI_SSWAP16(((short)i));
+}
+
+static int
+sgi_check_bootfile(const char* aFile)
+{
+ 	if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
+ 		printf(_("\nInvalid Bootfile!\n"
+ 			"\tThe bootfile must be an absolute non-zero pathname,\n"
+			"\te.g. \"/unix\" or \"/unix.save\".\n"));
+		return 0;
+	} else {
+		if (strlen(aFile) > 16) {
+			printf(_("\n\tName of Bootfile too long:  "
+				"16 bytes maximum.\n"));
+			return 0;
+		} else {
+			if (aFile[0] != '/') {
+				printf(_("\n\tBootfile must have a "
+					"fully qualified pathname.\n"));
+				return 0;
+			}
+		}
+ 	}
+	if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
+		printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
+			 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
+		/* filename is correct and did change */
+		return 1;
+	}
+	return 0;   /* filename did not change */
+}
+
+static const char *
+sgi_get_bootfile(void)
+{
+	return (char*)sgilabel->boot_file;
+}
+
+static void
+sgi_set_bootfile(const char* aFile)
+{
+	int i = 0;
+
+	if (sgi_check_bootfile(aFile)) {
+		while (i < 16) {
+			if ((aFile[i] != '\n')  /* in principle caught again by next line */
+			 && (strlen(aFile) > i))
+				sgilabel->boot_file[i] = aFile[i];
+			else
+				sgilabel->boot_file[i] = 0;
+			i++;
+		}
+		printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
+	}
+}
+
+static void
+create_sgiinfo(void)
+{
+	/* I keep SGI's habit to write the sgilabel to the second block */
+	sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
+	sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
+	strcpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel");
+}
+
+static sgiinfo *fill_sgiinfo(void);
+
+static void
+sgi_write_table(void)
+{
+	sgilabel->csum = 0;
+	sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
+			(unsigned int*)sgilabel, sizeof(*sgilabel)));
+	assert(two_s_complement_32bit_sum(
+		(unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
+
+	if (lseek(fd, 0, SEEK_SET) < 0)
+		fdisk_fatal(unable_to_seek);
+	if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
+		fdisk_fatal(unable_to_write);
+	if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
+		/*
+		 * keep this habit of first writing the "sgilabel".
+		 * I never tested whether it works without (AN 981002).
+		 */
+		sgiinfo *info = fill_sgiinfo();
+		int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
+		if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
+			fdisk_fatal(unable_to_seek);
+		if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
+			fdisk_fatal(unable_to_write);
+		free(info);
+	}
+}
+
+static int
+compare_start(int *x, int *y)
+{
+	/*
+	 * sort according to start sectors
+	 * and prefers largest partition:
+	 * entry zero is entire disk entry
+	 */
+	unsigned int i = *x;
+	unsigned int j = *y;
+	unsigned int a = sgi_get_start_sector(i);
+	unsigned int b = sgi_get_start_sector(j);
+	unsigned int c = sgi_get_num_sectors(i);
+	unsigned int d = sgi_get_num_sectors(j);
+
+	if (a == b)
+		return (d > c) ? 1 : (d == c) ? 0 : -1;
+	return (a > b) ? 1 : -1;
+}
+
+
+static int
+verify_sgi(int verbose)
+{
+	int Index[16];      /* list of valid partitions */
+	int sortcount = 0;  /* number of used partitions, i.e. non-zero lengths */
+	int entire = 0, i = 0;
+	unsigned int start = 0;
+	long long gap = 0;      /* count unused blocks */
+	unsigned int lastblock = sgi_get_lastblock();
+
+	clearfreelist();
+	for (i = 0; i < 16; i++) {
+		if (sgi_get_num_sectors(i) != 0) {
+			Index[sortcount++] = i;
+			if (sgi_get_sysid(i) == ENTIRE_DISK) {
+				if (entire++ == 1) {
+					if (verbose)
+						printf(_("More than one entire disk entry present.\n"));
+				}
+			}
+		}
+	}
+	if (sortcount == 0) {
+		if (verbose)
+			printf(_("No partitions defined\n"));
+		return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
+	}
+	qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
+	if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
+		if ((Index[0] != 10) && verbose)
+			printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
+		if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
+			printf(_("The entire disk partition should start "
+				"at block 0,\n"
+				"not at diskblock %d.\n"),
+		sgi_get_start_sector(Index[0]));
+		if (debug)      /* I do not understand how some disks fulfil it */
+			if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
+				printf(_("The entire disk partition is only %d diskblock large,\n"
+					"but the disk is %d diskblocks long.\n"),
+		sgi_get_num_sectors(Index[0]), lastblock);
+		lastblock = sgi_get_num_sectors(Index[0]);
+	} else {
+		if (verbose)
+			printf(_("One Partition (#11) should cover the entire disk.\n"));
+		if (debug > 2)
+			printf("sysid=%d\tpartition=%d\n",
+				sgi_get_sysid(Index[0]), Index[0]+1);
+	}
+	for (i = 1, start = 0; i < sortcount; i++) {
+		int cylsize = sgi_get_nsect() * sgi_get_ntrks();
+
+		if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
+			if (debug)      /* I do not understand how some disks fulfil it */
+				if (verbose)
+					printf(_("Partition %d does not start on cylinder boundary.\n"),
+						Index[i]+1);
+		}
+		if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
+			if (debug)      /* I do not understand how some disks fulfil it */
+				if (verbose)
+					printf(_("Partition %d does not end on cylinder boundary.\n"),
+						Index[i]+1);
+		}
+		/* We cannot handle several "entire disk" entries. */
+		if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
+		if (start > sgi_get_start_sector(Index[i])) {
+			if (verbose)
+				printf(_("The Partition %d and %d overlap by %d sectors.\n"),
+					Index[i-1]+1, Index[i]+1,
+					start - sgi_get_start_sector(Index[i]));
+			if (gap >  0) gap = -gap;
+			if (gap == 0) gap = -1;
+		}
+		if (start < sgi_get_start_sector(Index[i])) {
+			if (verbose)
+				printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
+					sgi_get_start_sector(Index[i]) - start,
+					start, sgi_get_start_sector(Index[i])-1);
+			gap += sgi_get_start_sector(Index[i]) - start;
+			add2freelist(start, sgi_get_start_sector(Index[i]));
+		}
+		start = sgi_get_start_sector(Index[i])
+			   + sgi_get_num_sectors(Index[i]);
+		if (debug > 1) {
+			if (verbose)
+				printf("%2d:%12d\t%12d\t%12d\n", Index[i],
+					sgi_get_start_sector(Index[i]),
+					sgi_get_num_sectors(Index[i]),
+					sgi_get_sysid(Index[i]));
+		}
+	}
+	if (start < lastblock) {
+		if (verbose)
+			printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
+				lastblock - start, start, lastblock-1);
+		gap += lastblock - start;
+		add2freelist(start, lastblock);
+	}
+	/*
+	 * Done with arithmetics
+	 * Go for details now
+	 */
+	if (verbose) {
+		if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
+			printf(_("\nThe boot partition does not exist.\n"));
+		}
+		if (!sgi_get_num_sectors(sgi_get_swappartition())) {
+			printf(_("\nThe swap partition does not exist.\n"));
+		} else {
+			if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
+			 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
+				printf(_("\nThe swap partition has no swap type.\n"));
+		}
+		if (sgi_check_bootfile("/unix"))
+			printf(_("\tYou have chosen an unusual boot file name.\n"));
+	}
+	return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
+}
+
+static int
+sgi_gaps(void)
+{
+	/*
+	 * returned value is:
+	 *  = 0 : disk is properly filled to the rim
+	 *  < 0 : there is an overlap
+	 *  > 0 : there is still some vacant space
+	 */
+	return verify_sgi(0);
+}
+
+static void
+sgi_change_sysid(int i, int sys)
+{
+	if( sgi_get_num_sectors(i) == 0 ) { /* caught already before, ... */
+		printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
+		return;
+	}
+	if (((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
+	 && (sgi_get_start_sector(i) < 1) ) {
+		read_chars(
+			_("It is highly recommended that the partition at offset 0\n"
+			"is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
+			"retrieve from its directory standalone tools like sash and fx.\n"
+			"Only the \"SGI volume\" entire disk section may violate this.\n"
+			"Type YES if you are sure about tagging this partition differently.\n"));
+		if (strcmp(line_ptr, _("YES\n")))
+			return;
+	}
+	sgilabel->partitions[i].id = SGI_SSWAP32(sys);
+}
+
+/* returns partition index of first entry marked as entire disk */
+static int
+sgi_entire(void)
+{
+	int i;
+
+	for (i = 0; i < 16; i++)
+		if (sgi_get_sysid(i) == SGI_VOLUME)
+			return i;
+	return -1;
+}
+
+static void
+sgi_set_partition(int i, unsigned int start, unsigned int length, int sys)
+{
+	sgilabel->partitions[i].id = SGI_SSWAP32(sys);
+	sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
+	sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
+	set_changed(i);
+	if (sgi_gaps() < 0)     /* rebuild freelist */
+		printf(_("Do You know, You got a partition overlap on the disk?\n"));
+}
+
+static void
+sgi_set_entire(void)
+{
+	int n;
+
+	for (n = 10; n < partitions; n++) {
+		if(!sgi_get_num_sectors(n) ) {
+			sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
+			break;
+		}
+	}
+}
+
+static void
+sgi_set_volhdr(void)
+{
+	int n;
+
+	for (n = 8; n < partitions; n++) {
+	if (!sgi_get_num_sectors(n)) {
+		/*
+		 * 5 cylinders is an arbitrary value I like
+		 * IRIX 5.3 stored files in the volume header
+		 * (like sash, symmon, fx, ide) with ca. 3200
+		 * sectors.
+		 */
+		if (heads * sectors * 5 < sgi_get_lastblock())
+			sgi_set_partition(n, 0, heads * sectors * 5, SGI_VOLHDR);
+			break;
+		}
+	}
+}
+
+static void
+sgi_delete_partition(int i)
+{
+	sgi_set_partition(i, 0, 0, 0);
+}
+
+static void
+sgi_add_partition(int n, int sys)
+{
+	char mesg[256];
+	unsigned int first = 0, last = 0;
+
+	if (n == 10) {
+		sys = SGI_VOLUME;
+	} else if (n == 8) {
+		sys = 0;
+	}
+	if(sgi_get_num_sectors(n)) {
+		printf(_("Partition %d is already defined.  Delete "
+			"it before re-adding it.\n"), n + 1);
+		return;
+	}
+	if ((sgi_entire() == -1) && (sys != SGI_VOLUME)) {
+		printf(_("Attempting to generate entire disk entry automatically.\n"));
+		sgi_set_entire();
+		sgi_set_volhdr();
+	}
+	if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) {
+		printf(_("The entire disk is already covered with partitions.\n"));
+		return;
+	}
+	if (sgi_gaps() < 0) {
+		printf(_("You got a partition overlap on the disk. Fix it first!\n"));
+		return;
+	}
+	snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
+	while (1) {
+		if(sys == SGI_VOLUME) {
+			last = sgi_get_lastblock();
+			first = read_int(0, 0, last-1, 0, mesg);
+			if (first != 0) {
+				printf(_("It is highly recommended that eleventh partition\n"
+						"covers the entire disk and is of type `SGI volume'\n"));
+			}
+		} else {
+			first = freelist[0].first;
+			last  = freelist[0].last;
+			first = read_int(scround(first), scround(first), scround(last)-1,
+				0, mesg);
+		}
+		if (display_in_cyl_units)
+			first *= units_per_sector;
+		else
+			first = first; /* align to cylinder if you know how ... */
+		if(!last )
+			last = isinfreelist(first);
+		if(last == 0) {
+			printf(_("You will get a partition overlap on the disk. "
+				"Fix it first!\n"));
+		} else
+			break;
+	}
+	snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
+	last = read_int(scround(first), scround(last)-1, scround(last)-1,
+			scround(first), mesg)+1;
+	if (display_in_cyl_units)
+		last *= units_per_sector;
+	else
+		last = last; /* align to cylinder if You know how ... */
+	if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) )
+		printf(_("It is highly recommended that eleventh partition\n"
+			"covers the entire disk and is of type `SGI volume'\n"));
+	sgi_set_partition(n, first, last-first, sys);
+}
+
+#ifdef CONFIG_FEATURE_FDISK_ADVANCED
+static void
+create_sgilabel(void)
+{
+	struct hd_geometry geometry;
+	struct {
+		unsigned int start;
+		unsigned int nsect;
+		int sysid;
+	} old[4];
+	int i = 0;
+	long longsectors;               /* the number of sectors on the device */
+	int res;                        /* the result from the ioctl */
+	int sec_fac;                    /* the sector factor */
+
+	sec_fac = sector_size / 512;    /* determine the sector factor */
+
+	fprintf( stderr,
+		_("Building a new SGI disklabel. Changes will remain in memory only,\n"
+		"until you decide to write them. After that, of course, the previous\n"
+		"content will be unrecoverably lost.\n\n"));
+
+	sgi_other_endian = (BB_LITTLE_ENDIAN);
+	res = ioctl(fd, BLKGETSIZE, &longsectors);
+	if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
+		heads = geometry.heads;
+		sectors = geometry.sectors;
+		if (res == 0) {
+			/* the get device size ioctl was successful */
+			cylinders = longsectors / (heads * sectors);
+			cylinders /= sec_fac;
+		} else {
+			/* otherwise print error and use truncated version */
+			cylinders = geometry.cylinders;
+			fprintf(stderr,
+				_("Warning:  BLKGETSIZE ioctl failed on %s.  "
+				"Using geometry cylinder value of %d.\n"
+				"This value may be truncated for devices"
+				" > 33.8 GB.\n"), disk_device, cylinders);
+		}
+	}
+	for (i = 0; i < 4; i++) {
+		old[i].sysid = 0;
+		if (valid_part_table_flag(MBRbuffer)) {
+			if(get_part_table(i)->sys_ind) {
+				old[i].sysid = get_part_table(i)->sys_ind;
+				old[i].start = get_start_sect(get_part_table(i));
+				old[i].nsect = get_nr_sects(get_part_table(i));
+				printf(_("Trying to keep parameters of partition %d.\n"), i);
+				if (debug)
+					printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
+				old[i].sysid, old[i].start, old[i].nsect);
+			}
+		}
+	}
+
+	memset(MBRbuffer, 0, sizeof(MBRbuffer));
+	sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
+	sgilabel->boot_part = SGI_SSWAP16(0);
+	sgilabel->swap_part = SGI_SSWAP16(1);
+
+	/* sizeof(sgilabel->boot_file) = 16 > 6 */
+	memset(sgilabel->boot_file, 0, 16);
+	strcpy((char*)sgilabel->boot_file, "/unix");
+
+	sgilabel->devparam.skew                     = (0);
+	sgilabel->devparam.gap1                     = (0);
+	sgilabel->devparam.gap2                     = (0);
+	sgilabel->devparam.sparecyl                 = (0);
+	sgilabel->devparam.pcylcount                = SGI_SSWAP16(geometry.cylinders);
+	sgilabel->devparam.head_vol0                = SGI_SSWAP16(0);
+	sgilabel->devparam.ntrks                    = SGI_SSWAP16(geometry.heads);
+						/* tracks/cylinder (heads) */
+	sgilabel->devparam.cmd_tag_queue_depth      = (0);
+	sgilabel->devparam.unused0                  = (0);
+	sgilabel->devparam.unused1                  = SGI_SSWAP16(0);
+	sgilabel->devparam.nsect                    = SGI_SSWAP16(geometry.sectors);
+						/* sectors/track */
+	sgilabel->devparam.bytes                    = SGI_SSWAP16(512);
+	sgilabel->devparam.ilfact                   = SGI_SSWAP16(1);
+	sgilabel->devparam.flags                    = SGI_SSWAP32(TRACK_FWD|
+							IGNORE_ERRORS|RESEEK);
+	sgilabel->devparam.datarate                 = SGI_SSWAP32(0);
+	sgilabel->devparam.retries_on_error         = SGI_SSWAP32(1);
+	sgilabel->devparam.ms_per_word              = SGI_SSWAP32(0);
+	sgilabel->devparam.xylogics_gap1            = SGI_SSWAP16(0);
+	sgilabel->devparam.xylogics_syncdelay       = SGI_SSWAP16(0);
+	sgilabel->devparam.xylogics_readdelay       = SGI_SSWAP16(0);
+	sgilabel->devparam.xylogics_gap2            = SGI_SSWAP16(0);
+	sgilabel->devparam.xylogics_readgate        = SGI_SSWAP16(0);
+	sgilabel->devparam.xylogics_writecont       = SGI_SSWAP16(0);
+	memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
+	memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
+	current_label_type = label_sgi;
+	partitions = 16;
+	sgi_volumes = 15;
+	sgi_set_entire();
+	sgi_set_volhdr();
+	for (i = 0; i < 4; i++) {
+		if(old[i].sysid) {
+			sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
+		}
+	}
+}
+
+static void
+sgi_set_xcyl(void)
+{
+	/* do nothing in the beginning */
+}
+#endif /* CONFIG_FEATURE_FDISK_ADVANCED */
+
+/* _____________________________________________________________
+ */
+
+static sgiinfo *
+fill_sgiinfo(void)
+{
+	sgiinfo *info = calloc(1, sizeof(sgiinfo));
+
+	info->magic = SGI_SSWAP32(SGI_INFO_MAGIC);
+	info->b1 = SGI_SSWAP32(-1);
+	info->b2 = SGI_SSWAP16(-1);
+	info->b3 = SGI_SSWAP16(1);
+	/* You may want to replace this string !!!!!!! */
+	strcpy( (char*)info->scsi_string, "IBM OEM 0662S12         3 30" );
+	strcpy( (char*)info->serial, "0000" );
+	info->check1816 = SGI_SSWAP16(18*256 +16 );
+	strcpy( (char*)info->installer, "Sfx version 5.3, Oct 18, 1994" );
+	return info;
+}
+#endif /* SGI_LABEL */
+
+
+#ifdef CONFIG_FEATURE_SUN_LABEL
+/*
+ * fdisksunlabel.c
+ *
+ * I think this is mostly, or entirely, due to
+ *      Jakub Jelinek (jj at sunsite.mff.cuni.cz), July 1996
+ *
+ * Merged with fdisk for other architectures, aeb, June 1998.
+ *
+ * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme at conectiva.com.br>
+ *      Internationalization
+ */
+
+
+static int sun_other_endian;
+static int scsi_disk;
+static int floppy;
+
+#ifndef IDE0_MAJOR
+#define IDE0_MAJOR 3
+#endif
+#ifndef IDE1_MAJOR
+#define IDE1_MAJOR 22
+#endif
+
+static void
+guess_device_type(void)
+{
+	struct stat bootstat;
+
+	if (fstat(fd, &bootstat) < 0) {
+		scsi_disk = 0;
+		floppy = 0;
+	} else if (S_ISBLK(bootstat.st_mode)
+		&& (major(bootstat.st_rdev) == IDE0_MAJOR ||
+		    major(bootstat.st_rdev) == IDE1_MAJOR)) {
+		scsi_disk = 0;
+		floppy = 0;
+	} else if (S_ISBLK(bootstat.st_mode)
+		&& major(bootstat.st_rdev) == FLOPPY_MAJOR) {
+		scsi_disk = 0;
+		floppy = 1;
+	} else {
+		scsi_disk = 1;
+		floppy = 0;
+	}
+}
+
+static const struct systypes sun_sys_types[] = {
+	{ "\x00" "Empty"        }, /* 0            */
+	{ "\x01" "Boot"         }, /* 1            */
+	{ "\x02" "SunOS root"   }, /* 2            */
+	{ "\x03" "SunOS swap"   }, /* SUNOS_SWAP   */
+	{ "\x04" "SunOS usr"    }, /* 4            */
+	{ "\x05" "Whole disk"   }, /* WHOLE_DISK   */
+	{ "\x06" "SunOS stand"  }, /* 6            */
+	{ "\x07" "SunOS var"    }, /* 7            */
+	{ "\x08" "SunOS home"   }, /* 8            */
+	{ "\x82" "Linux swap"   }, /* LINUX_SWAP   */
+	{ "\x83" "Linux native" }, /* LINUX_NATIVE */
+	{ "\x8e" "Linux LVM"    }, /* 0x8e         */
+/* New (2.2.x) raid partition with autodetect using persistent superblock */
+	{ "\xfd" "Linux raid autodetect" }, /* 0xfd         */  
+	{ NULL }
+};
+
+
+static void
+set_sun_partition(int i, uint start, uint stop, int sysid)
+{
+	sunlabel->infos[i].id = sysid;
+	sunlabel->partitions[i].start_cylinder =
+		SUN_SSWAP32(start / (heads * sectors));
+	sunlabel->partitions[i].num_sectors =
+		SUN_SSWAP32(stop - start);
+	set_changed(i);
+}
+
+static int
+check_sun_label(void)
+{
+	unsigned short *ush;
+	int csum;
+
+	if (sunlabel->magic != SUN_LABEL_MAGIC
+	 && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
+		current_label_type = label_dos;
+		sun_other_endian = 0;
+		return 0;
+	}
+	sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
+	ush = ((unsigned short *) (sunlabel + 1)) - 1;
+	for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
+	if (csum) {
+		fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
+				"Probably you'll have to set all the values,\n"
+				"e.g. heads, sectors, cylinders and partitions\n"
+				"or force a fresh label (s command in main menu)\n"));
+	} else {
+		heads = SUN_SSWAP16(sunlabel->ntrks);
+		cylinders = SUN_SSWAP16(sunlabel->ncyl);
+		sectors = SUN_SSWAP16(sunlabel->nsect);
+	}
+	update_units();
+	current_label_type = label_sun;
+	partitions = 8;
+	return 1;
+}
+
+static const struct sun_predefined_drives {
+	const char *vendor;
+	const char *model;
+	unsigned short sparecyl;
+	unsigned short ncyl;
+	unsigned short nacyl;
+	unsigned short pcylcount;
+	unsigned short ntrks;
+	unsigned short nsect;
+	unsigned short rspeed;
+} sun_drives[] = {
+	{ "Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
+	{ "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
+	{ "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
+	{ "IBM","DPES-31080",0,4901,2,4903,4,108,5400},
+	{ "IBM","DORS-32160",0,1015,2,1017,67,62,5400},
+	{ "IBM","DNES-318350",0,11199,2,11474,10,320,7200},
+	{ "SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
+	{ "","SUN0104",1,974,2,1019,6,35,3662},
+	{ "","SUN0207",4,1254,2,1272,9,36,3600},
+	{ "","SUN0327",3,1545,2,1549,9,46,3600},
+	{ "","SUN0340",0,1538,2,1544,6,72,4200},
+	{ "","SUN0424",2,1151,2,2500,9,80,4400},
+	{ "","SUN0535",0,1866,2,2500,7,80,5400},
+	{ "","SUN0669",5,1614,2,1632,15,54,3600},
+	{ "","SUN1.0G",5,1703,2,1931,15,80,3597},
+	{ "","SUN1.05",0,2036,2,2038,14,72,5400},
+	{ "","SUN1.3G",6,1965,2,3500,17,80,5400},
+	{ "","SUN2.1G",0,2733,2,3500,19,80,5400},
+	{ "IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
+};
+
+static const struct sun_predefined_drives *
+sun_autoconfigure_scsi(void)
+{
+	const struct sun_predefined_drives *p = NULL;
+
+#ifdef SCSI_IOCTL_GET_IDLUN
+	unsigned int id[2];
+	char buffer[2048];
+	char buffer2[2048];
+	FILE *pfd;
+	char *vendor;
+	char *model;
+	char *q;
+	int i;
+
+	if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
+		sprintf(buffer,
+			"Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
+#if 0
+			((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
+#else
+			/* This is very wrong (works only if you have one HBA),
+			   but I haven't found a way how to get hostno
+			   from the current kernel */
+			0,
+#endif
+			(id[0]>>16) & 0xff,
+			id[0] & 0xff,
+			(id[0]>>8) & 0xff
+		);
+		pfd = fopen("/proc/scsi/scsi","r");
+		if (pfd) {
+			while (fgets(buffer2, 2048, pfd)) {
+				if (!strcmp(buffer, buffer2)) {
+					if (fgets(buffer2,2048,pfd)) {
+						q = strstr(buffer2,"Vendor: ");
+						if (q) {
+							q += 8;
+							vendor = q;
+							q = strstr(q," ");
+							*q++ = 0;   /* truncate vendor name */
+							q = strstr(q,"Model: ");
+							if (q) {
+								*q = 0;
+								q += 7;
+								model = q;
+								q = strstr(q," Rev: ");
+								if (q) {
+									*q = 0;
+									for (i = 0; i < SIZE(sun_drives); i++) {
+										if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
+											continue;
+										if (!strstr(model, sun_drives[i].model))
+											continue;
+										printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
+										p = sun_drives + i;
+										break;
+									}
+								}
+							}
+						}
+					}
+					break;
+				}
+			}
+			fclose(pfd);
+		}
+	}
+#endif
+	return p;
+}
+
+static void
+create_sunlabel(void)
+{
+	struct hd_geometry geometry;
+	unsigned int ndiv;
+	int i;
+	unsigned char c;
+	const struct sun_predefined_drives *p = NULL;
+
+	fprintf(stderr,
+		_("Building a new sun disklabel. Changes will remain in memory only,\n"
+		"until you decide to write them. After that, of course, the previous\n"
+		"content won't be recoverable.\n\n"));
+	sun_other_endian = BB_LITTLE_ENDIAN;
+	memset(MBRbuffer, 0, sizeof(MBRbuffer));
+	sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
+	if (!floppy) {
+		puts(_("Drive type\n"
+		 "   ?   auto configure\n"
+		 "   0   custom (with hardware detected defaults)"));
+		for (i = 0; i < SIZE(sun_drives); i++) {
+			printf("   %c   %s%s%s\n",
+				i + 'a', sun_drives[i].vendor,
+				(*sun_drives[i].vendor) ? " " : "",
+				sun_drives[i].model);
+		}
+		while (1) {
+			c = read_char(_("Select type (? for auto, 0 for custom): "));
+			if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
+				p = sun_drives + c - 'a';
+				break;
+			} else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
+				p = sun_drives + c - 'A';
+				break;
+			} else if (c == '0') {
+				break;
+			} else if (c == '?' && scsi_disk) {
+				p = sun_autoconfigure_scsi();
+				if (!p)
+				printf(_("Autoconfigure failed.\n"));
+				else
+				break;
+			}
+		}
+	}
+	if (!p || floppy) {
+		if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
+			heads = geometry.heads;
+			sectors = geometry.sectors;
+			cylinders = geometry.cylinders;
+		} else {
+			heads = 0;
+			sectors = 0;
+			cylinders = 0;
+		}
+		if (floppy) {
+			sunlabel->nacyl = 0;
+			sunlabel->pcylcount = SUN_SSWAP16(cylinders);
+			sunlabel->rspeed = SUN_SSWAP16(300);
+			sunlabel->ilfact = SUN_SSWAP16(1);
+			sunlabel->sparecyl = 0;
+		} else {
+			heads = read_int(1,heads,1024,0,_("Heads"));
+			sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
+		if (cylinders)
+			cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
+		else
+			cylinders = read_int(1,0,65535,0,_("Cylinders"));
+			sunlabel->nacyl = SUN_SSWAP16(read_int(0,2,65535,0, _("Alternate cylinders")));
+			sunlabel->pcylcount = SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535,0, _("Physical cylinders")));
+			sunlabel->rspeed = SUN_SSWAP16(read_int(1,5400,100000,0, _("Rotation speed (rpm)")));
+			sunlabel->ilfact = SUN_SSWAP16(read_int(1,1,32,0, _("Interleave factor")));
+			sunlabel->sparecyl = SUN_SSWAP16(read_int(0,0,sectors,0, _("Extra sectors per cylinder")));
+		}
+	} else {
+		sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
+		sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
+		sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
+		sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
+		sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
+		sunlabel->nsect = SUN_SSWAP16(p->nsect);
+		sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
+		sunlabel->ilfact = SUN_SSWAP16(1);
+		cylinders = p->ncyl;
+		heads = p->ntrks;
+		sectors = p->nsect;
+		puts(_("You may change all the disk params from the x menu"));
+	}
+
+	snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
+		"%s%s%s cyl %d alt %d hd %d sec %d",
+		p ? p->vendor : "", (p && *p->vendor) ? " " : "",
+		p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")),
+		cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
+
+	sunlabel->ntrks = SUN_SSWAP16(heads);
+	sunlabel->nsect = SUN_SSWAP16(sectors);
+	sunlabel->ncyl = SUN_SSWAP16(cylinders);
+	if (floppy)
+		set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
+	else {
+		if (cylinders * heads * sectors >= 150 * 2048) {
+			ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
+		} else
+			ndiv = cylinders * 2 / 3;
+		set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
+		set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
+		sunlabel->infos[1].flags |= 0x01; /* Not mountable */
+	}
+	set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
+	{
+		unsigned short *ush = (unsigned short *)sunlabel;
+		unsigned short csum = 0;
+		while (ush < (unsigned short *)(&sunlabel->csum))
+			csum ^= *ush++;
+		sunlabel->csum = csum;
+	}
+
+	set_all_unchanged();
+	set_changed(0);
+	get_boot(create_empty_sun);
+}
+
+static void
+toggle_sunflags(int i, unsigned char mask)
+{
+	if (sunlabel->infos[i].flags & mask)
+		sunlabel->infos[i].flags &= ~mask;
+	else
+		sunlabel->infos[i].flags |= mask;
+	set_changed(i);
+}
+
+static void
+fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
+{
+	int i, continuous = 1;
+
+	*start = 0;
+	*stop = cylinders * heads * sectors;
+	for (i = 0; i < partitions; i++) {
+		if (sunlabel->partitions[i].num_sectors
+		 && sunlabel->infos[i].id
+		 && sunlabel->infos[i].id != WHOLE_DISK) {
+			starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
+			lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
+			if (continuous) {
+				if (starts[i] == *start)
+					*start += lens[i];
+				else if (starts[i] + lens[i] >= *stop)
+					*stop = starts[i];
+				else
+					continuous = 0;
+					/* There will be probably more gaps
+					  than one, so lets check afterwards */
+			}
+		} else {
+			starts[i] = 0;
+			lens[i] = 0;
+		}
+	}
+}
+
+static uint *verify_sun_starts;
+
+static int
+verify_sun_cmp(int *a, int *b)
+{
+	if (*a == -1) return 1;
+	if (*b == -1) return -1;
+	if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
+	return -1;
+}
+
+static void
+verify_sun(void)
+{
+	uint starts[8], lens[8], start, stop;
+	int i,j,k,starto,endo;
+	int array[8];
+
+	verify_sun_starts = starts;
+	fetch_sun(starts,lens,&start,&stop);
+	for (k = 0; k < 7; k++) {
+		for (i = 0; i < 8; i++) {
+			if (k && (lens[i] % (heads * sectors))) {
+				printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
+			}
+			if (lens[i]) {
+				for (j = 0; j < i; j++)
+					if (lens[j]) {
+						if (starts[j] == starts[i]+lens[i]) {
+							starts[j] = starts[i]; lens[j] += lens[i];
+							lens[i] = 0;
+						} else if (starts[i] == starts[j]+lens[j]){
+							lens[j] += lens[i];
+							lens[i] = 0;
+						} else if (!k) {
+							if (starts[i] < starts[j]+lens[j]
+							 && starts[j] < starts[i]+lens[i]) {
+								starto = starts[i];
+								if (starts[j] > starto)
+									starto = starts[j];
+								endo = starts[i]+lens[i];
+								if (starts[j]+lens[j] < endo)
+									endo = starts[j]+lens[j];
+								printf(_("Partition %d overlaps with others in "
+									"sectors %d-%d\n"), i+1, starto, endo);
+							}
+						}
+					}
+			}
+		}
+	}
+	for (i = 0; i < 8; i++) {
+		if (lens[i])
+			array[i] = i;
+		else
+			array[i] = -1;
+	}
+	qsort(array,SIZE(array),sizeof(array[0]),
+		(int (*)(const void *,const void *)) verify_sun_cmp);
+	if (array[0] == -1) {
+		printf(_("No partitions defined\n"));
+		return;
+	}
+	stop = cylinders * heads * sectors;
+	if (starts[array[0]])
+		printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
+	for (i = 0; i < 7 && array[i+1] != -1; i++) {
+		printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
+	}
+	start = starts[array[i]] + lens[array[i]];
+	if (start < stop)
+		printf(_("Unused gap - sectors %d-%d\n"),start,stop);
+}
+
+static void
+add_sun_partition(int n, int sys)
+{
+	uint start, stop, stop2;
+	uint starts[8], lens[8];
+	int whole_disk = 0;
+
+	char mesg[256];
+	int i, first, last;
+
+	if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
+		printf(_("Partition %d is already defined.  Delete "
+			"it before re-adding it.\n"), n + 1);
+		return;
+	}
+
+	fetch_sun(starts,lens,&start,&stop);
+	if (stop <= start) {
+		if (n == 2)
+			whole_disk = 1;
+		else {
+			printf(_("Other partitions already cover the whole disk.\nDelete "
+				   "some/shrink them before retry.\n"));
+			return;
+		}
+	}
+	snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
+	while (1) {
+		if (whole_disk)
+			first = read_int(0, 0, 0, 0, mesg);
+		else
+			first = read_int(scround(start), scround(stop)+1,
+					 scround(stop), 0, mesg);
+		if (display_in_cyl_units)
+			first *= units_per_sector;
+		else
+			/* Starting sector has to be properly aligned */
+			first = (first + heads * sectors - 1) / (heads * sectors);
+		if (n == 2 && first != 0)
+			printf("\
+It is highly recommended that the third partition covers the whole disk\n\
+and is of type `Whole disk'\n");
+		/* ewt asks to add: "don't start a partition at cyl 0"
+		   However, edmundo at rano.demon.co.uk writes:
+		   "In addition to having a Sun partition table, to be able to
+		   boot from the disc, the first partition, /dev/sdX1, must
+		   start at cylinder 0. This means that /dev/sdX1 contains
+		   the partition table and the boot block, as these are the
+		   first two sectors of the disc. Therefore you must be
+		   careful what you use /dev/sdX1 for. In particular, you must
+		   not use a partition starting at cylinder 0 for Linux swap,
+		   as that would overwrite the partition table and the boot
+		   block. You may, however, use such a partition for a UFS
+		   or EXT2 file system, as these file systems leave the first
+		   1024 bytes undisturbed. */
+		/* On the other hand, one should not use partitions
+		   starting at block 0 in an md, or the label will
+		   be trashed. */
+		for (i = 0; i < partitions; i++)
+			if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
+				break;
+		if (i < partitions && !whole_disk) {
+			if (n == 2 && !first) {
+				whole_disk = 1;
+				break;
+			}
+			printf(_("Sector %d is already allocated\n"), first);
+		} else
+			break;
+	}
+	stop = cylinders * heads * sectors;
+	stop2 = stop;
+	for (i = 0; i < partitions; i++) {
+		if (starts[i] > first && starts[i] < stop)
+			stop = starts[i];
+	}
+	snprintf(mesg, sizeof(mesg),
+		_("Last %s or +size or +sizeM or +sizeK"),
+		str_units(SINGULAR));
+	if (whole_disk)
+		last = read_int(scround(stop2), scround(stop2), scround(stop2),
+				0, mesg);
+	else if (n == 2 && !first)
+		last = read_int(scround(first), scround(stop2), scround(stop2),
+				scround(first), mesg);
+	else
+		last = read_int(scround(first), scround(stop), scround(stop),
+				scround(first), mesg);
+	if (display_in_cyl_units)
+		last *= units_per_sector;
+	if (n == 2 && !first) {
+		if (last >= stop2) {
+			whole_disk = 1;
+			last = stop2;
+		} else if (last > stop) {
+			printf(_("You haven't covered the whole disk with "
+				"the 3rd partition, but your value\n"
+				"%d %s covers some other partition. "
+				"Your entry has been changed\n"
+				"to %d %s\n"),
+				scround(last), str_units(SINGULAR),
+				scround(stop), str_units(SINGULAR));
+			last = stop;
+		}
+	} else if (!whole_disk && last > stop)
+		last = stop;
+
+	if (whole_disk)
+		sys = WHOLE_DISK;
+	set_sun_partition(n, first, last, sys);
+}
+
+static void
+sun_delete_partition(int i)
+{
+	unsigned int nsec;
+
+	if (i == 2
+	 && sunlabel->infos[i].id == WHOLE_DISK
+	 && !sunlabel->partitions[i].start_cylinder
+	 && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders)
+		printf(_("If you want to maintain SunOS/Solaris compatibility, "
+			"consider leaving this\n"
+			"partition as Whole disk (5), starting at 0, with %u "
+			"sectors\n"), nsec);
+	sunlabel->infos[i].id = 0;
+	sunlabel->partitions[i].num_sectors = 0;
+}
+
+static void
+sun_change_sysid(int i, int sys)
+{
+	if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
+		read_chars(
+			_("It is highly recommended that the partition at offset 0\n"
+			"is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
+			"there may destroy your partition table and bootblock.\n"
+			"Type YES if you're very sure you would like that partition\n"
+			"tagged with 82 (Linux swap): "));
+		if (strcmp (line_ptr, _("YES\n")))
+			return;
+	}
+	switch (sys) {
+	case SUNOS_SWAP:
+	case LINUX_SWAP:
+		/* swaps are not mountable by default */
+		sunlabel->infos[i].flags |= 0x01;
+		break;
+	default:
+		/* assume other types are mountable;
+		   user can change it anyway */
+		sunlabel->infos[i].flags &= ~0x01;
+		break;
+	}
+	sunlabel->infos[i].id = sys;
+}
+
+static void
+sun_list_table(int xtra)
+{
+	int i, w;
+
+	w = strlen(disk_device);
+	if (xtra)
+		printf(
+		_("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
+		"%d cylinders, %d alternate cylinders, %d physical cylinders\n"
+		"%d extra sects/cyl, interleave %d:1\n"
+		"%s\n"
+		"Units = %s of %d * 512 bytes\n\n"),
+			disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
+			cylinders, SUN_SSWAP16(sunlabel->nacyl),
+			SUN_SSWAP16(sunlabel->pcylcount),
+			SUN_SSWAP16(sunlabel->sparecyl),
+			SUN_SSWAP16(sunlabel->ilfact),
+			(char *)sunlabel,
+			str_units(PLURAL), units_per_sector);
+	else
+		printf(
+	_("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
+	"Units = %s of %d * 512 bytes\n\n"),
+			disk_device, heads, sectors, cylinders,
+			str_units(PLURAL), units_per_sector);
+
+	printf(_("%*s Flag    Start       End    Blocks   Id  System\n"),
+		w + 1, _("Device"));
+	for (i = 0 ; i < partitions; i++) {
+		if (sunlabel->partitions[i].num_sectors) {
+			uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
+			uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
+			printf("%s %c%c %9ld %9ld %9ld%c  %2x  %s\n",
+				partname(disk_device, i+1, w),			/* device */            
+				(sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',  /* flags */             
+				(sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',  			
+				(long) scround(start),                          /* start */             
+				(long) scround(start+len),                      /* end */               
+				(long) len / 2, len & 1 ? '+' : ' ',            /* odd flag on end */   
+				sunlabel->infos[i].id,                          /* type id */           
+				partition_type(sunlabel->infos[i].id));         /* type name */         
+		}
+	}
+}
+
+#ifdef CONFIG_FEATURE_FDISK_ADVANCED
+
+static void
+sun_set_alt_cyl(void)
+{
+	sunlabel->nacyl =
+		SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
+				_("Number of alternate cylinders")));
+}
+
+static void
+sun_set_ncyl(int cyl)
+{
+	sunlabel->ncyl = SUN_SSWAP16(cyl);
+}
+
+static void
+sun_set_xcyl(void)
+{
+	sunlabel->sparecyl =
+		SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
+				_("Extra sectors per cylinder")));
+}
+
+static void
+sun_set_ilfact(void)
+{
+	sunlabel->ilfact =
+		SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
+				_("Interleave factor")));
+}
+
+static void
+sun_set_rspeed(void)
+{
+	sunlabel->rspeed =
+		SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
+				_("Rotation speed (rpm)")));
+}
+
+static void
+sun_set_pcylcount(void)
+{
+	sunlabel->pcylcount =
+		SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
+				_("Number of physical cylinders")));
+}
+#endif /* CONFIG_FEATURE_FDISK_ADVANCED */
+
+static void
+sun_write_table(void)
+{
+	unsigned short *ush = (unsigned short *)sunlabel;
+	unsigned short csum = 0;
+
+	while (ush < (unsigned short *)(&sunlabel->csum))
+		csum ^= *ush++;
+	sunlabel->csum = csum;
+	if (lseek(fd, 0, SEEK_SET) < 0)
+		fdisk_fatal(unable_to_seek);
+	if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
+		fdisk_fatal(unable_to_write);
+}
+#endif /* SUN_LABEL */
+
+/* DOS partition types */
+
+static const struct systypes i386_sys_types[] = {
+	{ "\x00" "Empty" },
+	{ "\x01" "FAT12" },
+	{ "\x04" "FAT16 <32M" },
+	{ "\x05" "Extended" },         /* DOS 3.3+ extended partition */
+	{ "\x06" "FAT16" },            /* DOS 16-bit >=32M */
+	{ "\x07" "HPFS/NTFS" },        /* OS/2 IFS, eg, HPFS or NTFS or QNX */
+	{ "\x0a" "OS/2 Boot Manager" },/* OS/2 Boot Manager */
+	{ "\x0b" "Win95 FAT32" },
+	{ "\x0c" "Win95 FAT32 (LBA)" },/* LBA really is `Extended Int 13h' */
+	{ "\x0e" "Win95 FAT16 (LBA)" },
+	{ "\x0f" "Win95 Ext'd (LBA)" },
+	{ "\x11" "Hidden FAT12" },
+	{ "\x12" "Compaq diagnostics" },
+	{ "\x14" "Hidden FAT16 <32M" },
+	{ "\x16" "Hidden FAT16" },
+	{ "\x17" "Hidden HPFS/NTFS" },
+	{ "\x1b" "Hidden Win95 FAT32" },
+	{ "\x1c" "Hidden Win95 FAT32 (LBA)" },
+	{ "\x1e" "Hidden Win95 FAT16 (LBA)" },
+	{ "\x3c" "PartitionMagic recovery" },
+	{ "\x41" "PPC PReP Boot" },
+	{ "\x42" "SFS" },
+	{ "\x63" "GNU HURD or SysV" }, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
+	{ "\x80" "Old Minix" },        /* Minix 1.4a and earlier */
+	{ "\x81" "Minix / old Linux" },/* Minix 1.4b and later */
+	{ "\x82" "Linux swap" },       /* also Solaris */
+	{ "\x83" "Linux" },
+	{ "\x84" "OS/2 hidden C: drive" },
+	{ "\x85" "Linux extended" },
+	{ "\x86" "NTFS volume set" },
+	{ "\x87" "NTFS volume set" },
+	{ "\x8e" "Linux LVM" },
+	{ "\x9f" "BSD/OS" },           /* BSDI */
+	{ "\xa0" "IBM Thinkpad hibernation" },
+	{ "\xa5" "FreeBSD" },          /* various BSD flavours */
+	{ "\xa6" "OpenBSD" },
+	{ "\xa8" "Darwin UFS" },
+	{ "\xa9" "NetBSD" },
+	{ "\xab" "Darwin boot" },
+	{ "\xb7" "BSDI fs" },
+	{ "\xb8" "BSDI swap" },
+	{ "\xbe" "Solaris boot" },
+	{ "\xeb" "BeOS fs" },
+	{ "\xee" "EFI GPT" },          /* Intel EFI GUID Partition Table */
+	{ "\xef" "EFI (FAT-12/16/32)" },/* Intel EFI System Partition */
+	{ "\xf0" "Linux/PA-RISC boot" },/* Linux/PA-RISC boot loader */
+	{ "\xf2" "DOS secondary" },    /* DOS 3.3+ secondary */
+	{ "\xfd" "Linux raid autodetect" },/* New (2.2.x) raid partition with
+						autodetect using persistent
+						superblock */
+#ifdef CONFIG_WEIRD_PARTITION_TYPES
+	{ "\x02" "XENIX root" },
+	{ "\x03" "XENIX usr" },
+	{ "\x08" "AIX" },              /* AIX boot (AIX -- PS/2 port) or SplitDrive */
+	{ "\x09" "AIX bootable" },     /* AIX data or Coherent */
+	{ "\x10" "OPUS" },
+	{ "\x18" "AST SmartSleep" },
+	{ "\x24" "NEC DOS" },
+	{ "\x39" "Plan 9" },
+	{ "\x40" "Venix 80286" },
+	{ "\x4d" "QNX4.x" },
+	{ "\x4e" "QNX4.x 2nd part" },
+	{ "\x4f" "QNX4.x 3rd part" },
+	{ "\x50" "OnTrack DM" },
+	{ "\x51" "OnTrack DM6 Aux1" }, /* (or Novell) */
+	{ "\x52" "CP/M" },             /* CP/M or Microport SysV/AT */
+	{ "\x53" "OnTrack DM6 Aux3" },
+	{ "\x54" "OnTrackDM6" },
+	{ "\x55" "EZ-Drive" },
+	{ "\x56" "Golden Bow" },
+	{ "\x5c" "Priam Edisk" },
+	{ "\x61" "SpeedStor" },
+	{ "\x64" "Novell Netware 286" },
+	{ "\x65" "Novell Netware 386" },
+	{ "\x70" "DiskSecure Multi-Boot" },
+	{ "\x75" "PC/IX" },
+	{ "\x93" "Amoeba" },
+	{ "\x94" "Amoeba BBT" },       /* (bad block table) */
+	{ "\xa7" "NeXTSTEP" },
+	{ "\xbb" "Boot Wizard hidden" },
+	{ "\xc1" "DRDOS/sec (FAT-12)" },
+	{ "\xc4" "DRDOS/sec (FAT-16 < 32M)" },
+	{ "\xc6" "DRDOS/sec (FAT-16)" },
+	{ "\xc7" "Syrinx" },
+	{ "\xda" "Non-FS data" },
+	{ "\xdb" "CP/M / CTOS / ..." },/* CP/M or Concurrent CP/M or
+					Concurrent DOS or CTOS */
+	{ "\xde" "Dell Utility" },     /* Dell PowerEdge Server utilities */
+	{ "\xdf" "BootIt" },           /* BootIt EMBRM */
+	{ "\xe1" "DOS access" },       /* DOS access or SpeedStor 12-bit FAT
+					extended partition */
+	{ "\xe3" "DOS R/O" },          /* DOS R/O or SpeedStor */
+	{ "\xe4" "SpeedStor" },        /* SpeedStor 16-bit FAT extended
+					partition < 1024 cyl. */
+	{ "\xf1" "SpeedStor" },
+	{ "\xf4" "SpeedStor" },        /* SpeedStor large partition */
+	{ "\xfe" "LANstep" },          /* SpeedStor >1024 cyl. or LANstep */
+	{ "\xff" "BBT" },              /* Xenix Bad Block Table */
+#endif
+	{ 0 }
+};
+
+
+
+/* A valid partition table sector ends in 0x55 0xaa */
+static unsigned int
+part_table_flag(const char *b)
+{
+	return ((uint) b[510]) + (((uint) b[511]) << 8);
+}
+
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static void
+write_part_table_flag(char *b)
+{
+	b[510] = 0x55;
+	b[511] = 0xaa;
+}
+
+/* start_sect and nr_sects are stored little endian on all machines */
+/* moreover, they are not aligned correctly */
+static void
+store4_little_endian(unsigned char *cp, unsigned int val)
+{
+	cp[0] = (val & 0xff);
+	cp[1] = ((val >> 8) & 0xff);
+	cp[2] = ((val >> 16) & 0xff);
+	cp[3] = ((val >> 24) & 0xff);
+}
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
+
+static unsigned int
+read4_little_endian(const unsigned char *cp)
+{
+	return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
+		+ ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
+}
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static void
+set_start_sect(struct partition *p, unsigned int start_sect)
+{
+	store4_little_endian(p->start4, start_sect);
+}
+#endif
+
+static int32_t
+get_start_sect(const struct partition *p)
+{
+	return read4_little_endian(p->start4);
+}
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static void
+set_nr_sects(struct partition *p, int32_t nr_sects)
+{
+	store4_little_endian(p->size4, nr_sects);
+}
+#endif
+
+static int32_t
+get_nr_sects(const struct partition *p)
+{
+	return read4_little_endian(p->size4);
+}
+
+/* normally O_RDWR, -l option gives O_RDONLY */
+static int type_open = O_RDWR;
+
+
+static int ext_index;               /* the prime extended partition */
+static int listing;                    /* no aborts for fdisk -l */
+static int dos_compatible_flag = ~0;
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static int dos_changed;
+static int nowarn;            /* no warnings for fdisk -l/-s */
+#endif
+
+
+
+static uint user_cylinders, user_heads, user_sectors;
+static uint pt_heads, pt_sectors;
+static uint kern_heads, kern_sectors;
+
+static off_t extended_offset;            /* offset of link pointers */
+
+static unsigned long long total_number_of_sectors;
+
+
+static jmp_buf listingbuf;
+
+static void fdisk_fatal(enum failure why)
+{
+	const char *message;
+
+	if (listing) {
+		close(fd);
+		longjmp(listingbuf, 1);
+	}
+
+	switch (why) {
+	case unable_to_open:
+		message = "Unable to open %s\n";
+		break;
+	case unable_to_read:
+		message = "Unable to read %s\n";
+		break;
+	case unable_to_seek:
+		message = "Unable to seek on %s\n";
+		break;
+	case unable_to_write:
+		message = "Unable to write %s\n";
+		break;
+	case ioctl_error:
+		message = "BLKGETSIZE ioctl failed on %s\n";
+		break;
+	default:
+		message = "Fatal error\n";
+	}
+
+	fputc('\n', stderr);
+	fprintf(stderr, message, disk_device);
+	exit(1);
+}
+
+static void
+seek_sector(off_t secno)
+{
+	off_t offset = secno * sector_size;
+	if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
+		fdisk_fatal(unable_to_seek);
+}
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static void
+write_sector(off_t secno, char *buf)
+{
+	seek_sector(secno);
+	if (write(fd, buf, sector_size) != sector_size)
+		fdisk_fatal(unable_to_write);
+}
+#endif
+
+/* Allocate a buffer and read a partition table sector */
+static void
+read_pte(struct pte *pe, off_t offset)
+{
+	pe->offset = offset;
+	pe->sectorbuffer = (char *) xmalloc(sector_size);
+	seek_sector(offset);
+	if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
+		fdisk_fatal(unable_to_read);
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+	pe->changed = 0;
+#endif
+	pe->part_table = pe->ext_pointer = NULL;
+}
+
+static unsigned int
+get_partition_start(const struct pte *pe)
+{
+	return pe->offset + get_start_sect(pe->part_table);
+}
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+/*
+ * Avoid warning about DOS partitions when no DOS partition was changed.
+ * Here a heuristic "is probably dos partition".
+ * We might also do the opposite and warn in all cases except
+ * for "is probably nondos partition".
+ */
+static int
+is_dos_partition(int t)
+{
+	return (t == 1 || t == 4 || t == 6 ||
+		t == 0x0b || t == 0x0c || t == 0x0e ||
+		t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
+		t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
+		t == 0xc1 || t == 0xc4 || t == 0xc6);
+}
+
+static void
+menu(void)
+{
+#ifdef CONFIG_FEATURE_SUN_LABEL
+	if (label_sun == current_label_type) {
+		puts(_("Command action"));
+		puts(_("\ta\ttoggle a read only flag"));           /* sun */
+		puts(_("\tb\tedit bsd disklabel"));
+		puts(_("\tc\ttoggle the mountable flag"));         /* sun */
+		puts(_("\td\tdelete a partition"));
+		puts(_("\tl\tlist known partition types"));
+		puts(_("\tm\tprint this menu"));
+		puts(_("\tn\tadd a new partition"));
+		puts(_("\to\tcreate a new empty DOS partition table"));
+		puts(_("\tp\tprint the partition table"));
+		puts(_("\tq\tquit without saving changes"));
+		puts(_("\ts\tcreate a new empty Sun disklabel"));  /* sun */
+		puts(_("\tt\tchange a partition's system id"));
+		puts(_("\tu\tchange display/entry units"));
+		puts(_("\tv\tverify the partition table"));
+		puts(_("\tw\twrite table to disk and exit"));
+#ifdef CONFIG_FEATURE_FDISK_ADVANCED
+		puts(_("\tx\textra functionality (experts only)"));
+#endif
+	} else
+#endif
+#ifdef CONFIG_FEATURE_SGI_LABEL
+	if (label_sgi == current_label_type) {
+		puts(_("Command action"));
+		puts(_("\ta\tselect bootable partition"));    /* sgi flavour */
+		puts(_("\tb\tedit bootfile entry"));          /* sgi */
+		puts(_("\tc\tselect sgi swap partition"));    /* sgi flavour */
+		puts(_("\td\tdelete a partition"));
+		puts(_("\tl\tlist known partition types"));
+		puts(_("\tm\tprint this menu"));
+		puts(_("\tn\tadd a new partition"));
+		puts(_("\to\tcreate a new empty DOS partition table"));
+		puts(_("\tp\tprint the partition table"));
+		puts(_("\tq\tquit without saving changes"));
+		puts(_("\ts\tcreate a new empty Sun disklabel"));  /* sun */
+		puts(_("\tt\tchange a partition's system id"));
+		puts(_("\tu\tchange display/entry units"));
+		puts(_("\tv\tverify the partition table"));
+		puts(_("\tw\twrite table to disk and exit"));
+	} else
+#endif
+#ifdef CONFIG_FEATURE_AIX_LABEL
+	if (label_aix == current_label_type) {
+		puts(_("Command action"));
+		puts(_("\tm\tprint this menu"));
+		puts(_("\to\tcreate a new empty DOS partition table"));
+		puts(_("\tq\tquit without saving changes"));
+		puts(_("\ts\tcreate a new empty Sun disklabel"));  /* sun */
+	} else
+#endif
+	{
+		puts(_("Command action"));
+		puts(_("\ta\ttoggle a bootable flag"));
+		puts(_("\tb\tedit bsd disklabel"));
+		puts(_("\tc\ttoggle the dos compatibility flag"));
+		puts(_("\td\tdelete a partition"));
+		puts(_("\tl\tlist known partition types"));
+		puts(_("\tm\tprint this menu"));
+		puts(_("\tn\tadd a new partition"));
+		puts(_("\to\tcreate a new empty DOS partition table"));
+		puts(_("\tp\tprint the partition table"));
+		puts(_("\tq\tquit without saving changes"));
+		puts(_("\ts\tcreate a new empty Sun disklabel"));  /* sun */
+		puts(_("\tt\tchange a partition's system id"));
+		puts(_("\tu\tchange display/entry units"));
+		puts(_("\tv\tverify the partition table"));
+		puts(_("\tw\twrite table to disk and exit"));
+#ifdef CONFIG_FEATURE_FDISK_ADVANCED
+		puts(_("\tx\textra functionality (experts only)"));
+#endif
+	}
+}
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
+
+
+#ifdef CONFIG_FEATURE_FDISK_ADVANCED
+static void
+xmenu(void)
+{
+#ifdef CONFIG_FEATURE_SUN_LABEL
+	if (label_sun == current_label_type) {
+	puts(_("Command action"));
+	puts(_("\ta\tchange number of alternate cylinders"));      /*sun*/
+	puts(_("\tc\tchange number of cylinders"));
+	puts(_("\td\tprint the raw data in the partition table"));
+	puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
+	puts(_("\th\tchange number of heads"));
+	puts(_("\ti\tchange interleave factor"));                  /*sun*/
+	puts(_("\to\tchange rotation speed (rpm)"));               /*sun*/
+	puts(_("\tm\tprint this menu"));
+	puts(_("\tp\tprint the partition table"));
+	puts(_("\tq\tquit without saving changes"));
+	puts(_("\tr\treturn to main menu"));
+	puts(_("\ts\tchange number of sectors/track"));
+	puts(_("\tv\tverify the partition table"));
+	puts(_("\tw\twrite table to disk and exit"));
+	puts(_("\ty\tchange number of physical cylinders"));       /*sun*/
+	}  else
+#endif
+#ifdef CONFIG_FEATURE_SGI_LABEL
+	if (label_sgi == current_label_type) {
+		puts(_("Command action"));
+		puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
+		puts(_("\tc\tchange number of cylinders"));
+		puts(_("\td\tprint the raw data in the partition table"));
+		puts(_("\te\tlist extended partitions"));          /* !sun */
+		puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
+		puts(_("\th\tchange number of heads"));
+		puts(_("\tm\tprint this menu"));
+		puts(_("\tp\tprint the partition table"));
+		puts(_("\tq\tquit without saving changes"));
+		puts(_("\tr\treturn to main menu"));
+		puts(_("\ts\tchange number of sectors/track"));
+		puts(_("\tv\tverify the partition table"));
+		puts(_("\tw\twrite table to disk and exit"));
+	} else
+#endif
+#ifdef CONFIG_FEATURE_AIX_LABEL
+	if (label_aix == current_label_type) {
+		puts(_("Command action"));
+		puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
+		puts(_("\tc\tchange number of cylinders"));
+		puts(_("\td\tprint the raw data in the partition table"));
+		puts(_("\te\tlist extended partitions"));          /* !sun */
+		puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
+		puts(_("\th\tchange number of heads"));
+		puts(_("\tm\tprint this menu"));
+		puts(_("\tp\tprint the partition table"));
+		puts(_("\tq\tquit without saving changes"));
+		puts(_("\tr\treturn to main menu"));
+		puts(_("\ts\tchange number of sectors/track"));
+		puts(_("\tv\tverify the partition table"));
+		puts(_("\tw\twrite table to disk and exit"));
+	}  else
+#endif
+	{
+		puts(_("Command action"));
+		puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
+		puts(_("\tc\tchange number of cylinders"));
+		puts(_("\td\tprint the raw data in the partition table"));
+		puts(_("\te\tlist extended partitions"));          /* !sun */
+		puts(_("\tf\tfix partition order"));               /* !sun, !aix, !sgi */
+#ifdef CONFIG_FEATURE_SGI_LABEL
+		puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
+#endif
+		puts(_("\th\tchange number of heads"));
+		puts(_("\tm\tprint this menu"));
+		puts(_("\tp\tprint the partition table"));
+		puts(_("\tq\tquit without saving changes"));
+		puts(_("\tr\treturn to main menu"));
+		puts(_("\ts\tchange number of sectors/track"));
+		puts(_("\tv\tverify the partition table"));
+		puts(_("\tw\twrite table to disk and exit"));
+	}
+}
+#endif /* ADVANCED mode */
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static const struct systypes *
+get_sys_types(void)
+{
+	return (
+#ifdef CONFIG_FEATURE_SUN_LABEL
+		label_sun == current_label_type ? sun_sys_types :
+#endif
+#ifdef CONFIG_FEATURE_SGI_LABEL
+		label_sgi == current_label_type ? sgi_sys_types :
+#endif
+		i386_sys_types);
+}
+#else
+#define get_sys_types() i386_sys_types
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
+
+static const char *partition_type(unsigned char type)
+{
+	int i;
+	const struct systypes *types = get_sys_types();
+
+	for (i = 0; types[i].name; i++)
+		if ((unsigned char )types[i].name[0] == type)
+			return types[i].name + 1;
+
+	return _("Unknown");
+}
+
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static int
+get_sysid(int i)
+{
+	return (
+#ifdef CONFIG_FEATURE_SUN_LABEL
+		label_sun == current_label_type ? sunlabel->infos[i].id :
+#endif
+#ifdef CONFIG_FEATURE_SGI_LABEL
+		label_sgi == current_label_type ? sgi_get_sysid(i) :
+#endif
+		ptes[i].part_table->sys_ind);
+}
+
+void list_types(const struct systypes *sys)
+{
+	uint last[4], done = 0, next = 0, size;
+	int i;
+
+	for (i = 0; sys[i].name; i++);
+	size = i;
+
+	for (i = 3; i >= 0; i--)
+		last[3 - i] = done += (size + i - done) / (i + 1);
+	i = done = 0;
+
+	do {
+		printf("%c%2x  %-15.15s", i ? ' ' : '\n',
+			(unsigned char)sys[next].name[0],
+			partition_type((unsigned char)sys[next].name[0]));
+		next = last[i++] + done;
+		if (i > 3 || next >= last[i]) {
+			i = 0;
+			next = ++done;
+		}
+	} while (done < last[0]);
+	putchar('\n');
+}
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
+
+static int
+is_cleared_partition(const struct partition *p)
+{
+	return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
+		 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
+		 get_start_sect(p) || get_nr_sects(p));
+}
+
+static void
+clear_partition(struct partition *p)
+{
+	if (!p)
+		return;
+	memset(p, 0, sizeof(struct partition));
+}
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static void
+set_partition(int i, int doext, off_t start, off_t stop, int sysid)
+{
+	struct partition *p;
+	off_t offset;
+
+	if (doext) {
+		p = ptes[i].ext_pointer;
+		offset = extended_offset;
+	} else {
+		p = ptes[i].part_table;
+		offset = ptes[i].offset;
+	}
+	p->boot_ind = 0;
+	p->sys_ind = sysid;
+	set_start_sect(p, start - offset);
+	set_nr_sects(p, stop - start + 1);
+	if (dos_compatible_flag && (start/(sectors*heads) > 1023))
+		start = heads*sectors*1024 - 1;
+	set_hsc(p->head, p->sector, p->cyl, start);
+	if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
+		stop = heads*sectors*1024 - 1;
+	set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
+	ptes[i].changed = 1;
+}
+#endif
+
+static int
+test_c(const char **m, const char *mesg)
+{
+	int val = 0;
+	if (!*m)
+		fprintf(stderr, _("You must set"));
+	else {
+		fprintf(stderr, " %s", *m);
+		val = 1;
+	}
+	*m = mesg;
+	return val;
+}
+
+static int
+warn_geometry(void)
+{
+	const char *m = NULL;
+	int prev = 0;
+
+	if (!heads)
+		prev = test_c(&m, _("heads"));
+	if (!sectors)
+		prev = test_c(&m, _("sectors"));
+	if (!cylinders)
+		prev = test_c(&m, _("cylinders"));
+	if (!m)
+		return 0;
+
+	fprintf(stderr, "%s%s.\n"
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+			"You can do this from the extra functions menu.\n"
+#endif
+		, prev ? _(" and ") : " ", m);
+
+	return 1;
+}
+
+static void update_units(void)
+{
+	int cyl_units = heads * sectors;
+
+	if (display_in_cyl_units && cyl_units)
+		units_per_sector = cyl_units;
+	else
+		units_per_sector = 1;   /* in sectors */
+}
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static void
+warn_cylinders(void)
+{
+	if (label_dos == current_label_type && cylinders > 1024 && !nowarn)
+		fprintf(stderr, _("\n"
+"The number of cylinders for this disk is set to %d.\n"
+"There is nothing wrong with that, but this is larger than 1024,\n"
+"and could in certain setups cause problems with:\n"
+"1) software that runs at boot time (e.g., old versions of LILO)\n"
+"2) booting and partitioning software from other OSs\n"
+"   (e.g., DOS FDISK, OS/2 FDISK)\n"),
+			cylinders);
+}
+#endif
+
+static void
+read_extended(int ext)
+{
+	int i;
+	struct pte *pex;
+	struct partition *p, *q;
+
+	ext_index = ext;
+	pex = &ptes[ext];
+	pex->ext_pointer = pex->part_table;
+
+	p = pex->part_table;
+	if (!get_start_sect(p)) {
+		fprintf(stderr,
+			_("Bad offset in primary extended partition\n"));
+		return;
+	}
+
+	while (IS_EXTENDED(p->sys_ind)) {
+		struct pte *pe = &ptes[partitions];
+
+		if (partitions >= MAXIMUM_PARTS) {
+			/* This is not a Linux restriction, but
+			   this program uses arrays of size MAXIMUM_PARTS.
+			   Do not try to `improve' this test. */
+			struct pte *pre = &ptes[partitions-1];
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+			fprintf(stderr,
+				_("Warning: deleting partitions after %d\n"),
+				partitions);
+			pre->changed = 1;
+#endif
+			clear_partition(pre->ext_pointer);
+			return;
+		}
+
+		read_pte(pe, extended_offset + get_start_sect(p));
+
+		if (!extended_offset)
+			extended_offset = get_start_sect(p);
+
+		q = p = pt_offset(pe->sectorbuffer, 0);
+		for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
+			if (IS_EXTENDED(p->sys_ind)) {
+				if (pe->ext_pointer)
+					fprintf(stderr,
+						_("Warning: extra link "
+						  "pointer in partition table"
+						  " %d\n"), partitions + 1);
+				else
+					pe->ext_pointer = p;
+			} else if (p->sys_ind) {
+				if (pe->part_table)
+					fprintf(stderr,
+						_("Warning: ignoring extra "
+						  "data in partition table"
+						  " %d\n"), partitions + 1);
+				else
+					pe->part_table = p;
+			}
+		}
+
+		/* very strange code here... */
+		if (!pe->part_table) {
+			if (q != pe->ext_pointer)
+				pe->part_table = q;
+			else
+				pe->part_table = q + 1;
+		}
+		if (!pe->ext_pointer) {
+			if (q != pe->part_table)
+				pe->ext_pointer = q;
+			else
+				pe->ext_pointer = q + 1;
+		}
+
+		p = pe->ext_pointer;
+		partitions++;
+	}
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+	/* remove empty links */
+ remove:
+	for (i = 4; i < partitions; i++) {
+		struct pte *pe = &ptes[i];
+
+		if (!get_nr_sects(pe->part_table) &&
+			(partitions > 5 || ptes[4].part_table->sys_ind)) {
+			printf("omitting empty partition (%d)\n", i+1);
+			delete_partition(i);
+			goto remove;    /* numbering changed */
+		}
+	}
+#endif
+}
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static void
+create_doslabel(void)
+{
+	int i;
+
+	fprintf(stderr,
+	_("Building a new DOS disklabel. Changes will remain in memory only,\n"
+	  "until you decide to write them. After that, of course, the previous\n"
+	  "content won't be recoverable.\n\n"));
+
+	current_label_type = label_dos;
+
+#ifdef CONFIG_FEATURE_OSF_LABEL
+	possibly_osf_label = 0;
+#endif
+	partitions = 4;
+
+	for (i = 510-64; i < 510; i++)
+		MBRbuffer[i] = 0;
+	write_part_table_flag(MBRbuffer);
+	extended_offset = 0;
+	set_all_unchanged();
+	set_changed(0);
+	get_boot(create_empty_dos);
+}
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
+
+static void
+get_sectorsize(void)
+{
+	if (!user_set_sector_size) {
+		int arg;
+		if (ioctl(fd, BLKSSZGET, &arg) == 0)
+			sector_size = arg;
+		if (sector_size != DEFAULT_SECTOR_SIZE)
+			printf(_("Note: sector size is %d (not %d)\n"),
+				   sector_size, DEFAULT_SECTOR_SIZE);
+	}
+}
+
+static inline void
+get_kernel_geometry(void)
+{
+	struct hd_geometry geometry;
+
+	if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
+		kern_heads = geometry.heads;
+		kern_sectors = geometry.sectors;
+		/* never use geometry.cylinders - it is truncated */
+	}
+}
+
+static void
+get_partition_table_geometry(void)
+{
+	const unsigned char *bufp = (const unsigned char *)MBRbuffer;
+	struct partition *p;
+	int i, h, s, hh, ss;
+	int first = 1;
+	int bad = 0;
+
+	if (!(valid_part_table_flag((char*)bufp)))
+		return;
+
+	hh = ss = 0;
+	for (i = 0; i < 4; i++) {
+		p = pt_offset(bufp, i);
+		if (p->sys_ind != 0) {
+			h = p->end_head + 1;
+			s = (p->end_sector & 077);
+			if (first) {
+				hh = h;
+				ss = s;
+				first = 0;
+			} else if (hh != h || ss != s)
+				bad = 1;
+		}
+	}
+
+	if (!first && !bad) {
+		pt_heads = hh;
+		pt_sectors = ss;
+	}
+}
+
+static void
+get_geometry(void)
+{
+	int sec_fac;
+	unsigned long long bytes;       /* really u64 */
+
+	get_sectorsize();
+	sec_fac = sector_size / 512;
+#ifdef CONFIG_FEATURE_SUN_LABEL
+	guess_device_type();
+#endif
+	heads = cylinders = sectors = 0;
+	kern_heads = kern_sectors = 0;
+	pt_heads = pt_sectors = 0;
+
+	get_kernel_geometry();
+	get_partition_table_geometry();
+
+	heads = user_heads ? user_heads :
+		pt_heads ? pt_heads :
+		kern_heads ? kern_heads : 255;
+	sectors = user_sectors ? user_sectors :
+		pt_sectors ? pt_sectors :
+		kern_sectors ? kern_sectors : 63;
+	if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
+		/* got bytes */
+	} else {
+		unsigned long longsectors;
+
+	if (ioctl(fd, BLKGETSIZE, &longsectors))
+		longsectors = 0;
+			bytes = ((unsigned long long) longsectors) << 9;
+	}
+
+	total_number_of_sectors = (bytes >> 9);
+
+	sector_offset = 1;
+	if (dos_compatible_flag)
+		sector_offset = sectors;
+
+	cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
+	if (!cylinders)
+		cylinders = user_cylinders;
+}
+
+/*
+ * Read MBR.  Returns:
+ *   -1: no 0xaa55 flag present (possibly entire disk BSD)
+ *    0: found or created label
+ *    1: I/O error
+ */
+static int
+get_boot(enum action what)
+{
+	int i;
+
+	partitions = 4;
+
+	for (i = 0; i < 4; i++) {
+		struct pte *pe = &ptes[i];
+
+		pe->part_table = pt_offset(MBRbuffer, i);
+		pe->ext_pointer = NULL;
+		pe->offset = 0;
+		pe->sectorbuffer = MBRbuffer;
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+		pe->changed = (what == create_empty_dos);
+#endif
+	}
+
+#ifdef CONFIG_FEATURE_SUN_LABEL
+	if (what == create_empty_sun && check_sun_label())
+		return 0;
+#endif
+
+	memset(MBRbuffer, 0, 512);
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+	if (what == create_empty_dos)
+		goto got_dos_table;             /* skip reading disk */
+
+	if ((fd = open(disk_device, type_open)) < 0) {
+		if ((fd = open(disk_device, O_RDONLY)) < 0) {
+			if (what == try_only)
+				return 1;
+			fdisk_fatal(unable_to_open);
+		} else
+			printf(_("You will not be able to write "
+				"the partition table.\n"));
+	}
+
+	if (512 != read(fd, MBRbuffer, 512)) {
+		if (what == try_only)
+			return 1;
+		fdisk_fatal(unable_to_read);
+	}
+#else
+	if ((fd = open(disk_device, O_RDONLY)) < 0)
+		return 1;
+	if (512 != read(fd, MBRbuffer, 512))
+		return 1;
+#endif
+
+	get_geometry();
+
+	update_units();
+
+#ifdef CONFIG_FEATURE_SUN_LABEL
+	if (check_sun_label())
+		return 0;
+#endif
+
+#ifdef CONFIG_FEATURE_SGI_LABEL
+	if (check_sgi_label())
+		return 0;
+#endif
+
+#ifdef CONFIG_FEATURE_AIX_LABEL
+	if (check_aix_label())
+		return 0;
+#endif
+
+#ifdef CONFIG_FEATURE_OSF_LABEL
+	if (check_osf_label()) {
+		possibly_osf_label = 1;
+		if (!valid_part_table_flag(MBRbuffer)) {
+			current_label_type = label_osf;
+			return 0;
+		}
+		printf(_("This disk has both DOS and BSD magic.\n"
+			 "Give the 'b' command to go to BSD mode.\n"));
+	}
+#endif
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+ got_dos_table:
+#endif
+
+	if (!valid_part_table_flag(MBRbuffer)) {
+#ifndef CONFIG_FEATURE_FDISK_WRITABLE
+		return -1;
+#else
+		switch (what) {
+		case fdisk:
+			fprintf(stderr,
+				_("Device contains neither a valid DOS "
+				  "partition table, nor Sun, SGI or OSF "
+				  "disklabel\n"));
+#ifdef __sparc__
+#ifdef CONFIG_FEATURE_SUN_LABEL
+			create_sunlabel();
+#endif
+#else
+			create_doslabel();
+#endif
+			return 0;
+		case try_only:
+			return -1;
+		case create_empty_dos:
+#ifdef CONFIG_FEATURE_SUN_LABEL
+		case create_empty_sun:
+#endif
+			break;
+		default:
+			fprintf(stderr, _("Internal error\n"));
+			exit(1);
+		}
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
+	}
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+	warn_cylinders();
+#endif
+	warn_geometry();
+
+	for (i = 0; i < 4; i++) {
+		struct pte *pe = &ptes[i];
+
+		if (IS_EXTENDED(pe->part_table->sys_ind)) {
+			if (partitions != 4)
+				fprintf(stderr, _("Ignoring extra extended "
+					"partition %d\n"), i + 1);
+			else
+				read_extended(i);
+		}
+	}
+
+	for (i = 3; i < partitions; i++) {
+		struct pte *pe = &ptes[i];
+
+		if (!valid_part_table_flag(pe->sectorbuffer)) {
+			fprintf(stderr,
+				_("Warning: invalid flag 0x%04x of partition "
+				"table %d will be corrected by w(rite)\n"),
+				part_table_flag(pe->sectorbuffer), i + 1);
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+			pe->changed = 1;
+#endif
+		}
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+/*
+ * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
+ * If the user hits Enter, DFLT is returned.
+ * Answers like +10 are interpreted as offsets from BASE.
+ *
+ * There is no default if DFLT is not between LOW and HIGH.
+ */
+static uint
+read_int(uint low, uint dflt, uint high, uint base, char *mesg)
+{
+	uint i;
+	int default_ok = 1;
+	static char *ms = NULL;
+	static int mslen = 0;
+
+	if (!ms || strlen(mesg)+100 > mslen) {
+		mslen = strlen(mesg)+200;
+		ms = xrealloc(ms,mslen);
+	}
+
+	if (dflt < low || dflt > high)
+		default_ok = 0;
+
+	if (default_ok)
+		snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
+			 mesg, low, high, dflt);
+	else
+		snprintf(ms, mslen, "%s (%u-%u): ", mesg, low, high);
+
+	while (1) {
+		int use_default = default_ok;
+
+		/* ask question and read answer */
+		while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
+		 && *line_ptr != '-' && *line_ptr != '+')
+			continue;
+
+		if (*line_ptr == '+' || *line_ptr == '-') {
+			int minus = (*line_ptr == '-');
+			int absolute = 0;
+
+			i = atoi(line_ptr+1);
+
+			while (isdigit(*++line_ptr))
+				use_default = 0;
+
+			switch (*line_ptr) {
+			case 'c':
+			case 'C':
+				if (!display_in_cyl_units)
+					i *= heads * sectors;
+				break;
+			case 'K':
+				absolute = 1024;
+				break;
+			case 'k':
+				absolute = 1000;
+				break;
+			case 'm':
+			case 'M':
+				absolute = 1000000;
+				break;
+			case 'g':
+			case 'G':
+				absolute = 1000000000;
+				break;
+			default:
+				break;
+			}
+			if (absolute) {
+				unsigned long long bytes;
+				unsigned long unit;
+
+				bytes = (unsigned long long) i * absolute;
+				unit = sector_size * units_per_sector;
+				bytes += unit/2; /* round */
+				bytes /= unit;
+				i = bytes;
+			}
+			if (minus)
+				i = -i;
+			i += base;
+		} else {
+			i = atoi(line_ptr);
+			while (isdigit(*line_ptr)) {
+				line_ptr++;
+				use_default = 0;
+			}
+		}
+		if (use_default)
+			printf(_("Using default value %u\n"), i = dflt);
+		if (i >= low && i <= high)
+			break;
+		else
+			printf(_("Value out of range.\n"));
+	}
+	return i;
+}
+
+static int
+get_partition(int warn, int max)
+{
+	struct pte *pe;
+	int i;
+
+	i = read_int(1, 0, max, 0, _("Partition number")) - 1;
+	pe = &ptes[i];
+
+	if (warn) {
+		if (
+			(
+				label_sun != current_label_type && 
+				label_sgi != current_label_type && 
+				!pe->part_table->sys_ind
+			)
+#ifdef CONFIG_FEATURE_SUN_LABEL
+			|| (
+				label_sun == current_label_type &&
+				(
+					!sunlabel->partitions[i].num_sectors
+					|| !sunlabel->infos[i].id
+				)
+			)
+#endif
+#ifdef CONFIG_FEATURE_SGI_LABEL
+			|| (
+				label_sgi == current_label_type &&
+				 !sgi_get_num_sectors(i)
+			)
+#endif
+		){
+			fprintf(stderr,
+				_("Warning: partition %d has empty type\n"),
+				i+1
+			);
+		}
+	}
+	return i;
+}
+
+static int
+get_existing_partition(int warn, int max)
+{
+	int pno = -1;
+	int i;
+
+	for (i = 0; i < max; i++) {
+		struct pte *pe = &ptes[i];
+		struct partition *p = pe->part_table;
+
+		if (p && !is_cleared_partition(p)) {
+			if (pno >= 0)
+				goto not_unique;
+			pno = i;
+		}
+	}
+	if (pno >= 0) {
+		printf(_("Selected partition %d\n"), pno+1);
+		return pno;
+	}
+	printf(_("No partition is defined yet!\n"));
+	return -1;
+
+ not_unique:
+	return get_partition(warn, max);
+}
+
+static int
+get_nonexisting_partition(int warn, int max)
+{
+	int pno = -1;
+	int i;
+
+	for (i = 0; i < max; i++) {
+		struct pte *pe = &ptes[i];
+		struct partition *p = pe->part_table;
+
+		if (p && is_cleared_partition(p)) {
+			if (pno >= 0)
+				goto not_unique;
+			pno = i;
+		}
+	}
+	if (pno >= 0) {
+		printf(_("Selected partition %d\n"), pno+1);
+		return pno;
+	}
+	printf(_("All primary partitions have been defined already!\n"));
+	return -1;
+
+ not_unique:
+	return get_partition(warn, max);
+}
+
+
+void change_units(void)
+{
+	display_in_cyl_units = !display_in_cyl_units;
+	update_units();
+	printf(_("Changing display/entry units to %s\n"),
+		str_units(PLURAL));
+}
+
+static void
+toggle_active(int i)
+{
+	struct pte *pe = &ptes[i];
+	struct partition *p = pe->part_table;
+
+	if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
+		fprintf(stderr,
+			_("WARNING: Partition %d is an extended partition\n"),
+			i + 1);
+	p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
+	pe->changed = 1;
+}
+
+static void
+toggle_dos_compatibility_flag(void)
+{
+	dos_compatible_flag = ~dos_compatible_flag;
+	if (dos_compatible_flag) {
+		sector_offset = sectors;
+		printf(_("DOS Compatibility flag is set\n"));
+	}
+	else {
+		sector_offset = 1;
+		printf(_("DOS Compatibility flag is not set\n"));
+	}
+}
+
+static void
+delete_partition(int i)
+{
+	struct pte *pe = &ptes[i];
+	struct partition *p = pe->part_table;
+	struct partition *q = pe->ext_pointer;
+
+/* Note that for the fifth partition (i == 4) we don't actually
+ * decrement partitions.
+ */
+
+	if (warn_geometry())
+		return;         /* C/H/S not set */
+	pe->changed = 1;
+
+#ifdef CONFIG_FEATURE_SUN_LABEL
+	if (label_sun == current_label_type) {
+		sun_delete_partition(i);
+		return;
+	}
+#endif
+#ifdef CONFIG_FEATURE_SGI_LABEL
+	if (label_sgi == current_label_type) {
+		sgi_delete_partition(i);
+		return;
+	}
+#endif
+
+	if (i < 4) {
+		if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
+			partitions = 4;
+			ptes[ext_index].ext_pointer = NULL;
+			extended_offset = 0;
+		}
+		clear_partition(p);
+		return;
+	}
+
+	if (!q->sys_ind && i > 4) {
+		/* the last one in the chain - just delete */
+		--partitions;
+		--i;
+		clear_partition(ptes[i].ext_pointer);
+		ptes[i].changed = 1;
+	} else {
+		/* not the last one - further ones will be moved down */
+		if (i > 4) {
+			/* delete this link in the chain */
+			p = ptes[i-1].ext_pointer;
+			*p = *q;
+			set_start_sect(p, get_start_sect(q));
+			set_nr_sects(p, get_nr_sects(q));
+			ptes[i-1].changed = 1;
+		} else if (partitions > 5) {    /* 5 will be moved to 4 */
+			/* the first logical in a longer chain */
+			pe = &ptes[5];
+
+			if (pe->part_table) /* prevent SEGFAULT */
+				set_start_sect(pe->part_table,
+						   get_partition_start(pe) -
+						   extended_offset);
+			pe->offset = extended_offset;
+			pe->changed = 1;
+		}
+
+		if (partitions > 5) {
+			partitions--;
+			while (i < partitions) {
+				ptes[i] = ptes[i+1];
+				i++;
+			}
+		} else
+			/* the only logical: clear only */
+			clear_partition(ptes[i].part_table);
+	}
+}
+
+static void
+change_sysid(void)
+{
+	int i, sys, origsys;
+	struct partition *p;
+
+#ifdef CONFIG_FEATURE_SGI_LABEL
+	/* If sgi_label then don't use get_existing_partition,
+	   let the user select a partition, since get_existing_partition()
+	   only works for Linux like partition tables. */
+	if (label_sgi != current_label_type) {
+		i = get_existing_partition(0, partitions);
+	} else {
+		i = get_partition(0, partitions);
+	}
+#else
+	i = get_existing_partition(0, partitions);
+#endif
+	if (i == -1)
+		return;
+	p = ptes[i].part_table;
+	origsys = sys = get_sysid(i);
+
+	/* if changing types T to 0 is allowed, then
+	   the reverse change must be allowed, too */
+	if (!sys && label_sgi != current_label_type &&
+		label_sun != current_label_type && !get_nr_sects(p))
+	{
+		printf(_("Partition %d does not exist yet!\n"), i + 1);
+	}else{
+	    while (1) {
+		sys = read_hex (get_sys_types());
+
+		if (!sys && label_sgi != current_label_type &&
+			label_sun != current_label_type)
+		{
+			printf(_("Type 0 means free space to many systems\n"
+				   "(but not to Linux). Having partitions of\n"
+				   "type 0 is probably unwise. You can delete\n"
+				   "a partition using the `d' command.\n"));
+			/* break; */
+		}
+
+		if (label_sun != current_label_type && label_sgi != current_label_type) {
+			if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
+				printf(_("You cannot change a partition into"
+					   " an extended one or vice versa\n"
+					   "Delete it first.\n"));
+				break;
+			}
+		}
+
+		if (sys < 256) {
+#ifdef CONFIG_FEATURE_SUN_LABEL
+			if (label_sun == current_label_type && i == 2 && sys != WHOLE_DISK)
+				printf(_("Consider leaving partition 3 "
+					   "as Whole disk (5),\n"
+					   "as SunOS/Solaris expects it and "
+					   "even Linux likes it.\n\n"));
+#endif
+#ifdef CONFIG_FEATURE_SGI_LABEL
+			if (label_sgi == current_label_type &&
+				(
+					(i == 10 && sys != ENTIRE_DISK) ||
+					(i == 8 && sys != 0)
+				)
+			){
+				printf(_("Consider leaving partition 9 "
+					   "as volume header (0),\nand "
+					   "partition 11 as entire volume (6)"
+					   "as IRIX expects it.\n\n"));
+			}
+#endif
+			if (sys == origsys)
+				break;
+#ifdef CONFIG_FEATURE_SUN_LABEL
+			if (label_sun == current_label_type) {
+				sun_change_sysid(i, sys);
+			} else
+#endif
+#ifdef CONFIG_FEATURE_SGI_LABEL
+			if (label_sgi == current_label_type) {
+				sgi_change_sysid(i, sys);
+			} else
+#endif
+				p->sys_ind = sys;
+
+			printf(_("Changed system type of partition %d "
+				"to %x (%s)\n"), i + 1, sys,
+				partition_type(sys));
+			ptes[i].changed = 1;
+			if (is_dos_partition(origsys) ||
+				is_dos_partition(sys))
+				dos_changed = 1;
+			break;
+		}
+	    }
+	}
+}
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
+
+
+/* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
+ * faith at cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
+ * Jan.  1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
+ * Lubkin Oct.  1991). */
+
+static void
+long2chs(ulong ls, uint *c, uint *h, uint *s)
+{
+	int spc = heads * sectors;
+
+	*c = ls / spc;
+	ls = ls % spc;
+	*h = ls / sectors;
+	*s = ls % sectors + 1;  /* sectors count from 1 */
+}
+
+static void
+check_consistency(const struct partition *p, int partition)
+{
+	uint pbc, pbh, pbs;          /* physical beginning c, h, s */
+	uint pec, peh, pes;          /* physical ending c, h, s */
+	uint lbc, lbh, lbs;          /* logical beginning c, h, s */
+	uint lec, leh, les;          /* logical ending c, h, s */
+
+	if (!heads || !sectors || (partition >= 4))
+		return;         /* do not check extended partitions */
+
+/* physical beginning c, h, s */
+	pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
+	pbh = p->head;
+	pbs = p->sector & 0x3f;
+
+/* physical ending c, h, s */
+	pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
+	peh = p->end_head;
+	pes = p->end_sector & 0x3f;
+
+/* compute logical beginning (c, h, s) */
+	long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
+
+/* compute logical ending (c, h, s) */
+	long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
+
+/* Same physical / logical beginning? */
+	if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
+		printf(_("Partition %d has different physical/logical "
+			"beginnings (non-Linux?):\n"), partition + 1);
+		printf(_("     phys=(%d, %d, %d) "), pbc, pbh, pbs);
+		printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
+	}
+
+/* Same physical / logical ending? */
+	if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
+		printf(_("Partition %d has different physical/logical "
+			"endings:\n"), partition + 1);
+		printf(_("     phys=(%d, %d, %d) "), pec, peh, pes);
+		printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
+	}
+
+#if 0
+/* Beginning on cylinder boundary? */
+	if (pbh != !pbc || pbs != 1) {
+		printf(_("Partition %i does not start on cylinder "
+			"boundary:\n"), partition + 1);
+		printf(_("     phys=(%d, %d, %d) "), pbc, pbh, pbs);
+		printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
+	}
+#endif
+
+/* Ending on cylinder boundary? */
+	if (peh != (heads - 1) || pes != sectors) {
+		printf(_("Partition %i does not end on cylinder boundary.\n"),
+			partition + 1);
+#if 0
+		printf(_("     phys=(%d, %d, %d) "), pec, peh, pes);
+		printf(_("should be (%d, %d, %d)\n"),
+		pec, heads - 1, sectors);
+#endif
+	}
+}
+
+static void
+list_disk_geometry(void)
+{
+	long long bytes = (total_number_of_sectors << 9);
+	long megabytes = bytes/1000000;
+
+	if (megabytes < 10000)
+		printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
+			   disk_device, megabytes, bytes);
+	else
+		printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
+			   disk_device, megabytes/1000, (megabytes/100)%10, bytes);
+	printf(_("%d heads, %d sectors/track, %d cylinders"),
+		   heads, sectors, cylinders);
+	if (units_per_sector == 1)
+		printf(_(", total %llu sectors"),
+			   total_number_of_sectors / (sector_size/512));
+	printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
+		   str_units(PLURAL),
+		   units_per_sector, sector_size, units_per_sector * sector_size);
+}
+
+/*
+ * Check whether partition entries are ordered by their starting positions.
+ * Return 0 if OK. Return i if partition i should have been earlier.
+ * Two separate checks: primary and logical partitions.
+ */
+static int
+wrong_p_order(int *prev)
+{
+	const struct pte *pe;
+	const struct partition *p;
+	off_t last_p_start_pos = 0, p_start_pos;
+	int i, last_i = 0;
+
+	for (i = 0 ; i < partitions; i++) {
+		if (i == 4) {
+			last_i = 4;
+			last_p_start_pos = 0;
+		}
+		pe = &ptes[i];
+		if ((p = pe->part_table)->sys_ind) {
+			p_start_pos = get_partition_start(pe);
+
+			if (last_p_start_pos > p_start_pos) {
+				if (prev)
+					*prev = last_i;
+				return i;
+			}
+
+			last_p_start_pos = p_start_pos;
+			last_i = i;
+		}
+	}
+	return 0;
+}
+
+#ifdef CONFIG_FEATURE_FDISK_ADVANCED
+/*
+ * Fix the chain of logicals.
+ * extended_offset is unchanged, the set of sectors used is unchanged
+ * The chain is sorted so that sectors increase, and so that
+ * starting sectors increase.
+ *
+ * After this it may still be that cfdisk doesnt like the table.
+ * (This is because cfdisk considers expanded parts, from link to
+ * end of partition, and these may still overlap.)
+ * Now
+ *   sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
+ * may help.
+ */
+static void
+fix_chain_of_logicals(void)
+{
+	int j, oj, ojj, sj, sjj;
+	struct partition *pj,*pjj,tmp;
+
+	/* Stage 1: sort sectors but leave sector of part 4 */
+	/* (Its sector is the global extended_offset.) */
+ stage1:
+	for (j = 5; j < partitions-1; j++) {
+		oj = ptes[j].offset;
+		ojj = ptes[j+1].offset;
+		if (oj > ojj) {
+			ptes[j].offset = ojj;
+			ptes[j+1].offset = oj;
+			pj = ptes[j].part_table;
+			set_start_sect(pj, get_start_sect(pj)+oj-ojj);
+			pjj = ptes[j+1].part_table;
+			set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
+			set_start_sect(ptes[j-1].ext_pointer,
+					   ojj-extended_offset);
+			set_start_sect(ptes[j].ext_pointer,
+					   oj-extended_offset);
+			goto stage1;
+		}
+	}
+
+	/* Stage 2: sort starting sectors */
+ stage2:
+	for (j = 4; j < partitions-1; j++) {
+		pj = ptes[j].part_table;
+		pjj = ptes[j+1].part_table;
+		sj = get_start_sect(pj);
+		sjj = get_start_sect(pjj);
+		oj = ptes[j].offset;
+		ojj = ptes[j+1].offset;
+		if (oj+sj > ojj+sjj) {
+			tmp = *pj;
+			*pj = *pjj;
+			*pjj = tmp;
+			set_start_sect(pj, ojj+sjj-oj);
+			set_start_sect(pjj, oj+sj-ojj);
+			goto stage2;
+		}
+	}
+
+	/* Probably something was changed */
+	for (j = 4; j < partitions; j++)
+		ptes[j].changed = 1;
+}
+
+
+static void
+fix_partition_table_order(void)
+{
+	struct pte *pei, *pek;
+	int i,k;
+
+	if (!wrong_p_order(NULL)) {
+		printf(_("Nothing to do. Ordering is correct already.\n\n"));
+		return;
+	}
+
+	while ((i = wrong_p_order(&k)) != 0 && i < 4) {
+		/* partition i should have come earlier, move it */
+		/* We have to move data in the MBR */
+		struct partition *pi, *pk, *pe, pbuf;
+		pei = &ptes[i];
+		pek = &ptes[k];
+
+		pe = pei->ext_pointer;
+		pei->ext_pointer = pek->ext_pointer;
+		pek->ext_pointer = pe;
+
+		pi = pei->part_table;
+		pk = pek->part_table;
+
+		memmove(&pbuf, pi, sizeof(struct partition));
+		memmove(pi, pk, sizeof(struct partition));
+		memmove(pk, &pbuf, sizeof(struct partition));
+
+		pei->changed = pek->changed = 1;
+	}
+
+	if (i)
+		fix_chain_of_logicals();
+
+	printf("Done.\n");
+
+}
+#endif
+
+static void
+list_table(int xtra)
+{
+	const struct partition *p;
+	int i, w;
+
+#ifdef CONFIG_FEATURE_SUN_LABEL
+	if (label_sun == current_label_type) {
+		sun_list_table(xtra);
+		return;
+	}
+#endif
+
+#ifdef CONFIG_FEATURE_SGI_LABEL
+	if (label_sgi == current_label_type) {
+		sgi_list_table(xtra);
+		return;
+	}
+#endif
+
+	list_disk_geometry();
+
+#ifdef CONFIG_FEATURE_OSF_LABEL
+	if (label_osf == current_label_type) {
+		xbsd_print_disklabel(xtra);
+		return;
+	}
+#endif
+
+	/* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
+	   but if the device name ends in a digit, say /dev/foo1,
+	   then the partition is called /dev/foo1p3. */
+	w = strlen(disk_device);
+	if (w && isdigit(disk_device[w-1]))
+		w++;
+	if (w < 5)
+		w = 5;
+
+	printf(_("%*s Boot    Start       End    Blocks   Id  System\n"),
+		   w+1, _("Device"));
+
+	for (i = 0; i < partitions; i++) {
+		const struct pte *pe = &ptes[i];
+
+		p = pe->part_table;
+		if (p && !is_cleared_partition(p)) {
+			off_t psects = get_nr_sects(p);
+			off_t pblocks = psects;
+			unsigned int podd = 0;
+
+			if (sector_size < 1024) {
+				pblocks /= (1024 / sector_size);
+				podd = psects % (1024 / sector_size);
+			}
+			if (sector_size > 1024)
+				pblocks *= (sector_size / 1024);
+			printf(
+				"%s  %c %11llu %11llu %11llu%c  %2x  %s\n",
+			partname(disk_device, i+1, w+2),
+/* boot flag */         !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
+			? '*' : '?',
+/* start */             (unsigned long long) cround(get_partition_start(pe)),
+/* end */               (unsigned long long) cround(get_partition_start(pe) + psects
+				- (psects ? 1 : 0)),
+/* odd flag on end */   (unsigned long long) pblocks, podd ? '+' : ' ',
+/* type id */           p->sys_ind,
+/* type name */         partition_type(p->sys_ind));
+			check_consistency(p, i);
+		}
+	}
+
+	/* Is partition table in disk order? It need not be, but... */
+	/* partition table entries are not checked for correct order if this
+	   is a sgi, sun or aix labeled disk... */
+	if (label_dos == current_label_type && wrong_p_order(NULL)) {
+		/* FIXME */
+		printf(_("\nPartition table entries are not in disk order\n"));
+	}
+}
+
+#ifdef CONFIG_FEATURE_FDISK_ADVANCED
+static void
+x_list_table(int extend)
+{
+	const struct pte *pe;
+	const struct partition *p;
+	int i;
+
+	printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
+		disk_device, heads, sectors, cylinders);
+	printf(_("Nr AF  Hd Sec  Cyl  Hd Sec  Cyl    Start     Size ID\n"));
+	for (i = 0 ; i < partitions; i++) {
+		pe = &ptes[i];
+		p = (extend ? pe->ext_pointer : pe->part_table);
+		if (p != NULL) {
+			printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
+				i + 1, p->boot_ind, p->head,
+				sector(p->sector),
+				cylinder(p->sector, p->cyl), p->end_head,
+				sector(p->end_sector),
+				cylinder(p->end_sector, p->end_cyl),
+				get_start_sect(p), get_nr_sects(p), p->sys_ind);
+			if (p->sys_ind)
+				check_consistency(p, i);
+		}
+	}
+}
+#endif
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static void
+fill_bounds(off_t *first, off_t *last)
+{
+	int i;
+	const struct pte *pe = &ptes[0];
+	const struct partition *p;
+
+	for (i = 0; i < partitions; pe++,i++) {
+		p = pe->part_table;
+		if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
+			first[i] = 0xffffffff;
+			last[i] = 0;
+		} else {
+			first[i] = get_partition_start(pe);
+			last[i] = first[i] + get_nr_sects(p) - 1;
+		}
+	}
+}
+
+static void
+check(int n, uint h, uint s, uint c, off_t start)
+{
+	off_t total, real_s, real_c;
+
+	real_s = sector(s) - 1;
+	real_c = cylinder(s, c);
+	total = (real_c * sectors + real_s) * heads + h;
+	if (!total)
+		fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
+	if (h >= heads)
+		fprintf(stderr,
+			_("Partition %d: head %d greater than maximum %d\n"),
+			n, h + 1, heads);
+	if (real_s >= sectors)
+		fprintf(stderr, _("Partition %d: sector %d greater than "
+			"maximum %d\n"), n, s, sectors);
+	if (real_c >= cylinders)
+		fprintf(stderr, _("Partitions %d: cylinder %llu greater than "
+			"maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);
+	if (cylinders <= 1024 && start != total)
+		fprintf(stderr,
+			_("Partition %d: previous sectors %llu disagrees with "
+			"total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);
+}
+
+static void
+verify(void)
+{
+	int i, j;
+	uint total = 1;
+	off_t first[partitions], last[partitions];
+	struct partition *p;
+
+	if (warn_geometry())
+		return;
+
+#ifdef CONFIG_FEATURE_SUN_LABEL
+	if (label_sun == current_label_type) {
+		verify_sun();
+		return;
+	}
+#endif
+#ifdef CONFIG_FEATURE_SGI_LABEL
+	if (label_sgi == current_label_type) {
+		verify_sgi(1);
+		return;
+	}
+#endif
+
+	fill_bounds(first, last);
+	for (i = 0; i < partitions; i++) {
+		struct pte *pe = &ptes[i];
+
+		p = pe->part_table;
+		if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
+			check_consistency(p, i);
+			if (get_partition_start(pe) < first[i])
+				printf(_("Warning: bad start-of-data in "
+					"partition %d\n"), i + 1);
+			check(i + 1, p->end_head, p->end_sector, p->end_cyl,
+				last[i]);
+			total += last[i] + 1 - first[i];
+			for (j = 0; j < i; j++)
+			if ((first[i] >= first[j] && first[i] <= last[j])
+			 || ((last[i] <= last[j] && last[i] >= first[j]))) {
+				printf(_("Warning: partition %d overlaps "
+					"partition %d.\n"), j + 1, i + 1);
+				total += first[i] >= first[j] ?
+					first[i] : first[j];
+				total -= last[i] <= last[j] ?
+					last[i] : last[j];
+			}
+		}
+	}
+
+	if (extended_offset) {
+		struct pte *pex = &ptes[ext_index];
+		off_t e_last = get_start_sect(pex->part_table) +
+			get_nr_sects(pex->part_table) - 1;
+
+		for (i = 4; i < partitions; i++) {
+			total++;
+			p = ptes[i].part_table;
+			if (!p->sys_ind) {
+				if (i != 4 || i + 1 < partitions)
+					printf(_("Warning: partition %d "
+						"is empty\n"), i + 1);
+			}
+			else if (first[i] < extended_offset ||
+					last[i] > e_last)
+				printf(_("Logical partition %d not entirely in "
+					"partition %d\n"), i + 1, ext_index + 1);
+		}
+	}
+
+	if (total > heads * sectors * cylinders)
+		printf(_("Total allocated sectors %d greater than the maximum "
+			"%d\n"), total, heads * sectors * cylinders);
+	else if ((total = heads * sectors * cylinders - total) != 0)
+		printf(_("%d unallocated sectors\n"), total);
+}
+
+static void
+add_partition(int n, int sys)
+{
+	char mesg[256];         /* 48 does not suffice in Japanese */
+	int i, num_read = 0;
+	struct partition *p = ptes[n].part_table;
+	struct partition *q = ptes[ext_index].part_table;
+	long long llimit;
+	off_t start, stop = 0, limit, temp,
+		first[partitions], last[partitions];
+
+	if (p && p->sys_ind) {
+		printf(_("Partition %d is already defined.  Delete "
+			 "it before re-adding it.\n"), n + 1);
+		return;
+	}
+	fill_bounds(first, last);
+	if (n < 4) {
+		start = sector_offset;
+		if (display_in_cyl_units || !total_number_of_sectors)
+			llimit = heads * sectors * cylinders - 1;
+		else
+			llimit = total_number_of_sectors - 1;
+		limit = llimit;
+		if (limit != llimit)
+			limit = 0x7fffffff;
+		if (extended_offset) {
+			first[ext_index] = extended_offset;
+			last[ext_index] = get_start_sect(q) +
+				get_nr_sects(q) - 1;
+		}
+	} else {
+		start = extended_offset + sector_offset;
+		limit = get_start_sect(q) + get_nr_sects(q) - 1;
+	}
+	if (display_in_cyl_units)
+		for (i = 0; i < partitions; i++)
+			first[i] = (cround(first[i]) - 1) * units_per_sector;
+
+	snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
+	do {
+		temp = start;
+		for (i = 0; i < partitions; i++) {
+			int lastplusoff;
+
+			if (start == ptes[i].offset)
+				start += sector_offset;
+			lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
+			if (start >= first[i] && start <= lastplusoff)
+				start = lastplusoff + 1;
+		}
+		if (start > limit)
+			break;
+		if (start >= temp+units_per_sector && num_read) {
+			printf(_("Sector %llu is already allocated\n"), (unsigned long long)temp);
+			temp = start;
+			num_read = 0;
+		}
+		if (!num_read && start == temp) {
+			off_t saved_start;
+
+			saved_start = start;
+			start = read_int(cround(saved_start), cround(saved_start), cround(limit),
+					 0, mesg);
+			if (display_in_cyl_units) {
+				start = (start - 1) * units_per_sector;
+				if (start < saved_start) start = saved_start;
+			}
+			num_read = 1;
+		}
+	} while (start != temp || !num_read);
+	if (n > 4) {                    /* NOT for fifth partition */
+		struct pte *pe = &ptes[n];
+
+		pe->offset = start - sector_offset;
+		if (pe->offset == extended_offset) { /* must be corrected */
+			pe->offset++;
+			if (sector_offset == 1)
+				start++;
+		}
+	}
+
+	for (i = 0; i < partitions; i++) {
+		struct pte *pe = &ptes[i];
+
+		if (start < pe->offset && limit >= pe->offset)
+			limit = pe->offset - 1;
+		if (start < first[i] && limit >= first[i])
+			limit = first[i] - 1;
+	}
+	if (start > limit) {
+		printf(_("No free sectors available\n"));
+		if (n > 4)
+			partitions--;
+		return;
+	}
+	if (cround(start) == cround(limit)) {
+		stop = limit;
+	} else {
+		snprintf(mesg, sizeof(mesg),
+			 _("Last %s or +size or +sizeM or +sizeK"),
+			 str_units(SINGULAR));
+		stop = read_int(cround(start), cround(limit), cround(limit),
+				cround(start), mesg);
+		if (display_in_cyl_units) {
+			stop = stop * units_per_sector - 1;
+			if (stop >limit)
+				stop = limit;
+		}
+	}
+
+	set_partition(n, 0, start, stop, sys);
+	if (n > 4)
+		set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
+
+	if (IS_EXTENDED(sys)) {
+		struct pte *pe4 = &ptes[4];
+		struct pte *pen = &ptes[n];
+
+		ext_index = n;
+		pen->ext_pointer = p;
+		pe4->offset = extended_offset = start;
+		pe4->sectorbuffer = xcalloc(1, sector_size);
+		pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
+		pe4->ext_pointer = pe4->part_table + 1;
+		pe4->changed = 1;
+		partitions = 5;
+	}
+}
+
+static void
+add_logical(void)
+{
+	if (partitions > 5 || ptes[4].part_table->sys_ind) {
+		struct pte *pe = &ptes[partitions];
+
+		pe->sectorbuffer = xcalloc(1, sector_size);
+		pe->part_table = pt_offset(pe->sectorbuffer, 0);
+		pe->ext_pointer = pe->part_table + 1;
+		pe->offset = 0;
+		pe->changed = 1;
+		partitions++;
+	}
+	add_partition(partitions - 1, LINUX_NATIVE);
+}
+
+static void
+new_partition(void)
+{
+	int i, free_primary = 0;
+
+	if (warn_geometry())
+		return;
+
+#ifdef CONFIG_FEATURE_SUN_LABEL
+	if (label_sun == current_label_type) {
+		add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
+		return;
+	}
+#endif
+#ifdef CONFIG_FEATURE_SGI_LABEL
+	if (label_sgi == current_label_type) {
+		sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
+		return;
+	}
+#endif
+#ifdef CONFIG_FEATURE_AIX_LABEL
+	if (label_aix == current_label_type) {
+		printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
+			 "\n\tIf you want to add DOS-type partitions, create"
+			 "\n\ta new empty DOS partition table first. (Use o.)"
+			 "\n\tWARNING: "
+			 "This will destroy the present disk contents.\n"));
+		return;
+	}
+#endif
+
+	for (i = 0; i < 4; i++)
+		free_primary += !ptes[i].part_table->sys_ind;
+
+	if (!free_primary && partitions >= MAXIMUM_PARTS) {
+		printf(_("The maximum number of partitions has been created\n"));
+		return;
+	}
+
+	if (!free_primary) {
+		if (extended_offset)
+			add_logical();
+		else
+			printf(_("You must delete some partition and add "
+				 "an extended partition first\n"));
+	} else {
+		char c, line[LINE_LENGTH];
+		snprintf(line, sizeof(line), "%s\n   %s\n   p   primary "
+						"partition (1-4)\n",
+			 "Command action", (extended_offset ?
+			 "l   logical (5 or over)" : "e   extended"));
+		while (1) {
+			if ((c = read_char(line)) == 'p' || c == 'P') {
+				i = get_nonexisting_partition(0, 4);
+				if (i >= 0)
+					add_partition(i, LINUX_NATIVE);
+				return;
+			}
+			else if (c == 'l' && extended_offset) {
+				add_logical();
+				return;
+			}
+			else if (c == 'e' && !extended_offset) {
+				i = get_nonexisting_partition(0, 4);
+				if (i >= 0)
+					add_partition(i, EXTENDED);
+				return;
+			}
+			else
+				printf(_("Invalid partition number "
+					 "for type `%c'\n"), c);
+		}
+	}
+}
+
+static void
+write_table(void)
+{
+	int i;
+
+	if (label_dos == current_label_type) {
+		for (i = 0; i < 3; i++)
+			if (ptes[i].changed)
+				ptes[3].changed = 1;
+		for (i = 3; i < partitions; i++) {
+			struct pte *pe = &ptes[i];
+
+			if (pe->changed) {
+				write_part_table_flag(pe->sectorbuffer);
+				write_sector(pe->offset, pe->sectorbuffer);
+			}
+		}
+	}
+#ifdef CONFIG_FEATURE_SGI_LABEL
+	else if (label_sgi == current_label_type) {
+		/* no test on change? the printf below might be mistaken */
+		sgi_write_table();
+	}
+#endif
+#ifdef CONFIG_FEATURE_SUN_LABEL
+	else if (label_sun == current_label_type) {
+		int needw = 0;
+
+		for (i = 0; i < 8; i++)
+			if (ptes[i].changed)
+				needw = 1;
+		if (needw)
+			sun_write_table();
+	}
+#endif
+
+	printf(_("The partition table has been altered!\n\n"));
+	reread_partition_table(1);
+}
+
+static void
+reread_partition_table(int leave)
+{
+	int error = 0;
+	int i;
+
+	printf(_("Calling ioctl() to re-read partition table.\n"));
+	sync();
+	sleep(2);
+	if ((i = ioctl(fd, BLKRRPART)) != 0) {
+		error = errno;
+	} else {
+		/* some kernel versions (1.2.x) seem to have trouble
+		   rereading the partition table, but if asked to do it
+		   twice, the second time works. - biro at yggdrasil.com */
+		sync();
+		sleep(2);
+		if ((i = ioctl(fd, BLKRRPART)) != 0)
+			error = errno;
+	}
+
+	if (i) {
+		printf(_("\nWARNING: Re-reading the partition table "
+			 "failed with error %d: %s.\n"
+			 "The kernel still uses the old table.\n"
+			 "The new table will be used "
+			 "at the next reboot.\n"),
+			error, strerror(error));
+	}
+
+	if (dos_changed)
+		printf(
+		_("\nWARNING: If you have created or modified any DOS 6.x\n"
+		"partitions, please see the fdisk manual page for additional\n"
+		"information.\n"));
+
+	if (leave) {
+		close(fd);
+
+		printf(_("Syncing disks.\n"));
+		sync();
+		sleep(4);               /* for sync() */
+		exit(!!i);
+	}
+}
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
+
+#ifdef CONFIG_FEATURE_FDISK_ADVANCED
+#define MAX_PER_LINE    16
+static void
+print_buffer(char *pbuffer)
+{
+	int i,l;
+
+	for (i = 0, l = 0; i < sector_size; i++, l++) {
+		if (l == 0)
+			printf("0x%03X:", i);
+		printf(" %02X", (unsigned char) pbuffer[i]);
+		if (l == MAX_PER_LINE - 1) {
+			printf("\n");
+			l = -1;
+		}
+	}
+	if (l > 0)
+		printf("\n");
+	printf("\n");
+}
+
+
+static void
+print_raw(void)
+{
+	int i;
+
+	printf(_("Device: %s\n"), disk_device);
+#if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
+	if (label_sun == current_label_type || label_sgi == current_label_type)
+		print_buffer(MBRbuffer);
+	else
+#endif
+		for (i = 3; i < partitions; i++)
+			print_buffer(ptes[i].sectorbuffer);
+}
+
+static void
+move_begin(int i)
+{
+	struct pte *pe = &ptes[i];
+	struct partition *p = pe->part_table;
+	off_t new, first;
+
+	if (warn_geometry())
+		return;
+	if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
+		printf(_("Partition %d has no data area\n"), i + 1);
+		return;
+	}
+	first = get_partition_start(pe);
+	new = read_int(first, first, first + get_nr_sects(p) - 1, first,
+			   _("New beginning of data")) - pe->offset;
+
+	if (new != get_nr_sects(p)) {
+		first = get_nr_sects(p) + get_start_sect(p) - new;
+		set_nr_sects(p, first);
+		set_start_sect(p, new);
+		pe->changed = 1;
+	}
+}
+
+static void
+xselect(void)
+{
+	char c;
+
+	while (1) {
+		putchar('\n');
+		c = tolower(read_char(_("Expert command (m for help): ")));
+		switch (c) {
+		case 'a':
+#ifdef CONFIG_FEATURE_SUN_LABEL
+			if (label_sun == current_label_type)
+				sun_set_alt_cyl();
+#endif
+			break;
+		case 'b':
+			if (label_dos == current_label_type)
+				move_begin(get_partition(0, partitions));
+			break;
+		case 'c':
+			user_cylinders = cylinders =
+				read_int(1, cylinders, 1048576, 0,
+					_("Number of cylinders"));
+#ifdef CONFIG_FEATURE_SUN_LABEL
+			if (label_sun == current_label_type)
+				sun_set_ncyl(cylinders);
+#endif
+			if (label_dos == current_label_type)
+				warn_cylinders();
+			break;
+		case 'd':
+			print_raw();
+			break;
+		case 'e':
+#ifdef CONFIG_FEATURE_SGI_LABEL
+			if (label_sgi == current_label_type)
+				sgi_set_xcyl();
+			else
+#endif
+#ifdef CONFIG_FEATURE_SUN_LABEL
+			 if (label_sun == current_label_type)
+				sun_set_xcyl();
+			 else
+#endif
+			if (label_dos == current_label_type)
+				x_list_table(1);
+			break;
+		case 'f':
+			if (label_dos == current_label_type)
+				fix_partition_table_order();
+			break;
+		case 'g':
+#ifdef CONFIG_FEATURE_SGI_LABEL
+			create_sgilabel();
+#endif
+			break;
+		case 'h':
+			user_heads = heads = read_int(1, heads, 256, 0,
+					_("Number of heads"));
+			update_units();
+			break;
+		case 'i':
+#ifdef CONFIG_FEATURE_SUN_LABEL
+			if (label_sun == current_label_type)
+				sun_set_ilfact();
+#endif
+			break;
+		case 'o':
+#ifdef CONFIG_FEATURE_SUN_LABEL
+			if (label_sun == current_label_type)
+				sun_set_rspeed();
+#endif
+			break;
+		case 'p':
+#ifdef CONFIG_FEATURE_SUN_LABEL
+			if (label_sun == current_label_type)
+				list_table(1);
+			else
+#endif
+				x_list_table(0);
+			break;
+		case 'q':
+			close(fd);
+			printf("\n");
+			exit(0);
+		case 'r':
+			return;
+		case 's':
+			user_sectors = sectors = read_int(1, sectors, 63, 0,
+					   _("Number of sectors"));
+			if (dos_compatible_flag) {
+				sector_offset = sectors;
+				fprintf(stderr, _("Warning: setting "
+					"sector offset for DOS "
+					"compatiblity\n"));
+			}
+			update_units();
+			break;
+		case 'v':
+			verify();
+			break;
+		case 'w':
+			write_table();  /* does not return */
+			break;
+		case 'y':
+#ifdef CONFIG_FEATURE_SUN_LABEL
+			if (label_sun == current_label_type)
+				sun_set_pcylcount();
+#endif
+			break;
+		default:
+			xmenu();
+		}
+	}
+}
+#endif /* ADVANCED mode */
+
+static int
+is_ide_cdrom_or_tape(const char *device)
+{
+	FILE *procf;
+	char buf[100];
+	struct stat statbuf;
+	int is_ide = 0;
+
+	/* No device was given explicitly, and we are trying some
+	   likely things.  But opening /dev/hdc may produce errors like
+	   "hdc: tray open or drive not ready"
+	   if it happens to be a CD-ROM drive. It even happens that
+	   the process hangs on the attempt to read a music CD.
+	   So try to be careful. This only works since 2.1.73. */
+
+	if (strncmp("/dev/hd", device, 7))
+		return 0;
+
+	snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
+	procf = fopen(buf, "r");
+	if (procf != NULL && fgets(buf, sizeof(buf), procf))
+		is_ide = (!strncmp(buf, "cdrom", 5) ||
+			  !strncmp(buf, "tape", 4));
+	else
+		/* Now when this proc file does not exist, skip the
+		   device when it is read-only. */
+		if (stat(device, &statbuf) == 0)
+			is_ide = ((statbuf.st_mode & 0222) == 0);
+
+	if (procf)
+		fclose(procf);
+	return is_ide;
+}
+
+
+static void
+try(const char *device, int user_specified)
+{
+	int gb;
+
+	disk_device = device;
+	if (setjmp(listingbuf))
+		return;
+	if (!user_specified)
+		if (is_ide_cdrom_or_tape(device))
+			return;
+	if ((fd = open(disk_device, type_open)) >= 0) {
+		gb = get_boot(try_only);
+		if (gb > 0) {   /* I/O error */
+			close(fd);
+		} else if (gb < 0) { /* no DOS signature */
+			list_disk_geometry();
+			if (label_aix == current_label_type){
+				return;
+			}
+#ifdef CONFIG_FEATURE_OSF_LABEL
+			if (btrydev(device) < 0)
+#endif
+				fprintf(stderr,
+					_("Disk %s doesn't contain a valid "
+					"partition table\n"), device);
+			close(fd);
+		} else {
+			close(fd);
+			list_table(0);
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+			if (label_sun != current_label_type && partitions > 4){
+				delete_partition(ext_index);
+			}
+#endif
+		}
+	} else {
+		/* Ignore other errors, since we try IDE
+		   and SCSI hard disks which may not be
+		   installed on the system. */
+		if (errno == EACCES) {
+			fprintf(stderr, _("Cannot open %s\n"), device);
+			return;
+		}
+	}
+}
+
+/* for fdisk -l: try all things in /proc/partitions
+   that look like a partition name (do not end in a digit) */
+static void
+tryprocpt(void)
+{
+	FILE *procpt;
+	char line[100], ptname[100], devname[120], *s;
+	int ma, mi, sz;
+
+	procpt = bb_wfopen(PROC_PARTITIONS, "r");
+
+	while (fgets(line, sizeof(line), procpt)) {
+		if (sscanf(line, " %d %d %d %[^\n ]",
+				&ma, &mi, &sz, ptname) != 4)
+			continue;
+		for (s = ptname; *s; s++);
+		if (isdigit(s[-1]))
+			continue;
+		sprintf(devname, "/dev/%s", ptname);
+		try(devname, 0);
+	}
+#ifdef CONFIG_FEATURE_CLEAN_UP
+	fclose(procpt);
+#endif
+}
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static void
+unknown_command(int c)
+{
+	printf(_("%c: unknown command\n"), c);
+}
+#endif
+
+int fdisk_main(int argc, char **argv)
+{
+	int c;
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+	int optl = 0;
+#endif
+#ifdef CONFIG_FEATURE_FDISK_BLKSIZE
+	int opts = 0;
+#endif
+	/*
+	 * Calls:
+	 *  fdisk -v
+	 *  fdisk -l [-b sectorsize] [-u] device ...
+	 *  fdisk -s [partition] ...
+	 *  fdisk [-b sectorsize] [-u] device
+	 *
+	 * Options -C, -H, -S set the geometry.
+	 *
+	 */
+	while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
+#ifdef CONFIG_FEATURE_FDISK_BLKSIZE
+					"s"
+#endif
+						)) != -1) {
+		switch (c) {
+		case 'b':
+			/* Ugly: this sector size is really per device,
+			   so cannot be combined with multiple disks,
+			   and te same goes for the C/H/S options.
+			*/
+			sector_size = atoi(optarg);
+			if (sector_size != 512 && sector_size != 1024 &&
+				sector_size != 2048)
+				bb_show_usage();
+			sector_offset = 2;
+			user_set_sector_size = 1;
+			break;
+		case 'C':
+			user_cylinders = atoi(optarg);
+			break;
+		case 'H':
+			user_heads = atoi(optarg);
+			if (user_heads <= 0 || user_heads >= 256)
+				user_heads = 0;
+			break;
+		case 'S':
+			user_sectors = atoi(optarg);
+			if (user_sectors <= 0 || user_sectors >= 64)
+				user_sectors = 0;
+			break;
+		case 'l':
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+			optl = 1;
+#endif
+			break;
+#ifdef CONFIG_FEATURE_FDISK_BLKSIZE
+		case 's':
+			opts = 1;
+			break;
+#endif
+		case 'u':
+			display_in_cyl_units = 0;
+			break;
+		case 'V':
+		case 'v':
+			printf("fdisk v" UTIL_LINUX_VERSION "\n");
+			return 0;
+		default:
+			bb_show_usage();
+		}
+	}
+
+#if 0
+	printf(_("This kernel finds the sector size itself - "
+		 "-b option ignored\n"));
+#else
+	if (user_set_sector_size && argc-optind != 1)
+		printf(_("Warning: the -b (set sector size) option should"
+			 " be used with one specified device\n"));
+#endif
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+	if (optl) {
+		nowarn = 1;
+#endif
+		type_open = O_RDONLY;
+		if (argc > optind) {
+			int k;
+#if __GNUC__
+			/* avoid gcc warning:
+			   variable `k' might be clobbered by `longjmp' */
+			(void)&k;
+#endif
+			listing = 1;
+			for (k = optind; k < argc; k++)
+				try(argv[k], 1);
+		} else {
+			/* we no longer have default device names */
+			/* but, we can use /proc/partitions instead */
+			tryprocpt();
+		}
+		return 0;
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+	}
+#endif
+
+#ifdef CONFIG_FEATURE_FDISK_BLKSIZE
+	if (opts) {
+		long size;
+		int j;
+
+		nowarn = 1;
+		type_open = O_RDONLY;
+
+		opts = argc - optind;
+		if (opts <= 0)
+			bb_show_usage();
+
+		for (j = optind; j < argc; j++) {
+			disk_device = argv[j];
+			if ((fd = open(disk_device, type_open)) < 0)
+				fdisk_fatal(unable_to_open);
+			if (ioctl(fd, BLKGETSIZE, &size))
+				fdisk_fatal(ioctl_error);
+			close(fd);
+			if (opts == 1)
+				printf("%ld\n", size/2);
+			else
+				printf("%s: %ld\n", argv[j], size/2);
+		}
+		return 0;
+	}
+#endif
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+	if (argc-optind == 1)
+		disk_device = argv[optind];
+	else
+		bb_show_usage();
+
+	get_boot(fdisk);
+
+#ifdef CONFIG_FEATURE_OSF_LABEL
+	if (label_osf == current_label_type) {
+		/* OSF label, and no DOS label */
+		printf(_("Detected an OSF/1 disklabel on %s, entering "
+			 "disklabel mode.\n"),
+			   disk_device);
+		bselect();
+		/*Why do we do this?  It seems to be counter-intuitive*/
+		current_label_type = label_dos;
+		/* If we return we may want to make an empty DOS label? */
+	}
+#endif
+
+	while (1) {
+		putchar('\n');
+		c = tolower(read_char(_("Command (m for help): ")));
+		switch (c) {
+		case 'a':
+			if (label_dos == current_label_type)
+				toggle_active(get_partition(1, partitions));
+#ifdef CONFIG_FEATURE_SUN_LABEL
+			else if (label_sun == current_label_type)
+				toggle_sunflags(get_partition(1, partitions),
+						0x01);
+#endif
+#ifdef CONFIG_FEATURE_SGI_LABEL
+			else if (label_sgi == current_label_type)
+				sgi_set_bootpartition(
+					get_partition(1, partitions));
+#endif
+			else
+				unknown_command(c);
+			break;
+		case 'b':
+#ifdef CONFIG_FEATURE_SGI_LABEL
+			if (label_sgi == current_label_type) {
+				printf(_("\nThe current boot file is: %s\n"),
+					sgi_get_bootfile());
+				if (read_chars(_("Please enter the name of the "
+						   "new boot file: ")) == '\n')
+					printf(_("Boot file unchanged\n"));
+				else
+					sgi_set_bootfile(line_ptr);
+			} else
+#endif
+#ifdef CONFIG_FEATURE_OSF_LABEL
+				bselect();
+#endif
+			break;
+		case 'c':
+			if (label_dos == current_label_type)
+				toggle_dos_compatibility_flag();
+#ifdef CONFIG_FEATURE_SUN_LABEL
+			else if (label_sun == current_label_type)
+				toggle_sunflags(get_partition(1, partitions),
+						0x10);
+#endif
+#ifdef CONFIG_FEATURE_SGI_LABEL
+			else if (label_sgi == current_label_type)
+				sgi_set_swappartition(
+						get_partition(1, partitions));
+#endif
+			else
+				unknown_command(c);
+			break;
+		case 'd':
+			{
+				int j;
+#ifdef CONFIG_FEATURE_SGI_LABEL
+			/* If sgi_label then don't use get_existing_partition,
+			   let the user select a partition, since
+			   get_existing_partition() only works for Linux-like
+			   partition tables */
+				if (label_sgi != current_label_type) {
+					j = get_existing_partition(1, partitions);
+				} else {
+					j = get_partition(1, partitions);
+				}
+#else
+				j = get_existing_partition(1, partitions);
+#endif
+				if (j >= 0)
+					delete_partition(j);
+			}
+			break;
+		case 'i':
+#ifdef CONFIG_FEATURE_SGI_LABEL
+			if (label_sgi == current_label_type)
+				create_sgiinfo();
+			else
+#endif
+				unknown_command(c);
+		case 'l':
+			list_types(get_sys_types());
+			break;
+		case 'm':
+			menu();
+			break;
+		case 'n':
+			new_partition();
+			break;
+		case 'o':
+			create_doslabel();
+			break;
+		case 'p':
+			list_table(0);
+			break;
+		case 'q':
+			close(fd);
+			printf("\n");
+			return 0;
+		case 's':
+#ifdef CONFIG_FEATURE_SUN_LABEL
+			create_sunlabel();
+#endif
+			break;
+		case 't':
+			change_sysid();
+			break;
+		case 'u':
+			change_units();
+			break;
+		case 'v':
+			verify();
+			break;
+		case 'w':
+			write_table();          /* does not return */
+			break;
+#ifdef CONFIG_FEATURE_FDISK_ADVANCED
+		case 'x':
+#ifdef CONFIG_FEATURE_SGI_LABEL
+			if (label_sgi == current_label_type) {
+				fprintf(stderr,
+					_("\n\tSorry, no experts menu for SGI "
+					"partition tables available.\n\n"));
+			} else
+#endif
+
+				xselect();
+			break;
+#endif
+		default:
+			unknown_command(c);
+			menu();
+		}
+	}
+	return 0;
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/freeramdisk.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/freeramdisk.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/freeramdisk.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,41 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * freeramdisk and fdflush implementations for busybox
+ *
+ * Copyright (C) 2000 and written by Emanuele Caratti <wiz at iol.it>
+ * Adjusted a bit by Erik Andersen <andersen at codepoet.org>
+ * Unified with fdflush by Tito Ragusa <farmatito at tiscali.it>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "busybox.h"
+
+/* From <linux/fd.h> */
+#define FDFLUSH  _IO(2,0x4b)
+
+int freeramdisk_main(int argc, char **argv)
+{
+	int result;
+	int fd;
+
+	if (argc != 2) bb_show_usage();
+
+	fd = bb_xopen(argv[1], O_RDWR);
+
+	// Act like freeramdisk, fdflush, or both depending on configuration.
+	result = ioctl(fd, (ENABLE_FREERAMDISK && bb_applet_name[1]=='r')
+			|| !ENABLE_FDFLUSH ? BLKFLSBUF : FDFLUSH);
+
+	if (ENABLE_FEATURE_CLEAN_UP) close(fd);
+
+	if (result) bb_perror_msg_and_die("%s", argv[1]);
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/fsck_minix.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/fsck_minix.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/fsck_minix.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,1425 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * fsck.c - a file system consistency checker for Linux.
+ *
+ * (C) 1991, 1992 Linus Torvalds. This file may be redistributed
+ * as per the GNU copyleft.
+ */
+
+/*
+ * 09.11.91  -  made the first rudimentary functions
+ *
+ * 10.11.91  -  updated, does checking, no repairs yet.
+ *		Sent out to the mailing-list for testing.
+ *
+ * 14.11.91  -	Testing seems to have gone well. Added some
+ *		correction-code, and changed some functions.
+ *
+ * 15.11.91  -  More correction code. Hopefully it notices most
+ *		cases now, and tries to do something about them.
+ *
+ * 16.11.91  -  More corrections (thanks to Mika Jalava). Most
+ *		things seem to work now. Yeah, sure.
+ *
+ *
+ * 19.04.92  -	Had to start over again from this old version, as a
+ *		kernel bug ate my enhanced fsck in february.
+ *
+ * 28.02.93  -	added support for different directory entry sizes..
+ *
+ * Sat Mar  6 18:59:42 1993, faith at cs.unc.edu: Output namelen with
+ *                           super-block information
+ *
+ * Sat Oct  9 11:17:11 1993, faith at cs.unc.edu: make exit status conform
+ *                           to that required by fsutil
+ *
+ * Mon Jan  3 11:06:52 1994 - Dr. Wettstein (greg%wind.uucp at plains.nodak.edu)
+ *			      Added support for file system valid flag.  Also
+ *			      added program_version variable and output of
+ *			      program name and version number when program
+ *			      is executed.
+ *
+ * 30.10.94 - added support for v2 filesystem
+ *            (Andreas Schwab, schwab at issan.informatik.uni-dortmund.de)
+ *
+ * 10.12.94  -  added test to prevent checking of mounted fs adapted
+ *              from Theodore Ts'o's (tytso at athena.mit.edu) e2fsck
+ *              program.  (Daniel Quinlan, quinlan at yggdrasil.com)
+ *
+ * 01.07.96  - Fixed the v2 fs stuff to use the right #defines and such
+ *	       for modern libcs (janl at math.uio.no, Nicolai Langfeldt)
+ *
+ * 02.07.96  - Added C bit fiddling routines from rmk at ecs.soton.ac.uk
+ *             (Russell King).  He made them for ARM.  It would seem
+ *	       that the ARM is powerful enough to do this in C whereas
+ *             i386 and m64k must use assembly to get it fast >:-)
+ *	       This should make minix fsck system-independent.
+ *	       (janl at math.uio.no, Nicolai Langfeldt)
+ *
+ * 04.11.96  - Added minor fixes from Andreas Schwab to avoid compiler
+ *             warnings.  Added mc68k bitops from
+ *	       Joerg Dorchain <dorchain at mpi-sb.mpg.de>.
+ *
+ * 06.11.96  - Added v2 code submitted by Joerg Dorchain, but written by
+ *             Andreas Schwab.
+ *
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek at misiek.eu.org>
+ * - added Native Language Support
+ *
+ *
+ * I've had no time to add comments - hopefully the function names
+ * are comments enough. As with all file system checkers, this assumes
+ * the file system is quiescent - don't use it on a mounted device
+ * unless you can be sure nobody is writing to it (and remember that the
+ * kernel can write to it when it searches for files).
+ *
+ * Usage: fsck [-larvsm] device
+ *	-l for a listing of all the filenames
+ *	-a for automatic repairs (not implemented)
+ *	-r for repairs (interactive) (not implemented)
+ *	-v for verbose (tells how many files)
+ *	-s for super-block info
+ *	-m for minix-like "mode not cleared" warnings
+ *	-f force filesystem check even if filesystem marked as valid
+ *
+ * The device may be a block device or a image of one, but this isn't
+ * enforced (but it's not much fun on a character device :-).
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <mntent.h>
+#include <sys/param.h>
+#include "busybox.h"
+
+/*
+ * This is the original minix inode layout on disk.
+ * Note the 8-bit gid and atime and ctime.
+ */
+struct minix_inode {
+	uint16_t i_mode;
+	uint16_t i_uid;
+	uint32_t i_size;
+	uint32_t i_time;
+	uint8_t  i_gid;
+	uint8_t  i_nlinks;
+	uint16_t i_zone[9];
+};
+
+/*
+ * The new minix inode has all the time entries, as well as
+ * long block numbers and a third indirect block (7+1+1+1
+ * instead of 7+1+1). Also, some previously 8-bit values are
+ * now 16-bit. The inode is now 64 bytes instead of 32.
+ */
+struct minix2_inode {
+	uint16_t i_mode;
+	uint16_t i_nlinks;
+	uint16_t i_uid;
+	uint16_t i_gid;
+	uint32_t i_size;
+	uint32_t i_atime;
+	uint32_t i_mtime;
+	uint32_t i_ctime;
+	uint32_t i_zone[10];
+};
+
+enum {
+	MINIX_ROOT_INO = 1,
+	MINIX_LINK_MAX = 250,
+	MINIX2_LINK_MAX = 65530,
+
+	MINIX_I_MAP_SLOTS = 8,
+	MINIX_Z_MAP_SLOTS = 64,
+	MINIX_SUPER_MAGIC = 0x137F,		/* original minix fs */
+	MINIX_SUPER_MAGIC2 = 0x138F,		/* minix fs, 30 char names */
+	MINIX2_SUPER_MAGIC = 0x2468,		/* minix V2 fs */
+	MINIX2_SUPER_MAGIC2 = 0x2478,		/* minix V2 fs, 30 char names */
+	MINIX_VALID_FS = 0x0001,		/* Clean fs. */
+	MINIX_ERROR_FS = 0x0002,		/* fs has errors. */
+
+	MINIX_INODES_PER_BLOCK = ((BLOCK_SIZE)/(sizeof (struct minix_inode))),
+	MINIX2_INODES_PER_BLOCK = ((BLOCK_SIZE)/(sizeof (struct minix2_inode))),
+
+	MINIX_V1 = 0x0001,		/* original minix fs */
+	MINIX_V2 = 0x0002 		/* minix V2 fs */
+};
+
+#define INODE_VERSION(inode)	inode->i_sb->u.minix_sb.s_version
+
+/*
+ * minix super-block data on disk
+ */
+struct minix_super_block {
+	uint16_t s_ninodes;
+	uint16_t s_nzones;
+	uint16_t s_imap_blocks;
+	uint16_t s_zmap_blocks;
+	uint16_t s_firstdatazone;
+	uint16_t s_log_zone_size;
+	uint32_t s_max_size;
+	uint16_t s_magic;
+	uint16_t s_state;
+	uint32_t s_zones;
+};
+
+struct minix_dir_entry {
+	uint16_t inode;
+	char name[0];
+};
+
+
+#define NAME_MAX         255   /* # chars in a file name */
+
+#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
+
+#ifndef BLKGETSIZE
+#define BLKGETSIZE _IO(0x12,96)    /* return device size */
+#endif
+
+#ifndef __linux__
+#define volatile
+#endif
+
+enum { ROOT_INO = 1 };
+
+#define UPPER(size,n) ((size+((n)-1))/(n))
+#define INODE_SIZE (sizeof(struct minix_inode))
+#ifdef CONFIG_FEATURE_MINIX2
+#define INODE_SIZE2 (sizeof(struct minix2_inode))
+#define INODE_BLOCKS UPPER(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \
+				    : MINIX_INODES_PER_BLOCK))
+#else
+#define INODE_BLOCKS UPPER(INODES, (MINIX_INODES_PER_BLOCK))
+#endif
+#define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE)
+
+#define BITS_PER_BLOCK (BLOCK_SIZE<<3)
+
+static char *program_version = "1.2 - 11/11/96";
+static char *device_name;
+static int IN;
+static int repair, automatic, verbose, list, show, warn_mode, force;
+static int directory, regular, blockdev, chardev, links, symlinks, total;
+
+static int changed;			/* flags if the filesystem has been changed */
+static int errors_uncorrected;	/* flag if some error was not corrected */
+static int dirsize = 16;
+static int namelen = 14;
+static struct termios termios;
+static int termios_set;
+
+static char *inode_buffer;
+#define Inode (((struct minix_inode *) inode_buffer)-1)
+#define Inode2 (((struct minix2_inode *) inode_buffer)-1)
+static char super_block_buffer[BLOCK_SIZE];
+
+#define Super (*(struct minix_super_block *)super_block_buffer)
+#define INODES ((unsigned long)Super.s_ninodes)
+#ifdef CONFIG_FEATURE_MINIX2
+static int version2;
+#define ZONES ((unsigned long)(version2 ? Super.s_zones : Super.s_nzones))
+#else
+#define ZONES ((unsigned long)(Super.s_nzones))
+#endif
+#define IMAPS ((unsigned long)Super.s_imap_blocks)
+#define ZMAPS ((unsigned long)Super.s_zmap_blocks)
+#define FIRSTZONE ((unsigned long)Super.s_firstdatazone)
+#define ZONESIZE ((unsigned long)Super.s_log_zone_size)
+#define MAXSIZE ((unsigned long)Super.s_max_size)
+#define MAGIC (Super.s_magic)
+#define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS)
+
+static char *inode_map;
+static char *zone_map;
+
+static unsigned char *inode_count;
+static unsigned char *zone_count;
+
+static void recursive_check(unsigned int ino);
+#ifdef CONFIG_FEATURE_MINIX2
+static void recursive_check2(unsigned int ino);
+#endif
+
+static inline int bit(char *a, unsigned int i)
+{
+	  return (a[i >> 3] & (1<<(i & 7))) != 0;
+}
+#define inode_in_use(x) (bit(inode_map,(x)))
+#define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1))
+
+#define mark_inode(x) (setbit(inode_map,(x)),changed=1)
+#define unmark_inode(x) (clrbit(inode_map,(x)),changed=1)
+
+#define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1),changed=1)
+#define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1),changed=1)
+
+static void leave(int) ATTRIBUTE_NORETURN;
+static void leave(int status)
+{
+	if (termios_set)
+		tcsetattr(0, TCSANOW, &termios);
+	exit(status);
+}
+
+static void die(const char *str)
+{
+	bb_error_msg("%s", str);
+	leave(8);
+}
+
+/* File-name data */
+enum { MAX_DEPTH = 32 };
+static int name_depth;
+static char *current_name;
+static char *name_component[MAX_DEPTH+1];
+
+/* Wed Feb  9 15:17:06 MST 2000 */
+/* dynamically allocate name_list (instead of making it static) */
+static inline void alloc_current_name(void)
+{
+	current_name = xmalloc(MAX_DEPTH * (BUFSIZ + 1));
+	current_name[0] = '/';
+	current_name[1] = '\0';
+	name_component[0] = &current_name[0];
+}
+
+#ifdef CONFIG_FEATURE_CLEAN_UP
+/* execute this atexit() to deallocate name_list[] */
+/* piptigger was here */
+static inline void free_current_name(void)
+{
+	free(current_name);
+}
+#endif
+
+static void push_filename(const char *name)
+{
+	//  /dir/dir/dir/file
+	//  ^   ^   ^
+	// [0] [1] [2] <-name_component[i]
+	if (name_depth < MAX_DEPTH) {
+		int len;
+		char *p = name_component[name_depth];
+		*p++ = '/';
+		len = sprintf(p, "%.*s", namelen, name);
+		name_component[name_depth + 1] = p + len;
+	}
+	name_depth++;
+}
+
+static void pop_filename(void) {
+	name_depth--;
+	if (name_depth < MAX_DEPTH) {
+		*name_component[name_depth] = '\0';
+		if (!name_depth) {
+			current_name[0] = '/';
+			current_name[1] = '\0';
+		}
+	}
+}
+
+static int ask(const char *string, int def)
+{
+	int c;
+
+	if (!repair) {
+		printf("\n");
+		errors_uncorrected = 1;
+		return 0;
+	}
+	if (automatic) {
+		printf("\n");
+		if (!def)
+			errors_uncorrected = 1;
+		return def;
+	}
+	printf(def ? "%s (y/n)? " : "%s (n/y)? ", string);
+	for (;;) {
+		fflush(stdout);
+		if ((c = getchar()) == EOF) {
+			if (!def)
+				errors_uncorrected = 1;
+			return def;
+		}
+		c = toupper(c);
+		if (c == 'Y') {
+			def = 1;
+			break;
+		} else if (c == 'N') {
+			def = 0;
+			break;
+		} else if (c == ' ' || c == '\n')
+			break;
+	}
+	if (def)
+		printf("y\n");
+	else {
+		printf("n\n");
+		errors_uncorrected = 1;
+	}
+	return def;
+}
+
+/*
+ * Make certain that we aren't checking a filesystem that is on a
+ * mounted partition.  Code adapted from e2fsck, Copyright (C) 1993,
+ * 1994 Theodore Ts'o.  Also licensed under GPL.
+ */
+static void check_mount(void)
+{
+	FILE *f;
+	struct mntent *mnt;
+	int cont;
+	int fd;
+
+	if ((f = setmntent(MOUNTED, "r")) == NULL)
+		return;
+	while ((mnt = getmntent(f)) != NULL)
+		if (strcmp(device_name, mnt->mnt_fsname) == 0)
+			break;
+	endmntent(f);
+	if (!mnt)
+		return;
+
+	/*
+	 * If the root is mounted read-only, then /etc/mtab is
+	 * probably not correct; so we won't issue a warning based on
+	 * it.
+	 */
+	fd = open(MOUNTED, O_RDWR);
+	if (fd < 0 && errno == EROFS)
+		return;
+	else
+		close(fd);
+
+	printf("%s is mounted. ", device_name);
+	cont = 0;
+	if (isatty(0) && isatty(1))
+		cont = ask("Do you really want to continue", 0);
+	if (!cont) {
+		printf("Check aborted\n");
+		exit(0);
+	}
+	return;
+}
+
+/*
+ * check_zone_nr checks to see that *nr is a valid zone nr. If it
+ * isn't, it will possibly be repaired. Check_zone_nr sets *corrected
+ * if an error was corrected, and returns the zone (0 for no zone
+ * or a bad zone-number).
+ */
+static int check_zone_nr2(uint32_t *nr, int *corrected)
+{
+	const char *msg;
+	if (!*nr)
+		return 0;
+	if (*nr < FIRSTZONE)
+		msg = "< FIRSTZONE";
+	else if (*nr >= ZONES)
+		msg = ">= ZONES";
+	else
+		return *nr;
+	printf("Zone nr %s in file '%s'. ", msg, current_name);
+	if (ask("Remove block", 1)) {
+		*nr = 0;
+		*corrected = 1;
+	}
+	return 0;
+}
+
+static int check_zone_nr(uint16_t *nr, int *corrected)
+{
+	uint32_t nr32 = *nr;
+	int r = check_zone_nr2(&nr32, corrected);
+	*nr = (uint16_t)nr32;
+	return r;
+}
+
+/*
+ * read-block reads block nr into the buffer at addr.
+ */
+static void read_block(unsigned int nr, char *addr)
+{
+	if (!nr) {
+		memset(addr, 0, BLOCK_SIZE);
+		return;
+	}
+	if (BLOCK_SIZE * nr != lseek(IN, BLOCK_SIZE * nr, SEEK_SET)) {
+		printf("%s: unable to seek to block in file '%s'\n",
+				bb_msg_read_error, current_name);
+		errors_uncorrected = 1;
+		memset(addr, 0, BLOCK_SIZE);
+	} else if (BLOCK_SIZE != read(IN, addr, BLOCK_SIZE)) {
+		printf("%s: bad block in file '%s'\n",
+				bb_msg_read_error, current_name);
+		errors_uncorrected = 1;
+		memset(addr, 0, BLOCK_SIZE);
+	}
+}
+
+/*
+ * write_block writes block nr to disk.
+ */
+static void write_block(unsigned int nr, char *addr)
+{
+	if (!nr)
+		return;
+	if (nr < FIRSTZONE || nr >= ZONES) {
+		printf("Internal error: trying to write bad block\n"
+			   "Write request ignored\n");
+		errors_uncorrected = 1;
+		return;
+	}
+	if (BLOCK_SIZE * nr != lseek(IN, BLOCK_SIZE * nr, SEEK_SET))
+		die("Seek failed in write_block");
+	if (BLOCK_SIZE != write(IN, addr, BLOCK_SIZE)) {
+		printf("%s: bad block in file '%s'\n",
+				bb_msg_write_error, current_name);
+		errors_uncorrected = 1;
+	}
+}
+
+/*
+ * map_block calculates the absolute block nr of a block in a file.
+ * It sets 'changed' if the inode has needed changing, and re-writes
+ * any indirect blocks with errors.
+ */
+static int map_block(struct minix_inode *inode, unsigned int blknr)
+{
+	uint16_t ind[BLOCK_SIZE >> 1];
+	uint16_t dind[BLOCK_SIZE >> 1];
+	int blk_chg, block, result;
+
+	if (blknr < 7)
+		return check_zone_nr(inode->i_zone + blknr, &changed);
+	blknr -= 7;
+	if (blknr < 512) {
+		block = check_zone_nr(inode->i_zone + 7, &changed);
+		read_block(block, (char *) ind);
+		blk_chg = 0;
+		result = check_zone_nr(blknr + ind, &blk_chg);
+		if (blk_chg)
+			write_block(block, (char *) ind);
+		return result;
+	}
+	blknr -= 512;
+	block = check_zone_nr(inode->i_zone + 8, &changed);
+	read_block(block, (char *) dind);
+	blk_chg = 0;
+	result = check_zone_nr(dind + (blknr / 512), &blk_chg);
+	if (blk_chg)
+		write_block(block, (char *) dind);
+	block = result;
+	read_block(block, (char *) ind);
+	blk_chg = 0;
+	result = check_zone_nr(ind + (blknr % 512), &blk_chg);
+	if (blk_chg)
+		write_block(block, (char *) ind);
+	return result;
+}
+
+#ifdef CONFIG_FEATURE_MINIX2
+static int map_block2(struct minix2_inode *inode, unsigned int blknr)
+{
+	uint32_t ind[BLOCK_SIZE >> 2];
+	uint32_t dind[BLOCK_SIZE >> 2];
+	uint32_t tind[BLOCK_SIZE >> 2];
+	int blk_chg, block, result;
+
+	if (blknr < 7)
+		return check_zone_nr2(inode->i_zone + blknr, &changed);
+	blknr -= 7;
+	if (blknr < 256) {
+		block = check_zone_nr2(inode->i_zone + 7, &changed);
+		read_block(block, (char *) ind);
+		blk_chg = 0;
+		result = check_zone_nr2(blknr + ind, &blk_chg);
+		if (blk_chg)
+			write_block(block, (char *) ind);
+		return result;
+	}
+	blknr -= 256;
+	if (blknr >= 256 * 256) {
+		block = check_zone_nr2(inode->i_zone + 8, &changed);
+		read_block(block, (char *) dind);
+		blk_chg = 0;
+		result = check_zone_nr2(dind + blknr / 256, &blk_chg);
+		if (blk_chg)
+			write_block(block, (char *) dind);
+		block = result;
+		read_block(block, (char *) ind);
+		blk_chg = 0;
+		result = check_zone_nr2(ind + blknr % 256, &blk_chg);
+		if (blk_chg)
+			write_block(block, (char *) ind);
+		return result;
+	}
+	blknr -= 256 * 256;
+	block = check_zone_nr2(inode->i_zone + 9, &changed);
+	read_block(block, (char *) tind);
+	blk_chg = 0;
+	result = check_zone_nr2(tind + blknr / (256 * 256), &blk_chg);
+	if (blk_chg)
+		write_block(block, (char *) tind);
+	block = result;
+	read_block(block, (char *) dind);
+	blk_chg = 0;
+	result = check_zone_nr2(dind + (blknr / 256) % 256, &blk_chg);
+	if (blk_chg)
+		write_block(block, (char *) dind);
+	block = result;
+	read_block(block, (char *) ind);
+	blk_chg = 0;
+	result = check_zone_nr2(ind + blknr % 256, &blk_chg);
+	if (blk_chg)
+		write_block(block, (char *) ind);
+	return result;
+}
+#endif
+
+static void write_super_block(void)
+{
+	/*
+	 * Set the state of the filesystem based on whether or not there
+	 * are uncorrected errors.  The filesystem valid flag is
+	 * unconditionally set if we get this far.
+	 */
+	Super.s_state |= MINIX_VALID_FS;
+	if (errors_uncorrected)
+		Super.s_state |= MINIX_ERROR_FS;
+	else
+		Super.s_state &= ~MINIX_ERROR_FS;
+
+	if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET))
+		die("Seek failed in write_super_block");
+	if (BLOCK_SIZE != write(IN, super_block_buffer, BLOCK_SIZE))
+		die("Unable to write super-block");
+}
+
+static void write_tables(void)
+{
+	write_super_block();
+
+	if (IMAPS * BLOCK_SIZE != write(IN, inode_map, IMAPS * BLOCK_SIZE))
+		die("Unable to write inode map");
+	if (ZMAPS * BLOCK_SIZE != write(IN, zone_map, ZMAPS * BLOCK_SIZE))
+		die("Unable to write zone map");
+	if (INODE_BUFFER_SIZE != write(IN, inode_buffer, INODE_BUFFER_SIZE))
+		die("Unable to write inodes");
+}
+
+static void get_dirsize(void)
+{
+	int block;
+	char blk[BLOCK_SIZE];
+	int size;
+
+#ifdef CONFIG_FEATURE_MINIX2
+	if (version2)
+		block = Inode2[ROOT_INO].i_zone[0];
+	else
+#endif
+		block = Inode[ROOT_INO].i_zone[0];
+	read_block(block, blk);
+	for (size = 16; size < BLOCK_SIZE; size <<= 1) {
+		if (strcmp(blk + size + 2, "..") == 0) {
+			dirsize = size;
+			namelen = size - 2;
+			return;
+		}
+	}
+	/* use defaults */
+}
+
+static void read_superblock(void)
+{
+	if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET))
+		die("Seek failed");
+	if (BLOCK_SIZE != read(IN, super_block_buffer, BLOCK_SIZE))
+		die("Unable to read super block");
+	/* already initialized to:
+	namelen = 14;
+	dirsize = 16;
+	version2 = 0;
+	*/
+	if (MAGIC == MINIX_SUPER_MAGIC) {
+	} else if (MAGIC == MINIX_SUPER_MAGIC2) {
+		namelen = 30;
+		dirsize = 32;
+#ifdef CONFIG_FEATURE_MINIX2
+	} else if (MAGIC == MINIX2_SUPER_MAGIC) {
+		version2 = 1;
+	} else if (MAGIC == MINIX2_SUPER_MAGIC2) {
+		namelen = 30;
+		dirsize = 32;
+		version2 = 1;
+#endif
+	} else
+		die("Bad magic number in super-block");
+	if (ZONESIZE != 0 || BLOCK_SIZE != 1024)
+		die("Only 1k blocks/zones supported");
+	if (IMAPS * BLOCK_SIZE * 8 < INODES + 1)
+		die("Bad s_imap_blocks field in super-block");
+	if (ZMAPS * BLOCK_SIZE * 8 < ZONES - FIRSTZONE + 1)
+		die("Bad s_zmap_blocks field in super-block");
+}
+
+static void read_tables(void)
+{
+	inode_map = xzalloc(IMAPS * BLOCK_SIZE);
+	zone_map = xzalloc(ZMAPS * BLOCK_SIZE);
+	inode_buffer = xmalloc(INODE_BUFFER_SIZE);
+	inode_count = xmalloc(INODES + 1);
+	zone_count = xmalloc(ZONES);
+	if (IMAPS * BLOCK_SIZE != read(IN, inode_map, IMAPS * BLOCK_SIZE))
+		die("Unable to read inode map");
+	if (ZMAPS * BLOCK_SIZE != read(IN, zone_map, ZMAPS * BLOCK_SIZE))
+		die("Unable to read zone map");
+	if (INODE_BUFFER_SIZE != read(IN, inode_buffer, INODE_BUFFER_SIZE))
+		die("Unable to read inodes");
+	if (NORM_FIRSTZONE != FIRSTZONE) {
+		printf("Warning: Firstzone!=Norm_firstzone\n");
+		errors_uncorrected = 1;
+	}
+	get_dirsize();
+	if (show) {
+		printf("%ld inodes\n"
+			"%ld blocks\n"
+			"Firstdatazone=%ld (%ld)\n"
+			"Zonesize=%d\n"
+			"Maxsize=%ld\n"
+			"Filesystem state=%d\n"
+			"namelen=%d\n\n",
+			INODES,
+			ZONES,
+			FIRSTZONE, NORM_FIRSTZONE,
+			BLOCK_SIZE << ZONESIZE,
+			MAXSIZE,
+			Super.s_state,
+			namelen);
+	}
+}
+
+static struct minix_inode *get_inode(unsigned int nr)
+{
+	struct minix_inode *inode;
+
+	if (!nr || nr > INODES)
+		return NULL;
+	total++;
+	inode = Inode + nr;
+	if (!inode_count[nr]) {
+		if (!inode_in_use(nr)) {
+			printf("Inode %d is marked as 'unused', but it is used "
+					"for file '%s'\n", nr, current_name);
+			if (repair) {
+				if (ask("Mark as 'in use'", 1))
+					mark_inode(nr);
+			} else {
+				errors_uncorrected = 1;
+			}
+		}
+		if (S_ISDIR(inode->i_mode))
+			directory++;
+		else if (S_ISREG(inode->i_mode))
+			regular++;
+		else if (S_ISCHR(inode->i_mode))
+			chardev++;
+		else if (S_ISBLK(inode->i_mode))
+			blockdev++;
+		else if (S_ISLNK(inode->i_mode))
+			symlinks++;
+		else if (S_ISSOCK(inode->i_mode));
+		else if (S_ISFIFO(inode->i_mode));
+		else {
+			printf("%s has mode %05o\n", current_name, inode->i_mode);
+		}
+
+	} else
+		links++;
+	if (!++inode_count[nr]) {
+		printf("Warning: inode count too big\n");
+		inode_count[nr]--;
+		errors_uncorrected = 1;
+	}
+	return inode;
+}
+
+#ifdef CONFIG_FEATURE_MINIX2
+static struct minix2_inode *get_inode2(unsigned int nr)
+{
+	struct minix2_inode *inode;
+
+	if (!nr || nr > INODES)
+		return NULL;
+	total++;
+	inode = Inode2 + nr;
+	if (!inode_count[nr]) {
+		if (!inode_in_use(nr)) {
+			printf("Inode %d is marked as 'unused', but it is used "
+					"for file '%s'\n", nr, current_name);
+			if (repair) {
+				if (ask("Mark as 'in use'", 1))
+					mark_inode(nr);
+				else
+					errors_uncorrected = 1;
+			}
+		}
+		if (S_ISDIR(inode->i_mode))
+			directory++;
+		else if (S_ISREG(inode->i_mode))
+			regular++;
+		else if (S_ISCHR(inode->i_mode))
+			chardev++;
+		else if (S_ISBLK(inode->i_mode))
+			blockdev++;
+		else if (S_ISLNK(inode->i_mode))
+			symlinks++;
+		else if (S_ISSOCK(inode->i_mode));
+		else if (S_ISFIFO(inode->i_mode));
+		else {
+			printf("%s has mode %05o\n", current_name, inode->i_mode);
+		}
+	} else
+		links++;
+	if (!++inode_count[nr]) {
+		printf("Warning: inode count too big\n");
+		inode_count[nr]--;
+		errors_uncorrected = 1;
+	}
+	return inode;
+}
+#endif
+
+static void check_root(void)
+{
+	struct minix_inode *inode = Inode + ROOT_INO;
+
+	if (!inode || !S_ISDIR(inode->i_mode))
+		die("Root inode isn't a directory");
+}
+
+#ifdef CONFIG_FEATURE_MINIX2
+static void check_root2(void)
+{
+	struct minix2_inode *inode = Inode2 + ROOT_INO;
+
+	if (!inode || !S_ISDIR(inode->i_mode))
+		die("Root inode isn't a directory");
+}
+#endif
+
+static int add_zone(uint16_t *znr, int *corrected)
+{
+	int result;
+	int block;
+
+	result = 0;
+	block = check_zone_nr(znr, corrected);
+	if (!block)
+		return 0;
+	if (zone_count[block]) {
+		printf("Already used block is reused in file '%s'. ",
+				current_name);
+		if (ask("Clear", 1)) {
+			*znr = 0;
+			block = 0;
+			*corrected = 1;
+			return 0;
+		}
+	}
+	if (!zone_in_use(block)) {
+		printf("Block %d in file '%s' is marked as 'unused'. ",
+				block, current_name);
+		if (ask("Correct", 1))
+			mark_zone(block);
+	}
+	if (!++zone_count[block])
+		zone_count[block]--;
+	return block;
+}
+
+#ifdef CONFIG_FEATURE_MINIX2
+static int add_zone2(uint32_t *znr, int *corrected)
+{
+	int result;
+	int block;
+
+	result = 0;
+	block = check_zone_nr2(znr, corrected);
+	if (!block)
+		return 0;
+	if (zone_count[block]) {
+		printf("Already used block is reused in file '%s'. ",
+				current_name);
+		if (ask("Clear", 1)) {
+			*znr = 0;
+			block = 0;
+			*corrected = 1;
+			return 0;
+		}
+	}
+	if (!zone_in_use(block)) {
+		printf("Block %d in file '%s' is marked as 'unused'. ",
+				block, current_name);
+		if (ask("Correct", 1))
+			mark_zone(block);
+	}
+	if (!++zone_count[block])
+		zone_count[block]--;
+	return block;
+}
+#endif
+
+static void add_zone_ind(uint16_t *znr, int *corrected)
+{
+	static char blk[BLOCK_SIZE];
+	int i, chg_blk = 0;
+	int block;
+
+	block = add_zone(znr, corrected);
+	if (!block)
+		return;
+	read_block(block, blk);
+	for (i = 0; i < (BLOCK_SIZE >> 1); i++)
+		add_zone(i + (uint16_t *) blk, &chg_blk);
+	if (chg_blk)
+		write_block(block, blk);
+}
+
+#ifdef CONFIG_FEATURE_MINIX2
+static void add_zone_ind2(uint32_t *znr, int *corrected)
+{
+	static char blk[BLOCK_SIZE];
+	int i, chg_blk = 0;
+	int block;
+
+	block = add_zone2(znr, corrected);
+	if (!block)
+		return;
+	read_block(block, blk);
+	for (i = 0; i < BLOCK_SIZE >> 2; i++)
+		add_zone2(i + (uint32_t *) blk, &chg_blk);
+	if (chg_blk)
+		write_block(block, blk);
+}
+#endif
+
+static void add_zone_dind(uint16_t *znr, int *corrected)
+{
+	static char blk[BLOCK_SIZE];
+	int i, blk_chg = 0;
+	int block;
+
+	block = add_zone(znr, corrected);
+	if (!block)
+		return;
+	read_block(block, blk);
+	for (i = 0; i < (BLOCK_SIZE >> 1); i++)
+		add_zone_ind(i + (uint16_t *) blk, &blk_chg);
+	if (blk_chg)
+		write_block(block, blk);
+}
+
+#ifdef CONFIG_FEATURE_MINIX2
+static void add_zone_dind2(uint32_t *znr, int *corrected)
+{
+	static char blk[BLOCK_SIZE];
+	int i, blk_chg = 0;
+	int block;
+
+	block = add_zone2(znr, corrected);
+	if (!block)
+		return;
+	read_block(block, blk);
+	for (i = 0; i < BLOCK_SIZE >> 2; i++)
+		add_zone_ind2(i + (uint32_t *) blk, &blk_chg);
+	if (blk_chg)
+		write_block(block, blk);
+}
+
+static void add_zone_tind2(uint32_t *znr, int *corrected)
+{
+	static char blk[BLOCK_SIZE];
+	int i, blk_chg = 0;
+	int block;
+
+	block = add_zone2(znr, corrected);
+	if (!block)
+		return;
+	read_block(block, blk);
+	for (i = 0; i < BLOCK_SIZE >> 2; i++)
+		add_zone_dind2(i + (uint32_t *) blk, &blk_chg);
+	if (blk_chg)
+		write_block(block, blk);
+}
+#endif
+
+static void check_zones(unsigned int i)
+{
+	struct minix_inode *inode;
+
+	if (!i || i > INODES)
+		return;
+	if (inode_count[i] > 1)		/* have we counted this file already? */
+		return;
+	inode = Inode + i;
+	if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) &&
+		!S_ISLNK(inode->i_mode)) return;
+	for (i = 0; i < 7; i++)
+		add_zone(i + inode->i_zone, &changed);
+	add_zone_ind(7 + inode->i_zone, &changed);
+	add_zone_dind(8 + inode->i_zone, &changed);
+}
+
+#ifdef CONFIG_FEATURE_MINIX2
+static void check_zones2(unsigned int i)
+{
+	struct minix2_inode *inode;
+
+	if (!i || i > INODES)
+		return;
+	if (inode_count[i] > 1)		/* have we counted this file already? */
+		return;
+	inode = Inode2 + i;
+	if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode)
+		&& !S_ISLNK(inode->i_mode))
+		return;
+	for (i = 0; i < 7; i++)
+		add_zone2(i + inode->i_zone, &changed);
+	add_zone_ind2(7 + inode->i_zone, &changed);
+	add_zone_dind2(8 + inode->i_zone, &changed);
+	add_zone_tind2(9 + inode->i_zone, &changed);
+}
+#endif
+
+static void check_file(struct minix_inode *dir, unsigned int offset)
+{
+	static char blk[BLOCK_SIZE];
+	struct minix_inode *inode;
+	int ino;
+	char *name;
+	int block;
+
+	block = map_block(dir, offset / BLOCK_SIZE);
+	read_block(block, blk);
+	name = blk + (offset % BLOCK_SIZE) + 2;
+	ino = *(uint16_t *) (name - 2);
+	if (ino > INODES) {
+		printf("%s contains a bad inode number for file '%.*s'. ",
+				current_name, namelen, name);
+		if (ask("Remove", 1)) {
+			*(uint16_t *) (name - 2) = 0;
+			write_block(block, blk);
+		}
+		ino = 0;
+	}
+	push_filename(name);
+	inode = get_inode(ino);
+	pop_filename();
+	if (!offset) {
+		if (!inode || strcmp(".", name)) {
+			printf("%s: bad directory: '.' isn't first\n", current_name);
+			errors_uncorrected = 1;
+		} else
+			return;
+	}
+	if (offset == dirsize) {
+		if (!inode || strcmp("..", name)) {
+			printf("%s: bad directory: '..' isn't second\n", current_name);
+			errors_uncorrected = 1;
+		} else
+			return;
+	}
+	if (!inode)
+		return;
+	push_filename(name);
+	if (list) {
+		if (verbose)
+			printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks);
+		printf("%s%s\n", current_name, S_ISDIR(inode->i_mode) ? ":" : "");
+	}
+	check_zones(ino);
+	if (inode && S_ISDIR(inode->i_mode))
+		recursive_check(ino);
+	pop_filename();
+	return;
+}
+
+#ifdef CONFIG_FEATURE_MINIX2
+static void check_file2(struct minix2_inode *dir, unsigned int offset)
+{
+	static char blk[BLOCK_SIZE];
+	struct minix2_inode *inode;
+	int ino;
+	char *name;
+	int block;
+
+	block = map_block2(dir, offset / BLOCK_SIZE);
+	read_block(block, blk);
+	name = blk + (offset % BLOCK_SIZE) + 2;
+	ino = *(uint16_t *) (name - 2);
+	if (ino > INODES) {
+		printf("%s contains a bad inode number for file '%.*s'. ",
+				current_name, namelen, name);
+		if (ask("Remove", 1)) {
+			*(uint16_t *) (name - 2) = 0;
+			write_block(block, blk);
+		}
+		ino = 0;
+	}
+	push_filename(name);
+	inode = get_inode2(ino);
+	pop_filename();
+	if (!offset) {
+		if (!inode || strcmp(".", name)) {
+			printf("%s: bad directory: '.' isn't first\n", current_name);
+			errors_uncorrected = 1;
+		} else
+			return;
+	}
+	if (offset == dirsize) {
+		if (!inode || strcmp("..", name)) {
+			printf("%s: bad directory: '..' isn't second\n", current_name);
+			errors_uncorrected = 1;
+		} else
+			return;
+	}
+	if (!inode)
+		return;
+	push_filename(name);
+	if (list) {
+		if (verbose)
+			printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks);
+		printf("%s%s\n", current_name, S_ISDIR(inode->i_mode) ? ":" : "");
+	}
+	check_zones2(ino);
+	if (inode && S_ISDIR(inode->i_mode))
+		recursive_check2(ino);
+	pop_filename();
+	return;
+}
+#endif
+
+static void recursive_check(unsigned int ino)
+{
+	struct minix_inode *dir;
+	unsigned int offset;
+
+	dir = Inode + ino;
+	if (!S_ISDIR(dir->i_mode))
+		die("Internal error");
+	if (dir->i_size < 2 * dirsize) {
+		printf("%s: bad directory: size<32", current_name);
+		errors_uncorrected = 1;
+	}
+	for (offset = 0; offset < dir->i_size; offset += dirsize)
+		check_file(dir, offset);
+}
+
+#ifdef CONFIG_FEATURE_MINIX2
+static void recursive_check2(unsigned int ino)
+{
+	struct minix2_inode *dir;
+	unsigned int offset;
+
+	dir = Inode2 + ino;
+	if (!S_ISDIR(dir->i_mode))
+		die("Internal error");
+	if (dir->i_size < 2 * dirsize) {
+		printf("%s: bad directory: size<32", current_name);
+		errors_uncorrected = 1;
+	}
+	for (offset = 0; offset < dir->i_size; offset += dirsize)
+		check_file2(dir, offset);
+}
+#endif
+
+static int bad_zone(int i)
+{
+	char buffer[1024];
+
+	if (BLOCK_SIZE * i != lseek(IN, BLOCK_SIZE * i, SEEK_SET))
+		die("Seek failed in bad_zone");
+	return (BLOCK_SIZE != read(IN, buffer, BLOCK_SIZE));
+}
+
+static void check_counts(void)
+{
+	int i;
+
+	for (i = 1; i <= INODES; i++) {
+		if (warn_mode && Inode[i].i_mode && !inode_in_use(i)) {
+			printf("Inode %d has non-zero mode. ", i);
+			if (ask("Clear", 1)) {
+				Inode[i].i_mode = 0;
+				changed = 1;
+			}
+		}
+		if (!inode_count[i]) {
+			if (!inode_in_use(i))
+				continue;
+			printf("Unused inode %d is marked as 'used' in the bitmap. ", i);
+			if (ask("Clear", 1))
+				unmark_inode(i);
+			continue;
+		}
+		if (!inode_in_use(i)) {
+			printf("Inode %d is used, but marked as 'unused' in the bitmap. ", i);
+			if (ask("Set", 1))
+				mark_inode(i);
+		}
+		if (Inode[i].i_nlinks != inode_count[i]) {
+			printf("Inode %d (mode=%07o), i_nlinks=%d, counted=%d. ",
+				   i, Inode[i].i_mode, Inode[i].i_nlinks, inode_count[i]);
+			if (ask("Set i_nlinks to count", 1)) {
+				Inode[i].i_nlinks = inode_count[i];
+				changed = 1;
+			}
+		}
+	}
+	for (i = FIRSTZONE; i < ZONES; i++) {
+		if (zone_in_use(i) == zone_count[i])
+			continue;
+		if (!zone_count[i]) {
+			if (bad_zone(i))
+				continue;
+			printf("Zone %d is marked 'in use', but no file uses it. ", i);
+			if (ask("Unmark", 1))
+				unmark_zone(i);
+			continue;
+		}
+		printf("Zone %d: %sin use, counted=%d\n",
+			   i, zone_in_use(i) ? "" : "not ", zone_count[i]);
+	}
+}
+
+#ifdef CONFIG_FEATURE_MINIX2
+static void check_counts2(void)
+{
+	int i;
+
+	for (i = 1; i <= INODES; i++) {
+		if (warn_mode && Inode2[i].i_mode && !inode_in_use(i)) {
+			printf("Inode %d has non-zero mode. ", i);
+			if (ask("Clear", 1)) {
+				Inode2[i].i_mode = 0;
+				changed = 1;
+			}
+		}
+		if (!inode_count[i]) {
+			if (!inode_in_use(i))
+				continue;
+			printf("Unused inode %d is marked as 'used' in the bitmap. ", i);
+			if (ask("Clear", 1))
+				unmark_inode(i);
+			continue;
+		}
+		if (!inode_in_use(i)) {
+			printf("Inode %d is used, but marked as 'unused' in the bitmap. ", i);
+			if (ask("Set", 1))
+				mark_inode(i);
+		}
+		if (Inode2[i].i_nlinks != inode_count[i]) {
+			printf("Inode %d (mode=%07o), i_nlinks=%d, counted=%d. ",
+				   i, Inode2[i].i_mode, Inode2[i].i_nlinks,
+				   inode_count[i]);
+			if (ask("Set i_nlinks to count", 1)) {
+				Inode2[i].i_nlinks = inode_count[i];
+				changed = 1;
+			}
+		}
+	}
+	for (i = FIRSTZONE; i < ZONES; i++) {
+		if (zone_in_use(i) == zone_count[i])
+			continue;
+		if (!zone_count[i]) {
+			if (bad_zone(i))
+				continue;
+			printf("Zone %d is marked 'in use', but no file uses it. ", i);
+			if (ask("Unmark", 1))
+				unmark_zone(i);
+			continue;
+		}
+		printf("Zone %d: %sin use, counted=%d\n",
+			   i, zone_in_use(i) ? "" : "not ", zone_count[i]);
+	}
+}
+#endif
+
+static void check(void)
+{
+	memset(inode_count, 0, (INODES + 1) * sizeof(*inode_count));
+	memset(zone_count, 0, ZONES * sizeof(*zone_count));
+	check_zones(ROOT_INO);
+	recursive_check(ROOT_INO);
+	check_counts();
+}
+
+#ifdef CONFIG_FEATURE_MINIX2
+static void check2(void)
+{
+	memset(inode_count, 0, (INODES + 1) * sizeof(*inode_count));
+	memset(zone_count, 0, ZONES * sizeof(*zone_count));
+	check_zones2(ROOT_INO);
+	recursive_check2(ROOT_INO);
+	check_counts2();
+}
+#endif
+
+int fsck_minix_main(int argc, char **argv)
+{
+	struct termios tmp;
+	int retcode = 0;
+
+	alloc_current_name();
+#ifdef CONFIG_FEATURE_CLEAN_UP
+	/* Don't bother to free memory.  Exit does
+	 * that automagically, so we can save a few bytes */
+	atexit(free_current_name);
+#endif
+
+	if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE)
+		die("Bad inode size");
+#ifdef CONFIG_FEATURE_MINIX2
+	if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE)
+		die("Bad v2 inode size");
+#endif
+	while (argc-- > 1) {
+		argv++;
+		if (argv[0][0] != '-') {
+			if (device_name)
+				bb_show_usage();
+			else
+				device_name = argv[0];
+		} else
+			while (*++argv[0])
+				switch (argv[0][0]) {
+				case 'l':
+					list = 1;
+					break;
+				case 'a':
+					automatic = 1;
+					repair = 1;
+					break;
+				case 'r':
+					automatic = 0;
+					repair = 1;
+					break;
+				case 'v':
+					verbose = 1;
+					break;
+				case 's':
+					show = 1;
+					break;
+				case 'm':
+					warn_mode = 1;
+					break;
+				case 'f':
+					force = 1;
+					break;
+				default:
+					bb_show_usage();
+				}
+	}
+	if (!device_name)
+		bb_show_usage();
+	check_mount();				/* trying to check a mounted filesystem? */
+	if (repair && !automatic) {
+		if (!isatty(0) || !isatty(1))
+			die("Need terminal for interactive repairs");
+	}
+	IN = open(device_name, repair ? O_RDWR : O_RDONLY);
+	if (IN < 0){
+		printf("Unable to open device '%s'\n", device_name);
+		leave(8);
+	}
+	sync(); /* paranoia? */
+	read_superblock();
+
+	/*
+	 * Determine whether or not we should continue with the checking.
+	 * This is based on the status of the filesystem valid and error
+	 * flags and whether or not the -f switch was specified on the
+	 * command line.
+	 */
+	printf("%s, %s\n", bb_applet_name, program_version);
+	if (!(Super.s_state & MINIX_ERROR_FS) &&
+		(Super.s_state & MINIX_VALID_FS) && !force) {
+		if (repair)
+			printf("%s is clean, check is skipped\n", device_name);
+		return retcode;
+	} else if (force)
+		printf("Forcing filesystem check on %s\n", device_name);
+	else if (repair)
+		printf("Filesystem on %s is dirty, needs checking\n",
+			   device_name);
+
+	read_tables();
+
+	if (repair && !automatic) {
+		tcgetattr(0, &termios);
+		tmp = termios;
+		tmp.c_lflag &= ~(ICANON | ECHO);
+		tcsetattr(0, TCSANOW, &tmp);
+		termios_set = 1;
+	}
+#ifdef CONFIG_FEATURE_MINIX2
+	if (version2) {
+		check_root2();
+		check2();
+	} else
+#endif
+	{
+		check_root();
+		check();
+	}
+	if (verbose) {
+		int i, free_cnt;
+
+		for (i = 1, free_cnt = 0; i <= INODES; i++)
+			if (!inode_in_use(i))
+				free_cnt++;
+		printf("\n%6ld inodes used (%ld%%)\n", (INODES - free_cnt),
+			   100 * (INODES - free_cnt) / INODES);
+		for (i = FIRSTZONE, free_cnt = 0; i < ZONES; i++)
+			if (!zone_in_use(i))
+				free_cnt++;
+		printf("%6ld zones used (%ld%%)\n\n"
+			   "%6d regular files\n"
+			   "%6d directories\n"
+			   "%6d character device files\n"
+			   "%6d block device files\n"
+			   "%6d links\n"
+			   "%6d symbolic links\n"
+			   "------\n"
+			   "%6d files\n",
+			   (ZONES - free_cnt), 100 * (ZONES - free_cnt) / ZONES,
+			   regular, directory, chardev, blockdev,
+			   links - 2 * directory + 1, symlinks,
+			   total - 2 * directory + 1);
+	}
+	if (changed) {
+		write_tables();
+		printf("FILE SYSTEM HAS BEEN CHANGED\n");
+		sync();
+	} else if (repair)
+		write_super_block();
+
+	if (repair && !automatic)
+		tcsetattr(0, TCSANOW, &termios);
+
+	if (changed)
+		retcode += 3;
+	if (errors_uncorrected)
+		retcode += 4;
+	return retcode;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/getopt.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/getopt.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/getopt.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,370 @@
+/*
+ * getopt.c - Enhanced implementation of BSD getopt(1)
+ *   Copyright (c) 1997, 1998, 1999, 2000  Frodo Looijaard <frodol at dds.nl>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/*
+ * Version 1.0-b4: Tue Sep 23 1997. First public release.
+ * Version 1.0: Wed Nov 19 1997.
+ *   Bumped up the version number to 1.0
+ *   Fixed minor typo (CSH instead of TCSH)
+ * Version 1.0.1: Tue Jun 3 1998
+ *   Fixed sizeof instead of strlen bug
+ *   Bumped up the version number to 1.0.1
+ * Version 1.0.2: Thu Jun 11 1998 (not present)
+ *   Fixed gcc-2.8.1 warnings
+ *   Fixed --version/-V option (not present)
+ * Version 1.0.5: Tue Jun 22 1999
+ *   Make -u option work (not present)
+ * Version 1.0.6: Tue Jun 27 2000
+ *   No important changes
+ * Version 1.1.0: Tue Jun 30 2000
+ *   Added NLS support (partly written by Arkadiusz Mi<B6>kiewicz
+ *     <misiek at misiek.eu.org>)
+ * Ported to Busybox - Alfred M. Szmidt <ams at trillian.itslinux.org>
+ *  Removed --version/-V and --help/-h in
+ *  Removed parse_error(), using bb_error_msg() from Busybox instead
+ *  Replaced our_malloc with xmalloc and our_realloc with xrealloc
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <getopt.h>
+
+#include "busybox.h"
+
+/* NON_OPT is the code that is returned when a non-option is found in '+'
+   mode */
+enum {
+	NON_OPT = 1,
+/* LONG_OPT is the code that is returned when a long option is found. */
+	LONG_OPT = 2
+};
+
+/* The shells recognized. */
+typedef enum {BASH,TCSH} shell_t;
+
+
+/* Some global variables that tells us how to parse. */
+static shell_t shell=BASH; /* The shell we generate output for. */
+static int quiet_errors; /* 0 is not quiet. */
+static int quiet_output; /* 0 is not quiet. */
+static int quote=1; /* 1 is do quote. */
+static int alternative; /* 0 is getopt_long, 1 is getopt_long_only */
+
+/* Function prototypes */
+static const char *normalize(const char *arg);
+static int generate_output(char * argv[],int argc,const char *optstr,
+		    const struct option *longopts);
+static void add_long_options(char *options);
+static void add_longopt(const char *name,int has_arg);
+static void set_shell(const char *new_shell);
+
+
+/*
+ * This function 'normalizes' a single argument: it puts single quotes around
+ * it and escapes other special characters. If quote is false, it just
+ * returns its argument.
+ * Bash only needs special treatment for single quotes; tcsh also recognizes
+ * exclamation marks within single quotes, and nukes whitespace.
+ * This function returns a pointer to a buffer that is overwritten by
+ * each call.
+ */
+const char *normalize(const char *arg)
+{
+	static char *BUFFER=NULL;
+	const char *argptr=arg;
+	char *bufptr;
+
+	free(BUFFER);
+
+	if (!quote) { /* Just copy arg */
+	       BUFFER=bb_xstrdup(arg);
+		return BUFFER;
+	}
+
+	/* Each character in arg may take up to four characters in the result:
+	   For a quote we need a closing quote, a backslash, a quote and an
+	   opening quote! We need also the global opening and closing quote,
+	   and one extra character for '\0'. */
+	BUFFER=xmalloc(strlen(arg)*4+3);
+
+	bufptr=BUFFER;
+	*bufptr++='\'';
+
+	while (*argptr) {
+		if (*argptr == '\'') {
+			/* Quote: replace it with: '\'' */
+			*bufptr++='\'';
+			*bufptr++='\\';
+			*bufptr++='\'';
+			*bufptr++='\'';
+		} else if (shell==TCSH && *argptr=='!') {
+			/* Exclamation mark: replace it with: \! */
+			*bufptr++='\'';
+			*bufptr++='\\';
+			*bufptr++='!';
+			*bufptr++='\'';
+		} else if (shell==TCSH && *argptr=='\n') {
+			/* Newline: replace it with: \n */
+			*bufptr++='\\';
+			*bufptr++='n';
+		} else if (shell==TCSH && isspace(*argptr)) {
+			/* Non-newline whitespace: replace it with \<ws> */
+			*bufptr++='\'';
+			*bufptr++='\\';
+			*bufptr++=*argptr;
+			*bufptr++='\'';
+		} else
+			/* Just copy */
+			*bufptr++=*argptr;
+		argptr++;
+	}
+	*bufptr++='\'';
+	*bufptr++='\0';
+	return BUFFER;
+}
+
+/*
+ * Generate the output. argv[0] is the program name (used for reporting errors).
+ * argv[1..] contains the options to be parsed. argc must be the number of
+ * elements in argv (ie. 1 if there are no options, only the program name),
+ * optstr must contain the short options, and longopts the long options.
+ * Other settings are found in global variables.
+ */
+int generate_output(char * argv[],int argc,const char *optstr,
+		    const struct option *longopts)
+{
+	int exit_code = 0; /* We assume everything will be OK */
+	int opt;
+	int longindex;
+	const char *charptr;
+
+	if (quiet_errors) /* No error reporting from getopt(3) */
+		opterr=0;
+	optind=0; /* Reset getopt(3) */
+
+	while ((opt = (alternative?
+		       getopt_long_only(argc,argv,optstr,longopts,&longindex):
+		       getopt_long(argc,argv,optstr,longopts,&longindex)))
+	       != EOF)
+		if (opt == '?' || opt == ':' )
+			exit_code = 1;
+		else if (!quiet_output) {
+			if (opt == LONG_OPT) {
+				printf(" --%s",longopts[longindex].name);
+				if (longopts[longindex].has_arg)
+					printf(" %s",
+					       normalize(optarg?optarg:""));
+			} else if (opt == NON_OPT)
+				printf(" %s",normalize(optarg));
+			else {
+				printf(" -%c",opt);
+				charptr = strchr(optstr,opt);
+				if (charptr != NULL && *++charptr == ':')
+					printf(" %s",
+					       normalize(optarg?optarg:""));
+			}
+		}
+
+	if (! quiet_output) {
+		printf(" --");
+		while (optind < argc)
+			printf(" %s",normalize(argv[optind++]));
+		printf("\n");
+	}
+	return exit_code;
+}
+
+static struct option *long_options;
+static int long_options_length; /* Length of array */
+static int long_options_nr; /* Nr of used elements in array */
+enum { LONG_OPTIONS_INCR = 10 };
+#define init_longopt() add_longopt(NULL,0)
+
+/* Register a long option. The contents of name is copied. */
+void add_longopt(const char *name,int has_arg)
+{
+	if (!name) { /* init */
+		free(long_options);
+		long_options=NULL;
+		long_options_length=0;
+		long_options_nr=0;
+	}
+
+	if (long_options_nr == long_options_length) {
+		long_options_length += LONG_OPTIONS_INCR;
+		long_options=xrealloc(long_options,
+					 sizeof(struct option) *
+					 long_options_length);
+	}
+
+	long_options[long_options_nr].name=NULL;
+	long_options[long_options_nr].has_arg=0;
+	long_options[long_options_nr].flag=NULL;
+	long_options[long_options_nr].val=0;
+
+	if (long_options_nr) { /* Not for init! */
+		long_options[long_options_nr-1].has_arg=has_arg;
+		long_options[long_options_nr-1].flag=NULL;
+		long_options[long_options_nr-1].val=LONG_OPT;
+	       long_options[long_options_nr-1].name=bb_xstrdup(name);
+	}
+	long_options_nr++;
+}
+
+
+/*
+ * Register several long options. options is a string of long options,
+ * separated by commas or whitespace.
+ * This nukes options!
+ */
+void add_long_options(char *options)
+{
+	int arg_opt, tlen;
+	char *tokptr=strtok(options,", \t\n");
+	while (tokptr) {
+		arg_opt=no_argument;
+		tlen=strlen(tokptr);
+		if (tlen > 0) {
+			if (tokptr[tlen-1] == ':') {
+				if (tlen > 1 && tokptr[tlen-2] == ':') {
+					tokptr[tlen-2]='\0';
+					tlen -= 2;
+					arg_opt=optional_argument;
+				} else {
+					tokptr[tlen-1]='\0';
+					tlen -= 1;
+					arg_opt=required_argument;
+				}
+				if (tlen == 0)
+					bb_error_msg("empty long option after -l or --long argument");
+			}
+			add_longopt(tokptr,arg_opt);
+		}
+		tokptr=strtok(NULL,", \t\n");
+	}
+}
+
+void set_shell(const char *new_shell)
+{
+	if (!strcmp(new_shell,"bash"))
+		shell=BASH;
+	else if (!strcmp(new_shell,"tcsh"))
+		shell=TCSH;
+	else if (!strcmp(new_shell,"sh"))
+		shell=BASH;
+	else if (!strcmp(new_shell,"csh"))
+		shell=TCSH;
+	else
+		bb_error_msg("unknown shell after -s or --shell argument");
+}
+
+
+/* Exit codes:
+ *   0) No errors, successful operation.
+ *   1) getopt(3) returned an error.
+ *   2) A problem with parameter parsing for getopt(1).
+ *   3) Internal error, out of memory
+ *   4) Returned for -T
+ */
+
+static const struct option longopts[]=
+{
+	{"options",required_argument,NULL,'o'},
+	{"longoptions",required_argument,NULL,'l'},
+	{"quiet",no_argument,NULL,'q'},
+	{"quiet-output",no_argument,NULL,'Q'},
+	{"shell",required_argument,NULL,'s'},
+	{"test",no_argument,NULL,'T'},
+	{"unquoted",no_argument,NULL,'u'},
+	{"alternative",no_argument,NULL,'a'},
+	{"name",required_argument,NULL,'n'},
+	{NULL,0,NULL,0}
+};
+
+/* Stop scanning as soon as a non-option argument is found! */
+static const char shortopts[]="+ao:l:n:qQs:Tu";
+
+
+int getopt_main(int argc, char *argv[])
+{
+	const char *optstr = NULL;
+	char *name = NULL;
+	int opt;
+	int compatible=0;
+
+	init_longopt();
+
+	if (getenv("GETOPT_COMPATIBLE"))
+		compatible=1;
+
+	if (argc == 1) {
+		if (compatible) {
+			/* For some reason, the original getopt gave no error
+			   when there were no arguments. */
+			printf(" --\n");
+		       return 0;
+		} else
+			bb_error_msg_and_die("missing optstring argument");
+	}
+
+	if (argv[1][0] != '-' || compatible) {
+		char *s;
+
+		quote=0;
+		s=xmalloc(strlen(argv[1])+1);
+		strcpy(s,argv[1]+strspn(argv[1],"-+"));
+		argv[1]=argv[0];
+	       return (generate_output(argv+1,argc-1,s,long_options));
+	}
+
+	while ((opt=getopt_long(argc,argv,shortopts,longopts,NULL)) != EOF)
+		switch (opt) {
+		case 'a':
+			alternative=1;
+			break;
+		case 'o':
+		       optstr = optarg;
+			break;
+		case 'l':
+			add_long_options(optarg);
+			break;
+		case 'n':
+		       name = optarg;
+			break;
+		case 'q':
+			quiet_errors=1;
+			break;
+		case 'Q':
+			quiet_output=1;
+			break;
+		case 's':
+			set_shell(optarg);
+			break;
+		case 'T':
+		       return 4;
+		case 'u':
+			quote=0;
+			break;
+		default:
+			bb_show_usage();
+		}
+
+	if (!optstr) {
+		if (optind >= argc)
+			bb_error_msg_and_die("missing optstring argument");
+		else optstr=argv[optind++];
+	}
+	if (name)
+		argv[optind-1]=name;
+	else
+		argv[optind-1]=argv[0];
+       return (generate_output(argv+optind-1,argc-optind+1,optstr,long_options));
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/hexdump.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/hexdump.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/hexdump.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,103 @@
+/*
+ * hexdump implementation for busybox
+ * Based on code from util-linux v 2.11l
+ *
+ * Copyright (c) 1989
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Licensed under GPLv2 or later, see file License in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <getopt.h>
+#include <string.h>
+#include "dump.h"
+
+static void bb_dump_addfile(char *name)
+{
+	register char *p;
+	FILE *fp;
+	char *buf;
+
+	fp = bb_xfopen(name, "r");
+
+	while ((buf = bb_get_chomped_line_from_file(fp)) != NULL) {
+		p = skip_whitespace(buf);
+
+		if (*p && (*p != '#')) {
+			bb_dump_add(p);
+		}
+		free(buf);
+	}
+	fclose(fp);
+}
+
+static const char * const add_strings[] = {
+			"\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"",		/* b */
+			"\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"",		/* c */
+			"\"%07.7_ax \" 8/2 \"  %05u \" \"\\n\"",	/* d */
+			"\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"",		/* o */
+			"\"%07.7_ax \" 8/2 \"   %04x \" \"\\n\"",	/* x */
+};
+
+static const char add_first[] = "\"%07.7_Ax\n\"";
+
+static const char hexdump_opts[] = "bcdoxCe:f:n:s:v";
+
+static const struct suffix_mult suffixes[] = {
+	{"b",  512 },
+	{"k",  1024 },
+	{"m",  1024*1024 },
+	{NULL, 0 }
+};
+
+int hexdump_main(int argc, char **argv)
+{
+//	register FS *tfs;
+	const char *p;
+	int ch;
+
+	bb_dump_vflag = FIRST;
+	bb_dump_length = -1;
+
+	while ((ch = getopt(argc, argv, hexdump_opts)) > 0) {
+		if ((p = strchr(hexdump_opts, ch)) != NULL) {
+			if ((p - hexdump_opts) < 5) {
+				bb_dump_add(add_first);
+				bb_dump_add(add_strings[(int)(p - hexdump_opts)]);
+			} else if (ch == 'C') {
+			        bb_dump_add("\"%08.8_Ax\n\"");
+				bb_dump_add("\"%08.8_ax  \" 8/1 \"%02x \" \"  \" 8/1 \"%02x \" ");
+			        bb_dump_add("\"  |\" 16/1 \"%_p\" \"|\\n\"");
+			} else {
+				/* Sae a little bit of space below by omitting the 'else's. */
+				if (ch == 'e') {
+					bb_dump_add(optarg);
+				} /* else */
+				if (ch == 'f') {
+					bb_dump_addfile(optarg);
+				} /* else */
+				if (ch == 'n') {
+					bb_dump_length = bb_xgetularg10_bnd(optarg, 0, INT_MAX);
+				} /* else */
+				if (ch == 's') {
+					bb_dump_skip = bb_xgetularg_bnd_sfx(optarg, 10, 0, LONG_MAX, suffixes);
+				} /* else */
+				if (ch == 'v') {
+					bb_dump_vflag = ALL;
+				}
+			}
+		} else {
+			bb_show_usage();
+		}
+	}
+
+	if (!bb_dump_fshead) {
+		bb_dump_add(add_first);
+		bb_dump_add("\"%07.7_ax \" 8/2 \"%04x \" \"\\n\"");
+	}
+
+	argv += optind;
+
+	return(bb_dump_dump(argv));
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/hwclock.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/hwclock.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/hwclock.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,218 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini hwclock implementation for busybox
+ *
+ * Copyright (C) 2002 Robert Griebl <griebl at gmx.de>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+*/
+
+
+#include <sys/ioctl.h>
+#include <sys/utsname.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+#include "busybox.h"
+
+/* Copied from linux/rtc.h to eliminate the kernel dependency */
+struct linux_rtc_time {
+	int tm_sec;
+	int tm_min;
+	int tm_hour;
+	int tm_mday;
+	int tm_mon;
+	int tm_year;
+	int tm_wday;
+	int tm_yday;
+	int tm_isdst;
+};
+
+#define RTC_SET_TIME   _IOW('p', 0x0a, struct linux_rtc_time) /* Set RTC time    */
+#define RTC_RD_TIME    _IOR('p', 0x09, struct linux_rtc_time) /* Read RTC time   */
+
+#if ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS
+# ifndef _GNU_SOURCE
+#  define _GNU_SOURCE
+# endif
+#endif
+
+static time_t read_rtc(int utc)
+{
+	int rtc;
+	struct tm tm;
+	char *oldtz = 0;
+	time_t t = 0;
+
+	if (( rtc = open ( "/dev/rtc", O_RDONLY )) < 0 ) {
+		if (( rtc = open ( "/dev/misc/rtc", O_RDONLY )) < 0 )
+			bb_perror_msg_and_die ( "Could not access RTC" );
+	}
+	memset ( &tm, 0, sizeof( struct tm ));
+	if ( ioctl ( rtc, RTC_RD_TIME, &tm ) < 0 )
+		bb_perror_msg_and_die ( "Could not read time from RTC" );
+	tm.tm_isdst = -1; /* not known */
+
+	close ( rtc );
+
+	if ( utc ) {
+		oldtz = getenv ( "TZ" );
+		setenv ( "TZ", "UTC 0", 1 );
+		tzset ( );
+	}
+
+	t = mktime ( &tm );
+
+	if ( utc ) {
+		if ( oldtz )
+			setenv ( "TZ", oldtz, 1 );
+		else
+			unsetenv ( "TZ" );
+		tzset ( );
+	}
+	return t;
+}
+
+static void write_rtc(time_t t, int utc)
+{
+	int rtc;
+	struct tm tm;
+
+	if (( rtc = open ( "/dev/rtc", O_WRONLY )) < 0 ) {
+		if (( rtc = open ( "/dev/misc/rtc", O_WRONLY )) < 0 )
+			bb_perror_msg_and_die ( "Could not access RTC" );
+	}
+
+	tm = *( utc ? gmtime ( &t ) : localtime ( &t ));
+	tm.tm_isdst = 0;
+
+	if ( ioctl ( rtc, RTC_SET_TIME, &tm ) < 0 )
+		bb_perror_msg_and_die ( "Could not set the RTC time" );
+
+	close ( rtc );
+}
+
+static int show_clock(int utc)
+{
+	struct tm *ptm;
+	time_t t;
+	RESERVE_CONFIG_BUFFER(buffer, 64);
+
+	t = read_rtc ( utc );
+	ptm = localtime ( &t );  /* Sets 'tzname[]' */
+
+	safe_strncpy ( buffer, ctime ( &t ), 64);
+	if ( buffer [0] )
+		buffer [strlen ( buffer ) - 1] = 0;
+
+	//printf ( "%s  %.6f seconds %s\n", buffer, 0.0, utc ? "" : ( ptm-> tm_isdst ? tzname [1] : tzname [0] ));
+	printf ( "%s  %.6f seconds\n", buffer, 0.0 );
+	RELEASE_CONFIG_BUFFER(buffer);
+
+	return 0;
+}
+
+static int to_sys_clock(int utc)
+{
+	struct timeval tv = { 0, 0 };
+	const struct timezone tz = { timezone/60 - 60*daylight, 0 };
+
+	tv.tv_sec = read_rtc ( utc );
+
+	if ( settimeofday ( &tv, &tz ))
+		bb_perror_msg_and_die ( "settimeofday() failed" );
+
+	return 0;
+}
+
+static int from_sys_clock(int utc)
+{
+	struct timeval tv = { 0, 0 };
+	struct timezone tz = { 0, 0 };
+
+	if ( gettimeofday ( &tv, &tz ))
+		bb_perror_msg_and_die ( "gettimeofday() failed" );
+
+	write_rtc ( tv.tv_sec, utc );
+	return 0;
+}
+
+#ifdef CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS
+# define ADJTIME_PATH "/var/lib/hwclock/adjtime"
+#else
+# define ADJTIME_PATH "/etc/adjtime"
+#endif
+static int check_utc(void)
+{
+	int utc = 0;
+	FILE *f = fopen ( ADJTIME_PATH, "r" );
+
+	if ( f ) {
+		RESERVE_CONFIG_BUFFER(buffer, 128);
+
+		while ( fgets ( buffer, sizeof( buffer ), f )) {
+			int len = strlen ( buffer );
+
+			while ( len && isspace ( buffer [len - 1] ))
+				len--;
+
+			buffer [len] = 0;
+
+			if ( strncmp ( buffer, "UTC", 3 ) == 0 ) {
+				utc = 1;
+				break;
+			}
+		}
+		fclose ( f );
+		RELEASE_CONFIG_BUFFER(buffer);
+	}
+	return utc;
+}
+
+#define HWCLOCK_OPT_LOCALTIME	0x01
+#define HWCLOCK_OPT_UTC			0x02
+#define HWCLOCK_OPT_SHOW		0x04
+#define HWCLOCK_OPT_HCTOSYS		0x08
+#define HWCLOCK_OPT_SYSTOHC		0x10
+
+int hwclock_main ( int argc, char **argv )
+{
+	unsigned long opt;
+	int utc;
+
+#if ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS
+static const struct option hwclock_long_options[] = {
+		{ "localtime", 0, 0, 'l' },
+		{ "utc",       0, 0, 'u' },
+		{ "show",      0, 0, 'r' },
+		{ "hctosys",   0, 0, 's' },
+		{ "systohc",   0, 0, 'w' },
+		{ 0,           0, 0, 0 }
+	};
+	bb_applet_long_options = hwclock_long_options;
+#endif
+
+	bb_opt_complementally = "?:r--ws:w--rs:s--wr:l--u:u--l";
+	opt = bb_getopt_ulflags(argc, argv, "lursw");
+
+	/* If -u or -l wasn't given check if we are using utc */
+	if (opt & (HWCLOCK_OPT_UTC | HWCLOCK_OPT_LOCALTIME))
+		utc = opt & HWCLOCK_OPT_UTC;
+	else
+		utc = check_utc();
+
+	if (opt & HWCLOCK_OPT_HCTOSYS) {
+		return to_sys_clock ( utc );
+	}
+	else if (opt & HWCLOCK_OPT_SYSTOHC) {
+		return from_sys_clock ( utc );
+	} else {
+		/* default HWCLOCK_OPT_SHOW */
+		return show_clock ( utc );
+	}
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/ipcrm.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/ipcrm.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/ipcrm.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,273 @@
+/*
+ * ipcrm.c -- utility to allow removal of IPC objects and data structures.
+ *
+ * 01 Sept 2004 - Rodney Radford <rradford at mindspring.com>
+ * Adapted for busybox from util-linux-2.12a.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * --- Pre-busybox history from util-linux-2.12a ------------------------
+ *
+ * 1999-04-02 frank zago
+ * - can now remove several id's in the same call
+ *
+ * 1999-02-22 Arkadiusz Miÿkiewicz <misiek at pld.ORG.PL>
+ * - added Native Language Support
+ *
+ * Original author - krishna balasubramanian 1993
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/msg.h>
+#include <sys/sem.h>
+
+/* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
+/* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
+/* for getopt */
+#include <unistd.h>
+
+/* for tolower and isupper */
+#include <ctype.h>
+
+#include "busybox.h"
+
+#if defined (__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
+/* union semun is defined by including <sys/sem.h> */
+#else
+/* according to X/OPEN we have to define it ourselves */
+union semun {
+	int val;
+	struct semid_ds *buf;
+	unsigned short int *array;
+	struct seminfo *__buf;
+};
+#endif
+
+typedef enum type_id {
+	SHM,
+	SEM,
+	MSG
+} type_id;
+
+static int
+remove_ids(type_id type, int argc, char **argv) {
+	int id;
+	int ret = 0;		/* for gcc */
+	char *end;
+	int nb_errors = 0;
+	union semun arg;
+
+	arg.val = 0;
+
+	while(argc) {
+
+		id = strtoul(argv[0], &end, 10);
+
+		if (*end != 0) {
+			bb_printf ("invalid id: %s\n", argv[0]);
+			nb_errors ++;
+		} else {
+			switch(type) {
+			case SEM:
+				ret = semctl (id, 0, IPC_RMID, arg);
+				break;
+
+			case MSG:
+				ret = msgctl (id, IPC_RMID, NULL);
+				break;
+
+			case SHM:
+				ret = shmctl (id, IPC_RMID, NULL);
+				break;
+			}
+
+			if (ret) {
+				bb_printf ("cannot remove id %s (%s)\n",
+					argv[0], strerror(errno));
+				nb_errors ++;
+			}
+		}
+		argc--;
+		argv++;
+	}
+
+	return(nb_errors);
+}
+
+static int deprecated_main(int argc, char **argv)
+{
+	if (argc < 3) {
+		bb_show_usage();
+		bb_fflush_stdout_and_exit(1);
+	}
+
+	if (!strcmp(argv[1], "shm")) {
+		if (remove_ids(SHM, argc-2, &argv[2]))
+			bb_fflush_stdout_and_exit(1);
+	}
+	else if (!strcmp(argv[1], "msg")) {
+		if (remove_ids(MSG, argc-2, &argv[2]))
+			bb_fflush_stdout_and_exit(1);
+	}
+	else if (!strcmp(argv[1], "sem")) {
+		if (remove_ids(SEM, argc-2, &argv[2]))
+			bb_fflush_stdout_and_exit(1);
+	}
+	else {
+		bb_printf ("unknown resource type: %s\n", argv[1]);
+		bb_show_usage();
+		bb_fflush_stdout_and_exit(1);
+	}
+
+	bb_printf ("resource(s) deleted\n");
+	return 0;
+}
+
+
+int ipcrm_main(int argc, char **argv)
+{
+	int   c;
+	int   error = 0;
+	char *prog = argv[0];
+
+	/* if the command is executed without parameters, do nothing */
+	if (argc == 1)
+		return 0;
+
+	/* check to see if the command is being invoked in the old way if so
+	   then run the old code */
+	if (strcmp(argv[1], "shm") == 0 ||
+		strcmp(argv[1], "msg") == 0 ||
+		strcmp(argv[1], "sem") == 0)
+		return deprecated_main(argc, argv);
+
+	/* process new syntax to conform with SYSV ipcrm */
+	while ((c = getopt(argc, argv, "q:m:s:Q:M:S:h?")) != -1) {
+		int result;
+		int id = 0;
+		int iskey = isupper(c);
+
+		/* needed to delete semaphores */
+		union semun arg;
+		arg.val = 0;
+
+		if ((c == '?') || (c == 'h'))
+		{
+			bb_show_usage();
+			return 0;
+		}
+
+		/* we don't need case information any more */
+		c = tolower(c);
+
+		/* make sure the option is in range */
+		if (c != 'q' && c != 'm' && c != 's') {
+			bb_show_usage();
+			error++;
+			return error;
+		}
+
+		if (iskey) {
+			/* keys are in hex or decimal */
+			key_t key = strtoul(optarg, NULL, 0);
+			if (key == IPC_PRIVATE) {
+				error++;
+				bb_fprintf(stderr, "%s: illegal key (%s)\n",
+					prog, optarg);
+				continue;
+			}
+
+			/* convert key to id */
+			id = ((c == 'q') ? msgget(key, 0) :
+				  (c == 'm') ? shmget(key, 0, 0) :
+				  semget(key, 0, 0));
+
+			if (id < 0) {
+				char *errmsg;
+				error++;
+				switch(errno) {
+				case EACCES:
+					errmsg = "permission denied for key";
+					break;
+				case EIDRM:
+					errmsg = "already removed key";
+					break;
+				case ENOENT:
+					errmsg = "invalid key";
+					break;
+				default:
+					errmsg = "unknown error in key";
+					break;
+				}
+				bb_fprintf(stderr, "%s: %s (%s)\n",
+					prog, errmsg, optarg);
+				continue;
+			}
+		} else {
+			/* ids are in decimal */
+			id = strtoul(optarg, NULL, 10);
+		}
+
+		result = ((c == 'q') ? msgctl(id, IPC_RMID, NULL) :
+			  (c == 'm') ? shmctl(id, IPC_RMID, NULL) :
+			  semctl(id, 0, IPC_RMID, arg));
+
+		if (result < 0) {
+			char *errmsg;
+			error++;
+			switch(errno) {
+			case EACCES:
+			case EPERM:
+				errmsg = iskey
+					? "permission denied for key"
+					: "permission denied for id";
+				break;
+			case EINVAL:
+				errmsg = iskey
+					? "invalid key"
+					: "invalid id";
+				break;
+			case EIDRM:
+				errmsg = iskey
+					? "already removed key"
+					: "already removed id";
+				break;
+			default:
+				errmsg = iskey
+					? "unknown error in key"
+					: "unknown error in id";
+				break;
+			}
+			bb_fprintf(stderr, "%s: %s (%s)\n",
+				prog, errmsg, optarg);
+			continue;
+		}
+	}
+
+	/* print usage if we still have some arguments left over */
+	if (optind != argc) {
+		bb_show_usage();
+	}
+
+	/* exit value reflects the number of errors encountered */
+	return error;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/ipcs.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/ipcs.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/ipcs.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,670 @@
+/*
+ * ipcs.c -- provides information on allocated ipc resources.
+ *
+ * 01 Sept 2004 - Rodney Radford <rradford at mindspring.com>
+ * Adapted for busybox from util-linux-2.12a.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <errno.h>
+#include <time.h>
+#include <pwd.h>
+#include <grp.h>
+
+/* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
+/* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
+/* X/OPEN tells us to use <sys/{types,ipc,shm}.h> for shmctl() */
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/msg.h>
+#include <sys/shm.h>
+
+#include "busybox.h"
+
+/*-------------------------------------------------------------------*/
+/* SHM_DEST and SHM_LOCKED are defined in kernel headers,
+   but inside #ifdef __KERNEL__ ... #endif */
+#ifndef SHM_DEST
+/* shm_mode upper byte flags */
+#define SHM_DEST        01000   /* segment will be destroyed on last detach */
+#define SHM_LOCKED      02000   /* segment will not be swapped */
+#endif
+
+/* For older kernels the same holds for the defines below */
+#ifndef MSG_STAT
+#define MSG_STAT	11
+#define MSG_INFO	12
+#endif
+
+#ifndef SHM_STAT
+#define SHM_STAT        13
+#define SHM_INFO        14
+struct shm_info {
+	 int   used_ids;
+	 ulong shm_tot; /* total allocated shm */
+	 ulong shm_rss; /* total resident shm */
+	 ulong shm_swp; /* total swapped shm */
+	 ulong swap_attempts;
+	 ulong swap_successes;
+};
+#endif
+
+#ifndef SEM_STAT
+#define SEM_STAT	18
+#define SEM_INFO	19
+#endif
+
+/* Some versions of libc only define IPC_INFO when __USE_GNU is defined. */
+#ifndef IPC_INFO
+#define IPC_INFO        3
+#endif
+/*-------------------------------------------------------------------*/
+
+/* The last arg of semctl is a union semun, but where is it defined?
+   X/OPEN tells us to define it ourselves, but until recently
+   Linux include files would also define it. */
+#if defined (__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
+/* union semun is defined by including <sys/sem.h> */
+#else
+/* according to X/OPEN we have to define it ourselves */
+union semun {
+	int val;
+	struct semid_ds *buf;
+	unsigned short int *array;
+	struct seminfo *__buf;
+};
+#endif
+
+/* X/OPEN (Jan 1987) does not define fields key, seq in struct ipc_perm;
+   libc 4/5 does not mention struct ipc_term at all, but includes
+   <linux/ipc.h>, which defines a struct ipc_perm with such fields.
+   glibc-1.09 has no support for sysv ipc.
+   glibc 2 uses __key, __seq */
+#if defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
+#define KEY __key
+#else
+#define KEY key
+#endif
+
+#define LIMITS 1
+#define STATUS 2
+#define CREATOR 3
+#define TIME 4
+#define PID 5
+
+
+static void print_perms (int id, struct ipc_perm *ipcp) {
+	struct passwd *pw;
+	struct group *gr;
+
+	bb_printf ("%-10d %-10o", id, ipcp->mode & 0777);
+
+	if ((pw = getpwuid(ipcp->cuid)))
+		bb_printf(" %-10s", pw->pw_name);
+	else
+		bb_printf(" %-10d", ipcp->cuid);
+	if ((gr = getgrgid(ipcp->cgid)))
+		bb_printf(" %-10s", gr->gr_name);
+	else
+		bb_printf(" %-10d", ipcp->cgid);
+
+	if ((pw = getpwuid(ipcp->uid)))
+		bb_printf(" %-10s", pw->pw_name);
+	else
+		bb_printf(" %-10d", ipcp->uid);
+	if ((gr = getgrgid(ipcp->gid)))
+		bb_printf(" %-10s\n", gr->gr_name);
+	else
+		bb_printf(" %-10d\n", ipcp->gid);
+}
+
+
+static void do_shm (char format)
+{
+	int maxid, shmid, id;
+	struct shmid_ds shmseg;
+	struct shm_info shm_info;
+	struct shminfo shminfo;
+	struct ipc_perm *ipcp = &shmseg.shm_perm;
+	struct passwd *pw;
+
+	maxid = shmctl (0, SHM_INFO, (struct shmid_ds *) (void *) &shm_info);
+	if (maxid < 0) {
+		bb_printf ("kernel not configured for shared memory\n");
+		return;
+	}
+
+	switch (format) {
+	case LIMITS:
+		bb_printf ("------ Shared Memory Limits --------\n");
+		if ((shmctl (0, IPC_INFO, (struct shmid_ds *) (void *) &shminfo)) < 0 )
+			return;
+		/* glibc 2.1.3 and all earlier libc's have ints as fields
+		   of struct shminfo; glibc 2.1.91 has unsigned long; ach */
+		bb_printf ("max number of segments = %lu\n"
+			"max seg size (kbytes) = %lu\n"
+			"max total shared memory (pages) = %lu\n"
+			"min seg size (bytes) = %lu\n",
+			(unsigned long) shminfo.shmmni,
+			(unsigned long) (shminfo.shmmax >> 10),
+			(unsigned long) shminfo.shmall,
+			(unsigned long) shminfo.shmmin);
+		return;
+
+	case STATUS:
+		bb_printf ("------ Shared Memory Status --------\n"
+			"segments allocated %d\n"
+			"pages allocated %ld\n"
+			"pages resident  %ld\n"
+			"pages swapped   %ld\n"
+			"Swap performance: %ld attempts\t %ld successes\n",
+			shm_info.used_ids,
+			shm_info.shm_tot,
+			shm_info.shm_rss,
+			shm_info.shm_swp,
+			shm_info.swap_attempts, shm_info.swap_successes);
+		return;
+
+	case CREATOR:
+		bb_printf ("------ Shared Memory Segment Creators/Owners --------\n"
+			"%-10s %-10s %-10s %-10s %-10s %-10s\n",
+			"shmid","perms","cuid","cgid","uid","gid");
+		break;
+
+	case TIME:
+		bb_printf ("------ Shared Memory Attach/Detach/Change Times --------\n"
+			"%-10s %-10s %-20s %-20s %-20s\n",
+			"shmid","owner","attached","detached","changed");
+		break;
+
+	case PID:
+		bb_printf ("------ Shared Memory Creator/Last-op --------\n"
+			"%-10s %-10s %-10s %-10s\n",
+			"shmid","owner","cpid","lpid");
+		break;
+
+	default:
+		bb_printf ("------ Shared Memory Segments --------\n"
+			"%-10s %-10s %-10s %-10s %-10s %-10s %-12s\n",
+			"key","shmid","owner","perms","bytes","nattch","status");
+		break;
+	}
+
+	for (id = 0; id <= maxid; id++) {
+		shmid = shmctl (id, SHM_STAT, &shmseg);
+		if (shmid < 0)
+			continue;
+		if (format == CREATOR)  {
+			print_perms (shmid, ipcp);
+			continue;
+		}
+		pw = getpwuid(ipcp->uid);
+		switch (format) {
+		case TIME:
+			if (pw)
+				bb_printf ("%-10d %-10.10s", shmid, pw->pw_name);
+			else
+				bb_printf ("%-10d %-10d", shmid, ipcp->uid);
+			/* ctime uses static buffer: use separate calls */
+			bb_printf("  %-20.16s", shmseg.shm_atime
+				   ? ctime(&shmseg.shm_atime) + 4 : "Not set");
+			bb_printf(" %-20.16s", shmseg.shm_dtime
+				   ? ctime(&shmseg.shm_dtime) + 4 : "Not set");
+			bb_printf(" %-20.16s\n", shmseg.shm_ctime
+				   ? ctime(&shmseg.shm_ctime) + 4 : "Not set");
+			break;
+		case PID:
+			if (pw)
+				bb_printf ("%-10d %-10.10s", shmid, pw->pw_name);
+			else
+				bb_printf ("%-10d %-10d", shmid, ipcp->uid);
+			bb_printf (" %-10d %-10d\n",
+				shmseg.shm_cpid, shmseg.shm_lpid);
+			break;
+
+		default:
+				bb_printf("0x%08x ",ipcp->KEY );
+			if (pw)
+				bb_printf ("%-10d %-10.10s", shmid, pw->pw_name);
+			else
+				bb_printf ("%-10d %-10d", shmid, ipcp->uid);
+			bb_printf ("%-10o %-10lu %-10ld %-6s %-6s\n",
+				ipcp->mode & 0777,
+				/*
+				 * earlier: int, Austin has size_t
+				 */
+				(unsigned long) shmseg.shm_segsz,
+				/*
+				 * glibc-2.1.3 and earlier has unsigned short;
+				 * Austin has shmatt_t
+				 */
+				(long) shmseg.shm_nattch,
+				ipcp->mode & SHM_DEST ? "dest" : " ",
+				ipcp->mode & SHM_LOCKED ? "locked" : " ");
+			break;
+		}
+	}
+	return;
+}
+
+
+static void do_sem (char format)
+{
+	int maxid, semid, id;
+	struct semid_ds semary;
+	struct seminfo seminfo;
+	struct ipc_perm *ipcp = &semary.sem_perm;
+	struct passwd *pw;
+	union semun arg;
+
+	arg.array = (ushort *)  (void *) &seminfo;
+	maxid = semctl (0, 0, SEM_INFO, arg);
+	if (maxid < 0) {
+		bb_printf ("kernel not configured for semaphores\n");
+		return;
+	}
+
+	switch (format) {
+	case LIMITS:
+		bb_printf ("------ Semaphore Limits --------\n");
+		arg.array = (ushort *) (void *) &seminfo; /* damn union */
+		if ((semctl (0, 0, IPC_INFO, arg)) < 0 )
+			return;
+		bb_printf ("max number of arrays = %d\n"
+			"max semaphores per array = %d\n"
+			"max semaphores system wide = %d\n"
+			"max ops per semop call = %d\n"
+			"semaphore max value = %d\n",
+			seminfo.semmni,
+			seminfo.semmsl,
+			seminfo.semmns,
+			seminfo.semopm,
+			seminfo.semvmx);
+		return;
+
+	case STATUS:
+		bb_printf ("------ Semaphore Status --------\n"
+			"used arrays = %d\n"
+			"allocated semaphores = %d\n",
+			seminfo.semusz,
+			seminfo.semaem);
+		return;
+
+	case CREATOR:
+		bb_printf ("------ Semaphore Arrays Creators/Owners --------\n"
+			"%-10s %-10s %-10s %-10s %-10s %-10s\n",
+			"semid","perms","cuid","cgid","uid","gid");
+		break;
+
+	case TIME:
+		bb_printf ("------ Shared Memory Operation/Change Times --------\n"
+			"%-8s %-10s %-26.24s %-26.24s\n",
+			"shmid","owner","last-op","last-changed");
+		break;
+
+	case PID:
+		break;
+
+	default:
+		bb_printf ("------ Semaphore Arrays --------\n"
+			"%-10s %-10s %-10s %-10s %-10s\n",
+			"key","semid","owner","perms","nsems");
+		break;
+	}
+
+	for (id = 0; id <= maxid; id++) {
+		arg.buf = (struct semid_ds *) &semary;
+		semid = semctl (id, 0, SEM_STAT, arg);
+		if (semid < 0)
+			continue;
+		if (format == CREATOR)  {
+			print_perms (semid, ipcp);
+			continue;
+		}
+		pw = getpwuid(ipcp->uid);
+		switch (format) {
+		case TIME:
+			if (pw)
+				bb_printf ("%-8d %-10.10s", semid, pw->pw_name);
+			else
+				bb_printf ("%-8d %-10d", semid, ipcp->uid);
+			bb_printf ("  %-26.24s", semary.sem_otime
+				? ctime(&semary.sem_otime) : "Not set");
+			bb_printf (" %-26.24s\n", semary.sem_ctime
+				? ctime(&semary.sem_ctime) : "Not set");
+			break;
+		case PID:
+			break;
+
+		default:
+				bb_printf("0x%08x ", ipcp->KEY);
+			if (pw)
+				bb_printf ("%-10d %-10.9s", semid, pw->pw_name);
+			else
+				bb_printf ("%-10d %-9d", semid, ipcp->uid);
+					bb_printf ("%-10o %-10ld\n",
+				ipcp->mode & 0777,
+				/*
+				 * glibc-2.1.3 and earlier has unsigned short;
+				 * glibc-2.1.91 has variation between
+				 * unsigned short and unsigned long
+				 * Austin prescribes unsigned short.
+				 */
+				(long) semary.sem_nsems);
+			break;
+		}
+	}
+}
+
+
+static void do_msg (char format)
+{
+	int maxid, msqid, id;
+	struct msqid_ds msgque;
+	struct msginfo msginfo;
+	struct ipc_perm *ipcp = &msgque.msg_perm;
+	struct passwd *pw;
+
+	maxid = msgctl (0, MSG_INFO, (struct msqid_ds *) (void *) &msginfo);
+	if (maxid < 0) {
+		bb_printf ("kernel not configured for message queues\n");
+		return;
+	}
+
+	switch (format) {
+	case LIMITS:
+		if ((msgctl (0, IPC_INFO, (struct msqid_ds *) (void *) &msginfo)) < 0 )
+			return;
+		bb_printf ("------ Messages: Limits --------\n"
+			"max queues system wide = %d\n"
+			"max size of message (bytes) = %d\n"
+			"default max size of queue (bytes) = %d\n",
+			msginfo.msgmni,
+			msginfo.msgmax,
+			msginfo.msgmnb);
+		return;
+
+	case STATUS:
+		bb_printf ("------ Messages: Status --------\n"
+			"allocated queues = %d\n"
+			"used headers = %d\n"
+			"used space = %d bytes\n",
+			msginfo.msgpool,
+			msginfo.msgmap,
+			msginfo.msgtql);
+		return;
+
+	case CREATOR:
+		bb_printf ("------ Message Queues: Creators/Owners --------\n"
+			"%-10s %-10s %-10s %-10s %-10s %-10s\n",
+			"msqid","perms","cuid","cgid","uid","gid");
+		break;
+
+	case TIME:
+		bb_printf ("------ Message Queues Send/Recv/Change Times --------\n"
+			"%-8s %-10s %-20s %-20s %-20s\n",
+			"msqid","owner","send","recv","change");
+		break;
+
+	case PID:
+		bb_printf ("------ Message Queues PIDs --------\n"
+			"%-10s %-10s %-10s %-10s\n",
+			"msqid","owner","lspid","lrpid");
+		break;
+
+	default:
+		bb_printf ("------ Message Queues --------\n"
+			"%-10s %-10s %-10s %-10s %-12s %-12s\n",
+			"key","msqid","owner","perms","used-bytes","messages");
+		break;
+	}
+
+	for (id = 0; id <= maxid; id++) {
+		msqid = msgctl (id, MSG_STAT, &msgque);
+		if (msqid < 0)
+			continue;
+		if (format == CREATOR)  {
+			print_perms (msqid, ipcp);
+			continue;
+		}
+		pw = getpwuid(ipcp->uid);
+		switch (format) {
+		case TIME:
+			if (pw)
+				bb_printf ("%-8d %-10.10s", msqid, pw->pw_name);
+			else
+				bb_printf ("%-8d %-10d", msqid, ipcp->uid);
+			bb_printf (" %-20.16s", msgque.msg_stime
+				? ctime(&msgque.msg_stime) + 4 : "Not set");
+			bb_printf (" %-20.16s", msgque.msg_rtime
+				? ctime(&msgque.msg_rtime) + 4 : "Not set");
+			bb_printf (" %-20.16s\n", msgque.msg_ctime
+				? ctime(&msgque.msg_ctime) + 4 : "Not set");
+			break;
+		case PID:
+			if (pw)
+				bb_printf ("%-8d %-10.10s", msqid, pw->pw_name);
+			else
+				bb_printf ("%-8d %-10d", msqid, ipcp->uid);
+			bb_printf ("  %5d     %5d\n",
+				msgque.msg_lspid, msgque.msg_lrpid);
+			break;
+
+		default:
+				bb_printf( "0x%08x ",ipcp->KEY );
+			if (pw)
+				bb_printf ("%-10d %-10.10s", msqid, pw->pw_name);
+			else
+				bb_printf ("%-10d %-10d", msqid, ipcp->uid);
+					bb_printf (" %-10o %-12ld %-12ld\n",
+				ipcp->mode & 0777,
+				/*
+				 * glibc-2.1.3 and earlier has unsigned short;
+				 * glibc-2.1.91 has variation between
+				 * unsigned short, unsigned long
+				 * Austin has msgqnum_t
+				 */
+				(long) msgque.msg_cbytes,
+				(long) msgque.msg_qnum);
+			break;
+		}
+	}
+	return;
+}
+
+
+static void print_shm (int shmid)
+{
+	struct shmid_ds shmds;
+	struct ipc_perm *ipcp = &shmds.shm_perm;
+
+	if (shmctl (shmid, IPC_STAT, &shmds) == -1) {
+		perror ("shmctl ");
+		return;
+	}
+
+	bb_printf ("\nShared memory Segment shmid=%d\n"
+		"uid=%d\tgid=%d\tcuid=%d\tcgid=%d\n"
+		"mode=%#o\taccess_perms=%#o\n"
+		"bytes=%ld\tlpid=%d\tcpid=%d\tnattch=%ld\n"
+		"att_time=%-26.24s\n"
+		"det_time=%-26.24s\n"
+		"change_time=%-26.24s\n"
+		"\n",
+		shmid,
+		ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
+		ipcp->mode, ipcp->mode & 0777,
+		(long) shmds.shm_segsz, shmds.shm_lpid, shmds.shm_cpid,
+		(long) shmds.shm_nattch,
+		shmds.shm_atime ? ctime (&shmds.shm_atime) : "Not set",
+		shmds.shm_dtime ? ctime (&shmds.shm_dtime) : "Not set",
+		ctime (&shmds.shm_ctime));
+	return;
+}
+
+
+static void print_msg (int msqid)
+{
+	struct msqid_ds buf;
+	struct ipc_perm *ipcp = &buf.msg_perm;
+
+	if (msgctl (msqid, IPC_STAT, &buf) == -1) {
+		perror ("msgctl ");
+		return;
+	}
+
+	bb_printf ("\nMessage Queue msqid=%d\n"
+		"uid=%d\tgid=%d\tcuid=%d\tcgid=%d\tmode=%#o\n"
+		"cbytes=%ld\tqbytes=%ld\tqnum=%ld\tlspid=%d\tlrpid=%d\n"
+		"send_time=%-26.24s\n"
+		"rcv_time=%-26.24s\n"
+		"change_time=%-26.24s\n"
+		"\n",
+		msqid,
+		ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, ipcp->mode,
+		/*
+		 * glibc-2.1.3 and earlier has unsigned short;
+		 * glibc-2.1.91 has variation between
+		 * unsigned short, unsigned long
+		 * Austin has msgqnum_t (for msg_qbytes)
+		 */
+		(long) buf.msg_cbytes, (long) buf.msg_qbytes,
+		(long) buf.msg_qnum, buf.msg_lspid, buf.msg_lrpid,
+		buf.msg_stime ? ctime (&buf.msg_stime) : "Not set",
+		buf.msg_rtime ? ctime (&buf.msg_rtime) : "Not set",
+		buf.msg_ctime ? ctime (&buf.msg_ctime) : "Not set");
+	return;
+}
+
+static void print_sem (int semid)
+{
+	struct semid_ds semds;
+	struct ipc_perm *ipcp = &semds.sem_perm;
+	union semun arg;
+	unsigned int i;
+
+	arg.buf = &semds;
+	if (semctl (semid, 0, IPC_STAT, arg) < 0) {
+		perror ("semctl ");
+		return;
+	}
+
+	bb_printf ("\nSemaphore Array semid=%d\n"
+		"uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n"
+		"mode=%#o, access_perms=%#o\n"
+		"nsems = %ld\n"
+		"otime = %-26.24s\n"
+		"ctime = %-26.24s\n"
+		"%-10s %-10s %-10s %-10s %-10s\n",
+		semid,
+		ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
+		ipcp->mode, ipcp->mode & 0777,
+		(long) semds.sem_nsems,
+		semds.sem_otime ? ctime (&semds.sem_otime) : "Not set",
+		ctime (&semds.sem_ctime),
+		"semnum","value","ncount","zcount","pid");
+
+	arg.val = 0;
+	for (i=0; i < semds.sem_nsems; i++) {
+		int val, ncnt, zcnt, pid;
+		val = semctl (semid, i, GETVAL, arg);
+		ncnt = semctl (semid, i, GETNCNT, arg);
+		zcnt = semctl (semid, i, GETZCNT, arg);
+		pid = semctl (semid, i, GETPID, arg);
+		if (val < 0 || ncnt < 0 || zcnt < 0 || pid < 0) {
+			perror ("semctl ");
+			bb_fflush_stdout_and_exit (1);
+		}
+		bb_printf ("%-10d %-10d %-10d %-10d %-10d\n",
+			i, val, ncnt, zcnt, pid);
+	}
+	bb_printf ("\n");
+	return;
+}
+
+int ipcs_main (int argc, char **argv) {
+	int opt, msg = 0, sem = 0, shm = 0, id=0, print=0;
+	char format = 0;
+	char options[] = "atclupsmqi:ih?";
+
+	while ((opt = getopt (argc, argv, options)) != -1) {
+		switch (opt) {
+		case 'i':
+			id = atoi (optarg);
+			print = 1;
+			break;
+		case 'a':
+			msg = shm = sem = 1;
+			break;
+		case 'q':
+			msg = 1;
+			break;
+		case 's':
+			sem = 1;
+			break;
+		case 'm':
+			shm = 1;
+			break;
+		case 't':
+			format = TIME;
+			break;
+		case 'c':
+			format = CREATOR;
+			break;
+		case 'p':
+			format = PID;
+			break;
+		case 'l':
+			format = LIMITS;
+			break;
+		case 'u':
+			format = STATUS;
+			break;
+		case 'h':
+		case '?':
+			bb_show_usage();
+			bb_fflush_stdout_and_exit (0);
+		}
+	}
+
+	if  (print) {
+		if (shm) {
+			print_shm (id);
+			bb_fflush_stdout_and_exit (0);
+		}
+		if (sem) {
+			print_sem (id);
+			bb_fflush_stdout_and_exit (0);
+		}
+		if (msg) {
+			print_msg (id);
+			bb_fflush_stdout_and_exit (0);
+		}
+		bb_show_usage();
+		bb_fflush_stdout_and_exit (0);
+	}
+
+	if ( !shm && !msg && !sem)
+		msg = sem = shm = 1;
+	bb_printf ("\n");
+
+	if (shm) {
+		do_shm (format);
+		bb_printf ("\n");
+	}
+	if (sem) {
+		do_sem (format);
+		bb_printf ("\n");
+	}
+	if (msg) {
+		do_msg (format);
+		bb_printf ("\n");
+	}
+	return 0;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/losetup.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/losetup.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/losetup.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,49 @@
+/*
+ * Mini losetup implementation for busybox
+ *
+ * Copyright (C) 2002  Matt Kraai.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include <getopt.h>
+#include <stdlib.h>
+
+#include "busybox.h"
+
+int losetup_main (int argc, char **argv)
+{
+  int offset = 0;
+
+  /* This will need a "while(getopt()!=-1)" loop when we can have more than
+     one option, but for now we can't. */
+  switch(getopt(argc,argv, "do:")) {
+    case 'd':
+      /* detach takes exactly one argument */
+      if(optind+1!=argc) bb_show_usage();
+      if(!del_loop(argv[optind])) return EXIT_SUCCESS;
+die_failed:
+      bb_perror_msg_and_die("%s",argv[optind]);
+
+    case 'o':
+      offset = bb_xparse_number (optarg, NULL);
+      /* Fall through to do the losetup */
+    case -1:
+      /* losetup takes two argument:, loop_device and file */
+      if(optind+2==argc) {
+	if(set_loop(&argv[optind], argv[optind + 1], offset)>=0)
+	  return EXIT_SUCCESS;
+	else goto die_failed;
+      }
+      if(optind+1==argc) {
+	char *s=query_loop(argv[optind]);
+	if (!s) goto die_failed;
+	printf("%s: %s\n",argv[optind],s);
+	if(ENABLE_FEATURE_CLEAN_UP) free(s);
+	return EXIT_SUCCESS;
+      }
+      break;
+  }
+  bb_show_usage();
+  return EXIT_FAILURE;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/mdev.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/mdev.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/mdev.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,264 @@
+/* vi:set ts=4:
+ *
+ * mdev - Mini udev for busybox
+ *
+ * Copyright 2005 Rob Landley <rob at landley.net>
+ * Copyright 2005 Frank Sorenson <frank at tuxrocks.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <ctype.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/sysmacros.h>
+#include "xregex.h"
+
+#define DEV_PATH	"/dev"
+
+struct mdev_globals
+{
+	int root_major, root_minor;
+} mdev_globals;
+
+#define bbg mdev_globals
+
+/* mknod in /dev based on a path like "/sys/block/hda/hda1" */
+static void make_device(char *path, int delete)
+{
+	char *device_name;
+	int major, minor, type, len, fd;
+	int mode = 0660;
+	uid_t uid = 0;
+	gid_t gid = 0;
+	char *temp = path + strlen(path);
+	char *command = NULL;
+
+	/* Try to read major/minor string.  Note that the kernel puts \n after
+	 * the data, so we don't need to worry about null terminating the string
+	 * because sscanf() will stop at the first nondigit, which \n is.  We
+	 * also depend on path having writeable space after it. */
+
+	strcat(path, "/dev");
+	fd = open(path, O_RDONLY);
+	len = read(fd, temp + 1, 64);
+	*temp++ = 0;
+	close(fd);
+	if (len < 1) return;
+
+	/* Determine device name, type, major and minor */
+
+	device_name = strrchr(path, '/') + 1;
+	type = path[5]=='c' ? S_IFCHR : S_IFBLK;
+	if (sscanf(temp, "%d:%d", &major, &minor) != 2) return;
+
+	/* If we have a config file, look up permissions for this device */
+
+	if (ENABLE_FEATURE_MDEV_CONF) {
+		char *conf, *pos, *end;
+
+		/* mmap the config file */
+		if (-1 != (fd=open("/etc/mdev.conf",O_RDONLY))) {
+			len = lseek(fd, 0, SEEK_END);
+			conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
+			if (conf) {
+				int line = 0;
+
+				/* Loop through lines in mmaped file*/
+				for (pos=conf; pos-conf<len;) {
+					int field;
+					char *end2;
+
+					line++;
+					/* find end of this line */
+					for(end=pos; end-conf<len && *end!='\n'; end++)
+						;
+
+					/* Three fields: regex, uid:gid, mode */
+					for (field=0; field < (3 + ENABLE_FEATURE_MDEV_EXEC);
+							field++)
+					{
+						/* Skip whitespace */
+						while (pos<end && isspace(*pos)) pos++;
+						if (pos==end || *pos=='#') break;
+						for (end2=pos;
+							end2<end && !isspace(*end2) && *end2!='#'; end2++)
+							;
+
+						if (!field) {
+							/* Regex to match this device */
+
+							char *regex = strndupa(pos, end2-pos);
+							regex_t match;
+							regmatch_t off;
+							int result;
+
+							/* Is this it? */
+							xregcomp(&match,regex, REG_EXTENDED);
+							result = regexec(&match, device_name, 1, &off, 0);
+							regfree(&match);
+
+							/* If not this device, skip rest of line */
+							if (result || off.rm_so
+									|| off.rm_eo != strlen(device_name))
+								break;
+
+						} else if (field == 1) {
+							/* uid:gid */
+
+							char *s, *s2;
+
+							/* Find : */
+							for(s=pos; s<end2 && *s!=':'; s++)
+								;
+							if (s == end2) break;
+
+							/* Parse UID */
+							uid = strtoul(pos,&s2,10);
+							if (s != s2) {
+								struct passwd *pass;
+								pass = getpwnam(strndupa(pos, s-pos));
+								if (!pass) break;
+								uid = pass->pw_uid;
+							}
+							s++;
+							/* parse GID */
+							gid = strtoul(s, &s2, 10);
+							if (end2 != s2) {
+								struct group *grp;
+								grp = getgrnam(strndupa(s, end2-s));
+								if (!grp) break;
+								gid = grp->gr_gid;
+							}
+						} else if (field == 2) {
+							/* mode */
+
+							mode = strtoul(pos, &pos, 8);
+							if (pos != end2) break;
+						} else if (ENABLE_FEATURE_MDEV_EXEC && field == 3) {
+							// Command to run
+							char *s = "@$*", *s2;
+							if (!(s2 = strchr(s, *pos++))) {
+							  	// Force error
+								field = 1;
+								break;
+							}
+							if ((s2-s+1) & (1<<delete))
+								command = bb_xstrndup(pos, end-pos);
+						}
+
+						pos = end2;
+					}
+
+					/* Did everything parse happily? */
+
+					if (field > 2) break;
+					if (field) bb_error_msg_and_die("Bad line %d",line);
+
+					/* Next line */
+					pos = ++end;
+				}
+				munmap(conf, len);
+			}
+			close(fd);
+		}
+	}
+
+	umask(0);
+	if (!delete) {
+		if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST)
+			bb_perror_msg_and_die("mknod %s failed", device_name);
+
+		if (major == bbg.root_major && minor == bbg.root_minor)
+			symlink(device_name, "root");
+	
+		if (ENABLE_FEATURE_MDEV_CONF) chown(device_name, uid, gid);
+	}
+	if (command) {
+		int rc;
+		char *s;
+		
+		s=bb_xasprintf("MDEV=%s",device_name);
+		putenv(s);
+		rc = system(command);
+		s[4]=0;
+		putenv(s);
+		free(s);
+		free(command);
+		if (rc == -1) bb_perror_msg_and_die("Couldn't run %s", command);
+	}
+	if (delete) unlink(device_name);
+}
+
+/* Recursive search of /sys/block or /sys/class.  path must be a writeable
+ * buffer of size PATH_MAX containing the directory string to start at. */
+
+static void find_dev(char *path)
+{
+	DIR *dir;
+	size_t len = strlen(path);
+	struct dirent *entry;
+
+	if ((dir = opendir(path)) == NULL)
+		return;
+
+	while ((entry = readdir(dir)) != NULL) {
+		struct stat st;
+
+		/* Skip "." and ".." (also skips hidden files, which is ok) */
+
+		if (entry->d_name[0] == '.')
+			continue;
+
+		// uClibc doesn't fill out entry->d_type reliably. so we use lstat().
+
+		snprintf(path+len, PATH_MAX-len, "/%s", entry->d_name);
+		if (!lstat(path, &st) && S_ISDIR(st.st_mode)) find_dev(path);
+		path[len] = 0;
+
+		/* If there's a dev entry, mknod it */
+
+		if (!strcmp(entry->d_name, "dev")) make_device(path, 0);
+	}
+
+	closedir(dir);
+}
+
+int mdev_main(int argc, char *argv[])
+{
+	char *action;
+	char *env_path;
+	RESERVE_CONFIG_BUFFER(temp,PATH_MAX);
+
+	bb_xchdir(DEV_PATH);
+
+	/* Scan */
+
+	if (argc == 2 && !strcmp(argv[1],"-s")) {
+		struct stat st;
+
+		stat("/", &st);  // If this fails, we have bigger problems.
+		bbg.root_major=major(st.st_dev);
+		bbg.root_minor=minor(st.st_dev);
+		strcpy(temp,"/sys/block");
+		find_dev(temp);
+		strcpy(temp,"/sys/class");
+		find_dev(temp);
+
+	/* Hotplug */
+
+	} else {
+		action = getenv("ACTION");
+		env_path = getenv("DEVPATH");
+	    if (!action || !env_path)
+			bb_show_usage();
+
+		sprintf(temp, "/sys%s", env_path);
+		if (!strcmp(action, "add")) make_device(temp,0);
+		else if (!strcmp(action, "remove")) make_device(temp,1);
+	}
+
+	if (ENABLE_FEATURE_CLEAN_UP) RELEASE_CONFIG_BUFFER(temp);
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/mkfs_minix.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/mkfs_minix.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/mkfs_minix.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,846 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * mkfs.c - make a linux (minix) file-system.
+ *
+ * (C) 1991 Linus Torvalds. This file may be redistributed as per
+ * the Linux copyright.
+ */
+
+/*
+ * DD.MM.YY
+ *
+ * 24.11.91  -	Time began. Used the fsck sources to get started.
+ *
+ * 25.11.91  -	Corrected some bugs. Added support for ".badblocks"
+ *		The algorithm for ".badblocks" is a bit weird, but
+ *		it should work. Oh, well.
+ *
+ * 25.01.92  -	Added the -l option for getting the list of bad blocks
+ *		out of a named file. (Dave Rivers, rivers at ponds.uucp)
+ *
+ * 28.02.92  -	Added %-information when using -c.
+ *
+ * 28.02.93  -	Added support for other namelengths than the original
+ *		14 characters so that I can test the new kernel routines..
+ *
+ * 09.10.93  -	Make exit status conform to that required by fsutil
+ *		(Rik Faith, faith at cs.unc.edu)
+ *
+ * 31.10.93  -	Added inode request feature, for backup floppies: use
+ *		32 inodes, for a news partition use more.
+ *		(Scott Heavner, sdh at po.cwru.edu)
+ *
+ * 03.01.94  -	Added support for file system valid flag.
+ *		(Dr. Wettstein, greg%wind.uucp at plains.nodak.edu)
+ *
+ * 30.10.94 - added support for v2 filesystem
+ *	      (Andreas Schwab, schwab at issan.informatik.uni-dortmund.de)
+ *
+ * 09.11.94  -	Added test to prevent overwrite of mounted fs adapted
+ *		from Theodore Ts'o's (tytso at athena.mit.edu) mke2fs
+ *		program.  (Daniel Quinlan, quinlan at yggdrasil.com)
+ *
+ * 03.20.95  -	Clear first 512 bytes of filesystem to make certain that
+ *		the filesystem is not misidentified as a MS-DOS FAT filesystem.
+ *		(Daniel Quinlan, quinlan at yggdrasil.com)
+ *
+ * 02.07.96  -  Added small patch from Russell King to make the program a
+ *		good deal more portable (janl at math.uio.no)
+ *
+ * Usage:  mkfs [-c | -l filename ] [-v] [-nXX] [-iXX] device [size-in-blocks]
+ *
+ *	-c for readability checking (SLOW!)
+ *      -l for getting a list of bad blocks from a file.
+ *	-n for namelength (currently the kernel only uses 14 or 30)
+ *	-i for number of inodes
+ *	-v for v2 filesystem
+ *
+ * The device may be a block device or a image of one, but this isn't
+ * enforced (but it's not much fun on a character device :-).
+ *
+ * Modified for BusyBox by Erik Andersen <andersen at debian.org> --
+ *	removed getopt based parser and added a hand rolled one.
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <mntent.h>
+#include "busybox.h"
+
+#define MINIX_ROOT_INO 1
+#define MINIX_LINK_MAX	250
+#define MINIX2_LINK_MAX	65530
+
+#define MINIX_I_MAP_SLOTS	8
+#define MINIX_Z_MAP_SLOTS	64
+#define MINIX_SUPER_MAGIC	0x137F		/* original minix fs */
+#define MINIX_SUPER_MAGIC2	0x138F		/* minix fs, 30 char names */
+#define MINIX2_SUPER_MAGIC	0x2468		/* minix V2 fs */
+#define MINIX2_SUPER_MAGIC2	0x2478		/* minix V2 fs, 30 char names */
+#define MINIX_VALID_FS		0x0001		/* Clean fs. */
+#define MINIX_ERROR_FS		0x0002		/* fs has errors. */
+
+#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
+#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode)))
+
+#define MINIX_V1		0x0001		/* original minix fs */
+#define MINIX_V2		0x0002		/* minix V2 fs */
+
+#define INODE_VERSION(inode)	inode->i_sb->u.minix_sb.s_version
+
+/*
+ * This is the original minix inode layout on disk.
+ * Note the 8-bit gid and atime and ctime.
+ */
+struct minix_inode {
+	uint16_t i_mode;
+	uint16_t i_uid;
+	uint32_t i_size;
+	uint32_t i_time;
+	uint8_t  i_gid;
+	uint8_t  i_nlinks;
+	uint16_t i_zone[9];
+};
+
+/*
+ * The new minix inode has all the time entries, as well as
+ * long block numbers and a third indirect block (7+1+1+1
+ * instead of 7+1+1). Also, some previously 8-bit values are
+ * now 16-bit. The inode is now 64 bytes instead of 32.
+ */
+struct minix2_inode {
+	uint16_t i_mode;
+	uint16_t i_nlinks;
+	uint16_t i_uid;
+	uint16_t i_gid;
+	uint32_t i_size;
+	uint32_t i_atime;
+	uint32_t i_mtime;
+	uint32_t i_ctime;
+	uint32_t i_zone[10];
+};
+
+/*
+ * minix super-block data on disk
+ */
+struct minix_super_block {
+	uint16_t s_ninodes;
+	uint16_t s_nzones;
+	uint16_t s_imap_blocks;
+	uint16_t s_zmap_blocks;
+	uint16_t s_firstdatazone;
+	uint16_t s_log_zone_size;
+	uint32_t s_max_size;
+	uint16_t s_magic;
+	uint16_t s_state;
+	uint32_t s_zones;
+};
+
+struct minix_dir_entry {
+	uint16_t inode;
+	char name[0];
+};
+
+#define NAME_MAX         255   /* # chars in a file name */
+
+#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
+
+#define MINIX_VALID_FS               0x0001          /* Clean fs. */
+#define MINIX_ERROR_FS               0x0002          /* fs has errors. */
+
+#define MINIX_SUPER_MAGIC    0x137F          /* original minix fs */
+#define MINIX_SUPER_MAGIC2   0x138F          /* minix fs, 30 char names */
+
+#ifndef BLKGETSIZE
+#define BLKGETSIZE _IO(0x12,96)    /* return device size */
+#endif
+
+
+#ifndef __linux__
+#define volatile
+#endif
+
+#define MINIX_ROOT_INO 1
+#define MINIX_BAD_INO 2
+
+#define TEST_BUFFER_BLOCKS 16
+#define MAX_GOOD_BLOCKS 512
+
+#define UPPER(size,n) (((size)+((n)-1))/(n))
+#define INODE_SIZE (sizeof(struct minix_inode))
+#ifdef CONFIG_FEATURE_MINIX2
+#define INODE_SIZE2 (sizeof(struct minix2_inode))
+#define INODE_BLOCKS UPPER(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \
+				    : MINIX_INODES_PER_BLOCK))
+#else
+#define INODE_BLOCKS UPPER(INODES, (MINIX_INODES_PER_BLOCK))
+#endif
+#define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE)
+
+#define BITS_PER_BLOCK (BLOCK_SIZE<<3)
+
+static char *device_name;
+static int DEV = -1;
+static uint32_t BLOCKS;
+static int check;
+static int badblocks;
+static int namelen = 30;		/* default (changed to 30, per Linus's
+
+								   suggestion, Sun Nov 21 08:05:07 1993) */
+static int dirsize = 32;
+static int magic = MINIX_SUPER_MAGIC2;
+static int version2;
+
+static char root_block[BLOCK_SIZE];
+
+static char *inode_buffer;
+
+#define Inode (((struct minix_inode *) inode_buffer)-1)
+#ifdef CONFIG_FEATURE_MINIX2
+#define Inode2 (((struct minix2_inode *) inode_buffer)-1)
+#endif
+static char super_block_buffer[BLOCK_SIZE];
+static char boot_block_buffer[512];
+
+#define Super (*(struct minix_super_block *)super_block_buffer)
+#define INODES (Super.s_ninodes)
+#ifdef CONFIG_FEATURE_MINIX2
+#define ZONES (version2 ? Super.s_zones : Super.s_nzones)
+#else
+#define ZONES (Super.s_nzones)
+#endif
+#define IMAPS (Super.s_imap_blocks)
+#define ZMAPS (Super.s_zmap_blocks)
+#define FIRSTZONE (Super.s_firstdatazone)
+#define ZONESIZE (Super.s_log_zone_size)
+#define MAXSIZE (Super.s_max_size)
+#define MAGIC (Super.s_magic)
+#define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS)
+
+static char *inode_map;
+static char *zone_map;
+
+static unsigned short good_blocks_table[MAX_GOOD_BLOCKS];
+static int used_good_blocks;
+static unsigned long req_nr_inodes;
+
+static inline int bit(char * a,unsigned int i)
+{
+	  return (a[i >> 3] & (1<<(i & 7))) != 0;
+}
+#define inode_in_use(x) (bit(inode_map,(x)))
+#define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1))
+
+#define mark_inode(x) (setbit(inode_map,(x)))
+#define unmark_inode(x) (clrbit(inode_map,(x)))
+
+#define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1))
+#define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1))
+
+/*
+ * Check to make certain that our new filesystem won't be created on
+ * an already mounted partition.  Code adapted from mke2fs, Copyright
+ * (C) 1994 Theodore Ts'o.  Also licensed under GPL.
+ */
+static inline void check_mount(void)
+{
+	FILE *f;
+	struct mntent *mnt;
+
+	if ((f = setmntent(MOUNTED, "r")) == NULL)
+		return;
+	while ((mnt = getmntent(f)) != NULL)
+		if (strcmp(device_name, mnt->mnt_fsname) == 0)
+			break;
+	endmntent(f);
+	if (!mnt)
+		return;
+
+	bb_error_msg_and_die("%s is mounted; will not make a filesystem here!", device_name);
+}
+
+static long valid_offset(int fd, int offset)
+{
+	char ch;
+
+	if (lseek(fd, offset, 0) < 0)
+		return 0;
+	if (read(fd, &ch, 1) < 1)
+		return 0;
+	return 1;
+}
+
+static inline int count_blocks(int fd)
+{
+	int high, low;
+
+	low = 0;
+	for (high = 1; valid_offset(fd, high); high *= 2)
+		low = high;
+	while (low < high - 1) {
+		const int mid = (low + high) / 2;
+
+		if (valid_offset(fd, mid))
+			low = mid;
+		else
+			high = mid;
+	}
+	valid_offset(fd, 0);
+	return (low + 1);
+}
+
+static inline int get_size(const char *file)
+{
+	int fd;
+	long size;
+
+	fd = bb_xopen3(file, O_RDWR, 0);
+	if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
+		close(fd);
+		return (size * 512);
+	}
+
+	size = count_blocks(fd);
+	close(fd);
+	return size;
+}
+
+static inline void write_tables(void)
+{
+	/* Mark the super block valid. */
+	Super.s_state |= MINIX_VALID_FS;
+	Super.s_state &= ~MINIX_ERROR_FS;
+
+	if (lseek(DEV, 0, SEEK_SET))
+		bb_error_msg_and_die("seek to boot block failed in write_tables");
+	if (512 != write(DEV, boot_block_buffer, 512))
+		bb_error_msg_and_die("unable to clear boot sector");
+	if (BLOCK_SIZE != lseek(DEV, BLOCK_SIZE, SEEK_SET))
+		bb_error_msg_and_die("seek failed in write_tables");
+	if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE))
+		bb_error_msg_and_die("unable to write super-block");
+	if (IMAPS * BLOCK_SIZE != write(DEV, inode_map, IMAPS * BLOCK_SIZE))
+		bb_error_msg_and_die("unable to write inode map");
+	if (ZMAPS * BLOCK_SIZE != write(DEV, zone_map, ZMAPS * BLOCK_SIZE))
+		bb_error_msg_and_die("unable to write zone map");
+	if (INODE_BUFFER_SIZE != write(DEV, inode_buffer, INODE_BUFFER_SIZE))
+		bb_error_msg_and_die("unable to write inodes");
+
+}
+
+static void write_block(int blk, char *buffer)
+{
+	if (blk * BLOCK_SIZE != lseek(DEV, blk * BLOCK_SIZE, SEEK_SET))
+		bb_error_msg_and_die("seek failed in write_block");
+	if (BLOCK_SIZE != write(DEV, buffer, BLOCK_SIZE))
+		bb_error_msg_and_die("write failed in write_block");
+}
+
+static int get_free_block(void)
+{
+	int blk;
+
+	if (used_good_blocks + 1 >= MAX_GOOD_BLOCKS)
+		bb_error_msg_and_die("too many bad blocks");
+	if (used_good_blocks)
+		blk = good_blocks_table[used_good_blocks - 1] + 1;
+	else
+		blk = FIRSTZONE;
+	while (blk < ZONES && zone_in_use(blk))
+		blk++;
+	if (blk >= ZONES)
+		bb_error_msg_and_die("not enough good blocks");
+	good_blocks_table[used_good_blocks] = blk;
+	used_good_blocks++;
+	return blk;
+}
+
+static inline void mark_good_blocks(void)
+{
+	int blk;
+
+	for (blk = 0; blk < used_good_blocks; blk++)
+		mark_zone(good_blocks_table[blk]);
+}
+
+static int next(int zone)
+{
+	if (!zone)
+		zone = FIRSTZONE - 1;
+	while (++zone < ZONES)
+		if (zone_in_use(zone))
+			return zone;
+	return 0;
+}
+
+static inline void make_bad_inode(void)
+{
+	struct minix_inode *inode = &Inode[MINIX_BAD_INO];
+	int i, j, zone;
+	int ind = 0, dind = 0;
+	unsigned short ind_block[BLOCK_SIZE >> 1];
+	unsigned short dind_block[BLOCK_SIZE >> 1];
+
+#define NEXT_BAD (zone = next(zone))
+
+	if (!badblocks)
+		return;
+	mark_inode(MINIX_BAD_INO);
+	inode->i_nlinks = 1;
+	inode->i_time = time(NULL);
+	inode->i_mode = S_IFREG + 0000;
+	inode->i_size = badblocks * BLOCK_SIZE;
+	zone = next(0);
+	for (i = 0; i < 7; i++) {
+		inode->i_zone[i] = zone;
+		if (!NEXT_BAD)
+			goto end_bad;
+	}
+	inode->i_zone[7] = ind = get_free_block();
+	memset(ind_block, 0, BLOCK_SIZE);
+	for (i = 0; i < 512; i++) {
+		ind_block[i] = zone;
+		if (!NEXT_BAD)
+			goto end_bad;
+	}
+	inode->i_zone[8] = dind = get_free_block();
+	memset(dind_block, 0, BLOCK_SIZE);
+	for (i = 0; i < 512; i++) {
+		write_block(ind, (char *) ind_block);
+		dind_block[i] = ind = get_free_block();
+		memset(ind_block, 0, BLOCK_SIZE);
+		for (j = 0; j < 512; j++) {
+			ind_block[j] = zone;
+			if (!NEXT_BAD)
+				goto end_bad;
+		}
+	}
+	bb_error_msg_and_die("too many bad blocks");
+  end_bad:
+	if (ind)
+		write_block(ind, (char *) ind_block);
+	if (dind)
+		write_block(dind, (char *) dind_block);
+}
+
+#ifdef CONFIG_FEATURE_MINIX2
+static inline void make_bad_inode2(void)
+{
+	struct minix2_inode *inode = &Inode2[MINIX_BAD_INO];
+	int i, j, zone;
+	int ind = 0, dind = 0;
+	unsigned long ind_block[BLOCK_SIZE >> 2];
+	unsigned long dind_block[BLOCK_SIZE >> 2];
+
+	if (!badblocks)
+		return;
+	mark_inode(MINIX_BAD_INO);
+	inode->i_nlinks = 1;
+	inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL);
+	inode->i_mode = S_IFREG + 0000;
+	inode->i_size = badblocks * BLOCK_SIZE;
+	zone = next(0);
+	for (i = 0; i < 7; i++) {
+		inode->i_zone[i] = zone;
+		if (!NEXT_BAD)
+			goto end_bad;
+	}
+	inode->i_zone[7] = ind = get_free_block();
+	memset(ind_block, 0, BLOCK_SIZE);
+	for (i = 0; i < 256; i++) {
+		ind_block[i] = zone;
+		if (!NEXT_BAD)
+			goto end_bad;
+	}
+	inode->i_zone[8] = dind = get_free_block();
+	memset(dind_block, 0, BLOCK_SIZE);
+	for (i = 0; i < 256; i++) {
+		write_block(ind, (char *) ind_block);
+		dind_block[i] = ind = get_free_block();
+		memset(ind_block, 0, BLOCK_SIZE);
+		for (j = 0; j < 256; j++) {
+			ind_block[j] = zone;
+			if (!NEXT_BAD)
+				goto end_bad;
+		}
+	}
+	/* Could make triple indirect block here */
+	bb_error_msg_and_die("too many bad blocks");
+  end_bad:
+	if (ind)
+		write_block(ind, (char *) ind_block);
+	if (dind)
+		write_block(dind, (char *) dind_block);
+}
+#endif
+
+static inline void make_root_inode(void)
+{
+	struct minix_inode *inode = &Inode[MINIX_ROOT_INO];
+
+	mark_inode(MINIX_ROOT_INO);
+	inode->i_zone[0] = get_free_block();
+	inode->i_nlinks = 2;
+	inode->i_time = time(NULL);
+	if (badblocks)
+		inode->i_size = 3 * dirsize;
+	else {
+		root_block[2 * dirsize] = '\0';
+		root_block[2 * dirsize + 1] = '\0';
+		inode->i_size = 2 * dirsize;
+	}
+	inode->i_mode = S_IFDIR + 0755;
+	inode->i_uid = getuid();
+	if (inode->i_uid)
+		inode->i_gid = getgid();
+	write_block(inode->i_zone[0], root_block);
+}
+
+#ifdef CONFIG_FEATURE_MINIX2
+static inline void make_root_inode2(void)
+{
+	struct minix2_inode *inode = &Inode2[MINIX_ROOT_INO];
+
+	mark_inode(MINIX_ROOT_INO);
+	inode->i_zone[0] = get_free_block();
+	inode->i_nlinks = 2;
+	inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL);
+	if (badblocks)
+		inode->i_size = 3 * dirsize;
+	else {
+		root_block[2 * dirsize] = '\0';
+		root_block[2 * dirsize + 1] = '\0';
+		inode->i_size = 2 * dirsize;
+	}
+	inode->i_mode = S_IFDIR + 0755;
+	inode->i_uid = getuid();
+	if (inode->i_uid)
+		inode->i_gid = getgid();
+	write_block(inode->i_zone[0], root_block);
+}
+#endif
+
+static inline void setup_tables(void)
+{
+	int i;
+	unsigned long inodes;
+
+	memset(super_block_buffer, 0, BLOCK_SIZE);
+	memset(boot_block_buffer, 0, 512);
+	MAGIC = magic;
+	ZONESIZE = 0;
+	MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024;
+#ifdef CONFIG_FEATURE_MINIX2
+	if (version2) {
+		Super.s_zones =  BLOCKS;
+	} else
+#endif
+		Super.s_nzones = BLOCKS;
+
+/* some magic nrs: 1 inode / 3 blocks */
+	if (req_nr_inodes == 0)
+		inodes = BLOCKS / 3;
+	else
+		inodes = req_nr_inodes;
+	/* Round up inode count to fill block size */
+#ifdef CONFIG_FEATURE_MINIX2
+	if (version2)
+		inodes = ((inodes + MINIX2_INODES_PER_BLOCK - 1) &
+				  ~(MINIX2_INODES_PER_BLOCK - 1));
+	else
+#endif
+		inodes = ((inodes + MINIX_INODES_PER_BLOCK - 1) &
+				  ~(MINIX_INODES_PER_BLOCK - 1));
+	if (inodes > 65535)
+		inodes = 65535;
+	INODES = inodes;
+	IMAPS = UPPER(INODES + 1, BITS_PER_BLOCK);
+	ZMAPS = 0;
+	i = 0;
+	while (ZMAPS !=
+		   UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1,
+				 BITS_PER_BLOCK) && i < 1000) {
+		ZMAPS =
+			UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1,
+				  BITS_PER_BLOCK);
+		i++;
+	}
+	/* Real bad hack but overwise mkfs.minix can be thrown
+	 * in infinite loop...
+	 * try:
+	 * dd if=/dev/zero of=test.fs count=10 bs=1024
+	 * /sbin/mkfs.minix -i 200 test.fs
+	 * */
+	if (i >= 999) {
+		bb_error_msg_and_die("unable to allocate buffers for maps");
+	}
+	FIRSTZONE = NORM_FIRSTZONE;
+	inode_map = xmalloc(IMAPS * BLOCK_SIZE);
+	zone_map = xmalloc(ZMAPS * BLOCK_SIZE);
+	memset(inode_map, 0xff, IMAPS * BLOCK_SIZE);
+	memset(zone_map, 0xff, ZMAPS * BLOCK_SIZE);
+	for (i = FIRSTZONE; i < ZONES; i++)
+		unmark_zone(i);
+	for (i = MINIX_ROOT_INO; i <= INODES; i++)
+		unmark_inode(i);
+	inode_buffer = xmalloc(INODE_BUFFER_SIZE);
+	memset(inode_buffer, 0, INODE_BUFFER_SIZE);
+	printf("%ld inodes\n", (long)INODES);
+	printf("%ld blocks\n", (long)ZONES);
+	printf("Firstdatazone=%ld (%ld)\n", (long)FIRSTZONE, (long)NORM_FIRSTZONE);
+	printf("Zonesize=%d\n", BLOCK_SIZE << ZONESIZE);
+	printf("Maxsize=%ld\n\n", (long)MAXSIZE);
+}
+
+/*
+ * Perform a test of a block; return the number of
+ * blocks readable/writable.
+ */
+static inline long do_check(char *buffer, int try, unsigned int current_block)
+{
+	long got;
+
+	/* Seek to the correct loc. */
+	if (lseek(DEV, current_block * BLOCK_SIZE, SEEK_SET) !=
+		current_block * BLOCK_SIZE) {
+		bb_error_msg_and_die("seek failed during testing of blocks");
+	}
+
+
+	/* Try the read */
+	got = read(DEV, buffer, try * BLOCK_SIZE);
+	if (got < 0)
+		got = 0;
+	if (got & (BLOCK_SIZE - 1)) {
+		printf("Weird values in do_check: probably bugs\n");
+	}
+	got /= BLOCK_SIZE;
+	return got;
+}
+
+static unsigned int currently_testing;
+
+static void alarm_intr(int alnum)
+{
+	if (currently_testing >= ZONES)
+		return;
+	signal(SIGALRM, alarm_intr);
+	alarm(5);
+	if (!currently_testing)
+		return;
+	printf("%d ...", currently_testing);
+	fflush(stdout);
+}
+
+static void check_blocks(void)
+{
+	int try, got;
+	static char buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS];
+
+	currently_testing = 0;
+	signal(SIGALRM, alarm_intr);
+	alarm(5);
+	while (currently_testing < ZONES) {
+		if (lseek(DEV, currently_testing * BLOCK_SIZE, SEEK_SET) !=
+			currently_testing * BLOCK_SIZE)
+			bb_error_msg_and_die("seek failed in check_blocks");
+		try = TEST_BUFFER_BLOCKS;
+		if (currently_testing + try > ZONES)
+			try = ZONES - currently_testing;
+		got = do_check(buffer, try, currently_testing);
+		currently_testing += got;
+		if (got == try)
+			continue;
+		if (currently_testing < FIRSTZONE)
+			bb_error_msg_and_die("bad blocks before data-area: cannot make fs");
+		mark_zone(currently_testing);
+		badblocks++;
+		currently_testing++;
+	}
+	if (badblocks > 1)
+		printf("%d bad blocks\n", badblocks);
+	else if (badblocks == 1)
+		printf("one bad block\n");
+}
+
+static void get_list_blocks(char *filename)
+{
+	FILE *listfile;
+	unsigned long blockno;
+
+	listfile = bb_xfopen(filename, "r");
+	while (!feof(listfile)) {
+		fscanf(listfile, "%ld\n", &blockno);
+		mark_zone(blockno);
+		badblocks++;
+	}
+	if (badblocks > 1)
+		printf("%d bad blocks\n", badblocks);
+	else if (badblocks == 1)
+		printf("one bad block\n");
+}
+
+int mkfs_minix_main(int argc, char **argv)
+{
+	int i=1;
+	char *tmp;
+	struct stat statbuf;
+	char *listfile = NULL;
+	int stopIt=FALSE;
+
+	if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE)
+		bb_error_msg_and_die("bad inode size");
+#ifdef CONFIG_FEATURE_MINIX2
+	if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE)
+		bb_error_msg_and_die("bad inode size");
+#endif
+
+	/* Parse options */
+	argv++;
+	while (--argc >= 0 && *argv && **argv) {
+		if (**argv == '-') {
+			stopIt=FALSE;
+			while (i > 0 && *++(*argv) && stopIt==FALSE) {
+				switch (**argv) {
+					case 'c':
+						check = 1;
+						break;
+					case 'i':
+						{
+							char *cp=NULL;
+							if (*(*argv+1) != 0) {
+								cp = ++(*argv);
+							} else {
+								if (--argc == 0) {
+									goto goodbye;
+								}
+								cp = *(++argv);
+							}
+							req_nr_inodes = strtoul(cp, &tmp, 0);
+							if (*tmp)
+								bb_show_usage();
+							stopIt=TRUE;
+							break;
+						}
+					case 'l':
+						if (--argc == 0) {
+							goto goodbye;
+						}
+						listfile = *(++argv);
+						break;
+					case 'n':
+						{
+							char *cp=NULL;
+
+							if (*(*argv+1) != 0) {
+								cp = ++(*argv);
+							} else {
+								if (--argc == 0) {
+									goto goodbye;
+								}
+								cp = *(++argv);
+							}
+							i = strtoul(cp, &tmp, 0);
+							if (*tmp)
+								bb_show_usage();
+							if (i == 14)
+								magic = MINIX_SUPER_MAGIC;
+							else if (i == 30)
+								magic = MINIX_SUPER_MAGIC2;
+							else
+								bb_show_usage();
+							namelen = i;
+							dirsize = i + 2;
+							stopIt=TRUE;
+							break;
+						}
+					case 'v':
+#ifdef CONFIG_FEATURE_MINIX2
+						version2 = 1;
+#else
+						bb_error_msg("%s: not compiled with minix v2 support",
+								device_name);
+						exit(-1);
+#endif
+						break;
+					case '-':
+					case 'h':
+					default:
+goodbye:
+						bb_show_usage();
+				}
+			}
+		} else {
+			if (device_name == NULL)
+				device_name = *argv;
+			else if (BLOCKS == 0)
+				BLOCKS = strtol(*argv, &tmp, 0);
+			else {
+				goto goodbye;
+			}
+		}
+		argv++;
+	}
+
+	if (device_name && !BLOCKS)
+		BLOCKS = get_size(device_name) / 1024;
+	if (!device_name || BLOCKS < 10) {
+		bb_show_usage();
+	}
+#ifdef CONFIG_FEATURE_MINIX2
+	if (version2) {
+		if (namelen == 14)
+			magic = MINIX2_SUPER_MAGIC;
+		else
+			magic = MINIX2_SUPER_MAGIC2;
+	} else
+#endif
+	if (BLOCKS > 65535)
+		BLOCKS = 65535;
+	check_mount();				/* is it already mounted? */
+	tmp = root_block;
+	*(short *) tmp = 1;
+	strcpy(tmp + 2, ".");
+	tmp += dirsize;
+	*(short *) tmp = 1;
+	strcpy(tmp + 2, "..");
+	tmp += dirsize;
+	*(short *) tmp = 2;
+	strcpy(tmp + 2, ".badblocks");
+	DEV = bb_xopen3(device_name, O_RDWR, 0);
+	if (fstat(DEV, &statbuf) < 0)
+		bb_error_msg_and_die("unable to stat %s", device_name);
+	if (!S_ISBLK(statbuf.st_mode))
+		check = 0;
+	else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
+		bb_error_msg_and_die("will not try to make filesystem on '%s'", device_name);
+	setup_tables();
+	if (check)
+		check_blocks();
+	else if (listfile)
+		get_list_blocks(listfile);
+#ifdef CONFIG_FEATURE_MINIX2
+	if (version2) {
+		make_root_inode2();
+		make_bad_inode2();
+	} else
+#endif
+	{
+		make_root_inode();
+		make_bad_inode();
+	}
+	mark_good_blocks();
+	write_tables();
+	return 0;
+
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/mkswap.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/mkswap.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/mkswap.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,401 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * mkswap.c - set up a linux swap device
+ *
+ * (C) 1991 Linus Torvalds. This file may be redistributed as per
+ * the Linux copyright.
+ */
+
+/*
+ * 20.12.91  -	time began. Got VM working yesterday by doing this by hand.
+ *
+ * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks]
+ *
+ *	-c   for readability checking. (Use it unless you are SURE!)
+ *	-vN  for swap areas version N. (Only N=0,1 known today.)
+ *      -f   for forcing swap creation even if it would smash partition table.
+ *
+ * The device may be a block device or an image of one, but this isn't
+ * enforced (but it's not much fun on a character device :-).
+ *
+ * Patches from jaggy at purplet.demon.co.uk (Mike Jagdis) to make the
+ * size-in-blocks parameter optional added Wed Feb  8 10:33:43 1995.
+ *
+ * Version 1 swap area code (for kernel 2.1.117), aeb, 981010.
+ *
+ * Sparc fixes, jj at ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb.
+ * V1_MAX_PAGES fixes, jj, 990325.
+ *
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek at misiek.eu.org>
+ * - added Native Language Support
+ *
+ *  from util-linux -- adapted for busybox by
+ *  Erik Andersen <andersen at codepoet.org>. I ripped out Native Language
+ *  Support, made some stuff smaller, and fitted for life in busybox.
+ *
+ */
+
+#include "busybox.h"
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>			/* for _IO */
+#include <sys/utsname.h>
+#include <asm/page.h>			/* for PAGE_SIZE and PAGE_SHIFT */
+				/* we also get PAGE_SIZE via getpagesize() */
+
+static char *device_name = NULL;
+static int DEV = -1;
+static long PAGES = 0;
+static int check = 0;
+static int badpages = 0;
+#if ENABLE_FEATURE_MKSWAP_V0
+static int version = -1;
+#else
+#define version 1
+/* and make sure that we optimize away anything which would deal with checking
+ * the kernel revision as we have v1 support only anyway.
+ */
+#undef KERNEL_VERSION
+#define KERNEL_VERSION(p,q,r) 1
+#define get_linux_version_code() 1
+#endif
+
+/*
+ * The definition of the union swap_header uses the constant PAGE_SIZE.
+ * Unfortunately, on some architectures this depends on the hardware model,
+ * and can only be found at run time -- we use getpagesize().
+ */
+
+static int pagesize;
+static unsigned int *signature_page;
+
+static struct swap_header_v1 {
+	char bootbits[1024];		/* Space for disklabel etc. */
+	unsigned int swap_version;
+	unsigned int last_page;
+	unsigned int nr_badpages;
+	unsigned int padding[125];
+	unsigned int badpages[1];
+} *p;
+
+static inline void init_signature_page(void)
+{
+	pagesize = getpagesize();
+
+#ifdef PAGE_SIZE
+	if (pagesize != PAGE_SIZE)
+		bb_error_msg("Assuming pages of size %d", pagesize);
+#endif
+	signature_page = (unsigned int *) xmalloc(pagesize);
+	memset(signature_page, 0, pagesize);
+	p = (struct swap_header_v1 *) signature_page;
+}
+
+static inline void write_signature(char *sig)
+{
+	char *sp = (char *) signature_page;
+
+	strncpy(sp + pagesize - 10, sig, 10);
+}
+
+#define V0_MAX_PAGES	(8 * (pagesize - 10))
+/* Before 2.2.0pre9 */
+#define V1_OLD_MAX_PAGES	((0x7fffffff / pagesize) - 1)
+/* Since 2.2.0pre9:
+   error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
+   with variations on
+	#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
+	#define SWP_OFFSET(entry) ((entry) >> 8)
+   on the various architectures. Below the result - yuk.
+
+   Machine	pagesize	SWP_ENTRY	SWP_OFFSET	bound+1	oldbound+2
+   i386		2^12		o<<8		e>>8		1<<24	1<<19
+   mips		2^12		o<<15		e>>15		1<<17	1<<19
+   alpha	2^13		o<<40		e>>40		1<<24	1<<18
+   m68k		2^12		o<<12		e>>12		1<<20	1<<19
+   sparc	2^{12,13}	(o&0x3ffff)<<9	(e>>9)&0x3ffff	1<<18	1<<{19,18}
+   sparc64	2^13		o<<13		e>>13		1<<51	1<<18
+   ppc		2^12		o<<8		e>>8		1<<24	1<<19
+   armo		2^{13,14,15}	o<<8		e>>8		1<<24	1<<{18,17,16}
+   armv		2^12		o<<9		e>>9		1<<23	1<<19
+
+   assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
+
+   The bad part is that we need to know this since the kernel will
+   refuse a swap space if it is too large.
+*/
+/* patch from jj - why does this differ from the above? */
+#if defined(__alpha__)
+#define V1_MAX_PAGES           ((1 << 24) - 1)
+#elif defined(__mips__)
+#define V1_MAX_PAGES           ((1 << 17) - 1)
+#elif defined(__sparc_v9__)
+#define V1_MAX_PAGES           ((3 << 29) - 1)
+#elif defined(__sparc__)
+#define V1_MAX_PAGES           (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
+#else
+#define V1_MAX_PAGES           V1_OLD_MAX_PAGES
+#endif
+/* man page now says:
+The maximum useful size of a swap area now depends on the architecture.
+It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
+128GB on alpha and 3TB on sparc64.
+*/
+
+#define MAX_BADPAGES	((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
+
+static inline void bit_set(unsigned int *addr, unsigned int nr)
+{
+	unsigned int r, m;
+
+	addr += nr / (8 * sizeof(int));
+
+	r = *addr;
+	m = 1 << (nr & (8 * sizeof(int) - 1));
+
+	*addr = r | m;
+}
+
+static int bit_test_and_clear(unsigned int *addr, unsigned int nr)
+{
+	unsigned int r, m;
+
+	addr += nr / (8 * sizeof(int));
+
+	r = *addr;
+	m = 1 << (nr & (8 * sizeof(int) - 1));
+
+	*addr = r & ~m;
+	return (r & m) != 0;
+}
+
+static void page_ok(int page)
+{
+	if (ENABLE_FEATURE_MKSWAP_V0) {
+		bit_set(signature_page, page);
+	}
+}
+
+static void check_blocks(void)
+{
+	unsigned int current_page;
+	int do_seek = 1;
+	char *buffer;
+
+	buffer = xmalloc(pagesize);
+	current_page = 0;
+	while (current_page < PAGES) {
+		if (!check && version == 0) {
+			page_ok(current_page++);
+			continue;
+		}
+		if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
+			current_page * pagesize)
+			bb_error_msg_and_die("seek failed in check_blocks");
+		if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
+			current_page++;
+			if (version == 0)
+				bit_test_and_clear(signature_page, current_page);
+			else {
+				if (badpages == MAX_BADPAGES)
+					bb_error_msg_and_die("too many bad pages");
+				p->badpages[badpages] = current_page;
+			}
+			badpages++;
+			continue;
+		}
+		page_ok(current_page++);
+	}
+	if (ENABLE_FEATURE_CLEAN_UP)
+		free(buffer);
+	if (badpages > 0)
+		printf("%d bad page%s\n", badpages, (badpages==1)?"":"s");
+}
+
+static long valid_offset(int fd, int offset)
+{
+	char ch;
+
+	if (lseek(fd, offset, 0) < 0)
+		return 0;
+	if (read(fd, &ch, 1) < 1)
+		return 0;
+	return 1;
+}
+
+static int find_size(int fd)
+{
+	unsigned int high, low;
+
+	low = 0;
+	for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
+		low = high;
+	while (low < high - 1) {
+		const int mid = (low + high) / 2;
+
+		if (valid_offset(fd, mid))
+			low = mid;
+		else
+			high = mid;
+	}
+	return (low + 1);
+}
+
+/* return size in pages, to avoid integer overflow */
+static inline long get_size(const char *file)
+{
+	int fd;
+	long size;
+
+	fd = bb_xopen3(file, O_RDONLY, 0);
+	if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
+		size /= pagesize / 512;
+	} else {
+		size = find_size(fd) / pagesize;
+	}
+	close(fd);
+	return size;
+}
+
+int mkswap_main(int argc, char **argv)
+{
+	char *tmp;
+	struct stat statbuf;
+	int sz;
+	int maxpages;
+	int goodpages;
+#ifdef __sparc__
+	int force = 0;
+#endif
+
+	init_signature_page();		/* get pagesize */
+
+	bb_opt_complementally = "?"; /* call bb_show_usage internally */
+	sz = bb_getopt_ulflags(argc, argv, "+cfv:", &tmp);
+	if (sz & 1)
+		check = 1;
+#ifdef __sparc__
+	if (sz & 2)
+		force = 1;
+#endif
+#if ENABLE_FEATURE_MKSWAP_V0
+	if (sz & 4) {
+		version = bb_xgetlarg(tmp, 10, 0, 1);
+	} else {
+		if (get_linux_version_code() < KERNEL_VERSION(2, 1, 117))
+			version = 0;
+		else
+			version = 1;
+	}
+#endif
+
+	argv += optind;
+	argc -= optind;
+
+	goodpages = pagesize / 1024; /* cache division */
+	while (argc--) {
+		if (device_name) {
+			PAGES = bb_xgetlarg(argv[0], 0, 10, sz * goodpages) / goodpages;
+			argc = 0; /* ignore any surplus args.. */
+		} else {
+			device_name = argv[0];
+			sz = get_size(device_name);
+			argv++;
+		}
+	}
+
+	if (!device_name) {
+		bb_error_msg_and_die("error: Nowhere to set up swap on?");
+	}
+	if (!PAGES) {
+		PAGES = sz;
+	}
+
+#if 0
+	maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
+#else
+	if (!version)
+		maxpages = V0_MAX_PAGES;
+	else if (get_linux_version_code() >= KERNEL_VERSION(2,2,1))
+		maxpages = V1_MAX_PAGES;
+	else {
+		maxpages = V1_OLD_MAX_PAGES;
+		if (maxpages > V1_MAX_PAGES)
+			maxpages = V1_MAX_PAGES;
+	}
+#endif
+	if (PAGES > maxpages) {
+		PAGES = maxpages;
+		bb_error_msg("warning: truncating swap area to %ldkB",
+				PAGES * goodpages);
+	}
+
+	DEV = bb_xopen3(device_name, O_RDWR, 0);
+	if (fstat(DEV, &statbuf) < 0)
+		bb_perror_msg_and_die("%s", device_name);
+	if (!S_ISBLK(statbuf.st_mode))
+		check = 0;
+	else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
+		bb_error_msg_and_die("Will not try to make swapdevice on '%s'", device_name);
+
+#ifdef __sparc__
+	if (!force && version == 0) {
+		/* Don't overwrite partition table unless forced */
+		unsigned char *buffer = (unsigned char *) signature_page;
+		unsigned short *q, sum;
+
+		if (read(DEV, buffer, 512) != 512)
+			bb_error_msg_and_die("fatal: first page unreadable");
+		if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
+			q = (unsigned short *) (buffer + 510);
+			for (sum = 0; q >= (unsigned short *) buffer;)
+				sum ^= *q--;
+			if (!sum) {
+				bb_error_msg("Device '%s' contains a valid Sun disklabel.\n"
+"This probably means creating v0 swap would destroy your partition table\n"
+"No swap created. If you really want to create swap v0 on that device, use\n"
+"the -f option to force it.", device_name);
+				return EXIT_FAILURE;
+			}
+		}
+	}
+#endif
+
+	if (version == 0 || check)
+		check_blocks();
+	if (version == 0 && !bit_test_and_clear(signature_page, 0))
+		bb_error_msg_and_die("fatal: first page unreadable");
+	if (version == 1) {
+		p->swap_version = version;
+		p->last_page = PAGES - 1;
+		p->nr_badpages = badpages;
+	}
+
+	goodpages = PAGES - badpages - 1;
+	if (goodpages <= 0)
+		bb_error_msg_and_die("Unable to set up swap-space: unreadable");
+	printf("Setting up swapspace version %d, size = %ld bytes\n",
+		   version, (long) (goodpages * pagesize));
+	write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
+
+	sz = ((version == 0) ? 0 : 1024); /* offset */
+	if (lseek(DEV, sz, SEEK_SET) != sz)
+		bb_error_msg_and_die("unable to rewind swap-device");
+	goodpages = pagesize - sz; /* cache substraction */
+	if (write(DEV, (char *) signature_page + sz, goodpages)
+		!= goodpages)
+		bb_error_msg_and_die("unable to write signature page");
+
+	/*
+	 * A subsequent swapon() will fail if the signature
+	 * is not actually on disk. (This is a kernel bug.)
+	 */
+	if (fsync(DEV))
+		bb_error_msg_and_die("fsync failed");
+	if (ENABLE_FEATURE_CLEAN_UP) {
+		close(DEV);
+		free(signature_page);
+	}
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/more.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/more.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/more.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,208 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini more implementation for busybox
+ *
+ * Copyright (C) 1995, 1996 by Bruce Perens <bruce at pixar.com>.
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Latest version blended together by Erik Andersen <andersen at codepoet.org>,
+ * based on the original more implementation by Bruce, and code from the
+ * Debian boot-floppies team.
+ *
+ * Termios corrects by Vladimir Oleynik <dzo at simtreas.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include "busybox.h"
+
+
+#ifdef CONFIG_FEATURE_USE_TERMIOS
+static int cin_fileno;
+#include <termios.h>
+#define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp)
+#define getTermSettings(fd,argp) tcgetattr(fd, argp);
+
+static struct termios initial_settings, new_settings;
+
+static void set_tty_to_initial_mode(void)
+{
+	setTermSettings(cin_fileno, &initial_settings);
+}
+
+static void gotsig(int sig)
+{
+	putchar('\n');
+	exit(EXIT_FAILURE);
+}
+#endif /* CONFIG_FEATURE_USE_TERMIOS */
+
+
+int more_main(int argc, char **argv)
+{
+	int c, lines, input = 0;
+	int please_display_more_prompt = 0;
+	struct stat st;
+	FILE *file;
+	FILE *cin;
+	int len, page_height;
+	int terminal_width;
+	int terminal_height;
+
+	argc--;
+	argv++;
+
+
+	/* not use inputing from terminal if usage: more > outfile */
+	if(isatty(STDOUT_FILENO)) {
+		cin = fopen(CURRENT_TTY, "r");
+		if (!cin)
+			cin = bb_xfopen(CONSOLE_DEV, "r");
+		please_display_more_prompt = 2;
+#ifdef CONFIG_FEATURE_USE_TERMIOS
+		cin_fileno = fileno(cin);
+		getTermSettings(cin_fileno, &initial_settings);
+		new_settings = initial_settings;
+		new_settings.c_lflag &= ~ICANON;
+		new_settings.c_lflag &= ~ECHO;
+		new_settings.c_cc[VMIN] = 1;
+		new_settings.c_cc[VTIME] = 0;
+		setTermSettings(cin_fileno, &new_settings);
+		atexit(set_tty_to_initial_mode);
+		(void) signal(SIGINT, gotsig);
+		(void) signal(SIGQUIT, gotsig);
+		(void) signal(SIGTERM, gotsig);
+#endif
+	} else {
+		cin = stdin;
+	}
+
+	do {
+		if (argc == 0) {
+			file = stdin;
+		} else
+			file = bb_wfopen(*argv, "r");
+		if(file==0)
+			goto loop;
+
+		st.st_size = 0;
+		fstat(fileno(file), &st);
+
+		please_display_more_prompt &= ~1;
+
+		get_terminal_width_height(fileno(cin), &terminal_width, &terminal_height);
+		if (terminal_height > 4)
+			terminal_height -= 2;
+		if (terminal_width > 0)
+			terminal_width -= 1;
+
+		len=0;
+		lines = 0;
+		page_height = terminal_height;
+		while ((c = getc(file)) != EOF) {
+
+			if ((please_display_more_prompt & 3) == 3) {
+				len = printf("--More-- ");
+				if (file != stdin && st.st_size > 0) {
+#if _FILE_OFFSET_BITS == 64
+					len += printf("(%d%% of %lld bytes)",
+						   (int) (100 * ((double) ftell(file) /
+						   (double) st.st_size)), (long long)st.st_size);
+#else
+					len += printf("(%d%% of %ld bytes)",
+						   (int) (100 * ((double) ftell(file) /
+						   (double) st.st_size)), (long)st.st_size);
+#endif
+				}
+
+				fflush(stdout);
+
+				/*
+				 * We've just displayed the "--More--" prompt, so now we need
+				 * to get input from the user.
+				 */
+				input = getc(cin);
+#ifndef CONFIG_FEATURE_USE_TERMIOS
+				printf("\033[A"); /* up cursor */
+#endif
+				/* Erase the "More" message */
+				putc('\r', stdout);
+				while (--len >= 0)
+					putc(' ', stdout);
+				putc('\r', stdout);
+				len=0;
+				lines = 0;
+				page_height = terminal_height;
+				please_display_more_prompt &= ~1;
+
+				if (input == 'q')
+					goto end;
+			}
+
+			/*
+			 * There are two input streams to worry about here:
+			 *
+			 * c     : the character we are reading from the file being "mored"
+			 * input : a character received from the keyboard
+			 *
+			 * If we hit a newline in the _file_ stream, we want to test and
+			 * see if any characters have been hit in the _input_ stream. This
+			 * allows the user to quit while in the middle of a file.
+			 */
+			if (c == '\n') {
+				/* increment by just one line if we are at
+				 * the end of this line */
+				if (input == '\n')
+					please_display_more_prompt |= 1;
+				/* Adjust the terminal height for any overlap, so that
+				 * no lines get lost off the top. */
+				if (len >= terminal_width) {
+					int quot, rem;
+					quot = len / terminal_width;
+					rem  = len - (quot * terminal_width);
+					if (quot) {
+						if (rem)
+							page_height-=quot;
+						else
+							page_height-=(quot-1);
+					}
+				}
+				if (++lines >= page_height) {
+					please_display_more_prompt |= 1;
+				}
+				len=0;
+			}
+			/*
+			 * If we just read a newline from the file being 'mored' and any
+			 * key other than a return is hit, scroll by one page
+			 */
+			putc(c, stdout);
+			len++;
+		}
+		fclose(file);
+		fflush(stdout);
+loop:
+		argv++;
+	} while (--argc > 0);
+  end:
+	return 0;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/mount.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/mount.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/mount.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,552 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini mount implementation for busybox
+ *
+ * Copyright (C) 1995, 1996 by Bruce Perens <bruce at pixar.com>.
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ * Copyright (C) 2005-2006 by Rob Landley <rob at landley.net>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* todo:
+ * bb_getopt_ulflags();
+ */
+
+/* Design notes: There is no spec for mount.  Remind me to write one.
+
+   mount_main() calls singlemount() which calls mount_it_now().
+
+   mount_main() can loop through /etc/fstab for mount -a
+   singlemount() can loop through /etc/filesystems for fstype detection.
+   mount_it_now() does the actual mount.
+*/
+
+#include "busybox.h"
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <mntent.h>
+#include <ctype.h>
+#include <fcntl.h>		// for CONFIG_FEATURE_MOUNT_LOOP
+#include <sys/ioctl.h>  // for CONFIG_FEATURE_MOUNT_LOOP
+
+// These two aren't always defined in old headers
+#ifndef MS_BIND
+#define MS_BIND		4096
+#endif
+#ifndef MS_MOVE
+#define MS_MOVE		8192
+#endif
+#ifndef MS_SILENT
+#define MS_SILENT	32768
+#endif
+
+// Not real flags, but we want to be able to check for this.
+#define MOUNT_NOAUTO    (1<<29)
+#define MOUNT_SWAP      (1<<30)
+/* Standard mount options (from -o options or --options), with corresponding
+ * flags */
+
+struct {
+	const char *name;
+	long flags;
+} static const mount_options[] = {
+	// NOP flags.
+
+	{"loop", 0},
+	{"defaults", 0},
+	{"quiet", 0},
+
+	// vfs flags
+
+	{"ro", MS_RDONLY},
+	{"rw", ~MS_RDONLY},
+	{"nosuid", MS_NOSUID},
+	{"suid", ~MS_NOSUID},
+	{"dev", ~MS_NODEV},
+	{"nodev", MS_NODEV},
+	{"exec", ~MS_NOEXEC},
+	{"noexec", MS_NOEXEC},
+	{"sync", MS_SYNCHRONOUS},
+	{"async", ~MS_SYNCHRONOUS},
+	{"atime", ~MS_NOATIME},
+	{"noatime", MS_NOATIME},
+	{"diratime", ~MS_NODIRATIME},
+	{"nodiratime", MS_NODIRATIME},
+	{"loud", ~MS_SILENT},
+
+	// action flags
+
+	{"remount", MS_REMOUNT},
+	{"bind", MS_BIND},
+	{"move", MS_MOVE},
+	{"noauto",MOUNT_NOAUTO},
+	{"swap",MOUNT_SWAP}
+};
+
+/* Append mount options to string */
+static void append_mount_options(char **oldopts, char *newopts)
+{
+	if(*oldopts && **oldopts) {
+		char *temp=bb_xasprintf("%s,%s",*oldopts,newopts);
+		free(*oldopts);
+		*oldopts=temp;
+	} else {
+		if (ENABLE_FEATURE_CLEAN_UP) free(*oldopts);
+		*oldopts = bb_xstrdup(newopts);
+	}
+}
+
+/* Use the mount_options list to parse options into flags.
+ * Return list of unrecognized options in *strflags if strflags!=NULL */
+static int parse_mount_options(char *options, char **unrecognized)
+{
+	int flags = MS_SILENT;
+
+	// Loop through options
+	for (;;) {
+		int i;
+		char *comma = strchr(options, ',');
+
+		if (comma) *comma = 0;
+
+		// Find this option in mount_options
+		for (i = 0; i < (sizeof(mount_options) / sizeof(*mount_options)); i++) {
+			if (!strcasecmp(mount_options[i].name, options)) {
+				long fl = mount_options[i].flags;
+				if(fl < 0) flags &= fl;
+				else flags |= fl;
+				break;
+			}
+		}
+		// If unrecognized not NULL, append unrecognized mount options */
+		if (unrecognized
+				&& i == (sizeof(mount_options) / sizeof(*mount_options)))
+		{
+			// Add it to strflags, to pass on to kernel
+			i = *unrecognized ? strlen(*unrecognized) : 0;
+			*unrecognized = xrealloc(*unrecognized, i+strlen(options)+2);
+
+			// Comma separated if it's not the first one
+			if (i) (*unrecognized)[i++] = ',';
+			strcpy((*unrecognized)+i, options);
+		}
+
+		// Advance to next option, or finish
+		if(comma) {
+			*comma = ',';
+			options = ++comma;
+		} else break;
+	}
+
+	return flags;
+}
+
+// Return a list of all block device backed filesystems
+
+static llist_t *get_block_backed_filesystems(void)
+{
+	char *fs, *buf,
+		 *filesystems[] = {"/etc/filesystems", "/proc/filesystems", 0};
+	llist_t *list = 0;
+	int i;
+	FILE *f;
+
+	for(i = 0; filesystems[i]; i++) {
+		if(!(f = fopen(filesystems[i], "r"))) continue;
+
+		for(fs = buf = 0; (fs = buf = bb_get_chomped_line_from_file(f));
+			free(buf))
+		{
+			if(!strncmp(buf,"nodev",5) && isspace(buf[5])) continue;
+
+			while(isspace(*fs)) fs++;
+			if(*fs=='#' || *fs=='*') continue;
+			if(!*fs) continue;
+
+			llist_add_to_end(&list,bb_xstrdup(fs));
+		}
+		if (ENABLE_FEATURE_CLEAN_UP) fclose(f);
+	}
+
+	return list;
+}
+
+llist_t *fslist = 0;
+
+#if ENABLE_FEATURE_CLEAN_UP
+static void delete_block_backed_filesystems(void)
+{
+	llist_free(fslist, free);
+}
+#else
+void delete_block_backed_filesystems(void);
+#endif
+
+#if ENABLE_FEATURE_MTAB_SUPPORT
+static int useMtab;
+static int fakeIt;
+#else
+#define useMtab 0
+#define fakeIt 0
+#endif
+
+// Perform actual mount of specific filesystem at specific location.
+
+static int mount_it_now(struct mntent *mp, int vfsflags, char *filteropts)
+{
+	int rc;
+
+	if (fakeIt) { return 0; }
+
+	// Mount, with fallback to read-only if necessary.
+
+	for(;;) {
+		rc = mount(mp->mnt_fsname, mp->mnt_dir, mp->mnt_type,
+				vfsflags, filteropts);
+		if(!rc || (vfsflags&MS_RDONLY) || (errno!=EACCES && errno!=EROFS))
+			break;
+		bb_error_msg("%s is write-protected, mounting read-only",
+				mp->mnt_fsname);
+		vfsflags |= MS_RDONLY;
+	}
+
+	// Abort entirely if permission denied.
+
+	if (rc && errno == EPERM)
+		bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+
+	/* If the mount was successful, and we're maintaining an old-style
+	 * mtab file by hand, add the new entry to it now. */
+
+	if(ENABLE_FEATURE_MTAB_SUPPORT && useMtab && !rc) {
+		FILE *mountTable = setmntent(bb_path_mtab_file, "a+");
+		int i;
+
+		if(!mountTable)
+			bb_error_msg("No %s\n",bb_path_mtab_file);
+
+		// Add vfs string flags
+
+		for(i=0; mount_options[i].flags != MS_REMOUNT; i++)
+			if (mount_options[i].flags > 0)
+				append_mount_options(&(mp->mnt_opts),
+// Shut up about the darn const.  It's not important.  I don't care.
+						(char *)mount_options[i].name);
+
+		// Remove trailing / (if any) from directory we mounted on
+
+		i = strlen(mp->mnt_dir);
+		if(i>1 && mp->mnt_dir[i-1] == '/') mp->mnt_dir[i-1] = 0;
+
+		// Write and close.
+
+		if(!mp->mnt_type || !*mp->mnt_type) mp->mnt_type="--bind";
+		addmntent(mountTable, mp);
+		endmntent(mountTable);
+		if (ENABLE_FEATURE_CLEAN_UP)
+			if(strcmp(mp->mnt_type,"--bind")) mp->mnt_type = 0;
+	}
+
+	return rc;
+}
+
+
+// Mount one directory.  Handles NFS, loopback, autobind, and filesystem type
+// detection.  Returns 0 for success, nonzero for failure.
+
+static int singlemount(struct mntent *mp, int ignore_busy)
+{
+	int rc = -1, vfsflags;
+	char *loopFile = 0, *filteropts = 0;
+	llist_t *fl = 0;
+	struct stat st;
+
+	vfsflags = parse_mount_options(mp->mnt_opts, &filteropts);
+
+	// Treat fstype "auto" as unspecified.
+
+	if (mp->mnt_type && !strcmp(mp->mnt_type,"auto")) mp->mnt_type = 0;
+
+	// Might this be an NFS filesystem?
+
+	if (ENABLE_FEATURE_MOUNT_NFS &&
+		(!mp->mnt_type || !strcmp(mp->mnt_type,"nfs")) &&
+		strchr(mp->mnt_fsname, ':') != NULL)
+	{
+		if (nfsmount(mp->mnt_fsname, mp->mnt_dir, &vfsflags, &filteropts, 1)) {
+			bb_perror_msg("nfsmount failed");
+			goto report_error;
+		} else {
+			// Strangely enough, nfsmount() doesn't actually mount() anything.
+			mp->mnt_type = "nfs";
+			rc = mount_it_now(mp, vfsflags, filteropts);
+			if (ENABLE_FEATURE_CLEAN_UP) free(filteropts);
+			
+			goto report_error;
+		}
+	}
+
+	// Look at the file.  (Not found isn't a failure for remount, or for
+	// a synthetic filesystem like proc or sysfs.)
+
+	if (lstat(mp->mnt_fsname, &st));
+	else if (!(vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE))) {
+		// Do we need to allocate a loopback device for it?
+
+		if (ENABLE_FEATURE_MOUNT_LOOP && S_ISREG(st.st_mode)) {
+			loopFile = bb_simplify_path(mp->mnt_fsname);
+			mp->mnt_fsname = 0;
+			switch(set_loop(&(mp->mnt_fsname), loopFile, 0)) {
+				case 0:
+				case 1:
+					break;
+				default:
+					bb_error_msg( errno == EPERM || errno == EACCES
+						? bb_msg_perm_denied_are_you_root
+					   	: "Couldn't setup loop device");
+					return errno;
+			}
+
+		// Autodetect bind mounts
+
+		} else if (S_ISDIR(st.st_mode) && !mp->mnt_type) vfsflags |= MS_BIND;
+	}
+
+	/* If we know the fstype (or don't need to), jump straight
+	 * to the actual mount. */
+
+	if (mp->mnt_type || (vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE)))
+		rc = mount_it_now(mp, vfsflags, filteropts);
+
+	// Loop through filesystem types until mount succeeds or we run out
+
+	else {
+
+		/* Initialize list of block backed filesystems.  This has to be
+		 * done here so that during "mount -a", mounts after /proc shows up
+		 * can autodetect. */
+
+		if (!fslist) {
+			fslist = get_block_backed_filesystems();
+			if (ENABLE_FEATURE_CLEAN_UP && fslist)
+				atexit(delete_block_backed_filesystems);
+		}
+
+		for (fl = fslist; fl; fl = fl->link) {
+			mp->mnt_type = fl->data;
+
+			if (!(rc = mount_it_now(mp,vfsflags, filteropts))) break;
+
+			mp->mnt_type = 0;
+		}
+	}
+
+	if (ENABLE_FEATURE_CLEAN_UP) free(filteropts);
+
+	// If mount failed, clean up loop file (if any).
+
+	if (ENABLE_FEATURE_MOUNT_LOOP && rc && loopFile) {
+		del_loop(mp->mnt_fsname);
+		if (ENABLE_FEATURE_CLEAN_UP) {
+			free(loopFile);
+			free(mp->mnt_fsname);
+		}
+	}
+report_error:
+	if (rc && errno == EBUSY && ignore_busy) rc = 0;
+	if (rc < 0)
+		bb_perror_msg("Mounting %s on %s failed", mp->mnt_fsname, mp->mnt_dir);
+
+	return rc;
+}
+
+// Parse options, if necessary parse fstab/mtab, and call singlemount for
+// each directory to be mounted.
+
+int mount_main(int argc, char **argv)
+{
+	char *cmdopts = bb_xstrdup(""), *fstabname, *fstype=0, *storage_path=0;
+	FILE *fstab;
+	int i, opt, all = FALSE, rc = 0;
+	struct mntent mtpair[2], *mtcur = mtpair;
+
+	/* parse long options, like --bind and --move.  Note that -o option
+	 * and --option are synonymous.  Yes, this means --remount,rw works. */
+
+	for (i = opt = 0; i < argc; i++) {
+		if (argv[i][0] == '-' && argv[i][1] == '-') {
+			append_mount_options(&cmdopts,argv[i]+2);
+		} else argv[opt++] = argv[i];
+	}
+	argc = opt;
+
+	// Parse remaining options
+
+	while ((opt = getopt(argc, argv, "o:t:rwavnf")) > 0) {
+		switch (opt) {
+			case 'o':
+				append_mount_options(&cmdopts, optarg);
+				break;
+			case 't':
+				fstype = optarg;
+				break;
+			case 'r':
+				append_mount_options(&cmdopts, "ro");
+				break;
+			case 'w':
+				append_mount_options(&cmdopts, "rw");
+				break;
+			case 'a':
+				all = TRUE;
+				break;
+			case 'n':
+				USE_FEATURE_MTAB_SUPPORT(useMtab = FALSE;)
+				break;
+			case 'f':
+				USE_FEATURE_MTAB_SUPPORT(fakeIt = FALSE;)
+				break;
+			case 'v':
+				break;		// ignore -v
+			default:
+				bb_show_usage();
+		}
+	}
+
+	// Three or more non-option arguments?  Die with a usage message.
+
+	if (optind-argc>2) bb_show_usage();
+
+	// If we have no arguments, show currently mounted filesystems
+
+	if (optind == argc) {
+		if (!all) {
+			FILE *mountTable = setmntent(bb_path_mtab_file, "r");
+
+			if(!mountTable) bb_error_msg_and_die("No %s",bb_path_mtab_file);
+
+			while (getmntent_r(mountTable,mtpair,bb_common_bufsiz1,
+								sizeof(bb_common_bufsiz1)))
+			{
+				// Don't show rootfs.
+				if (!strcmp(mtpair->mnt_fsname, "rootfs")) continue;
+
+				if (!fstype || !strcmp(mtpair->mnt_type, fstype))
+					printf("%s on %s type %s (%s)\n", mtpair->mnt_fsname,
+							mtpair->mnt_dir, mtpair->mnt_type,
+							mtpair->mnt_opts);
+			}
+			if (ENABLE_FEATURE_CLEAN_UP) endmntent(mountTable);
+			return EXIT_SUCCESS;
+		}
+	}
+
+	// When we have two arguments, the second is the directory and we can
+	// skip looking at fstab entirely.  We can always abspath() the directory
+	// argument when we get it.
+
+	if (optind+2 == argc) {
+		mtpair->mnt_fsname = argv[optind];
+		mtpair->mnt_dir = argv[optind+1];
+		mtpair->mnt_type = fstype;
+		mtpair->mnt_opts = cmdopts;
+		rc = singlemount(mtpair, 0);
+		goto clean_up;
+	}
+
+	// If we have at least one argument, it's the storage location
+
+	if (optind < argc) storage_path = bb_simplify_path(argv[optind]);
+
+	// Open either fstab or mtab
+
+	if (parse_mount_options(cmdopts,0) & MS_REMOUNT)
+		fstabname = (char *)bb_path_mtab_file;  // Again with the evil const.
+	else fstabname="/etc/fstab";
+
+	if (!(fstab=setmntent(fstabname,"r")))
+		bb_perror_msg_and_die("Cannot read %s",fstabname);
+
+	// Loop through entries until we find what we're looking for.
+
+	memset(mtpair,0,sizeof(mtpair));
+	for (;;) {
+		struct mntent *mtnext = mtpair + (mtcur==mtpair ? 1 : 0);
+
+		// Get next fstab entry
+
+		if (!getmntent_r(fstab, mtcur, bb_common_bufsiz1
+					+ (mtcur==mtpair ? sizeof(bb_common_bufsiz1)/2 : 0),
+				sizeof(bb_common_bufsiz1)/2))
+		{
+			// Were we looking for something specific?
+
+			if (optind != argc) {
+
+				// If we didn't find anything, complain.
+
+				if (!mtnext->mnt_fsname)
+					bb_error_msg_and_die("Can't find %s in %s",
+						argv[optind], fstabname);
+
+				// Mount the last thing we found.
+
+				mtcur = mtnext;
+				mtcur->mnt_opts=bb_xstrdup(mtcur->mnt_opts);
+				append_mount_options(&(mtcur->mnt_opts),cmdopts);
+				rc = singlemount(mtcur, 0);
+				free(mtcur->mnt_opts);
+			}
+			goto clean_up;
+		}
+
+		/* If we're trying to mount something specific and this isn't it,
+		 * skip it.  Note we must match both the exact text in fstab (ala
+		 * "proc") or a full path from root */
+
+		if (optind != argc) {
+
+			// Is this what we're looking for?
+
+			if(strcmp(argv[optind],mtcur->mnt_fsname) &&
+			   strcmp(storage_path,mtcur->mnt_fsname) &&
+			   strcmp(argv[optind],mtcur->mnt_dir) &&
+			   strcmp(storage_path,mtcur->mnt_dir)) continue;
+
+			// Remember this entry.  Something later may have overmounted
+			// it, and we want the _last_ match.
+
+			mtcur = mtnext;
+
+		// If we're mounting all.
+
+		} else {
+
+			// Do we need to match a filesystem type?
+			if (fstype && strcmp(mtcur->mnt_type,fstype)) continue;
+
+			// Skip noauto and swap anyway.
+
+			if (parse_mount_options(mtcur->mnt_opts,0)
+				& (MOUNT_NOAUTO | MOUNT_SWAP)) continue;
+
+			// Mount this thing.
+
+			if (singlemount(mtcur, 1)) {
+				/* Count number of failed mounts */
+				rc++;
+			}
+		}
+	}
+	if (ENABLE_FEATURE_CLEAN_UP) endmntent(fstab);
+
+clean_up:
+
+	if (ENABLE_FEATURE_CLEAN_UP) {
+		free(storage_path);
+		free(cmdopts);
+	}
+
+	return rc;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/nfsmount.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/nfsmount.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/nfsmount.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,991 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * nfsmount.c -- Linux NFS mount
+ * Copyright (C) 1993 Rick Sladkey <jrs at world.std.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * Wed Feb  8 12:51:48 1995, biro at yggdrasil.com (Ross Biro): allow all port
+ * numbers to be specified on the command line.
+ *
+ * Fri, 8 Mar 1996 18:01:39, Swen Thuemmler <swen at uni-paderborn.de>:
+ * Omit the call to connect() for Linux version 1.3.11 or later.
+ *
+ * Wed Oct  1 23:55:28 1997: Dick Streefland <dick_streefland at tasking.com>
+ * Implemented the "bg", "fg" and "retry" mount options for NFS.
+ *
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek at misiek.eu.org>
+ * - added Native Language Support
+ *
+ * Modified by Olaf Kirch and Trond Myklebust for new NFS code,
+ * plus NFSv3 stuff.
+ */
+
+/*
+ * nfsmount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
+ */
+
+#include "busybox.h"
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/utsname.h>
+#undef TRUE
+#undef FALSE
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include "nfsmount.h"
+
+
+/* This is just a warning of a common mistake.  Possibly this should be a
+ * uclibc faq entry rather than in busybox... */
+#if ENABLE_FEATURE_MOUNT_NFS && defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__)
+/* jmc error->warning */
+#warning "You need to build uClibc with UCLIBC_HAS_RPC for NFS support."
+#endif
+
+
+/*
+ * NFS stats. The good thing with these values is that NFSv3 errors are
+ * a superset of NFSv2 errors (with the exception of NFSERR_WFLUSH which
+ * no-one uses anyway), so we can happily mix code as long as we make sure
+ * no NFSv3 errors are returned to NFSv2 clients.
+ * Error codes that have a `--' in the v2 column are not part of the
+ * standard, but seem to be widely used nevertheless.
+ */
+enum nfs_stat {
+	NFS_OK = 0,			/* v2 v3 */
+	NFSERR_PERM = 1,		/* v2 v3 */
+	NFSERR_NOENT = 2,		/* v2 v3 */
+	NFSERR_IO = 5,			/* v2 v3 */
+	NFSERR_NXIO = 6,		/* v2 v3 */
+	NFSERR_EAGAIN = 11,		/* v2 v3 */
+	NFSERR_ACCES = 13,		/* v2 v3 */
+	NFSERR_EXIST = 17,		/* v2 v3 */
+	NFSERR_XDEV = 18,		/*    v3 */
+	NFSERR_NODEV = 19,		/* v2 v3 */
+	NFSERR_NOTDIR = 20,		/* v2 v3 */
+	NFSERR_ISDIR = 21,		/* v2 v3 */
+	NFSERR_INVAL = 22,		/* v2 v3 that Sun forgot */
+	NFSERR_FBIG = 27,		/* v2 v3 */
+	NFSERR_NOSPC = 28,		/* v2 v3 */
+	NFSERR_ROFS = 30,		/* v2 v3 */
+	NFSERR_MLINK = 31,		/*    v3 */
+	NFSERR_OPNOTSUPP = 45,		/* v2 v3 */
+	NFSERR_NAMETOOLONG = 63,	/* v2 v3 */
+	NFSERR_NOTEMPTY = 66,		/* v2 v3 */
+	NFSERR_DQUOT = 69,		/* v2 v3 */
+	NFSERR_STALE = 70,		/* v2 v3 */
+	NFSERR_REMOTE = 71,		/* v2 v3 */
+	NFSERR_WFLUSH = 99,		/* v2    */
+	NFSERR_BADHANDLE = 10001,	/*    v3 */
+	NFSERR_NOT_SYNC = 10002,	/*    v3 */
+	NFSERR_BAD_COOKIE = 10003,	/*    v3 */
+	NFSERR_NOTSUPP = 10004,		/*    v3 */
+	NFSERR_TOOSMALL = 10005,	/*    v3 */
+	NFSERR_SERVERFAULT = 10006,	/*    v3 */
+	NFSERR_BADTYPE = 10007,		/*    v3 */
+	NFSERR_JUKEBOX = 10008		/*    v3 */
+};
+
+#define NFS_PROGRAM	100003
+
+
+enum {
+#ifndef NFS_FHSIZE
+	NFS_FHSIZE = 32,
+#endif
+#ifndef NFS_PORT
+	NFS_PORT = 2049
+#endif
+};
+
+/* Disable the nls stuff */
+# undef bindtextdomain
+# define bindtextdomain(Domain, Directory) /* empty */
+# undef textdomain
+# define textdomain(Domain) /* empty */
+
+enum {
+	S_QUOTA = 128,     /* Quota initialized for file/directory/symlink */
+};
+
+
+/*
+ * We want to be able to compile mount on old kernels in such a way
+ * that the binary will work well on more recent kernels.
+ * Thus, if necessary we teach nfsmount.c the structure of new fields
+ * that will come later.
+ *
+ * Moreover, the new kernel includes conflict with glibc includes
+ * so it is easiest to ignore the kernel altogether (at compile time).
+ */
+
+/* NOTE: Do not make this into a 'static const int' because the pre-processor
+ * needs to test this value in some #if statements. */
+#define NFS_MOUNT_VERSION 4
+
+struct nfs2_fh {
+	char                    data[32];
+};
+struct nfs3_fh {
+	unsigned short          size;
+	unsigned char           data[64];
+};
+
+struct nfs_mount_data {
+	int		version;		/* 1 */
+	int		fd;			/* 1 */
+	struct nfs2_fh	old_root;		/* 1 */
+	int		flags;			/* 1 */
+	int		rsize;			/* 1 */
+	int		wsize;			/* 1 */
+	int		timeo;			/* 1 */
+	int		retrans;		/* 1 */
+	int		acregmin;		/* 1 */
+	int		acregmax;		/* 1 */
+	int		acdirmin;		/* 1 */
+	int		acdirmax;		/* 1 */
+	struct sockaddr_in addr;		/* 1 */
+	char		hostname[256];		/* 1 */
+	int		namlen;			/* 2 */
+	unsigned int	bsize;			/* 3 */
+	struct nfs3_fh	root;			/* 4 */
+};
+
+/* bits in the flags field */
+enum {
+	NFS_MOUNT_SOFT = 0x0001,	/* 1 */
+	NFS_MOUNT_INTR = 0x0002,	/* 1 */
+	NFS_MOUNT_SECURE = 0x0004,	/* 1 */
+	NFS_MOUNT_POSIX = 0x0008,	/* 1 */
+	NFS_MOUNT_NOCTO = 0x0010,	/* 1 */
+	NFS_MOUNT_NOAC = 0x0020,	/* 1 */
+	NFS_MOUNT_TCP = 0x0040,		/* 2 */
+	NFS_MOUNT_VER3 = 0x0080,	/* 3 */
+	NFS_MOUNT_KERBEROS = 0x0100,	/* 3 */
+	NFS_MOUNT_NONLM = 0x0200	/* 3 */
+};
+
+
+#define UTIL_LINUX_VERSION "2.10m"
+#define util_linux_version "util-linux-2.10m"
+
+#define HAVE_inet_aton
+#define HAVE_scsi_h
+#define HAVE_blkpg_h
+#define HAVE_kd_h
+#define HAVE_termcap
+#define HAVE_locale_h
+#define HAVE_libintl_h
+#define ENABLE_NLS
+#define HAVE_langinfo_h
+#define HAVE_progname
+#define HAVE_openpty
+#define HAVE_nanosleep
+#define HAVE_personality
+#define HAVE_tm_gmtoff
+
+static char *nfs_strerror(int status);
+
+#define MAX_NFSPROT ((nfs_mount_version >= 4) ? 3 : 2)
+
+enum {
+	EX_FAIL = 32,       /* mount failure */
+	EX_BG = 256        /* retry in background (internal only) */
+};
+
+
+/*
+ * nfs_mount_version according to the sources seen at compile time.
+ */
+static int nfs_mount_version;
+
+/*
+ * Unfortunately, the kernel prints annoying console messages
+ * in case of an unexpected nfs mount version (instead of
+ * just returning some error).  Therefore we'll have to try
+ * and figure out what version the kernel expects.
+ *
+ * Variables:
+ *	KERNEL_NFS_MOUNT_VERSION: kernel sources at compile time
+ *	NFS_MOUNT_VERSION: these nfsmount sources at compile time
+ *	nfs_mount_version: version this source and running kernel can handle
+ */
+static void
+find_kernel_nfs_mount_version(void)
+{
+	static int kernel_version = 0;
+
+	if (kernel_version)
+		return;
+
+	nfs_mount_version = NFS_MOUNT_VERSION; /* default */
+
+	kernel_version = get_linux_version_code();
+	if (kernel_version) {
+		if (kernel_version < KERNEL_VERSION(2,1,32))
+			nfs_mount_version = 1;
+		else if (kernel_version < KERNEL_VERSION(2,2,18) ||
+				(kernel_version >=   KERNEL_VERSION(2,3,0) &&
+				 kernel_version < KERNEL_VERSION(2,3,99)))
+			nfs_mount_version = 3;
+		else
+			nfs_mount_version = 4; /* since 2.3.99pre4 */
+	}
+	if (nfs_mount_version > NFS_MOUNT_VERSION)
+		nfs_mount_version = NFS_MOUNT_VERSION;
+}
+
+static struct pmap *
+get_mountport(struct sockaddr_in *server_addr,
+      long unsigned prog,
+      long unsigned version,
+      long unsigned proto,
+      long unsigned port)
+{
+struct pmaplist *pmap;
+static struct pmap p = {0, 0, 0, 0};
+
+server_addr->sin_port = PMAPPORT;
+pmap = pmap_getmaps(server_addr);
+
+if (version > MAX_NFSPROT)
+	version = MAX_NFSPROT;
+if (!prog)
+	prog = MOUNTPROG;
+p.pm_prog = prog;
+p.pm_vers = version;
+p.pm_prot = proto;
+p.pm_port = port;
+
+while (pmap) {
+	if (pmap->pml_map.pm_prog != prog)
+		goto next;
+	if (!version && p.pm_vers > pmap->pml_map.pm_vers)
+		goto next;
+	if (version > 2 && pmap->pml_map.pm_vers != version)
+		goto next;
+	if (version && version <= 2 && pmap->pml_map.pm_vers > 2)
+		goto next;
+	if (pmap->pml_map.pm_vers > MAX_NFSPROT ||
+	    (proto && p.pm_prot && pmap->pml_map.pm_prot != proto) ||
+	    (port && pmap->pml_map.pm_port != port))
+		goto next;
+	memcpy(&p, &pmap->pml_map, sizeof(p));
+next:
+	pmap = pmap->pml_next;
+}
+if (!p.pm_vers)
+	p.pm_vers = MOUNTVERS;
+if (!p.pm_port)
+	p.pm_port = MOUNTPORT;
+if (!p.pm_prot)
+	p.pm_prot = IPPROTO_TCP;
+return &p;
+}
+
+int nfsmount(const char *spec, const char *node, int *flags,
+	     char **mount_opts, int running_bg)
+{
+	static char *prev_bg_host;
+	char hostdir[1024];
+	CLIENT *mclient;
+	char *hostname;
+	char *pathname;
+	char *old_opts;
+	char *mounthost=NULL;
+	char new_opts[1024];
+	struct timeval total_timeout;
+	enum clnt_stat clnt_stat;
+	struct nfs_mount_data data;
+	char *opt, *opteq;
+	int val;
+	struct hostent *hp;
+	struct sockaddr_in server_addr;
+	struct sockaddr_in mount_server_addr;
+	struct pmap* pm_mnt;
+	int msock, fsock;
+	struct timeval retry_timeout;
+	union {
+		struct fhstatus nfsv2;
+		struct mountres3 nfsv3;
+	} status;
+	struct stat statbuf;
+	char *s;
+	int port;
+	int mountport;
+	int proto;
+	int bg;
+	int soft;
+	int intr;
+	int posix;
+	int nocto;
+	int noac;
+	int nolock;
+	int retry;
+	int tcp;
+	int mountprog;
+	int mountvers;
+	int nfsprog;
+	int nfsvers;
+	int retval;
+	time_t t;
+	time_t prevt;
+	time_t timeout;
+
+	find_kernel_nfs_mount_version();
+
+	retval = EX_FAIL;
+	msock = fsock = -1;
+	mclient = NULL;
+	if (strlen(spec) >= sizeof(hostdir)) {
+		bb_error_msg("excessively long host:dir argument");
+		goto fail;
+	}
+	strcpy(hostdir, spec);
+	if ((s = strchr(hostdir, ':'))) {
+		hostname = hostdir;
+		pathname = s + 1;
+		*s = '\0';
+		/* Ignore all but first hostname in replicated mounts
+		   until they can be fully supported. (mack at sgi.com) */
+		if ((s = strchr(hostdir, ','))) {
+			*s = '\0';
+			bb_error_msg("warning: multiple hostnames not supported");
+		}
+	} else {
+		bb_error_msg("directory to mount not in host:dir format");
+		goto fail;
+	}
+
+	server_addr.sin_family = AF_INET;
+#ifdef HAVE_inet_aton
+	if (!inet_aton(hostname, &server_addr.sin_addr))
+#endif
+	{
+		if ((hp = gethostbyname(hostname)) == NULL) {
+			bb_herror_msg("%s", hostname);
+			goto fail;
+		} else {
+			if (hp->h_length > sizeof(struct in_addr)) {
+				bb_error_msg("got bad hp->h_length");
+				hp->h_length = sizeof(struct in_addr);
+			}
+			memcpy(&server_addr.sin_addr,
+			       hp->h_addr, hp->h_length);
+		}
+	}
+
+	memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr));
+
+	/* add IP address to mtab options for use when unmounting */
+
+	s = inet_ntoa(server_addr.sin_addr);
+	old_opts = *mount_opts;
+	if (!old_opts)
+		old_opts = "";
+	if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
+		bb_error_msg("excessively long option argument");
+		goto fail;
+	}
+	sprintf(new_opts, "%s%saddr=%s",
+		old_opts, *old_opts ? "," : "", s);
+	*mount_opts = bb_xstrdup(new_opts);
+
+	/* Set default options.
+	 * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to
+	 * let the kernel decide.
+	 * timeo is filled in after we know whether it'll be TCP or UDP. */
+	memset(&data, 0, sizeof(data));
+	data.retrans	= 3;
+	data.acregmin	= 3;
+	data.acregmax	= 60;
+	data.acdirmin	= 30;
+	data.acdirmax	= 60;
+#if NFS_MOUNT_VERSION >= 2
+	data.namlen	= NAME_MAX;
+#endif
+
+	bg = 0;
+	soft = 0;
+	intr = 0;
+	posix = 0;
+	nocto = 0;
+	nolock = 0;
+	noac = 0;
+	retry = 10000;		/* 10000 minutes ~ 1 week */
+	tcp = 0;
+
+	mountprog = MOUNTPROG;
+	mountvers = 0;
+	port = 0;
+	mountport = 0;
+	nfsprog = NFS_PROGRAM;
+	nfsvers = 0;
+
+	/* parse options */
+
+	for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
+		if ((opteq = strchr(opt, '='))) {
+			val = atoi(opteq + 1);
+			*opteq = '\0';
+			if (!strcmp(opt, "rsize"))
+				data.rsize = val;
+			else if (!strcmp(opt, "wsize"))
+				data.wsize = val;
+			else if (!strcmp(opt, "timeo"))
+				data.timeo = val;
+			else if (!strcmp(opt, "retrans"))
+				data.retrans = val;
+			else if (!strcmp(opt, "acregmin"))
+				data.acregmin = val;
+			else if (!strcmp(opt, "acregmax"))
+				data.acregmax = val;
+			else if (!strcmp(opt, "acdirmin"))
+				data.acdirmin = val;
+			else if (!strcmp(opt, "acdirmax"))
+				data.acdirmax = val;
+			else if (!strcmp(opt, "actimeo")) {
+				data.acregmin = val;
+				data.acregmax = val;
+				data.acdirmin = val;
+				data.acdirmax = val;
+			}
+			else if (!strcmp(opt, "retry"))
+				retry = val;
+			else if (!strcmp(opt, "port"))
+				port = val;
+			else if (!strcmp(opt, "mountport"))
+			        mountport = val;
+			else if (!strcmp(opt, "mounthost"))
+			        mounthost=bb_xstrndup(opteq+1,
+						  strcspn(opteq+1," \t\n\r,"));
+			else if (!strcmp(opt, "mountprog"))
+				mountprog = val;
+			else if (!strcmp(opt, "mountvers"))
+				mountvers = val;
+			else if (!strcmp(opt, "nfsprog"))
+				nfsprog = val;
+			else if (!strcmp(opt, "nfsvers") ||
+				 !strcmp(opt, "vers"))
+				nfsvers = val;
+			else if (!strcmp(opt, "proto")) {
+				if (!strncmp(opteq+1, "tcp", 3))
+					tcp = 1;
+				else if (!strncmp(opteq+1, "udp", 3))
+					tcp = 0;
+				else
+					printf("Warning: Unrecognized proto= option.\n");
+			} else if (!strcmp(opt, "namlen")) {
+#if NFS_MOUNT_VERSION >= 2
+				if (nfs_mount_version >= 2)
+					data.namlen = val;
+				else
+#endif
+				printf("Warning: Option namlen is not supported.\n");
+			} else if (!strcmp(opt, "addr"))
+				/* ignore */;
+			else {
+				printf("unknown nfs mount parameter: %s=%d\n", opt, val);
+				goto fail;
+			}
+		}
+		else {
+			val = 1;
+			if (!strncmp(opt, "no", 2)) {
+				val = 0;
+				opt += 2;
+			}
+			if (!strcmp(opt, "bg"))
+				bg = val;
+			else if (!strcmp(opt, "fg"))
+				bg = !val;
+			else if (!strcmp(opt, "soft"))
+				soft = val;
+			else if (!strcmp(opt, "hard"))
+				soft = !val;
+			else if (!strcmp(opt, "intr"))
+				intr = val;
+			else if (!strcmp(opt, "posix"))
+				posix = val;
+			else if (!strcmp(opt, "cto"))
+				nocto = !val;
+			else if (!strcmp(opt, "ac"))
+				noac = !val;
+			else if (!strcmp(opt, "tcp"))
+				tcp = val;
+			else if (!strcmp(opt, "udp"))
+				tcp = !val;
+			else if (!strcmp(opt, "lock")) {
+				if (nfs_mount_version >= 3)
+					nolock = !val;
+				else
+					printf("Warning: option nolock is not supported.\n");
+			} else {
+				printf("unknown nfs mount option: %s%s\n", val ? "" : "no", opt);
+				goto fail;
+			}
+		}
+	}
+	proto = (tcp) ? IPPROTO_TCP : IPPROTO_UDP;
+
+	data.flags = (soft ? NFS_MOUNT_SOFT : 0)
+		| (intr ? NFS_MOUNT_INTR : 0)
+		| (posix ? NFS_MOUNT_POSIX : 0)
+		| (nocto ? NFS_MOUNT_NOCTO : 0)
+		| (noac ? NFS_MOUNT_NOAC : 0);
+#if NFS_MOUNT_VERSION >= 2
+	if (nfs_mount_version >= 2)
+		data.flags |= (tcp ? NFS_MOUNT_TCP : 0);
+#endif
+#if NFS_MOUNT_VERSION >= 3
+	if (nfs_mount_version >= 3)
+		data.flags |= (nolock ? NFS_MOUNT_NONLM : 0);
+#endif
+	if (nfsvers > MAX_NFSPROT || mountvers > MAX_NFSPROT) {
+		bb_error_msg("NFSv%d not supported!", nfsvers);
+		return 1;
+	}
+	if (nfsvers && !mountvers)
+		mountvers = (nfsvers < 3) ? 1 : nfsvers;
+	if (nfsvers && nfsvers < mountvers) {
+		mountvers = nfsvers;
+	}
+
+	/* Adjust options if none specified */
+	if (!data.timeo)
+		data.timeo = tcp ? 70 : 7;
+
+#ifdef NFS_MOUNT_DEBUG
+	printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
+		data.rsize, data.wsize, data.timeo, data.retrans);
+	printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n",
+		data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
+	printf("port = %d, bg = %d, retry = %d, flags = %.8x\n",
+		port, bg, retry, data.flags);
+	printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n",
+		mountprog, mountvers, nfsprog, nfsvers);
+	printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n",
+		(data.flags & NFS_MOUNT_SOFT) != 0,
+		(data.flags & NFS_MOUNT_INTR) != 0,
+		(data.flags & NFS_MOUNT_POSIX) != 0,
+		(data.flags & NFS_MOUNT_NOCTO) != 0,
+		(data.flags & NFS_MOUNT_NOAC) != 0);
+#if NFS_MOUNT_VERSION >= 2
+	printf("tcp = %d\n",
+		(data.flags & NFS_MOUNT_TCP) != 0);
+#endif
+#endif
+
+	data.version = nfs_mount_version;
+
+	if (*flags & MS_REMOUNT)
+		goto copy_data_and_return;
+
+	/*
+	 * If the previous mount operation on the same host was
+	 * backgrounded, and the "bg" for this mount is also set,
+	 * give up immediately, to avoid the initial timeout.
+	 */
+	if (bg && !running_bg &&
+	    prev_bg_host && strcmp(hostname, prev_bg_host) == 0) {
+		if (retry > 0)
+			retval = EX_BG;
+		return retval;
+	}
+
+	/* create mount daemon client */
+	/* See if the nfs host = mount host. */
+	if (mounthost) {
+	  if (mounthost[0] >= '0' && mounthost[0] <= '9') {
+	    mount_server_addr.sin_family = AF_INET;
+	    mount_server_addr.sin_addr.s_addr = inet_addr(hostname);
+	  } else {
+		  if ((hp = gethostbyname(mounthost)) == NULL) {
+			  bb_herror_msg("%s", mounthost);
+			  goto fail;
+		  } else {
+			  if (hp->h_length > sizeof(struct in_addr)) {
+				  bb_error_msg("got bad hp->h_length?");
+				  hp->h_length = sizeof(struct in_addr);
+			  }
+			  mount_server_addr.sin_family = AF_INET;
+			  memcpy(&mount_server_addr.sin_addr,
+				 hp->h_addr, hp->h_length);
+		  }
+	  }
+	}
+
+	/*
+	 * The following loop implements the mount retries. On the first
+	 * call, "running_bg" is 0. When the mount times out, and the
+	 * "bg" option is set, the exit status EX_BG will be returned.
+	 * For a backgrounded mount, there will be a second call by the
+	 * child process with "running_bg" set to 1.
+	 *
+	 * The case where the mount point is not present and the "bg"
+	 * option is set, is treated as a timeout. This is done to
+	 * support nested mounts.
+	 *
+	 * The "retry" count specified by the user is the number of
+	 * minutes to retry before giving up.
+	 *
+	 * Only the first error message will be displayed.
+	 */
+	retry_timeout.tv_sec = 3;
+	retry_timeout.tv_usec = 0;
+	total_timeout.tv_sec = 20;
+	total_timeout.tv_usec = 0;
+	timeout = time(NULL) + 60 * retry;
+	prevt = 0;
+	t = 30;
+	val = 1;
+	for (;;) {
+		if (bg && stat(node, &statbuf) == -1) {
+			if (running_bg) {
+				sleep(val);	/* 1, 2, 4, 8, 16, 30, ... */
+				val *= 2;
+				if (val > 30)
+					val = 30;
+			}
+		} else {
+			/* be careful not to use too many CPU cycles */
+			if (t - prevt < 30)
+				sleep(30);
+
+			pm_mnt = get_mountport(&mount_server_addr,
+				       mountprog,
+				       mountvers,
+				       proto,
+				       mountport);
+
+			/* contact the mount daemon via TCP */
+			mount_server_addr.sin_port = htons(pm_mnt->pm_port);
+			msock = RPC_ANYSOCK;
+
+			switch (pm_mnt->pm_prot) {
+			case IPPROTO_UDP:
+				mclient = clntudp_create(&mount_server_addr,
+						 pm_mnt->pm_prog,
+						 pm_mnt->pm_vers,
+						 retry_timeout,
+						 &msock);
+		  if (mclient)
+			  break;
+		  mount_server_addr.sin_port = htons(pm_mnt->pm_port);
+		  msock = RPC_ANYSOCK;
+		case IPPROTO_TCP:
+			mclient = clnttcp_create(&mount_server_addr,
+						 pm_mnt->pm_prog,
+						 pm_mnt->pm_vers,
+						 &msock, 0, 0);
+			break;
+		default:
+			mclient = 0;
+			}
+			if (mclient) {
+				/* try to mount hostname:pathname */
+				mclient->cl_auth = authunix_create_default();
+
+			/* make pointers in xdr_mountres3 NULL so
+			 * that xdr_array allocates memory for us
+			 */
+			memset(&status, 0, sizeof(status));
+
+			if (pm_mnt->pm_vers == 3)
+				clnt_stat = clnt_call(mclient, MOUNTPROC3_MNT,
+						      (xdrproc_t) xdr_dirpath,
+						      (caddr_t) &pathname,
+						      (xdrproc_t) xdr_mountres3,
+						      (caddr_t) &status,
+					total_timeout);
+			else
+				clnt_stat = clnt_call(mclient, MOUNTPROC_MNT,
+						      (xdrproc_t) xdr_dirpath,
+						      (caddr_t) &pathname,
+						      (xdrproc_t) xdr_fhstatus,
+						      (caddr_t) &status,
+						      total_timeout);
+
+				if (clnt_stat == RPC_SUCCESS)
+					break;		/* we're done */
+				if (errno != ECONNREFUSED) {
+					clnt_perror(mclient, "mount");
+					goto fail;	/* don't retry */
+				}
+				if (!running_bg && prevt == 0)
+					clnt_perror(mclient, "mount");
+				auth_destroy(mclient->cl_auth);
+				clnt_destroy(mclient);
+				mclient = 0;
+				close(msock);
+			} else {
+				if (!running_bg && prevt == 0)
+					clnt_pcreateerror("mount");
+			}
+			prevt = t;
+		}
+		if (!bg)
+		        goto fail;
+		if (!running_bg) {
+			prev_bg_host = bb_xstrdup(hostname);
+			if (retry > 0)
+				retval = EX_BG;
+			goto fail;
+		}
+		t = time(NULL);
+		if (t >= timeout)
+			goto fail;
+	}
+	nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers;
+
+	if (nfsvers == 2) {
+		if (status.nfsv2.fhs_status != 0) {
+			bb_error_msg("%s:%s failed, reason given by server: %s",
+				hostname, pathname,
+				nfs_strerror(status.nfsv2.fhs_status));
+			goto fail;
+		}
+		memcpy(data.root.data,
+		       (char *) status.nfsv2.fhstatus_u.fhs_fhandle,
+		       NFS_FHSIZE);
+#if NFS_MOUNT_VERSION >= 4
+		data.root.size = NFS_FHSIZE;
+		memcpy(data.old_root.data,
+		       (char *) status.nfsv2.fhstatus_u.fhs_fhandle,
+		       NFS_FHSIZE);
+#endif
+	} else {
+#if NFS_MOUNT_VERSION >= 4
+		fhandle3 *my_fhandle;
+		if (status.nfsv3.fhs_status != 0) {
+			bb_error_msg("%s:%s failed, reason given by server: %s",
+				hostname, pathname,
+				nfs_strerror(status.nfsv3.fhs_status));
+			goto fail;
+		}
+		my_fhandle = &status.nfsv3.mountres3_u.mountinfo.fhandle;
+		memset(data.old_root.data, 0, NFS_FHSIZE);
+		memset(&data.root, 0, sizeof(data.root));
+		data.root.size = my_fhandle->fhandle3_len;
+		memcpy(data.root.data,
+		       (char *) my_fhandle->fhandle3_val,
+		       my_fhandle->fhandle3_len);
+
+		data.flags |= NFS_MOUNT_VER3;
+#endif
+	}
+
+	/* create nfs socket for kernel */
+
+	if (tcp) {
+		if (nfs_mount_version < 3) {
+			printf("NFS over TCP is not supported.\n");
+			goto fail;
+		}
+		fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+	} else
+		fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+	if (fsock < 0) {
+		perror("nfs socket");
+		goto fail;
+	}
+	if (bindresvport(fsock, 0) < 0) {
+		perror("nfs bindresvport");
+		goto fail;
+	}
+	if (port == 0) {
+		server_addr.sin_port = PMAPPORT;
+		port = pmap_getport(&server_addr, nfsprog, nfsvers,
+			tcp ? IPPROTO_TCP : IPPROTO_UDP);
+		if (port == 0)
+			port = NFS_PORT;
+#ifdef NFS_MOUNT_DEBUG
+		else
+			printf("used portmapper to find NFS port\n");
+#endif
+	}
+#ifdef NFS_MOUNT_DEBUG
+	printf("using port %d for nfs daemon\n", port);
+#endif
+	server_addr.sin_port = htons(port);
+	 /*
+	  * connect() the socket for kernels 1.3.10 and below only,
+	  * to avoid problems with multihomed hosts.
+	  * --Swen
+	  */
+	if (get_linux_version_code() <= KERNEL_VERSION(2,3,10)
+	    && connect(fsock, (struct sockaddr *) &server_addr,
+		       sizeof (server_addr)) < 0) {
+		perror("nfs connect");
+		goto fail;
+	}
+
+	/* prepare data structure for kernel */
+
+	data.fd = fsock;
+	memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr));
+	strncpy(data.hostname, hostname, sizeof(data.hostname));
+
+	/* clean up */
+
+	auth_destroy(mclient->cl_auth);
+	clnt_destroy(mclient);
+	close(msock);
+copy_data_and_return:
+	*mount_opts = xrealloc(*mount_opts, sizeof(data));
+	memcpy(*mount_opts, &data, sizeof(data));
+	return 0;
+
+	/* abort */
+
+fail:
+	if (msock != -1) {
+		if (mclient) {
+			auth_destroy(mclient->cl_auth);
+			clnt_destroy(mclient);
+		}
+		close(msock);
+	}
+	if (fsock != -1)
+		close(fsock);
+	return retval;
+}
+
+/*
+ * We need to translate between nfs status return values and
+ * the local errno values which may not be the same.
+ *
+ * Andreas Schwab <schwab at LS5.informatik.uni-dortmund.de>: change errno:
+ * "after #include <errno.h> the symbol errno is reserved for any use,
+ *  it cannot even be used as a struct tag or field name".
+ */
+
+#ifndef EDQUOT
+#define EDQUOT	ENOSPC
+#endif
+
+static const struct {
+	enum nfs_stat stat;
+	int errnum;
+} nfs_errtbl[] = {
+	{ NFS_OK,		0		},
+	{ NFSERR_PERM,		EPERM		},
+	{ NFSERR_NOENT,		ENOENT		},
+	{ NFSERR_IO,		EIO		},
+	{ NFSERR_NXIO,		ENXIO		},
+	{ NFSERR_ACCES,		EACCES		},
+	{ NFSERR_EXIST,		EEXIST		},
+	{ NFSERR_NODEV,		ENODEV		},
+	{ NFSERR_NOTDIR,	ENOTDIR		},
+	{ NFSERR_ISDIR,		EISDIR		},
+#ifdef NFSERR_INVAL
+	{ NFSERR_INVAL,		EINVAL		},	/* that Sun forgot */
+#endif
+	{ NFSERR_FBIG,		EFBIG		},
+	{ NFSERR_NOSPC,		ENOSPC		},
+	{ NFSERR_ROFS,		EROFS		},
+	{ NFSERR_NAMETOOLONG,	ENAMETOOLONG	},
+	{ NFSERR_NOTEMPTY,	ENOTEMPTY	},
+	{ NFSERR_DQUOT,		EDQUOT		},
+	{ NFSERR_STALE,		ESTALE		},
+#ifdef EWFLUSH
+	{ NFSERR_WFLUSH,	EWFLUSH		},
+#endif
+	/* Throw in some NFSv3 values for even more fun (HP returns these) */
+	{ 71,			EREMOTE		},
+
+	{ -1,			EIO		}
+};
+
+static char *nfs_strerror(int status)
+{
+	int i;
+	static char buf[256];
+
+	for (i = 0; nfs_errtbl[i].stat != -1; i++) {
+		if (nfs_errtbl[i].stat == status)
+			return strerror(nfs_errtbl[i].errnum);
+	}
+	sprintf(buf, "unknown nfs status return value: %d", status);
+	return buf;
+}
+
+static bool_t
+xdr_fhandle (XDR *xdrs, fhandle objp)
+{
+	 if (!xdr_opaque (xdrs, objp, FHSIZE))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_fhstatus (XDR *xdrs, fhstatus *objp)
+{
+	 if (!xdr_u_int (xdrs, &objp->fhs_status))
+		 return FALSE;
+	switch (objp->fhs_status) {
+	case 0:
+		 if (!xdr_fhandle (xdrs, objp->fhstatus_u.fhs_fhandle))
+			 return FALSE;
+		break;
+	default:
+		break;
+	}
+	return TRUE;
+}
+
+bool_t
+xdr_dirpath (XDR *xdrs, dirpath *objp)
+{
+	 if (!xdr_string (xdrs, objp, MNTPATHLEN))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_fhandle3 (XDR *xdrs, fhandle3 *objp)
+{
+	 if (!xdr_bytes (xdrs, (char **)&objp->fhandle3_val, (unsigned int *) &objp->fhandle3_len, FHSIZE3))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_mountres3_ok (XDR *xdrs, mountres3_ok *objp)
+{
+	 if (!xdr_fhandle3 (xdrs, &objp->fhandle))
+		 return FALSE;
+	 if (!xdr_array (xdrs, &(objp->auth_flavours.auth_flavours_val), &(objp->auth_flavours.auth_flavours_len), ~0,
+		sizeof (int), (xdrproc_t) xdr_int))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_mountstat3 (XDR *xdrs, mountstat3 *objp)
+{
+	 if (!xdr_enum (xdrs, (enum_t *) objp))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_mountres3 (XDR *xdrs, mountres3 *objp)
+{
+	 if (!xdr_mountstat3 (xdrs, &objp->fhs_status))
+		 return FALSE;
+	switch (objp->fhs_status) {
+	case MNT_OK:
+		 if (!xdr_mountres3_ok (xdrs, &objp->mountres3_u.mountinfo))
+			 return FALSE;
+		break;
+	default:
+		break;
+	}
+	return TRUE;
+}
+

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/nfsmount.h
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/nfsmount.h	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/nfsmount.h	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,242 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * This file was originally generated using rpcgen.
+ * But now we edit it by hand as needed to make it
+ * shut up...
+ */
+
+#ifndef _NFSMOUNT_H_RPCGEN
+#define _NFSMOUNT_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+/*
+ * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+ */
+
+/* from @(#)mount.x	1.3 91/03/11 TIRPC 1.0 */
+#ifndef _rpcsvc_mount_h
+#define _rpcsvc_mount_h
+#include <asm/types.h>
+#define MOUNTPORT 635
+#define MNTPATHLEN 1024
+#define MNTNAMLEN 255
+#define FHSIZE 32
+#define FHSIZE3 64
+
+typedef char fhandle[FHSIZE];
+
+typedef struct {
+	unsigned int fhandle3_len;
+	char *fhandle3_val;
+} fhandle3;
+
+enum mountstat3 {
+	MNT_OK = 0,
+	MNT3ERR_PERM = 1,
+	MNT3ERR_NOENT = 2,
+	MNT3ERR_IO = 5,
+	MNT3ERR_ACCES = 13,
+	MNT3ERR_NOTDIR = 20,
+	MNT3ERR_INVAL = 22,
+	MNT3ERR_NAMETOOLONG = 63,
+	MNT3ERR_NOTSUPP = 10004,
+	MNT3ERR_SERVERFAULT = 10006,
+};
+typedef enum mountstat3 mountstat3;
+
+struct fhstatus {
+	unsigned int fhs_status;
+	union {
+		fhandle fhs_fhandle;
+	} fhstatus_u;
+};
+typedef struct fhstatus fhstatus;
+
+struct mountres3_ok {
+	fhandle3 fhandle;
+	struct {
+		unsigned int auth_flavours_len;
+		char *auth_flavours_val;
+	} auth_flavours;
+};
+typedef struct mountres3_ok mountres3_ok;
+
+struct mountres3 {
+	mountstat3 fhs_status;
+	union {
+		mountres3_ok mountinfo;
+	} mountres3_u;
+};
+typedef struct mountres3 mountres3;
+
+typedef char *dirpath;
+
+typedef char *name;
+
+typedef struct mountbody *mountlist;
+
+struct mountbody {
+	name ml_hostname;
+	dirpath ml_directory;
+	mountlist ml_next;
+};
+typedef struct mountbody mountbody;
+
+typedef struct groupnode *groups;
+
+struct groupnode {
+	name gr_name;
+	groups gr_next;
+};
+typedef struct groupnode groupnode;
+
+typedef struct exportnode *exports;
+
+struct exportnode {
+	dirpath ex_dir;
+	groups ex_groups;
+	exports ex_next;
+};
+typedef struct exportnode exportnode;
+
+struct ppathcnf {
+	int pc_link_max;
+	short pc_max_canon;
+	short pc_max_input;
+	short pc_name_max;
+	short pc_path_max;
+	short pc_pipe_buf;
+	u_char pc_vdisable;
+	char pc_xxx;
+	short pc_mask[2];
+};
+typedef struct ppathcnf ppathcnf;
+#endif /*!_rpcsvc_mount_h*/
+
+#define MOUNTPROG 100005
+#define MOUNTVERS 1
+
+#define MOUNTPROC_NULL 0
+extern  void * mountproc_null_1(void *, CLIENT *);
+extern  void * mountproc_null_1_svc(void *, struct svc_req *);
+#define MOUNTPROC_MNT 1
+extern  fhstatus * mountproc_mnt_1(dirpath *, CLIENT *);
+extern  fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *);
+#define MOUNTPROC_DUMP 2
+extern  mountlist * mountproc_dump_1(void *, CLIENT *);
+extern  mountlist * mountproc_dump_1_svc(void *, struct svc_req *);
+#define MOUNTPROC_UMNT 3
+extern  void * mountproc_umnt_1(dirpath *, CLIENT *);
+extern  void * mountproc_umnt_1_svc(dirpath *, struct svc_req *);
+#define MOUNTPROC_UMNTALL 4
+extern  void * mountproc_umntall_1(void *, CLIENT *);
+extern  void * mountproc_umntall_1_svc(void *, struct svc_req *);
+#define MOUNTPROC_EXPORT 5
+extern  exports * mountproc_export_1(void *, CLIENT *);
+extern  exports * mountproc_export_1_svc(void *, struct svc_req *);
+#define MOUNTPROC_EXPORTALL 6
+extern  exports * mountproc_exportall_1(void *, CLIENT *);
+extern  exports * mountproc_exportall_1_svc(void *, struct svc_req *);
+extern int mountprog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
+
+#define MOUNTVERS_POSIX 2
+
+extern  void * mountproc_null_2(void *, CLIENT *);
+extern  void * mountproc_null_2_svc(void *, struct svc_req *);
+extern  fhstatus * mountproc_mnt_2(dirpath *, CLIENT *);
+extern  fhstatus * mountproc_mnt_2_svc(dirpath *, struct svc_req *);
+extern  mountlist * mountproc_dump_2(void *, CLIENT *);
+extern  mountlist * mountproc_dump_2_svc(void *, struct svc_req *);
+extern  void * mountproc_umnt_2(dirpath *, CLIENT *);
+extern  void * mountproc_umnt_2_svc(dirpath *, struct svc_req *);
+extern  void * mountproc_umntall_2(void *, CLIENT *);
+extern  void * mountproc_umntall_2_svc(void *, struct svc_req *);
+extern  exports * mountproc_export_2(void *, CLIENT *);
+extern  exports * mountproc_export_2_svc(void *, struct svc_req *);
+extern  exports * mountproc_exportall_2(void *, CLIENT *);
+extern  exports * mountproc_exportall_2_svc(void *, struct svc_req *);
+#define MOUNTPROC_PATHCONF 7
+extern  ppathcnf * mountproc_pathconf_2(dirpath *, CLIENT *);
+extern  ppathcnf * mountproc_pathconf_2_svc(dirpath *, struct svc_req *);
+extern int mountprog_2_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
+
+#define MOUNT_V3 3
+
+#define MOUNTPROC3_NULL 0
+extern  void * mountproc3_null_3(void *, CLIENT *);
+extern  void * mountproc3_null_3_svc(void *, struct svc_req *);
+#define MOUNTPROC3_MNT 1
+extern  mountres3 * mountproc3_mnt_3(dirpath *, CLIENT *);
+extern  mountres3 * mountproc3_mnt_3_svc(dirpath *, struct svc_req *);
+#define MOUNTPROC3_DUMP 2
+extern  mountlist * mountproc3_dump_3(void *, CLIENT *);
+extern  mountlist * mountproc3_dump_3_svc(void *, struct svc_req *);
+#define MOUNTPROC3_UMNT 3
+extern  void * mountproc3_umnt_3(dirpath *, CLIENT *);
+extern  void * mountproc3_umnt_3_svc(dirpath *, struct svc_req *);
+#define MOUNTPROC3_UMNTALL 4
+extern  void * mountproc3_umntall_3(void *, CLIENT *);
+extern  void * mountproc3_umntall_3_svc(void *, struct svc_req *);
+#define MOUNTPROC3_EXPORT 5
+extern  exports * mountproc3_export_3(void *, CLIENT *);
+extern  exports * mountproc3_export_3_svc(void *, struct svc_req *);
+extern int mountprog_3_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
+
+/* the xdr functions */
+
+static  bool_t xdr_fhandle (XDR *, fhandle);
+extern  bool_t xdr_fhandle3 (XDR *, fhandle3*);
+extern  bool_t xdr_mountstat3 (XDR *, mountstat3*);
+extern  bool_t xdr_fhstatus (XDR *, fhstatus*);
+extern  bool_t xdr_mountres3_ok (XDR *, mountres3_ok*);
+extern  bool_t xdr_mountres3 (XDR *, mountres3*);
+extern  bool_t xdr_dirpath (XDR *, dirpath*);
+extern  bool_t xdr_name (XDR *, name*);
+extern  bool_t xdr_mountlist (XDR *, mountlist*);
+extern  bool_t xdr_mountbody (XDR *, mountbody*);
+extern  bool_t xdr_groups (XDR *, groups*);
+extern  bool_t xdr_groupnode (XDR *, groupnode*);
+extern  bool_t xdr_exports (XDR *, exports*);
+extern  bool_t xdr_exportnode (XDR *, exportnode*);
+extern  bool_t xdr_ppathcnf (XDR *, ppathcnf*);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_NFSMOUNT_H_RPCGEN */

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/pivot_root.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/pivot_root.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/pivot_root.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,28 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * pivot_root.c - Change root file system.  Based on util-linux 2.10s
+ *
+ * busyboxed by Evin Robertson
+ * pivot_root syscall stubbed by Erik Andersen, so it will compile
+ *     regardless of the kernel being used.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include "busybox.h"
+
+extern int pivot_root(const char * new_root,const char * put_old);
+
+int pivot_root_main(int argc, char **argv)
+{
+    if (argc != 3)
+	bb_show_usage();
+
+	if (pivot_root(argv[1],argv[2]) < 0)
+		bb_perror_msg_and_die("pivot_root");
+
+    return EXIT_SUCCESS;
+
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/rdate.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/rdate.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/rdate.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,86 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * The Rdate command will ask a time server for the RFC 868 time
+ *  and optionally set the system time.
+ *
+ * by Sterling Huxley <sterling at europa.com>
+ *
+ * Licensed under GPL v2 or later, see file License for details.
+*/
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "busybox.h"
+
+
+static const int RFC_868_BIAS = 2208988800UL;
+
+static void socket_timeout(int sig)
+{
+	bb_error_msg_and_die("timeout connecting to time server");
+}
+
+static time_t askremotedate(const char *host)
+{
+	unsigned long nett;
+	struct sockaddr_in s_in;
+	int fd;
+
+	bb_lookup_host(&s_in, host);
+	s_in.sin_port = bb_lookup_port("time", "tcp", 37);
+
+	/* Add a timeout for dead or inaccessible servers */
+	alarm(10);
+	signal(SIGALRM, socket_timeout);
+
+	fd = xconnect(&s_in);
+
+	if (safe_read(fd, (void *)&nett, 4) != 4)    /* read time from server */
+		bb_error_msg_and_die("%s did not send the complete time", host);
+	close(fd);
+
+	/* convert from network byte order to local byte order.
+	 * RFC 868 time is the number of seconds
+	 *  since 00:00 (midnight) 1 January 1900 GMT
+	 *  the RFC 868 time 2,208,988,800 corresponds to 00:00  1 Jan 1970 GMT
+	 * Subtract the RFC 868 time  to get Linux epoch
+	 */
+
+	return(ntohl(nett) - RFC_868_BIAS);
+}
+
+int rdate_main(int argc, char **argv)
+{
+	time_t remote_time;
+	unsigned long flags;
+
+	bb_opt_complementally = "-1";
+	flags = bb_getopt_ulflags(argc, argv, "sp");
+
+	remote_time = askremotedate(argv[optind]);
+
+	if ((flags & 2) == 0) {
+		time_t current_time;
+
+		time(&current_time);
+		if (current_time == remote_time)
+			bb_error_msg("Current time matches remote time.");
+		else
+			if (stime(&remote_time) < 0)
+				bb_perror_msg_and_die("Could not set time of day");
+	}
+
+	if ((flags & 1) == 0)
+		printf("%s", ctime(&remote_time));
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/readprofile.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/readprofile.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/readprofile.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,299 @@
+/*
+ *  readprofile.c - used to read /proc/profile
+ *
+ *  Copyright (C) 1994,1996 Alessandro Rubini (rubini at ipvvis.unipv.it)
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek at pld.ORG.PL>
+ * - added Native Language Support
+ * 1999-09-01 Stephane Eranian <eranian at cello.hpl.hp.com>
+ * - 64bit clean patch
+ * 3Feb2001 Andrew Morton <andrewm at uow.edu.au>
+ * - -M option to write profile multiplier.
+ * 2001-11-07 Werner Almesberger <wa at almesberger.net>
+ * - byte order auto-detection and -n option
+ * 2001-11-09 Werner Almesberger <wa at almesberger.net>
+ * - skip step size (index 0)
+ * 2002-03-09 John Levon <moz at compsoc.man.ac.uk>
+ * - make maplineno do something
+ * 2002-11-28 Mads Martin Joergensen +
+ * - also try /boot/System.map-`uname -r`
+ * 2003-04-09 Werner Almesberger <wa at almesberger.net>
+ * - fixed off-by eight error and improved heuristics in byte order detection
+ * 2003-08-12 Nikita Danilov <Nikita at Namesys.COM>
+ * - added -s option; example of use:
+ * "readprofile -s -m /boot/System.map-test | grep __d_lookup | sort -n -k3"
+ *
+ * Taken from util-linux and adapted for busybox by
+ * Paul Mundt <lethal at linux-sh.org>.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+
+#include "busybox.h"
+
+#define S_LEN 128
+
+/* These are the defaults */
+static const char defaultmap[]="/boot/System.map";
+static const char defaultpro[]="/proc/profile";
+
+int readprofile_main(int argc, char **argv)
+{
+	FILE *map;
+	int proFd;
+	const char *mapFile, *proFile, *mult=0;
+	unsigned long len=0, indx=1;
+	unsigned long long add0=0;
+	unsigned int step;
+	unsigned int *buf, total, fn_len;
+	unsigned long long fn_add, next_add;          /* current and next address */
+	char fn_name[S_LEN], next_name[S_LEN];   /* current and next name */
+	char mode[8];
+	int c;
+	int optAll=0, optInfo=0, optReset=0, optVerbose=0, optNative=0;
+	int optBins=0, optSub=0;
+	char mapline[S_LEN];
+	int maplineno=1;
+	int header_printed;
+
+#define next (current^1)
+
+	proFile = defaultpro;
+	mapFile = defaultmap;
+
+	while ((c = getopt(argc, argv, "M:m:np:itvarVbs")) != -1) {
+		switch(c) {
+		case 'm':
+			mapFile = optarg;
+			break;
+		case 'n':
+			optNative++;
+			break;
+		case 'p':
+			proFile = optarg;
+			break;
+		case 'a':
+			optAll++;
+			break;
+		case 'b':
+			optBins++;
+			break;
+		case 's':
+			optSub++;
+			break;
+		case 'i':
+			optInfo++;
+			break;
+		case 'M':
+			mult = optarg;
+			break;
+		case 'r':
+			optReset++;
+			break;
+		case 'v':
+			optVerbose++;
+			break;
+		default:
+			bb_show_usage();
+		}
+	}
+
+	if (optReset || mult) {
+		int multiplier, fd, to_write;
+
+		/*
+		 * When writing the multiplier, if the length of the write is
+		 * not sizeof(int), the multiplier is not changed
+		 */
+		if (mult) {
+			multiplier = strtoul(mult, 0, 10);
+			to_write = sizeof(int);
+		} else {
+			multiplier = 0;
+			to_write = 1;	/* sth different from sizeof(int) */
+		}
+
+		fd = bb_xopen(defaultpro,O_WRONLY);
+
+		if (write(fd, &multiplier, to_write) != to_write)
+			bb_perror_msg_and_die("error writing %s", defaultpro);
+
+		close(fd);
+		return EXIT_SUCCESS;
+	}
+
+	/*
+	 * Use an fd for the profiling buffer, to skip stdio overhead
+	 */
+
+	proFd = bb_xopen(proFile,O_RDONLY);
+
+	if (((int)(len=lseek(proFd,0,SEEK_END)) < 0)
+	    || (lseek(proFd,0,SEEK_SET) < 0))
+		bb_perror_msg_and_die(proFile);
+
+	buf = xmalloc(len);
+
+	if (read(proFd,buf,len) != len)
+		bb_perror_msg_and_die(proFile);
+
+	close(proFd);
+
+	if (!optNative) {
+		int entries = len/sizeof(*buf);
+		int big = 0,small = 0,i;
+		unsigned *p;
+
+		for (p = buf+1; p < buf+entries; p++) {
+			if (*p & ~0U << (sizeof(*buf)*4))
+				big++;
+			if (*p & ((1 << (sizeof(*buf)*4))-1))
+				small++;
+		}
+		if (big > small) {
+			bb_error_msg("Assuming reversed byte order. "
+				"Use -n to force native byte order.");
+			for (p = buf; p < buf+entries; p++)
+				for (i = 0; i < sizeof(*buf)/2; i++) {
+					unsigned char *b = (unsigned char *) p;
+					unsigned char tmp;
+
+					tmp = b[i];
+					b[i] = b[sizeof(*buf)-i-1];
+					b[sizeof(*buf)-i-1] = tmp;
+				}
+		}
+	}
+
+	step = buf[0];
+	if (optInfo) {
+		printf("Sampling_step: %i\n", step);
+		return EXIT_SUCCESS;
+	}
+
+	total = 0;
+
+	map = bb_xfopen(mapFile, "r");
+
+	while (fgets(mapline,S_LEN,map)) {
+		if (sscanf(mapline,"%llx %s %s",&fn_add,mode,fn_name) != 3)
+			bb_error_msg_and_die("%s(%i): wrong map line",
+					     mapFile, maplineno);
+
+		if (!strcmp(fn_name,"_stext")) /* only elf works like this */ {
+			add0 = fn_add;
+			break;
+		}
+		maplineno++;
+	}
+
+	if (!add0)
+		bb_error_msg_and_die("can't find \"_stext\" in %s", mapFile);
+
+	/*
+	 * Main loop.
+	 */
+	while (fgets(mapline,S_LEN,map)) {
+		unsigned int this = 0;
+
+		if (sscanf(mapline,"%llx %s %s",&next_add,mode,next_name) != 3)
+			bb_error_msg_and_die("%s(%i): wrong map line",
+					     mapFile, maplineno);
+
+		header_printed = 0;
+
+		/* ignore any LEADING (before a '[tT]' symbol is found)
+		   Absolute symbols */
+		if ((*mode == 'A' || *mode == '?') && total == 0) continue;
+		if (*mode != 'T' && *mode != 't' &&
+		    *mode != 'W' && *mode != 'w')
+			break;	/* only text is profiled */
+
+		if (indx >= len / sizeof(*buf))
+			bb_error_msg_and_die("profile address out of range. "
+					     "Wrong map file?");
+
+		while (indx < (next_add-add0)/step) {
+			if (optBins && (buf[indx] || optAll)) {
+				if (!header_printed) {
+					printf ("%s:\n", fn_name);
+					header_printed = 1;
+				}
+				printf ("\t%llx\t%u\n", (indx - 1)*step + add0, buf[indx]);
+			}
+			this += buf[indx++];
+		}
+		total += this;
+
+		if (optBins) {
+			if (optVerbose || this > 0)
+				printf ("  total\t\t\t\t%u\n", this);
+		} else if ((this || optAll) &&
+			   (fn_len = next_add-fn_add) != 0) {
+			if (optVerbose)
+				printf("%016llx %-40s %6i %8.4f\n", fn_add,
+				       fn_name,this,this/(double)fn_len);
+			else
+				printf("%6i %-40s %8.4f\n",
+				       this,fn_name,this/(double)fn_len);
+			if (optSub) {
+				unsigned long long scan;
+
+				for (scan = (fn_add-add0)/step + 1;
+				     scan < (next_add-add0)/step; scan++) {
+					unsigned long long addr;
+
+					addr = (scan - 1)*step + add0;
+					printf("\t%#llx\t%s+%#llx\t%u\n",
+					       addr, fn_name, addr - fn_add,
+					       buf[scan]);
+				}
+			}
+		}
+
+		fn_add = next_add;
+		strcpy(fn_name,next_name);
+
+		maplineno++;
+	}
+
+	/* clock ticks, out of kernel text - probably modules */
+	printf("%6i %s\n", buf[len/sizeof(*buf)-1], "*unknown*");
+
+	/* trailer */
+	if (optVerbose)
+		printf("%016x %-40s %6i %8.4f\n",
+		       0,"total",total,total/(double)(fn_add-add0));
+	else
+		printf("%6i %-40s %8.4f\n",
+		       total,"total",total/(double)(fn_add-add0));
+
+	fclose(map);
+	free(buf);
+
+	return EXIT_SUCCESS;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/setarch.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/setarch.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/setarch.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,52 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Linux32/linux64 allows for changing uname emulation.
+ *
+ * Copyright 2002 Andi Kleen, SuSE Labs.
+ *
+ * Licensed under GPL v2 or later, see file License for details.
+*/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/personality.h>
+
+#include "busybox.h"
+
+int setarch_main(int ATTRIBUTE_UNUSED argc, char **argv)
+{
+	int pers = -1;
+
+	/* Figure out what personality we are supposed to switch to ...
+	 * we can be invoked as either:
+	 * argv[0],argv[1] -> "setarch","personality"
+	 * argv[0]         -> "personality"
+	 */
+retry:
+	if (argv[0][5] == '6') /* linux64 */
+		pers = PER_LINUX;
+	else if (argv[0][5] == '3') /* linux32 */
+		pers = PER_LINUX32;
+	else if (pers == -1 && argv[1] != NULL) {
+		pers = PER_LINUX32;
+		++argv;
+		goto retry;
+	}
+
+	/* make user actually gave us something to do */
+	++argv;
+	if (argv[0] == NULL)
+		bb_show_usage();
+
+	/* Try to set personality */
+	if (personality(pers) >= 0) {
+
+		/* Try to execute the program */
+		execvp(argv[0], argv);
+	}
+
+	bb_perror_msg_and_die("%s", argv[0]);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/swaponoff.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/swaponoff.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/swaponoff.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,80 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini swapon/swapoff implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ *
+ * Licensed under the GPL v2, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+#include <mntent.h>
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/swap.h>
+
+
+static int swap_enable_disable(const char *device)
+{
+	int status;
+	struct stat st;
+
+	xstat(device, &st);
+
+	/* test for holes */
+	if (S_ISREG(st.st_mode))
+		if (st.st_blocks * 512 < st.st_size)
+			bb_error_msg_and_die("swap file has holes");
+
+	if (bb_applet_name[5] == 'n')
+		status = swapon(device, 0);
+	else
+		status = swapoff(device);
+
+	if (status != 0) {
+		bb_perror_msg("%s", device);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int do_em_all(void)
+{
+	struct mntent *m;
+	FILE *f;
+	int err;
+
+	f = setmntent("/etc/fstab", "r");
+	if (f == NULL)
+		bb_perror_msg_and_die("/etc/fstab");
+
+	err = 0;
+	while ((m = getmntent(f)) != NULL)
+		if (strcmp(m->mnt_type, MNTTYPE_SWAP) == 0)
+			err += swap_enable_disable(m->mnt_fsname);
+
+	endmntent(f);
+
+	return err;
+}
+
+#define DO_ALL    0x01
+
+int swap_on_off_main(int argc, char **argv)
+{
+	int ret;
+
+	if (argc == 1)
+		bb_show_usage();
+
+	ret = bb_getopt_ulflags(argc, argv, "a");
+	if (ret & DO_ALL)
+		return do_em_all();
+
+	ret = 0;
+	while (*++argv)
+		ret += swap_enable_disable(*argv);
+	return ret;
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/switch_root.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/switch_root.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/switch_root.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,125 @@
+/* vi:set ts=4:*/
+/* Copyright 2005 Rob Landley <rob at landley.net>
+ *
+ * Switch from rootfs to another filesystem as the root of the mount tree.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "busybox.h"
+#include <fcntl.h>
+#include <string.h>
+#include <sys/vfs.h>
+#include <unistd.h>
+
+
+// Make up for header deficiencies.
+
+#ifndef RAMFS_MAGIC
+#define RAMFS_MAGIC		0x858458f6
+#endif
+
+#ifndef TMPFS_MAGIC
+#define TMPFS_MAGIC		0x01021994
+#endif
+
+#ifndef MS_MOVE
+#define MS_MOVE			8192
+#endif
+
+dev_t rootdev;
+
+// Recursively delete contents of rootfs.
+
+static void delete_contents(char *directory)
+{
+	DIR *dir;
+	struct dirent *d;
+	struct stat st;
+
+	// Don't descend into other filesystems
+	if (lstat(directory,&st) || st.st_dev != rootdev) return;
+
+	// Recursively delete the contents of directories.
+	if (S_ISDIR(st.st_mode)) {
+		if((dir = opendir(directory))) {
+			while ((d = readdir(dir))) {
+				char *newdir=d->d_name;
+
+				// Skip . and ..
+				if(*newdir=='.' && (!newdir[1] || (newdir[1]=='.' && !newdir[2])))
+					continue;
+
+				// Recurse to delete contents
+				newdir = alloca(strlen(directory) + strlen(d->d_name) + 2);
+				sprintf(newdir, "%s/%s", directory, d->d_name);
+				delete_contents(newdir);
+			}
+			closedir(dir);
+
+			// Directory should now be empty.  Zap it.
+			rmdir(directory);
+		}
+
+	// It wasn't a directory.  Zap it.
+
+	} else unlink(directory);
+}
+
+int switch_root_main(int argc, char *argv[])
+{
+	char *newroot, *console=NULL;
+	struct stat st1, st2;
+	struct statfs stfs;
+
+	// Parse args (-c console)
+
+	bb_opt_complementally="-2";
+	bb_getopt_ulflags(argc,argv,"c:",&console);
+
+	// Change to new root directory and verify it's a different fs.
+
+	newroot=argv[optind++];
+
+	if (chdir(newroot) || lstat(".", &st1) || lstat("/", &st2) ||
+		st1.st_dev == st2.st_dev)
+	{
+		bb_error_msg_and_die("bad newroot %s",newroot);
+	}
+	rootdev=st2.st_dev;
+
+	// Additional sanity checks: we're about to rm -rf /,  so be REALLY SURE
+	// we mean it.  (I could make this a CONFIG option, but I would get email
+	// from all the people who WILL eat their filesystemss.)
+
+	if (lstat("/init", &st1) || !S_ISREG(st1.st_mode) || statfs("/", &stfs) ||
+		(stfs.f_type != RAMFS_MAGIC && stfs.f_type != TMPFS_MAGIC) ||
+		getpid() != 1)
+	{
+		bb_error_msg_and_die("not rootfs");
+	}
+
+	// Zap everything out of rootdev
+
+	delete_contents("/");
+
+	// Overmount / with newdir and chroot into it.  The chdir is needed to
+	// recalculate "." and ".." links.
+
+	if (mount(".", "/", NULL, MS_MOVE, NULL) || chroot(".") || chdir("/"))
+		bb_error_msg_and_die("moving root");
+
+	// If a new console specified, redirect stdin/stdout/stderr to that.
+
+	if (console) {
+		close(0);
+		if(open(console, O_RDWR) < 0)
+			bb_error_msg_and_die("Bad console '%s'",console);
+		dup2(0, 1);
+		dup2(0, 2);
+	}
+
+	// Exec real init.  (This is why we must be pid 1.)
+	execv(argv[optind],argv+optind);
+	bb_error_msg_and_die("Bad init '%s'",argv[optind]);
+}

Added: trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/umount.c
===================================================================
--- trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/umount.c	2006-09-17 20:14:33 UTC (rev 254)
+++ trunk/Marvell/Src/uClinux-dist/user.asus/busybox-1.2.1/util-linux/umount.c	2006-09-17 20:11:48 UTC (rev 255)
@@ -0,0 +1,149 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini umount implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen at codepoet.org>
+ * Copyright (C) 2005 by Rob Landley <rob at landley.net>
+ *
+ * This program is licensed under the GNU General Public license (GPL)
+ * version 2 or later, see http://www.fsf.org/licensing/licenses/gpl.html
+ * or the file "LICENSE" in the busybox source tarball for the full text.
+ *
+ */
+
+#include "busybox.h"
+#include <mntent.h>
+#include <errno.h>
+#include <string.h>
+#include <getopt.h>
+
+#define OPTION_STRING		"flDnrvad"
+#define OPT_FORCE			1
+#define OPT_LAZY			2
+#define OPT_DONTFREELOOP	4
+#define OPT_NO_MTAB			8
+#define OPT_REMOUNT			16
+#define OPT_IGNORED			32	// -v is ignored
+#define OPT_ALL				(ENABLE_FEATURE_UMOUNT_ALL ? 64 : 0)
+
+int umount_main(int argc, char **argv)
+{
+	int doForce;
+	char path[2*PATH_MAX];
+	struct mntent me;
+	FILE *fp;
+	int status = EXIT_SUCCESS;
+	unsigned long opt;
+	struct mtab_list {
+		char *dir;
+		char *device;
+		struct mtab_list *next;
+	} *mtl, *m;
+
+	/* Parse any options */
+
+	opt = bb_getopt_ulflags(argc, argv, OPTION_STRING);
+
+	argc -= optind;
+	argv += optind;
+
+	doForce = MAX((opt & OPT_FORCE), (opt & OPT_LAZY));
+
+	/* Get a list of mount points from mtab.  We read them all in now mostly
+	 * for umount -a (so we don't have to worry about the list changing while
+	 * we iterate over it, or about getting stuck in a loop on the same failing
+	 * entry.  Notice that this also naturally reverses the list so that -a
+	 * umounts the most recent entries first. */
+
+	m = mtl = 0;
+
+	/* If we're umounting all, then m points to the start of the list and
+	 * the argument list should be empty (which will match all). */
+
+	if (!(fp = setmntent(bb_path_mtab_file, "r"))) {
+		if (opt & OPT_ALL)
+			bb_error_msg_and_die("Cannot open %s", bb_path_mtab_file);
+	} else while (getmntent_r(fp,&me,path,sizeof(path))) {
+		m = xmalloc(sizeof(struct mtab_list));
+		m->next = mtl;
+		m->device = bb_xstrdup(me.mnt_fsname);
+		m->dir = bb_xstrdup(me.mnt_dir);
+		mtl = m;
+	}
+	endmntent(fp);
+
+	/* If we're not mounting all, we need at least one argument. */
+	if (!(opt & OPT_ALL)) {
+		m = 0;
+		if (!argc) bb_show_usage();
+	}
+
+
+	
+	// Loop through everything we're supposed to umount, and do so.
+	for (;;) {
+		int curstat;
+
+		// Do we already know what to umount this time through the loop?
+		if (m) safe_strncpy(path, m->dir, PATH_MAX);
+		// For umount -a, end of mtab means time to exit.
+		else if (opt & OPT_ALL) break;
+		// Get next command line argument (and look it up in mtab list)
+		else if (!argc--) break;
+		else {
+			realpath(*argv++, path);
+			for (m = mtl; m; m = m->next)
+				if (!strcmp(path, m->dir) || !strcmp(path, m->device))
+					break;
+		}
+
+		// Let's ask the thing nicely to unmount.
+		curstat = umount(path);
+
+		// Force the unmount, if necessary.
+		if (curstat && doForce) {
+			curstat = umount2(path, doForce);
+			if (curstat)
+				bb_error_msg_and_die("forced umount of %s failed!", path);
+		}
+
+		// If still can't umount, maybe remount read-only?
+		if (curstat && (opt & OPT_REMOUNT) && errno == EBUSY && m) {
+			curstat = mount(m->device, path, NULL, MS_REMOUNT|MS_RDONLY, NULL);
+			bb_error_msg(curstat ? "Cannot remount %s read-only" :
+						 "%s busy - remounted read-only", m->device);
+		}
+
+		/* De-allocate the loop device.  This ioctl should be ignored on any
+		 * non-loop block devices. */
+		if (ENABLE_FEATURE_MOUNT_LOOP && !(opt & OPT_DONTFREELOOP) && m)
+			del_loop(m->device);
+
+		if (curstat) {
+			/* Yes, the ENABLE is redundant here, but the optimizer for ARM
+			 * can't do simple constant propagation in local variables... */
+			if(ENABLE_FEATURE_MTAB_SUPPORT && !(opt & OPT_NO_MTAB) && m)
+				erase_mtab(m->dir);
+			status = EXIT_FAILURE;
+			bb_perror_msg("Couldn't umount %s", path);
+		}
+		// Find next matching mtab entry for -a or umount /dev
+		while (m && (m = m->next))
+			if ((opt & OPT_ALL) || !strcmp(path,m->device))
+				break;
+	}
+
+	// Free mtab list if necessary
+
+	if (ENABLE_FEATURE_CLEAN_UP) {
+		while (mtl) {
+			m = mtl->next;
+			free(mtl->device);
+			free(mtl->dir);
+			free(mtl);
+			mtl=m;
+		}
+	}
+
+	return status;
+}




More information about the Wl530g-svncheckins mailing list